From 11a79f951a4c5a3b6de4d8cc0131ac87f8a3961b Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 16 Jan 2024 19:34:43 +0900 Subject: [PATCH 001/502] improve: fix duplicated verification logic --- internal/delivery/http/auth.go | 31 +++++++++++++++++ internal/keycloak/keycloak.go | 12 +++---- .../auth/authenticator/keycloak/keycloak.go | 34 +++---------------- internal/route/route.go | 1 + internal/usecase/auth.go | 29 +++++++++++++++- 5 files changed, 71 insertions(+), 36 deletions(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 2c5fcd4d..1086faed 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -23,6 +23,7 @@ type IAuthHandler interface { VerifyIdentityForLostId(w http.ResponseWriter, r *http.Request) VerifyIdentityForLostPassword(w http.ResponseWriter, r *http.Request) + VerifyToken(w http.ResponseWriter, r *http.Request) //Authenticate(next http.Handler) http.Handler } type AuthHandler struct { @@ -284,3 +285,33 @@ func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, nil) } + +// VerifyToken godoc +// @Tags Auth +// @Summary verify token +// @Description verify token +// @Success 200 {object} nil +// @Router /auth/verify-token [get] + +func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { + token, ok := request.TokenFrom(r.Context()) + if !ok { + log.ErrorfWithContext(r.Context(), "token is not found") + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("token is not found"), "C_INTERNAL_ERROR", "")) + return + } + + isActive, err := h.usecase.VerifyToken(token) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + if !isActive { + ErrorJSON(w, r, httpErrors.NewUnauthorizedError(fmt.Errorf("token is not active"), "C_UNAUTHORIZED", "")) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 45976edb..7c3040a6 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -36,7 +36,7 @@ type IKeycloak interface { JoinGroup(organizationId string, userId string, groupName string) error LeaveGroup(organizationId string, userId string, groupName string) error - VerifyAccessToken(token string, organizationId string) error + VerifyAccessToken(token string, organizationId string) (bool, error) GetSessions(userId string, organizationId string) (*[]string, error) } type Keycloak struct { @@ -364,17 +364,17 @@ func (k *Keycloak) DeleteUser(organizationId string, userAccountId string) error return nil } -func (k *Keycloak) VerifyAccessToken(token string, organizationId string) error { +func (k *Keycloak) VerifyAccessToken(token string, organizationId string) (bool, error) { ctx := context.Background() rptResult, err := k.client.RetrospectToken(ctx, token, DefaultClientID, k.config.ClientSecret, organizationId) if err != nil { - return err + return false, err } - if !(*rptResult.Active) { - return err + return false, nil } - return nil + + return true, nil } func (k *Keycloak) GetSessions(userId string, organizationId string) (*[]string, error) { diff --git a/internal/middleware/auth/authenticator/keycloak/keycloak.go b/internal/middleware/auth/authenticator/keycloak/keycloak.go index 89c516c2..f480cc7e 100644 --- a/internal/middleware/auth/authenticator/keycloak/keycloak.go +++ b/internal/middleware/auth/authenticator/keycloak/keycloak.go @@ -53,23 +53,19 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) return nil, false, err } - if parsedToken.Method.Alg() != "RS256" { - return nil, false, fmt.Errorf("invalid token") - } - - if parsedToken.Claims.Valid() != nil { - return nil, false, fmt.Errorf("invalid token") - } - organizationId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["organization"].(string) if !ok { return nil, false, fmt.Errorf("organization is not found in token") } - if err := a.kc.VerifyAccessToken(token, organizationId); err != nil { + isActive, err := a.kc.VerifyAccessToken(token, organizationId) + if err != nil { log.Errorf("failed to verify access token: %v", err) return nil, false, err } + if !isActive { + return nil, false, fmt.Errorf("token is not active") + } roleProjectMapping := make(map[string]string) for _, role := range parsedToken.Claims.(jwtWithouKey.MapClaims)["tks-role"].([]interface{}) { @@ -93,26 +89,6 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) return nil, false, fmt.Errorf("session id is not found in token") } - sessionIds, err := a.kc.GetSessions(userId.String(), organizationId) - if err != nil { - log.Errorf("failed to get sessions: %v", err) - - return nil, false, err - } - if len(*sessionIds) == 0 { - return nil, false, fmt.Errorf("invalid session") - } - var matched bool = false - for _, id := range *sessionIds { - if id == requestSessionId { - matched = true - break - } - } - if !matched { - return nil, false, fmt.Errorf("invalid session") - } - userInfo := &user.DefaultInfo{ UserId: userId, OrganizationId: organizationId, diff --git a/internal/route/route.go b/internal/route/route.go index e82d6214..c798bb8c 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -80,6 +80,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-password/verification", authHandler.FindPassword).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-id/code", authHandler.VerifyIdentityForLostId).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-password/code", authHandler.VerifyIdentityForLostPassword).Methods(http.MethodPost) + r.HandleFunc(API_PREFIX+API_VERSION+"/auth/verify-token", authHandler.VerifyToken).Methods(http.MethodGet) //r.HandleFunc(API_PREFIX+API_VERSION+"/cookie-test", authHandler.CookieTest).Methods(http.MethodPost) //r.HandleFunc(API_PREFIX+API_VERSION+"/auth/callback", authHandler.CookieTestCallback).Methods(http.MethodGet) diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 3455505b..a7d2479e 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -39,6 +39,7 @@ type IAuthUsecase interface { FetchRoles() (out []domain.Role, err error) SingleSignIn(organizationId, accountId, password string) ([]*http.Cookie, error) SingleSignOut(organizationId string) (string, []*http.Cookie, error) + VerifyToken(token string) (bool, error) } const ( @@ -121,10 +122,14 @@ func (u *AuthUsecase) PingToken(accessToken string, organizationId string) error return fmt.Errorf("invalid token") } - if err := u.kc.VerifyAccessToken(accessToken, organizationId); err != nil { + isActive, err := u.kc.VerifyAccessToken(accessToken, organizationId) + if err != nil { log.Errorf("failed to verify access token: %v", err) return err } + if !isActive { + return fmt.Errorf("token is not active") + } userId, err := uuid.Parse(parsedToken.Claims.(jwtWithouKey.MapClaims)["sub"].(string)) if err != nil { @@ -381,6 +386,28 @@ func (u *AuthUsecase) SingleSignOut(organizationId string) (string, []*http.Cook return redirectUrl, cookies, nil } +func (u *AuthUsecase) VerifyToken(token string) (bool, error) { + parsedToken, _, err := new(jwtWithouKey.Parser).ParseUnverified(token, jwtWithouKey.MapClaims{}) + if err != nil { + return false, err + } + org, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["organization"].(string) + if !ok { + return false, fmt.Errorf("organization is not found in token") + } + + isActive, err := u.kc.VerifyAccessToken(token, org) + if err != nil { + log.Errorf("failed to verify access token: %v", err) + return false, err + } + if !isActive { + return false, fmt.Errorf("token is not active") + } + + return true, nil +} + func (u *AuthUsecase) isExpiredEmailCode(code repository.CacheEmailCode) bool { return !helper.IsDurationExpired(code.UpdatedAt, internal.EmailCodeExpireTime) } From 73a863782da60cd63b7403186757b9caaf35e660 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 17 Jan 2024 17:18:26 +0900 Subject: [PATCH 002/502] bugfix: fix verify-token API not working --- internal/delivery/http/auth.go | 1 + .../auth/authenticator/authenticator.go | 2 +- .../auth/authenticator/keycloak/keycloak.go | 15 ++++++++------- internal/route/route.go | 2 +- internal/usecase/auth.go | 3 +-- pkg/httpErrors/errorCode.go | 1 + 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 1086faed..361d33e0 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -291,6 +291,7 @@ func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { // @Summary verify token // @Description verify token // @Success 200 {object} nil +// @Failure 401 {object} nil // @Router /auth/verify-token [get] func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { diff --git a/internal/middleware/auth/authenticator/authenticator.go b/internal/middleware/auth/authenticator/authenticator.go index 07390f74..976850ac 100644 --- a/internal/middleware/auth/authenticator/authenticator.go +++ b/internal/middleware/auth/authenticator/authenticator.go @@ -33,7 +33,7 @@ func (a *defaultAuthenticator) WithAuthentication(handler http.Handler) http.Han resp, ok, err := a.auth.AuthenticateRequest(r) if !ok { log.Error(err) - internalHttp.ErrorJSON(w, r, httpErrors.NewUnauthorizedError(err, "", "")) + internalHttp.ErrorJSON(w, r, err) return } r = r.WithContext(request.WithUser(r.Context(), resp.User)) diff --git a/internal/middleware/auth/authenticator/keycloak/keycloak.go b/internal/middleware/auth/authenticator/keycloak/keycloak.go index f480cc7e..445eb774 100644 --- a/internal/middleware/auth/authenticator/keycloak/keycloak.go +++ b/internal/middleware/auth/authenticator/keycloak/keycloak.go @@ -2,6 +2,7 @@ package keycloak import ( "fmt" + "github.com/openinfradev/tks-api/pkg/httpErrors" "net/http" "strings" @@ -50,21 +51,21 @@ func (a *keycloakAuthenticator) AuthenticateRequest(r *http.Request) (*authentic func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) (*authenticator.Response, bool, error) { parsedToken, _, err := new(jwtWithouKey.Parser).ParseUnverified(token, jwtWithouKey.MapClaims{}) if err != nil { - return nil, false, err + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } organizationId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["organization"].(string) if !ok { - return nil, false, fmt.Errorf("organization is not found in token") + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("organization is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } isActive, err := a.kc.VerifyAccessToken(token, organizationId) if err != nil { log.Errorf("failed to verify access token: %v", err) - return nil, false, err + return nil, false, httpErrors.NewUnauthorizedError(err, "C_INTERNAL_ERROR", "") } if !isActive { - return nil, false, fmt.Errorf("token is not active") + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("token is deactivated"), "A_EXPIRED_TOKEN", "토큰이 만료되었습니다.") } roleProjectMapping := make(map[string]string) @@ -73,7 +74,7 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) if len(slice) != 2 { log.Errorf("invalid tks-role format: %v", role) - return nil, false, fmt.Errorf("invalid tks-role format") + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid tks-role format"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } // key is projectName and value is roleName roleProjectMapping[slice[1]] = slice[0] @@ -82,11 +83,11 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) if err != nil { log.Errorf("failed to verify access token: %v", err) - return nil, false, err + return nil, false, httpErrors.NewUnauthorizedError(err, "C_INTERNAL_ERROR", "") } requestSessionId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["sid"].(string) if !ok { - return nil, false, fmt.Errorf("session id is not found in token") + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("session id is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } userInfo := &user.DefaultInfo{ diff --git a/internal/route/route.go b/internal/route/route.go index c798bb8c..7bfd05ff 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -80,7 +80,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-password/verification", authHandler.FindPassword).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-id/code", authHandler.VerifyIdentityForLostId).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-password/code", authHandler.VerifyIdentityForLostPassword).Methods(http.MethodPost) - r.HandleFunc(API_PREFIX+API_VERSION+"/auth/verify-token", authHandler.VerifyToken).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/auth/verify-token", authMiddleware.Handle(http.HandlerFunc(authHandler.VerifyToken))).Methods(http.MethodGet) //r.HandleFunc(API_PREFIX+API_VERSION+"/cookie-test", authHandler.CookieTest).Methods(http.MethodPost) //r.HandleFunc(API_PREFIX+API_VERSION+"/auth/callback", authHandler.CookieTestCallback).Methods(http.MethodGet) diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index a7d2479e..a641fbee 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -398,11 +398,10 @@ func (u *AuthUsecase) VerifyToken(token string) (bool, error) { isActive, err := u.kc.VerifyAccessToken(token, org) if err != nil { - log.Errorf("failed to verify access token: %v", err) return false, err } if !isActive { - return false, fmt.Errorf("token is not active") + return false, nil } return true, nil diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 0fa40986..70558e34 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -22,6 +22,7 @@ var errorMap = map[ErrorCode]string{ "A_INVALID_PASSWORD": "비밀번호가 일치하지 않습니다.", "A_SAME_OLD_PASSWORD": "기존 비밀번호와 동일합니다.", "A_INVALID_TOKEN": "사용자 토큰 오류", + "A_EXPIRED_TOKEN": "사용자 토큰 만료", "A_INVALID_USER_CREDENTIAL": "비밀번호가 일치하지 않습니다.", "A_INVALID_ORIGIN_PASSWORD": "기존 비밀번호가 일치하지 않습니다.", "A_INVALID_CODE": "인증번호가 일치하지 않습니다.", From 60e5201e44588c746c9dad8194dae2de7ea0ee68 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 17 Jan 2024 18:58:07 +0900 Subject: [PATCH 003/502] project object prototype --- internal/delivery/http/project.go | 98 +++++++++++++++++++++++++++++++ internal/route/route.go | 15 +++++ internal/usecase/project.go | 26 ++++++++ 3 files changed, 139 insertions(+) create mode 100644 internal/delivery/http/project.go create mode 100644 internal/usecase/project.go diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go new file mode 100644 index 00000000..50fe49a0 --- /dev/null +++ b/internal/delivery/http/project.go @@ -0,0 +1,98 @@ +package http + +import ( + "github.com/openinfradev/tks-api/internal/usecase" + "net/http" +) + +type IProjectHandler interface { + CreateProject(w http.ResponseWriter, r *http.Request) + UpdateProject(w http.ResponseWriter, r *http.Request) + DeleteProject(w http.ResponseWriter, r *http.Request) + GetProject(w http.ResponseWriter, r *http.Request) + GetProjects(w http.ResponseWriter, r *http.Request) + + AddProjectMember(w http.ResponseWriter, r *http.Request) + RemoveProjectMember(w http.ResponseWriter, r *http.Request) + GetProjectMembers(w http.ResponseWriter, r *http.Request) + UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) + + CreateProjectNamespace(w http.ResponseWriter, r *http.Request) + GetProjectNamespaces(w http.ResponseWriter, r *http.Request) + GetProjectNamespace(w http.ResponseWriter, r *http.Request) + DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) +} +type ProjectHandler struct { + usecase usecase.IProjectUsecase +} + +func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func NewProjectHandler(u usecase.IProjectUsecase) IProjectHandler { + return &ProjectHandler{ + usecase: u, + } +} diff --git a/internal/route/route.go b/internal/route/route.go index 7bfd05ff..4c9bf5a8 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -191,6 +191,21 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", authMiddleware.Handle(http.HandlerFunc(stackHandler.DeleteFavorite))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/install", authMiddleware.Handle(http.HandlerFunc(stackHandler.InstallStack))).Methods(http.MethodPost) + projectHandler := delivery.NewProjectHandler(usecase.NewProjectUsecase(repoFactory)) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", authMiddleware.Handle(http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProjectMembers))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", authMiddleware.Handle(http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{accountId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{accountId}/role", authMiddleware.Handle(http.HandlerFunc(projectHandler.UpdateProjectMemberRole))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", authMiddleware.Handle(http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) + r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) diff --git a/internal/usecase/project.go b/internal/usecase/project.go new file mode 100644 index 00000000..d8fa9a9b --- /dev/null +++ b/internal/usecase/project.go @@ -0,0 +1,26 @@ +package usecase + +import ( + "github.com/openinfradev/tks-api/internal/repository" +) + +type IProjectUsecase interface { +} + +type ProjectUsecase struct { + userRepository repository.IUserRepository + authRepository repository.IAuthRepository + clusterRepository repository.IClusterRepository + appgroupRepository repository.IAppGroupRepository + organizationRepository repository.IOrganizationRepository +} + +func NewProjectUsecase(r repository.Repository) IProjectUsecase { + return &ProjectUsecase{ + userRepository: r.User, + authRepository: r.Auth, + clusterRepository: r.Cluster, + appgroupRepository: r.AppGroup, + organizationRepository: r.Organization, + } +} From c38519685fe510bce58b1806e659639047f9528d Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 23 Jan 2024 15:56:59 +0900 Subject: [PATCH 004/502] add file and line in log only for 1 depth functions --- pkg/log/log.go | 152 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 134 insertions(+), 18 deletions(-) diff --git a/pkg/log/log.go b/pkg/log/log.go index 5ad235dd..7bd6adb1 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -4,6 +4,8 @@ import ( "context" "io" "os" + "path" + "runtime" "strings" "github.com/openinfradev/tks-api/internal" @@ -18,10 +20,12 @@ var ( func init() { logger = logrus.New() logger.Out = os.Stdout - formatter := new(logrus.TextFormatter) - formatter.FullTimestamp = true - formatter.TimestampFormat = "2006-01-02 15:04:05" - logger.SetFormatter(formatter) + logger.SetFormatter(&CustomFormatter{&logrus.TextFormatter{ + FullTimestamp: true, + TimestampFormat: "2006-01-02 15:04:05", + DisableQuote: true, + }}) + //logger.SetReportCaller(true) logLevel := strings.ToLower(os.Getenv("LOG_LEVEL")) switch logLevel { @@ -40,12 +44,36 @@ func init() { } } +type CustomFormatter struct { + logrus.Formatter +} + +func (f *CustomFormatter) Format(entry *logrus.Entry) ([]byte, error) { + //_, file := path.Split(entry.Caller.File) + //entry.Data["file"] = file + return f.Formatter.Format(entry) +} + // [TODO] more pretty func Info(v ...interface{}) { - logger.Info(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": path.Base(file), + "line": line, + }).Info(v...) + } else { + logger.Info(v...) + } } func Infof(format string, v ...interface{}) { - logger.Infof(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": path.Base(file), + "line": line, + }).Infof(format, v...) + } else { + logger.Infof(format, v...) + } } func InfoWithContext(ctx context.Context, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) @@ -57,25 +85,69 @@ func InfofWithContext(ctx context.Context, format string, v ...interface{}) { } func Warn(v ...interface{}) { - logger.Warn(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + }).Warn(v...) + } else { + logger.Warn(v...) + } } func Warnf(format string, v ...interface{}) { - logger.Warnf(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + }).Warnf(format, v...) + } else { + logger.Warnf(format, v...) + } } func WarnWithContext(ctx context.Context, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) - logger.WithField(string(internal.ContextKeyRequestID), reqID).Warn(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + string(internal.ContextKeyRequestID): reqID, + }).Warn(v...) + } else { + logger.WithField(string(internal.ContextKeyRequestID), reqID).Warn(v...) + } } func WarnfWithContext(ctx context.Context, format string, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) - logger.WithField(string(internal.ContextKeyRequestID), reqID).Warnf(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + string(internal.ContextKeyRequestID): reqID, + }).Warnf(format, v...) + } else { + logger.WithField(string(internal.ContextKeyRequestID), reqID).Warnf(format, v...) + } } func Debug(v ...interface{}) { - logger.Debug(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + }).Debug(v...) + } else { + logger.Debug(v...) + } } func Debugf(format string, v ...interface{}) { - logger.Debugf(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + }).Debugf(format, v...) + } else { + logger.Debugf(format, v...) + } } func DebugWithContext(ctx context.Context, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) @@ -87,25 +159,69 @@ func DebugfWithContext(ctx context.Context, format string, v ...interface{}) { } func Error(v ...interface{}) { - logger.Error(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + }).Error(v...) + } else { + logger.Error(v...) + } } func Errorf(format string, v ...interface{}) { - logger.Errorf(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + }).Errorf(format, v...) + } else { + logger.Errorf(format, v...) + } } func ErrorWithContext(ctx context.Context, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) - logger.WithField(string(internal.ContextKeyRequestID), reqID).Error(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + string(internal.ContextKeyRequestID): reqID, + }).Error(v...) + } else { + logger.WithField(string(internal.ContextKeyRequestID), reqID).Error(v...) + } } func ErrorfWithContext(ctx context.Context, format string, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) - logger.WithField(string(internal.ContextKeyRequestID), reqID).Errorf(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + string(internal.ContextKeyRequestID): reqID, + }).Errorf(format, v...) + } else { + logger.WithField(string(internal.ContextKeyRequestID), reqID).Errorf(format, v...) + } } func Fatal(v ...interface{}) { - logger.Fatal(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + }).Fatal(v...) + } else { + logger.Fatal(v...) + } } func Fatalf(format string, v ...interface{}) { - logger.Fatalf(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file, + "line": line, + }).Fatalf(format, v...) + } else { + logger.Fatalf(format, v...) + } } func Disable() { From 40de76e260cd5872765812f5a849b28e57f0b36d Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 23 Jan 2024 16:40:21 +0900 Subject: [PATCH 005/502] project & rbac wip commit --- api/swagger/docs.go | 2 +- cmd/server/main.go | 2 +- go.work.sum | 356 ++++++ hack/ast-generator.go | 21 + hack/endpoint-codegen.go | 195 ++++ internal/delivery/api/api.go | 51 + internal/delivery/api/endpoint.go | 1026 +++++++++++++++++ internal/delivery/api/group.go | 9 + internal/delivery/api/project.go | 28 + internal/delivery/http/project.go | 30 +- internal/middleware/audit/audit.go | 1 + .../auth/authenticator/keycloak/keycloak.go | 49 +- .../middleware/auth/authorizer/authorizer.go | 1 + .../middleware/auth/authorizer/password.go | 14 + internal/middleware/auth/authorizer/rbac.go | 72 +- internal/middleware/auth/middleware.go | 27 - internal/middleware/auth/request/context.go | 12 +- .../auth/requestRecoder/requestRecoder.go | 33 + internal/middleware/auth/role/role.go | 44 + internal/middleware/auth/user/user.go | 18 +- internal/middleware/middleware.go | 33 + internal/route/route.go | 210 ++-- pkg/log/log.go | 3 +- 23 files changed, 2082 insertions(+), 155 deletions(-) create mode 100644 hack/ast-generator.go create mode 100644 hack/endpoint-codegen.go create mode 100644 internal/delivery/api/api.go create mode 100644 internal/delivery/api/endpoint.go create mode 100644 internal/delivery/api/group.go create mode 100644 internal/delivery/api/project.go create mode 100644 internal/middleware/audit/audit.go delete mode 100644 internal/middleware/auth/middleware.go create mode 100644 internal/middleware/auth/requestRecoder/requestRecoder.go create mode 100644 internal/middleware/auth/role/role.go create mode 100644 internal/middleware/middleware.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index ff2be9e4..27273773 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -21,7 +21,7 @@ const docTemplate = `{ "version": "{{.Version}}" }, "host": "{{.Host}}", - "basePath": "{{.BasePath}}", + "basePath": "{{.Path}}", "paths": { "/app-groups": { "get": { diff --git a/cmd/server/main.go b/cmd/server/main.go index eea9f26d..7e644142 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -92,7 +92,7 @@ func init() { // @name Authorization // @host tks-api-ft.taco-cat.xyz -// @BasePath /api/1.0/ +// @Path /api/1.0/ func main() { log.Info("*** Arguments *** ") for i, s := range viper.AllSettings() { diff --git a/go.work.sum b/go.work.sum index 06c1ca6b..dfaaf3a0 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,118 +1,474 @@ cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= cloud.google.com/go/compute v1.6.1 h1:2sMmt8prCn7DPaG4Pmh0N3Inmc8cT8ae5k1M6VJ9Wqc= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= cloud.google.com/go/firestore v1.6.1 h1:8rBq3zRjnHx8UtBvaOWqBB1xq9jH6/wltfQLlTMh2Fw= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= cloud.google.com/go/storage v1.14.0 h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= +github.com/Azure/azure-sdk-for-go v43.0.0+incompatible h1:/wSNCu0e6EsHFR4Qa3vBEBbicaprEHMyyga9g8RTULI= +github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= +github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= +github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= +github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= +github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/to v0.3.0 h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8= +github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= +github.com/Azure/go-autorest/autorest/validation v0.1.0 h1:ISSNzGUh+ZSzizJWOWzs8bwpXIePbGLW4z/AmUFGH5A= +github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/hcsshim v0.9.6 h1:VwnDOgLeoi2du6dAznfmspNqTiwczvjv4K7NxuY9jsY= +github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= +github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 h1:4SPQljF/GJ8Q+QlCWMWxRBepub4DresnOm4eI2ebFGc= +github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= +github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 h1:AUNCr9CiJuwrRYS3XieqF+Z9B9gNxo/eANAJCF2eiN4= +github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= +github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= +github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= +github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e h1:GCzyKMDDjSGnlpl3clrdAK7I1AaVoaiKDOYkUzChZzg= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= +github.com/aws/aws-sdk-go v1.35.24 h1:U3GNTg8+7xSM6OAJ8zksiSM4bRqxBWmVwwehvOSNG3A= +github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bketelsen/crypt v0.0.4 h1:w/jqZtC9YD4DS/Vp9GhWfWcCpuAL58oTnLoI8vE9YHU= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= +github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= +github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= +github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= +github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= +github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns= +github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= +github.com/containerd/stargz-snapshotter/estargz v0.7.0 h1:1d/rydzTywc76lnjJb6qbPCiTiCwts49AzKps/Ecblw= +github.com/containerd/stargz-snapshotter/estargz v0.7.0/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw= +github.com/coredns/caddy v1.1.0 h1:ezvsPrT/tA/7pYDBZxu0cT0VmWk75AfIaf6GSYCNMf0= +github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= +github.com/coredns/corefile-migration v1.0.17 h1:tNwh8+4WOANV6NjSljwgW7qViJfhvPUt1kosj4rR8yg= +github.com/coredns/corefile-migration v1.0.17/go.mod h1:XnhgULOEouimnzgn0t4WPuFDN2/PJQcTxdWKC5eXNGE= +github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= +github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= +github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= +github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= +github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= +github.com/cppforlife/cobrautil v0.0.0-20200514214827-bb86e6965d72 h1:rPWcUBgMb1ox2eCohCuZ8gsZVe0aB5qBbYaBpdoxfCE= +github.com/cppforlife/cobrautil v0.0.0-20200514214827-bb86e6965d72/go.mod h1:2w+qxVu2KSGW78Ex/XaIqfh/OvBgjEsmN53S4T8vEyA= +github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835 h1:mYQweUIBD+TBRjIeQnJmXr0GSVMpI6O0takyb/aaOgo= +github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835/go.mod h1:dYeVsKp1vvK8XjdTPR1gF+uk+9doxKeO3hqQTOCr7T4= +github.com/cppforlife/go-cli-ui v0.0.0-20200716203538-1e47f820817f h1:yVW0v4zDXzJo1i8G9G3vtvNpyzhvtLalO34BsN/K88E= +github.com/cppforlife/go-cli-ui v0.0.0-20200716203538-1e47f820817f/go.mod h1:L18TqO77ci8i+hFtlMC4zSFz/D3O8lf84TyVU+zFF8E= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= +github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4= +github.com/docker/cli v20.10.21+incompatible h1:qVkgyYUnOLQ98LtXBrwd/duVqPT2X4SHndOuGsfwyhU= +github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= +github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= +github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= +github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= +github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0= +github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 h1:dulLQAYQFYtG5MTplgNGHWuV2D+OBD+Z8lmDBmbLg+s= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/flatcar-linux/container-linux-config-transpiler v0.9.2 h1:EZKQ25jmhNfj+VAvdhPLLc4jmnSnRwFrI4x4dlPWXqE= +github.com/flatcar-linux/container-linux-config-transpiler v0.9.2/go.mod h1:AGVTulMzeIKwurV9ExYH3UiokET1Ur65g+EIeRDMwzM= +github.com/flatcar-linux/ignition v0.36.1 h1:yNvS9sQvm9HJ8VgxXskx88DsF73qdF35ALJkbTwcYhY= +github.com/flatcar-linux/ignition v0.36.1/go.mod h1:0jS5n4AopgOdwgi7QDo5MFgkMx/fQUDYjuxlGJC1Txg= +github.com/florianl/go-conntrack v0.3.0 h1:DUY84Mce+/lE9dJi2EWvGYacQtX2X96J9aVWV99l8UE= +github.com/florianl/go-conntrack v0.3.0/go.mod h1:Q+Um4J/nWUXSbnyzQRMOP4eweSeEQ2G8sfCO5gMz6Pw= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= +github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/getkin/kin-openapi v0.76.0 h1:j77zg3Ec+k+r+GA3d8hBoXpAc6KX9TbBPrwQGBIy2sY= +github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= +github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/log v0.1.0 h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobuffalo/flect v0.2.4/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= +github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/cel-go v0.9.0 h1:u1hg7lcZ/XWw2d3aV1jFS30ijQQ6q0/h1C2ZBeBD1gY= +github.com/google/cel-spec v0.6.0 h1:xuthJSiJGoSzq+lVEBIW1MTpaaZXknMCYC4WzVAWOsE= +github.com/google/go-containerregistry v0.6.0 h1:niQ+8XD//kKgArIFwDVBXsWVWbde16LPdHMyNwSC8h4= +github.com/google/go-containerregistry v0.6.0/go.mod h1:euCCtNbZ6tKqi1E72vwDj2xZcN5ttKpZLfa/wSo5iLw= +github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM= +github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 h1:zIaiqGYDQwa4HVx5wGRTXbx38Pqxjemn4BP98wpzpXo= github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/googleapis/gax-go/v2 v2.4.0 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/hashicorp/consul/api v1.12.0 h1:k3y1FYv6nuKyNTqj6w9gXOx5r5CfLj/k/euUeBXj1OY= +github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= +github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= +github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= +github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= +github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= +github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= +github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/serf v0.9.7 h1:hkdgbqizGQHuU5IPqYM1JdSMV8nKfpuOnZYXssk9muY= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd h1:efcJu2Vzz6DoSq245deWNzTz6l/gsqdphm3FjmI88/g= +github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= +github.com/jackpal/gateway v1.0.7 h1:7tIFeCGmpyrMx9qvT0EgYUi7cxVW48a0mMvnIL17bPM= +github.com/jackpal/gateway v1.0.7/go.mod h1:aRcO0UFKt+MgIZmRmvOmnejdDT4Y1DNiNOsSd1AcIbA= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= +github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/k14s/imgpkg v0.21.0 h1:zQvLI0PT9oH9emfAq7gXsyuKEF1MYdaSqO/012/QqQs= +github.com/k14s/imgpkg v0.21.0/go.mod h1:p2hsjGOtiIQlqO1+1TJ4PnCsK3SjnZgqmjoDMPewtlY= github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/klauspost/compress v1.13.0 h1:2T7tUoQrQT+fQWdaY5rjWztFGAFwbGD04iPJg90ZiOs= +github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= +github.com/kube-vip/kube-vip v0.5.5 h1:ZtCp3417IaZtI6JLKqf3mciERyopouyW5eB5QjVQ3Bk= +github.com/kube-vip/kube-vip v0.5.5/go.mod h1:60rF7LtNs7RopdOB8LYk+2X/SF5cT56Gb2n8a3ik4qQ= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= +github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= +github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc h1:m7rJJJeXrYCFpsxXYapkDW53wJCDmf9bsIXUg0HoeQY= +github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc/go.mod h1:eOj1DDj3NAZ6yv+WafaKzY37MFZ58TdfIhQ+8nQbiis= +github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE= +github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= +github.com/mdlayher/ndp v0.10.0 h1:Zdwol2bq1EHY8xSnejIYkq6LEj7dLjLymJX0o/2tjGw= +github.com/mdlayher/ndp v0.10.0/go.mod h1:Uv6IWvgvqirNUu2N3ZXJEB86xu6foyUsG0NrClSSfek= +github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0= +github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= +github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b h1:MHcTarUMC4sFA7eiyR8IEJ6j2PgmgXR+B9X2IIMjh7A= +github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= +github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM= +github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= +github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= +github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= +github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= +github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= +github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= +github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 h1:0XM1XL/OFFJjXsYXlG30spTkV/E9+gmd5GD1w2HE8xM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= +github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/zerolog v1.15.0 h1:uPRuwkWF4J6fGsJ2R0Gn2jB1EQiav9k3S6CSdygQJXY= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f h1:UFr9zpz4xgTnIE5yIMtWAMngCdZ9p/+q6lTbgelo80M= github.com/sagikazarmark/crypt v0.6.0 h1:REOEXCs/NFY/1jOCEouMuT4zEniE5YoXbvpC5X/TLF8= +github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= +github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= +github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME= +github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc= +github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= +github.com/vdemeester/k8s-pkg-credentialprovider v1.21.0-1 h1:7Ajl3rjeYoB5V47jPknnLbyxYlhMXTTJiQsye5aT7f0= +github.com/vdemeester/k8s-pkg-credentialprovider v1.21.0-1/go.mod h1:l4LxiP0cmEcc5q4BTDE8tZSyIiyXe0T28x37yHpMzoM= +github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= +github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= +github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec h1:Klu98tQ9Z1t23gvC7p7sCmvxkZxLhBHLNyrUPsWsYFg= +github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec/go.mod h1:wPlfmglZmRWMYv/qJy3P+fK/UnoQB5ISk4txfNd9tDo= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= +github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zenazn/goji v0.9.0 h1:RSQQAbXGArQ0dIDEq+PI6WqN6if+5KHu6x2Cx/GXLTQ= +gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f h1:Wku8eEdeJqIOFHtrfkYUByc4bCaTeA6fL0UJgfEiFMI= +gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:Tiuhl+njh/JIg0uS/sOJVYi0x2HEa5rc1OAaVsb5tAs= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= +go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= +go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.4 h1:Dcx3/MYyfKcPNLpR4VVQUP5KgYrBeJtktBwEKkw08Ao= +go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4= +go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= +go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= +go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= +go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= +go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= +go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= +go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= +go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= +go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= +go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= +go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= +go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= +go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go4.org v0.0.0-20201209231011-d4a079459e60 h1:iqAGo78tVOJXELHQFRjR6TMwItrvXH4hrGJ32I/NFF8= +go4.org v0.0.0-20201209231011-d4a079459e60/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.81.0 h1:o8WF5AvfidafWbFjsRyupxyEQJNUWxLZJCK5NXrxZZ8= +google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I= +google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ= +google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec h1:RlWgLqCMMIYYEVcAR5MDsuHlVkaIPDAF+5Dehzg8L5A= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= +gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA= +gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= +gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= +k8s.io/apiserver v0.23.5 h1:2Ly8oUjz5cnZRn1YwYr+aFgDZzUmEVL9RscXbnIeDSE= +k8s.io/cli-runtime v0.23.0 h1:UONt0BV2+edjUVAXuR1nnOAL2CB9r+Gl9yk4UBQpKfs= +k8s.io/cli-runtime v0.23.0/go.mod h1:B5N3YH0KP1iKr6gEuJ/RRmGjO0mJQ/f/JrsmEiPQAlU= +k8s.io/cloud-provider v0.21.0 h1:NSTS+czpv6LQAaIpY/VUghsT4oj62hYmQPErkDKTzKU= +k8s.io/cloud-provider v0.21.0/go.mod h1:z17TQgu3JgUFjcgby8sj5X86YdVK5Pbt+jm/eYMZU9M= +k8s.io/cluster-bootstrap v0.25.4 h1:m50ICwMsEW13N7Z/tdTmLwELGHt4SJEJaeriPdQRxs0= +k8s.io/cluster-bootstrap v0.25.4/go.mod h1:q6XZzStf/uGcXUZhMHmRB8ael1k+bv8//AajQ6FPJag= +k8s.io/code-generator v0.23.5 h1:xn3a6J5pUL49AoH6SPrOFtnB5cvdMl76f/bEY176R3c= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c h1:GohjlNKauSai7gN4wsJkeZ3WAJx4Sh+oT/b5IYn5suA= +k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg= +k8s.io/legacy-cloud-providers v0.21.0 h1:iWf5xaX9yvYT5mkz8UB96UtISQ5IkrWeuMPMhRp01ZY= +k8s.io/legacy-cloud-providers v0.21.0/go.mod h1:bNxo7gDg+PGkBmT/MFZswLTWdSWK9kAlS1s8DJca5q4= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 h1:dUk62HQ3ZFhD48Qr8MIXCiKA8wInBQCtuE4QGfFW7yA= +sigs.k8s.io/cluster-api/test v1.1.5 h1:jukMEA50R3V6G7VcJMR7dMZJPd3Tuf0Orc/6CKuS9Ek= +sigs.k8s.io/cluster-api/test v1.1.5/go.mod h1:NXFioUFKruk/PgpUt4QrprV9bN1rVUcm7OWao9dfesg= +sigs.k8s.io/kind v0.14.0 h1:cNmI3jGBvp7UegEGbC5we8plDtCUmaNRL+bod7JoSCE= +sigs.k8s.io/kind v0.14.0/go.mod h1:UrFRPHG+2a5j0Q7qiR4gtJ4rEyn8TuMQwuOPf+m4oHg= +sigs.k8s.io/kustomize/api v0.10.1 h1:KgU7hfYoscuqag84kxtzKdEC3mKMb99DPI3a0eaV1d0= +sigs.k8s.io/kustomize/api v0.10.1/go.mod h1:2FigT1QN6xKdcnGS2Ppp1uIWrtWN28Ms8A3OZUZhwr8= +sigs.k8s.io/kustomize/kyaml v0.13.0 h1:9c+ETyNfSrVhxvphs+K2dzT3dh5oVPPEqPOE/cUpScY= +sigs.k8s.io/kustomize/kyaml v0.13.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E= diff --git a/hack/ast-generator.go b/hack/ast-generator.go new file mode 100644 index 00000000..4d023040 --- /dev/null +++ b/hack/ast-generator.go @@ -0,0 +1,21 @@ +package main + +//func main() { +// fset := token.NewFileSet() +// +// node, err := parser.ParseFile(fset, "./internal/delivery/api/endpoint.go", nil, parser.ParseComments) +// if err != nil { +// log.Fatalf("파싱 오류: %v", err) +// } +// +// ast.Print(fset, node) +// +// // write ast to file +// f, err := os.Create("ast.txt") +// if err != nil { +// log.Fatalf("파일 생성 오류: %v", err) +// } +// defer f.Close() +// ast.Fprint(f, fset, node, nil) +// +//} diff --git a/hack/endpoint-codegen.go b/hack/endpoint-codegen.go new file mode 100644 index 00000000..eff018a0 --- /dev/null +++ b/hack/endpoint-codegen.go @@ -0,0 +1,195 @@ +package main + +import ( + "bytes" + "go/ast" + "go/parser" + "go/token" + "html/template" + "io/ioutil" + "log" + "strings" +) + +const endpointFilePath = "./internal/delivery/api/endpoint.go" + +type endpointDecl struct { + Name string + Group string +} + +//const indexTemplateStr = ` // This is generated code. DO NOT EDIT. +// +//package api +// +//type Endpoint int +//type EndpointInfo struct { +// Name string +// Group string +//} +//` + +//const endpointTemplateStr = `// Comment below is special purpose for code generation. +//// Do not edit this comment. +//// Endpoint for Code Generation +//const ( +//{{- range .}} +// {{.Name}} Endpoint = iota +//{{- end}} +//) +//` + +const apiMapTemplateStr = `var ApiMap = map[Endpoint]EndpointInfo{ +{{- range .}} + {{.Name}}: { + Name: "{{.Name}}", + Group: "{{.Group}}", + }, +{{- end}} +} +` + +const stringFunctionTemplateStr = `func (e Endpoint) String() string { + switch e { +{{- range .}} + case {{.Name}}: + return "{{.Name}}" +{{- end}} + default: + return "" + } +} +` + +const getEndpointFunctionTemplateStr = `func GetEndpoint(name string) Endpoint { + switch name { +{{- range .}} + case "{{.Name}}": + return {{.Name}} +{{- end}} + default: + return -1 + } +} +` + +func main() { + fset := token.NewFileSet() + node, err := parser.ParseFile(fset, endpointFilePath, nil, parser.ParseComments) + if err != nil { + log.Fatalf("failed to parse file: %v", err) + } + + var endpoints []endpointDecl + var currentGroup string + + // AST를 탐색합니다. + ast.Inspect(node, func(n ast.Node) bool { + switch x := n.(type) { + case *ast.GenDecl: + if x.Tok == token.CONST { + if x.Doc != nil { + for _, comment := range x.Doc.List { + if strings.Contains(comment.Text, "Endpoint for Code Generation") { + continue + } + if strings.HasPrefix(comment.Text, "//") { + currentGroup = strings.TrimSpace(strings.TrimPrefix(comment.Text, "//")) + } + } + } + for _, spec := range x.Specs { + vs, ok := spec.(*ast.ValueSpec) + if !ok { + continue + } + if vs.Doc != nil { + for _, comment := range vs.Doc.List { + if strings.HasPrefix(comment.Text, "//") { + currentGroup = strings.TrimSpace(strings.TrimPrefix(comment.Text, "//")) + } + } + } + + for _, name := range vs.Names { + endpoints = append(endpoints, endpointDecl{ + Name: name.Name, + Group: currentGroup, + }) + } + } + } + } + return true + }) + + for _, ep := range endpoints { + log.Printf("Endpoint: %s, Group: %s\n", ep.Name, ep.Group) + } + + //// contents for index + //indexTemplate := template.New("index") + //indexTemplate, err = indexTemplate.Parse(indexTemplateStr) + //if err != nil { + // log.Fatalf("failed to parse template: %v", err) + //} + //var indexCode bytes.Buffer + //if err := indexTemplate.Execute(&indexCode, endpoints); err != nil { + // log.Fatalf("failed to execute template: %v", err) + //} + + //// contents for endpoint + //endpointTemplate := template.New("endpoint") + //endpointTemplate, err = endpointTemplate.Parse(endpointTemplateStr) + //if err != nil { + // log.Fatalf("failed to parse template: %v", err) + //} + //var endpointCode bytes.Buffer + //if err := endpointTemplate.Execute(&endpointCode, endpoints); err != nil { + // log.Fatalf("failed to execute template: %v", err) + //} + + // contents for apiMap + apiMapTemplate := template.New("apiMap") + apiMapTemplate, err = apiMapTemplate.Parse(apiMapTemplateStr) + if err != nil { + log.Fatalf("failed to parse template: %v", err) + } + var apiMapCode bytes.Buffer + if err := apiMapTemplate.Execute(&apiMapCode, endpoints); err != nil { + log.Fatalf("failed to execute template: %v", err) + } + + // contents for stringFunction + stringFunctionTemplate := template.New("stringFunction") + stringFunctionTemplate, err = stringFunctionTemplate.Parse(stringFunctionTemplateStr) + if err != nil { + log.Fatalf("failed to parse template: %v", err) + } + var stringFunctionCode bytes.Buffer + if err := stringFunctionTemplate.Execute(&stringFunctionCode, endpoints); err != nil { + log.Fatalf("failed to execute template: %v", err) + } + + // contents for getEndpointFunction + getEndpointFunctionTemplate := template.New("getEndpointFunction") + getEndpointFunctionTemplate, err = getEndpointFunctionTemplate.Parse(getEndpointFunctionTemplateStr) + if err != nil { + log.Fatalf("failed to parse template: %v", err) + } + var getEndpointFunctionCode bytes.Buffer + if err := getEndpointFunctionTemplate.Execute(&getEndpointFunctionCode, endpoints); err != nil { + log.Fatalf("failed to execute template: %v", err) + } + + // replace original file(endpointFilePath) with new contents + //contents := indexCode.String() + endpointCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() + contents := apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() + newFilePath := strings.Replace(endpointFilePath, "endpoint", "generated_endpoints.go", 1) + + if err := ioutil.WriteFile(newFilePath, []byte(contents), 0644); err != nil { + log.Fatalf("failed to write file: %v", err) + } + + log.Println("Code generation is done.") +} diff --git a/internal/delivery/api/api.go b/internal/delivery/api/api.go new file mode 100644 index 00000000..10f42603 --- /dev/null +++ b/internal/delivery/api/api.go @@ -0,0 +1,51 @@ +package api + +// +//import ( +// "github.com/gorilla/mux" +// "net/http" +//) +// +//type IApi interface { +// //SetPath() +// API() Api +// //SetMethod() +// //GetMethod() string +// //SetHandler() +// //GetHandler() http.Handler +// // +// //RegisterApi(router *mux.Router) +//} +//type Api struct { +// Path string +// Method string +// Handler http.Handler +//} +// +//func (a Api) GetPath() string { +// return a.Path +//} +// +//func (a Api) GetMethod() string { +// return a.Method +//} +// +//func (a Api) GetHandler() http.Handler { +// return a.Handler +//} +// +//func (a Api) SetBasePath(path string) { +// a.Path = path +//} +// +//func (a Api) SetMethod(method string) { +// a.Method = method +//} +// +//func (a Api) SetHandler(handler http.Handler) { +// a.Handler = handler +//} +// +//func (a Api) RegisterApi(router *mux.Router) { +// router.Handle(a.GetPath(), a.GetHandler()) +//} diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go new file mode 100644 index 00000000..08782aae --- /dev/null +++ b/internal/delivery/api/endpoint.go @@ -0,0 +1,1026 @@ +package api + +type Endpoint int +type EndpointInfo struct { + Name string + Group string +} + +// Comment below is special purpose for code generation. +// Do not edit this comment. +// Endpoint for Code Generation +const ( + // Auth + Login Endpoint = iota + PingToken + Logout + RefreshToken + FindId + FindPassword + VerifyIdentityForLostId + VerifyIdentityForLostPassword + VerifyToken + + // User + CreateUser + ListUser + GetUser + DeleteUser + UpdateUser + ResetPassword + CheckId + CheckEmail + + // MyProfile + GetMyProfile + UpdateMyProfile + UpdateMyPassword + RenewPasswordExpiredDate + DeleteMyProfile + + // Organization + CreateOrganization + GetOrganizations + GetOrganization + DeleteOrganization + UpdateOrganization + UpdatePrimaryCluster + + // Cluster + CreateCluster + GetClusters + ImportCluster + GetCluster + DeleteCluster + GetClusterSiteValues + InstallCluster + CreateBootstrapKubeconfig + GetBootstrapKubeconfig + GetNodes + + //Appgroup + CreateAppgroup + GetAppgroups + GetAppgroup + DeleteAppgroup + GetApplications + CreateApplication + + // AppServeApp + CreateAppServeApp + GetAppServeApps + GetNumOfAppsOnStack + GetAppServeApp + GetAppServeAppLatestTask + IsAppServeAppExist + IsAppServeAppNameExist + DeleteAppServeApp + UpdateAppServeApp + UpdateAppServeAppStatus + UpdateAppServeAppEndpoint + RollbackAppServeApp + + // CloudAccount + GetCloudAccounts + CreateCloudAccount + CheckCloudAccountName + CheckAwsAccountId + GetCloudAccount + UpdateCloudAccount + DeleteCloudAccount + DeleteForceCloudAccount + GetResourceQuota + + // StackTemplate + GetStackTemplates + CreateStackTemplate + GetStackTemplate + UpdateStackTemplate + DeleteStackTemplate + + // Dashboard + GetChartsDashboard + GetChartDashboard + GetStacksDashboard + GetResourcesDashboard + + // Alert + CreateAlert + GetAlerts + GetAlert + DeleteAlert + UpdateAlert + CreateAlertAction + + // Stack + GetStacks + CreateStack + CheckStackName + GetStack + UpdateStack + DeleteStack + GetStackKubeConfig + GetStackStatus + SetFavoriteStack + DeleteFavoriteStack + InstallStack + + // Project + CreateProject + GetProjects + GetProject + UpdateProject + DeleteProject + AddProjectMember + GetProjectMembers + RemoveProjectMember + UpdateProjectMemberRole + CreateProjectNamespace + GetProjectNamespaces + GetProjectNamespace + DeleteProjectNamespace + SetFavoriteProject + SetFavoriteProjectNamespace + UnSetFavoriteProject + UnSetFavoriteProjectNamespace +) + +var ApiMap = map[Endpoint]EndpointInfo{ + Login: { + Name: "Login", + Group: "Auth", + }, + PingToken: { + Name: "PingToken", + Group: "Auth", + }, + Logout: { + Name: "Logout", + Group: "Auth", + }, + RefreshToken: { + Name: "RefreshToken", + Group: "Auth", + }, + FindId: { + Name: "FindId", + Group: "Auth", + }, + FindPassword: { + Name: "FindPassword", + Group: "Auth", + }, + VerifyIdentityForLostId: { + Name: "VerifyIdentityForLostId", + Group: "Auth", + }, + VerifyIdentityForLostPassword: { + Name: "VerifyIdentityForLostPassword", + Group: "Auth", + }, + VerifyToken: { + Name: "VerifyToken", + Group: "Auth", + }, + CreateUser: { + Name: "CreateUser", + Group: "User", + }, + ListUser: { + Name: "ListUser", + Group: "User", + }, + GetUser: { + Name: "GetUser", + Group: "User", + }, + DeleteUser: { + Name: "DeleteUser", + Group: "User", + }, + UpdateUser: { + Name: "UpdateUser", + Group: "User", + }, + ResetPassword: { + Name: "ResetPassword", + Group: "User", + }, + CheckId: { + Name: "CheckId", + Group: "User", + }, + CheckEmail: { + Name: "CheckEmail", + Group: "User", + }, + GetMyProfile: { + Name: "GetMyProfile", + Group: "MyProfile", + }, + UpdateMyProfile: { + Name: "UpdateMyProfile", + Group: "MyProfile", + }, + UpdateMyPassword: { + Name: "UpdateMyPassword", + Group: "MyProfile", + }, + RenewPasswordExpiredDate: { + Name: "RenewPasswordExpiredDate", + Group: "MyProfile", + }, + DeleteMyProfile: { + Name: "DeleteMyProfile", + Group: "MyProfile", + }, + CreateOrganization: { + Name: "CreateOrganization", + Group: "Organization", + }, + GetOrganizations: { + Name: "GetOrganizations", + Group: "Organization", + }, + GetOrganization: { + Name: "GetOrganization", + Group: "Organization", + }, + DeleteOrganization: { + Name: "DeleteOrganization", + Group: "Organization", + }, + UpdateOrganization: { + Name: "UpdateOrganization", + Group: "Organization", + }, + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", + Group: "Organization", + }, + CreateCluster: { + Name: "CreateCluster", + Group: "Cluster", + }, + GetClusters: { + Name: "GetClusters", + Group: "Cluster", + }, + ImportCluster: { + Name: "ImportCluster", + Group: "Cluster", + }, + GetCluster: { + Name: "GetCluster", + Group: "Cluster", + }, + DeleteCluster: { + Name: "DeleteCluster", + Group: "Cluster", + }, + GetClusterSiteValues: { + Name: "GetClusterSiteValues", + Group: "Cluster", + }, + InstallCluster: { + Name: "InstallCluster", + Group: "Cluster", + }, + CreateBootstrapKubeconfig: { + Name: "CreateBootstrapKubeconfig", + Group: "Cluster", + }, + GetBootstrapKubeconfig: { + Name: "GetBootstrapKubeconfig", + Group: "Cluster", + }, + GetNodes: { + Name: "GetNodes", + Group: "Cluster", + }, + CreateAppgroup: { + Name: "CreateAppgroup", + Group: "Appgroup", + }, + GetAppgroups: { + Name: "GetAppgroups", + Group: "Appgroup", + }, + GetAppgroup: { + Name: "GetAppgroup", + Group: "Appgroup", + }, + DeleteAppgroup: { + Name: "DeleteAppgroup", + Group: "Appgroup", + }, + GetApplications: { + Name: "GetApplications", + Group: "Appgroup", + }, + CreateApplication: { + Name: "CreateApplication", + Group: "Appgroup", + }, + CreateAppServeApp: { + Name: "CreateAppServeApp", + Group: "AppServeApp", + }, + GetAppServeApps: { + Name: "GetAppServeApps", + Group: "AppServeApp", + }, + GetNumOfAppsOnStack: { + Name: "GetNumOfAppsOnStack", + Group: "AppServeApp", + }, + GetAppServeApp: { + Name: "GetAppServeApp", + Group: "AppServeApp", + }, + GetAppServeAppLatestTask: { + Name: "GetAppServeAppLatestTask", + Group: "AppServeApp", + }, + IsAppServeAppExist: { + Name: "IsAppServeAppExist", + Group: "AppServeApp", + }, + IsAppServeAppNameExist: { + Name: "IsAppServeAppNameExist", + Group: "AppServeApp", + }, + DeleteAppServeApp: { + Name: "DeleteAppServeApp", + Group: "AppServeApp", + }, + UpdateAppServeApp: { + Name: "UpdateAppServeApp", + Group: "AppServeApp", + }, + UpdateAppServeAppStatus: { + Name: "UpdateAppServeAppStatus", + Group: "AppServeApp", + }, + UpdateAppServeAppEndpoint: { + Name: "UpdateAppServeAppEndpoint", + Group: "AppServeApp", + }, + RollbackAppServeApp: { + Name: "RollbackAppServeApp", + Group: "AppServeApp", + }, + GetCloudAccounts: { + Name: "GetCloudAccounts", + Group: "CloudAccount", + }, + CreateCloudAccount: { + Name: "CreateCloudAccount", + Group: "CloudAccount", + }, + CheckCloudAccountName: { + Name: "CheckCloudAccountName", + Group: "CloudAccount", + }, + CheckAwsAccountId: { + Name: "CheckAwsAccountId", + Group: "CloudAccount", + }, + GetCloudAccount: { + Name: "GetCloudAccount", + Group: "CloudAccount", + }, + UpdateCloudAccount: { + Name: "UpdateCloudAccount", + Group: "CloudAccount", + }, + DeleteCloudAccount: { + Name: "DeleteCloudAccount", + Group: "CloudAccount", + }, + DeleteForceCloudAccount: { + Name: "DeleteForceCloudAccount", + Group: "CloudAccount", + }, + GetResourceQuota: { + Name: "GetResourceQuota", + Group: "CloudAccount", + }, + GetStackTemplates: { + Name: "GetStackTemplates", + Group: "StackTemplate", + }, + CreateStackTemplate: { + Name: "CreateStackTemplate", + Group: "StackTemplate", + }, + GetStackTemplate: { + Name: "GetStackTemplate", + Group: "StackTemplate", + }, + UpdateStackTemplate: { + Name: "UpdateStackTemplate", + Group: "StackTemplate", + }, + DeleteStackTemplate: { + Name: "DeleteStackTemplate", + Group: "StackTemplate", + }, + GetChartsDashboard: { + Name: "GetChartsDashboard", + Group: "Dashboard", + }, + GetChartDashboard: { + Name: "GetChartDashboard", + Group: "Dashboard", + }, + GetStacksDashboard: { + Name: "GetStacksDashboard", + Group: "Dashboard", + }, + GetResourcesDashboard: { + Name: "GetResourcesDashboard", + Group: "Dashboard", + }, + CreateAlert: { + Name: "CreateAlert", + Group: "Alert", + }, + GetAlerts: { + Name: "GetAlerts", + Group: "Alert", + }, + GetAlert: { + Name: "GetAlert", + Group: "Alert", + }, + DeleteAlert: { + Name: "DeleteAlert", + Group: "Alert", + }, + UpdateAlert: { + Name: "UpdateAlert", + Group: "Alert", + }, + CreateAlertAction: { + Name: "CreateAlertAction", + Group: "Alert", + }, + GetStacks: { + Name: "GetStacks", + Group: "Stack", + }, + CreateStack: { + Name: "CreateStack", + Group: "Stack", + }, + CheckStackName: { + Name: "CheckStackName", + Group: "Stack", + }, + GetStack: { + Name: "GetStack", + Group: "Stack", + }, + UpdateStack: { + Name: "UpdateStack", + Group: "Stack", + }, + DeleteStack: { + Name: "DeleteStack", + Group: "Stack", + }, + GetStackKubeConfig: { + Name: "GetStackKubeConfig", + Group: "Stack", + }, + GetStackStatus: { + Name: "GetStackStatus", + Group: "Stack", + }, + SetFavoriteStack: { + Name: "SetFavoriteStack", + Group: "Stack", + }, + DeleteFavoriteStack: { + Name: "DeleteFavoriteStack", + Group: "Stack", + }, + InstallStack: { + Name: "InstallStack", + Group: "Stack", + }, + CreateProject: { + Name: "CreateProject", + Group: "Project", + }, + GetProjects: { + Name: "GetProjects", + Group: "Project", + }, + GetProject: { + Name: "GetProject", + Group: "Project", + }, + UpdateProject: { + Name: "UpdateProject", + Group: "Project", + }, + DeleteProject: { + Name: "DeleteProject", + Group: "Project", + }, + AddProjectMember: { + Name: "AddProjectMember", + Group: "Project", + }, + GetProjectMembers: { + Name: "GetProjectMembers", + Group: "Project", + }, + RemoveProjectMember: { + Name: "RemoveProjectMember", + Group: "Project", + }, + UpdateProjectMemberRole: { + Name: "UpdateProjectMemberRole", + Group: "Project", + }, + CreateProjectNamespace: { + Name: "CreateProjectNamespace", + Group: "Project", + }, + GetProjectNamespaces: { + Name: "GetProjectNamespaces", + Group: "Project", + }, + GetProjectNamespace: { + Name: "GetProjectNamespace", + Group: "Project", + }, + DeleteProjectNamespace: { + Name: "DeleteProjectNamespace", + Group: "Project", + }, + SetFavoriteProject: { + Name: "SetFavoriteProject", + Group: "Project", + }, + SetFavoriteProjectNamespace: { + Name: "SetFavoriteProjectNamespace", + Group: "Project", + }, + UnSetFavoriteProject: { + Name: "UnSetFavoriteProject", + Group: "Project", + }, + UnSetFavoriteProjectNamespace: { + Name: "UnSetFavoriteProjectNamespace", + Group: "Project", + }, +} + +func (e Endpoint) String() string { + switch e { + case Login: + return "Login" + case PingToken: + return "PingToken" + case Logout: + return "Logout" + case RefreshToken: + return "RefreshToken" + case FindId: + return "FindId" + case FindPassword: + return "FindPassword" + case VerifyIdentityForLostId: + return "VerifyIdentityForLostId" + case VerifyIdentityForLostPassword: + return "VerifyIdentityForLostPassword" + case VerifyToken: + return "VerifyToken" + case CreateUser: + return "CreateUser" + case ListUser: + return "ListUser" + case GetUser: + return "GetUser" + case DeleteUser: + return "DeleteUser" + case UpdateUser: + return "UpdateUser" + case ResetPassword: + return "ResetPassword" + case CheckId: + return "CheckId" + case CheckEmail: + return "CheckEmail" + case GetMyProfile: + return "GetMyProfile" + case UpdateMyProfile: + return "UpdateMyProfile" + case UpdateMyPassword: + return "UpdateMyPassword" + case RenewPasswordExpiredDate: + return "RenewPasswordExpiredDate" + case DeleteMyProfile: + return "DeleteMyProfile" + case CreateOrganization: + return "CreateOrganization" + case GetOrganizations: + return "GetOrganizations" + case GetOrganization: + return "GetOrganization" + case DeleteOrganization: + return "DeleteOrganization" + case UpdateOrganization: + return "UpdateOrganization" + case UpdatePrimaryCluster: + return "UpdatePrimaryCluster" + case CreateCluster: + return "CreateCluster" + case GetClusters: + return "GetClusters" + case ImportCluster: + return "ImportCluster" + case GetCluster: + return "GetCluster" + case DeleteCluster: + return "DeleteCluster" + case GetClusterSiteValues: + return "GetClusterSiteValues" + case InstallCluster: + return "InstallCluster" + case CreateBootstrapKubeconfig: + return "CreateBootstrapKubeconfig" + case GetBootstrapKubeconfig: + return "GetBootstrapKubeconfig" + case GetNodes: + return "GetNodes" + case CreateAppgroup: + return "CreateAppgroup" + case GetAppgroups: + return "GetAppgroups" + case GetAppgroup: + return "GetAppgroup" + case DeleteAppgroup: + return "DeleteAppgroup" + case GetApplications: + return "GetApplications" + case CreateApplication: + return "CreateApplication" + case CreateAppServeApp: + return "CreateAppServeApp" + case GetAppServeApps: + return "GetAppServeApps" + case GetNumOfAppsOnStack: + return "GetNumOfAppsOnStack" + case GetAppServeApp: + return "GetAppServeApp" + case GetAppServeAppLatestTask: + return "GetAppServeAppLatestTask" + case IsAppServeAppExist: + return "IsAppServeAppExist" + case IsAppServeAppNameExist: + return "IsAppServeAppNameExist" + case DeleteAppServeApp: + return "DeleteAppServeApp" + case UpdateAppServeApp: + return "UpdateAppServeApp" + case UpdateAppServeAppStatus: + return "UpdateAppServeAppStatus" + case UpdateAppServeAppEndpoint: + return "UpdateAppServeAppEndpoint" + case RollbackAppServeApp: + return "RollbackAppServeApp" + case GetCloudAccounts: + return "GetCloudAccounts" + case CreateCloudAccount: + return "CreateCloudAccount" + case CheckCloudAccountName: + return "CheckCloudAccountName" + case CheckAwsAccountId: + return "CheckAwsAccountId" + case GetCloudAccount: + return "GetCloudAccount" + case UpdateCloudAccount: + return "UpdateCloudAccount" + case DeleteCloudAccount: + return "DeleteCloudAccount" + case DeleteForceCloudAccount: + return "DeleteForceCloudAccount" + case GetResourceQuota: + return "GetResourceQuota" + case GetStackTemplates: + return "GetStackTemplates" + case CreateStackTemplate: + return "CreateStackTemplate" + case GetStackTemplate: + return "GetStackTemplate" + case UpdateStackTemplate: + return "UpdateStackTemplate" + case DeleteStackTemplate: + return "DeleteStackTemplate" + case GetChartsDashboard: + return "GetChartsDashboard" + case GetChartDashboard: + return "GetChartDashboard" + case GetStacksDashboard: + return "GetStacksDashboard" + case GetResourcesDashboard: + return "GetResourcesDashboard" + case CreateAlert: + return "CreateAlert" + case GetAlerts: + return "GetAlerts" + case GetAlert: + return "GetAlert" + case DeleteAlert: + return "DeleteAlert" + case UpdateAlert: + return "UpdateAlert" + case CreateAlertAction: + return "CreateAlertAction" + case GetStacks: + return "GetStacks" + case CreateStack: + return "CreateStack" + case CheckStackName: + return "CheckStackName" + case GetStack: + return "GetStack" + case UpdateStack: + return "UpdateStack" + case DeleteStack: + return "DeleteStack" + case GetStackKubeConfig: + return "GetStackKubeConfig" + case GetStackStatus: + return "GetStackStatus" + case SetFavoriteStack: + return "SetFavoriteStack" + case DeleteFavoriteStack: + return "DeleteFavoriteStack" + case InstallStack: + return "InstallStack" + case CreateProject: + return "CreateProject" + case GetProjects: + return "GetProjects" + case GetProject: + return "GetProject" + case UpdateProject: + return "UpdateProject" + case DeleteProject: + return "DeleteProject" + case AddProjectMember: + return "AddProjectMember" + case GetProjectMembers: + return "GetProjectMembers" + case RemoveProjectMember: + return "RemoveProjectMember" + case UpdateProjectMemberRole: + return "UpdateProjectMemberRole" + case CreateProjectNamespace: + return "CreateProjectNamespace" + case GetProjectNamespaces: + return "GetProjectNamespaces" + case GetProjectNamespace: + return "GetProjectNamespace" + case DeleteProjectNamespace: + return "DeleteProjectNamespace" + case SetFavoriteProject: + return "SetFavoriteProject" + case SetFavoriteProjectNamespace: + return "SetFavoriteProjectNamespace" + case UnSetFavoriteProject: + return "UnSetFavoriteProject" + case UnSetFavoriteProjectNamespace: + return "UnSetFavoriteProjectNamespace" + default: + return "" + } +} +func GetEndpoint(name string) Endpoint { + switch name { + case "Login": + return Login + case "PingToken": + return PingToken + case "Logout": + return Logout + case "RefreshToken": + return RefreshToken + case "FindId": + return FindId + case "FindPassword": + return FindPassword + case "VerifyIdentityForLostId": + return VerifyIdentityForLostId + case "VerifyIdentityForLostPassword": + return VerifyIdentityForLostPassword + case "VerifyToken": + return VerifyToken + case "CreateUser": + return CreateUser + case "ListUser": + return ListUser + case "GetUser": + return GetUser + case "DeleteUser": + return DeleteUser + case "UpdateUser": + return UpdateUser + case "ResetPassword": + return ResetPassword + case "CheckId": + return CheckId + case "CheckEmail": + return CheckEmail + case "GetMyProfile": + return GetMyProfile + case "UpdateMyProfile": + return UpdateMyProfile + case "UpdateMyPassword": + return UpdateMyPassword + case "RenewPasswordExpiredDate": + return RenewPasswordExpiredDate + case "DeleteMyProfile": + return DeleteMyProfile + case "CreateOrganization": + return CreateOrganization + case "GetOrganizations": + return GetOrganizations + case "GetOrganization": + return GetOrganization + case "DeleteOrganization": + return DeleteOrganization + case "UpdateOrganization": + return UpdateOrganization + case "UpdatePrimaryCluster": + return UpdatePrimaryCluster + case "CreateCluster": + return CreateCluster + case "GetClusters": + return GetClusters + case "ImportCluster": + return ImportCluster + case "GetCluster": + return GetCluster + case "DeleteCluster": + return DeleteCluster + case "GetClusterSiteValues": + return GetClusterSiteValues + case "InstallCluster": + return InstallCluster + case "CreateBootstrapKubeconfig": + return CreateBootstrapKubeconfig + case "GetBootstrapKubeconfig": + return GetBootstrapKubeconfig + case "GetNodes": + return GetNodes + case "CreateAppgroup": + return CreateAppgroup + case "GetAppgroups": + return GetAppgroups + case "GetAppgroup": + return GetAppgroup + case "DeleteAppgroup": + return DeleteAppgroup + case "GetApplications": + return GetApplications + case "CreateApplication": + return CreateApplication + case "CreateAppServeApp": + return CreateAppServeApp + case "GetAppServeApps": + return GetAppServeApps + case "GetNumOfAppsOnStack": + return GetNumOfAppsOnStack + case "GetAppServeApp": + return GetAppServeApp + case "GetAppServeAppLatestTask": + return GetAppServeAppLatestTask + case "IsAppServeAppExist": + return IsAppServeAppExist + case "IsAppServeAppNameExist": + return IsAppServeAppNameExist + case "DeleteAppServeApp": + return DeleteAppServeApp + case "UpdateAppServeApp": + return UpdateAppServeApp + case "UpdateAppServeAppStatus": + return UpdateAppServeAppStatus + case "UpdateAppServeAppEndpoint": + return UpdateAppServeAppEndpoint + case "RollbackAppServeApp": + return RollbackAppServeApp + case "GetCloudAccounts": + return GetCloudAccounts + case "CreateCloudAccount": + return CreateCloudAccount + case "CheckCloudAccountName": + return CheckCloudAccountName + case "CheckAwsAccountId": + return CheckAwsAccountId + case "GetCloudAccount": + return GetCloudAccount + case "UpdateCloudAccount": + return UpdateCloudAccount + case "DeleteCloudAccount": + return DeleteCloudAccount + case "DeleteForceCloudAccount": + return DeleteForceCloudAccount + case "GetResourceQuota": + return GetResourceQuota + case "GetStackTemplates": + return GetStackTemplates + case "CreateStackTemplate": + return CreateStackTemplate + case "GetStackTemplate": + return GetStackTemplate + case "UpdateStackTemplate": + return UpdateStackTemplate + case "DeleteStackTemplate": + return DeleteStackTemplate + case "GetChartsDashboard": + return GetChartsDashboard + case "GetChartDashboard": + return GetChartDashboard + case "GetStacksDashboard": + return GetStacksDashboard + case "GetResourcesDashboard": + return GetResourcesDashboard + case "CreateAlert": + return CreateAlert + case "GetAlerts": + return GetAlerts + case "GetAlert": + return GetAlert + case "DeleteAlert": + return DeleteAlert + case "UpdateAlert": + return UpdateAlert + case "CreateAlertAction": + return CreateAlertAction + case "GetStacks": + return GetStacks + case "CreateStack": + return CreateStack + case "CheckStackName": + return CheckStackName + case "GetStack": + return GetStack + case "UpdateStack": + return UpdateStack + case "DeleteStack": + return DeleteStack + case "GetStackKubeConfig": + return GetStackKubeConfig + case "GetStackStatus": + return GetStackStatus + case "SetFavoriteStack": + return SetFavoriteStack + case "DeleteFavoriteStack": + return DeleteFavoriteStack + case "InstallStack": + return InstallStack + case "CreateProject": + return CreateProject + case "GetProjects": + return GetProjects + case "GetProject": + return GetProject + case "UpdateProject": + return UpdateProject + case "DeleteProject": + return DeleteProject + case "AddProjectMember": + return AddProjectMember + case "GetProjectMembers": + return GetProjectMembers + case "RemoveProjectMember": + return RemoveProjectMember + case "UpdateProjectMemberRole": + return UpdateProjectMemberRole + case "CreateProjectNamespace": + return CreateProjectNamespace + case "GetProjectNamespaces": + return GetProjectNamespaces + case "GetProjectNamespace": + return GetProjectNamespace + case "DeleteProjectNamespace": + return DeleteProjectNamespace + case "SetFavoriteProject": + return SetFavoriteProject + case "SetFavoriteProjectNamespace": + return SetFavoriteProjectNamespace + case "UnSetFavoriteProject": + return UnSetFavoriteProject + case "UnSetFavoriteProjectNamespace": + return UnSetFavoriteProjectNamespace + default: + return -1 + } +} diff --git a/internal/delivery/api/group.go b/internal/delivery/api/group.go new file mode 100644 index 00000000..9b6362e0 --- /dev/null +++ b/internal/delivery/api/group.go @@ -0,0 +1,9 @@ +package api + +var ProjectEndpoints = []Endpoint{ + CreateProject, + UpdateProject, + DeleteProject, + GetProject, + GetProjects, +} diff --git a/internal/delivery/api/project.go b/internal/delivery/api/project.go new file mode 100644 index 00000000..13786557 --- /dev/null +++ b/internal/delivery/api/project.go @@ -0,0 +1,28 @@ +package api + +// +//var ProjectApis []IApi = []IApi{ +// &ProjectApi{ +// name: "CreateProject", +// Api: Api{ +// Path: "", +// Method: "", +// Handler: nil, +// }, +// }, +//} +// +//type ProjectApi struct { +// name string +// Api +//} +// +////func NewProjectApi(path string, method string) IApi { +//// return &ProjectApi{ +//// Api: Api{Path: path, Method: method}, +//// } +////} +// +//func (a ProjectApi) API() Api { +// return a.Api +//} diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 50fe49a0..2c2b2bf5 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1,6 +1,7 @@ package http import ( + "fmt" "github.com/openinfradev/tks-api/internal/usecase" "net/http" ) @@ -21,14 +22,21 @@ type IProjectHandler interface { GetProjectNamespaces(w http.ResponseWriter, r *http.Request) GetProjectNamespace(w http.ResponseWriter, r *http.Request) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) + + SetFavoriteProject(w http.ResponseWriter, r *http.Request) + SetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) + UnSetFavoriteProject(w http.ResponseWriter, r *http.Request) + UnSetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) } + type ProjectHandler struct { usecase usecase.IProjectUsecase } func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") + fmt.Println("print test") + //panic("implement me") } func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { @@ -91,6 +99,26 @@ func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Re panic("implement me") } +func (p ProjectHandler) SetFavoriteProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) SetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) UnSetFavoriteProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + +func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) { + //TODO implement me + panic("implement me") +} + func NewProjectHandler(u usecase.IProjectUsecase) IProjectHandler { return &ProjectHandler{ usecase: u, diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go new file mode 100644 index 00000000..6fd56fbc --- /dev/null +++ b/internal/middleware/audit/audit.go @@ -0,0 +1 @@ +package audit diff --git a/internal/middleware/auth/authenticator/keycloak/keycloak.go b/internal/middleware/auth/authenticator/keycloak/keycloak.go index 445eb774..b694bc36 100644 --- a/internal/middleware/auth/authenticator/keycloak/keycloak.go +++ b/internal/middleware/auth/authenticator/keycloak/keycloak.go @@ -68,17 +68,42 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("token is deactivated"), "A_EXPIRED_TOKEN", "토큰이 만료되었습니다.") } - roleProjectMapping := make(map[string]string) - for _, role := range parsedToken.Claims.(jwtWithouKey.MapClaims)["tks-role"].([]interface{}) { - slice := strings.Split(role.(string), "@") - if len(slice) != 2 { - log.Errorf("invalid tks-role format: %v", role) + // tks role extraction + roleOrganizationMapping := make(map[string]string) + if roles, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["tks-role"]; !ok { + log.Errorf("tks-role is not found in token") + + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("tks-role is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } else { + for _, role := range roles.([]interface{}) { + slice := strings.Split(role.(string), "@") + if len(slice) != 2 { + log.Errorf("invalid tks-role format: %v", role) + + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid tks-role format"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + // key is projectName and value is roleName + roleOrganizationMapping[slice[1]] = slice[0] + } - return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid tks-role format"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + // project role extraction + projectIds := make([]string, 0) + roleProjectMapping := make(map[string]string) + if roles, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["project-role"]; ok { + for _, role := range roles.([]interface{}) { + slice := strings.Split(role.(string), "@") + if len(slice) != 2 { + log.Errorf("invalid project-role format: %v", role) + + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid project-role format"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + // key is projectId and value is roleName + roleProjectMapping[slice[1]] = slice[0] + projectIds = append(projectIds, slice[1]) } - // key is projectName and value is roleName - roleProjectMapping[slice[1]] = slice[0] } + userId, err := uuid.Parse(parsedToken.Claims.(jwtWithouKey.MapClaims)["sub"].(string)) if err != nil { log.Errorf("failed to verify access token: %v", err) @@ -91,9 +116,11 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) } userInfo := &user.DefaultInfo{ - UserId: userId, - OrganizationId: organizationId, - RoleProjectMapping: roleProjectMapping, + UserId: userId, + OrganizationId: organizationId, + ProjectIds: projectIds, + RoleOrganizationMapping: roleOrganizationMapping, + RoleProjectMapping: roleProjectMapping, } //r = r.WithContext(request.WithToken(r.Context(), token)) *r = *(r.WithContext(request.WithToken(r.Context(), token))) diff --git a/internal/middleware/auth/authorizer/authorizer.go b/internal/middleware/auth/authorizer/authorizer.go index 79093ed0..9983dbd5 100644 --- a/internal/middleware/auth/authorizer/authorizer.go +++ b/internal/middleware/auth/authorizer/authorizer.go @@ -20,6 +20,7 @@ func NewDefaultAuthorization(repo repository.Repository) *defaultAuthorization { } d.addFilters(PasswordFilter) d.addFilters(RBACFilter) + d.addFilters(RBACFilterWithEndpoint) return d } diff --git a/internal/middleware/auth/authorizer/password.go b/internal/middleware/auth/authorizer/password.go index 47b474fe..fec862b7 100644 --- a/internal/middleware/auth/authorizer/password.go +++ b/internal/middleware/auth/authorizer/password.go @@ -2,6 +2,7 @@ package authorizer import ( "fmt" + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "net/http" "github.com/openinfradev/tks-api/internal" @@ -53,3 +54,16 @@ func urlContains(urls []string, url string) bool { } return false } + +func isBypassEndpoint(endpoint internalApi.Endpoint) bool { + switch endpoint { + case internalApi.Login: + case internalApi.PingToken: + case internalApi.FindId: + case internalApi.FindPassword: + case internalApi.VerifyIdentityForLostId: + case internalApi.VerifyIdentityForLostPassword: + return true + } + return false +} diff --git a/internal/middleware/auth/authorizer/rbac.go b/internal/middleware/auth/authorizer/rbac.go index b4ff8a6f..01764465 100644 --- a/internal/middleware/auth/authorizer/rbac.go +++ b/internal/middleware/auth/authorizer/rbac.go @@ -7,8 +7,10 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + internalRole "github.com/openinfradev/tks-api/internal/middleware/auth/role" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" @@ -21,17 +23,17 @@ func RBACFilter(handler http.Handler, repo repository.Repository) http.Handler { internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) return } - role := requestUserInfo.GetRoleProjectMapping()[requestUserInfo.GetOrganizationId()] + organizationRole := requestUserInfo.GetRoleOrganizationMapping()[requestUserInfo.GetOrganizationId()] // TODO: 추후 tks-admin role 수정 필요 - if role == "tks-admin" { + if organizationRole == "tks-admin" { handler.ServeHTTP(w, r) return } vars := mux.Vars(r) // Organization Filter - if role == "admin" || role == "user" { + if organizationRole == "admin" || organizationRole == "user" { if orgId, ok := vars["organizationId"]; ok { if orgId != requestUserInfo.GetOrganizationId() { internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) @@ -46,7 +48,7 @@ func RBACFilter(handler http.Handler, repo repository.Repository) http.Handler { if strings.HasPrefix(r.URL.Path, internal.API_PREFIX+internal.API_VERSION+"/organizations/"+requestUserInfo.GetOrganizationId()+"/user") { switch r.Method { case http.MethodPost, http.MethodPut, http.MethodDelete: - if role != "admin" { + if organizationRole != "admin" { internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) return } @@ -56,3 +58,65 @@ func RBACFilter(handler http.Handler, repo repository.Repository) http.Handler { handler.ServeHTTP(w, r) }) } + +func RBACFilterWithEndpoint(handler http.Handler, repo repository.Repository) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requestEndpointInfo, ok := request.EndpointFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) + return + } + + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + return + } + + // if requestEndpointInfo.String() is one of ProjectEndpoints, print true + if internalApi.ApiMap[requestEndpointInfo].Group == "Project" && requestEndpointInfo != internalApi.CreateProject { + log.Infof("RBACFilterWithEndpoint: %s is ProjectEndpoint", requestEndpointInfo.String()) + vars := mux.Vars(r) + var projectRole string + if projectId, ok := vars["projectId"]; ok { + projectRole = requestUserInfo.GetRoleProjectMapping()[projectId] + } else { + log.Warn("RBACFilterWithEndpoint: projectId not found. Passing through unsafely.") + } + if !internalRole.IsRoleAllowed(requestEndpointInfo, internalRole.StrToRole(projectRole)) { + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return + + } + } + + handler.ServeHTTP(w, r) + }) +} + +//type pair struct { +// regexp string +// method string +//} +// +//var LeaderPair = []pair{ +// {`/organizations/o[A-Za-z0-9]{8}/projects(?:\?.*)?$`, http.MethodPost}, +// {`/organizations/o[A-Za-z0-9]{8}/projects(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodPut}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodDelete}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members(?:\?.*)?$`, http.MethodPost}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(?:\?.*)?$`, http.MethodDelete}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/role(?:\?.*)?$`, http.MethodPut}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace(?:\?.*)?$`, http.MethodPost}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace/n[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace/n[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodDelete}, +//} +//var roleApiMapper = make(map[string][]pair) +// +//func projectFilter(url string, method string, userInfo user.Info) bool { +// +// return true +//} diff --git a/internal/middleware/auth/middleware.go b/internal/middleware/auth/middleware.go deleted file mode 100644 index f9e6e977..00000000 --- a/internal/middleware/auth/middleware.go +++ /dev/null @@ -1,27 +0,0 @@ -package auth - -import ( - "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" - "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" - "net/http" -) - -type authMiddleware struct { - authenticator authenticator.Interface - authorizer authorizer.Interface -} - -func NewAuthMiddleware(authenticator authenticator.Interface, - authorizer authorizer.Interface) *authMiddleware { - ret := &authMiddleware{ - authenticator: authenticator, - authorizer: authorizer, - } - return ret -} - -func (m *authMiddleware) Handle(handle http.Handler) http.Handler { - handler := m.authorizer.WithAuthorization(handle) - handler = m.authenticator.WithAuthentication(handler) - return handler -} diff --git a/internal/middleware/auth/request/context.go b/internal/middleware/auth/request/context.go index ecefd7b9..0fadfa1e 100644 --- a/internal/middleware/auth/request/context.go +++ b/internal/middleware/auth/request/context.go @@ -2,7 +2,7 @@ package request import ( "context" - + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/middleware/auth/user" ) @@ -12,6 +12,7 @@ const ( userKey key = iota userToken sessionKey + endpointKey ) func WithValue(parent context.Context, key, val interface{}) context.Context { @@ -44,3 +45,12 @@ func SessionFrom(ctx context.Context) (string, bool) { token, ok := ctx.Value(sessionKey).(string) return token, ok } + +func WithEndpoint(parent context.Context, endpoint internalApi.Endpoint) context.Context { + return WithValue(parent, endpointKey, endpoint) +} + +func EndpointFrom(ctx context.Context) (internalApi.Endpoint, bool) { + endpoint, ok := ctx.Value(endpointKey).(internalApi.Endpoint) + return endpoint, ok +} diff --git a/internal/middleware/auth/requestRecoder/requestRecoder.go b/internal/middleware/auth/requestRecoder/requestRecoder.go new file mode 100644 index 00000000..34b61944 --- /dev/null +++ b/internal/middleware/auth/requestRecoder/requestRecoder.go @@ -0,0 +1,33 @@ +package requestRecoder + +import ( + "fmt" + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "net/http" +) + +type Interface interface { + WithRequestRecoder(endpoint internalApi.Endpoint, handler http.Handler) http.Handler +} + +type defaultRequestRecoder struct { +} + +func NewDefaultRequestRecoder() *defaultRequestRecoder { + return &defaultRequestRecoder{} +} + +func (a *defaultRequestRecoder) WithRequestRecoder(endpoint internalApi.Endpoint, handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r = r.WithContext(request.WithEndpoint(r.Context(), endpoint)) + _, ok := request.EndpointFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) + return + } + handler.ServeHTTP(w, r) + }) +} diff --git a/internal/middleware/auth/role/role.go b/internal/middleware/auth/role/role.go new file mode 100644 index 00000000..b8908590 --- /dev/null +++ b/internal/middleware/auth/role/role.go @@ -0,0 +1,44 @@ +package role + +import internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + +type Role string + +const ( + Admin Role = "admin" + User Role = "user" + leader Role = "leader" +) + +func (r Role) String() string { + return string(r) +} + +var RBAC = map[internalApi.Endpoint][]Role{ + internalApi.CreateProject: {Admin, User, leader}, + internalApi.UpdateProject: {Admin, User, leader}, + internalApi.DeleteProject: {Admin, User, leader}, + internalApi.GetProject: {Admin, User, leader}, + internalApi.GetProjects: {Admin, User, leader}, +} + +func StrToRole(role string) Role { + switch role { + case "admin": + return Admin + case "user": + return User + case "leader": + return leader + default: + return "" + } +} +func IsRoleAllowed(endpoint internalApi.Endpoint, role Role) bool { + for _, r := range RBAC[endpoint] { + if r == role { + return true + } + } + return false +} diff --git a/internal/middleware/auth/user/user.go b/internal/middleware/auth/user/user.go index d853f295..92a0a6bb 100644 --- a/internal/middleware/auth/user/user.go +++ b/internal/middleware/auth/user/user.go @@ -8,15 +8,18 @@ import ( type Info interface { GetUserId() uuid.UUID GetOrganizationId() string + GetRoleOrganizationMapping() map[string]string GetRoleProjectMapping() map[string]string } // DefaultInfo provides a simple user information exchange object // for components that implement the UserInfo interface. type DefaultInfo struct { - UserId uuid.UUID - OrganizationId string - RoleProjectMapping map[string]string + UserId uuid.UUID + OrganizationId string + ProjectIds []string + RoleOrganizationMapping map[string]string + RoleProjectMapping map[string]string } func (i *DefaultInfo) GetUserId() uuid.UUID { @@ -27,11 +30,18 @@ func (i *DefaultInfo) GetOrganizationId() string { return i.OrganizationId } -// GetRoleGroupMapping key is project name, value is role name +func (i *DefaultInfo) GetProjectId() []string { + return i.ProjectIds +} + func (i *DefaultInfo) GetRoleProjectMapping() map[string]string { return i.RoleProjectMapping } +func (i *DefaultInfo) GetRoleOrganizationMapping() map[string]string { + return i.RoleOrganizationMapping +} + // well-known user and group names const ( TksAdminRole = "tks_admin" diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go new file mode 100644 index 00000000..f9bd3098 --- /dev/null +++ b/internal/middleware/middleware.go @@ -0,0 +1,33 @@ +package middleware + +import ( + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" + "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" + "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" + "net/http" +) + +type Middleware struct { + authenticator authenticator.Interface + authorizer authorizer.Interface + requestRecoder requestRecoder.Interface +} + +func NewMiddleware(authenticator authenticator.Interface, + authorizer authorizer.Interface, + requestRecoder requestRecoder.Interface) *Middleware { + ret := &Middleware{ + authenticator: authenticator, + authorizer: authorizer, + requestRecoder: requestRecoder, + } + return ret +} + +func (m *Middleware) Handle(endpoint internalApi.Endpoint, handle http.Handler) http.Handler { + handler := m.authorizer.WithAuthorization(handle) + handler = m.requestRecoder.WithRequestRecoder(endpoint, handler) + handler = m.authenticator.WithAuthentication(handler) + return handler +} diff --git a/internal/route/route.go b/internal/route/route.go index 4c9bf5a8..6cbd1522 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -4,6 +4,8 @@ import ( "bytes" "context" "fmt" + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" "io" "net/http" "time" @@ -14,7 +16,7 @@ import ( "github.com/openinfradev/tks-api/internal" delivery "github.com/openinfradev/tks-api/internal/delivery/http" "github.com/openinfradev/tks-api/internal/keycloak" - "github.com/openinfradev/tks-api/internal/middleware/auth" + internalMiddleware "github.com/openinfradev/tks-api/internal/middleware" "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" authKeycloak "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator/keycloak" "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" @@ -60,9 +62,10 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa StackTemplate: repository.NewStackTemplateRepository(db), Alert: repository.NewAlertRepository(db), } - authMiddleware := auth.NewAuthMiddleware( + customMiddleware := internalMiddleware.NewMiddleware( authenticator.NewAuthenticator(authKeycloak.NewKeycloakAuthenticator(kc)), - authorizer.NewDefaultAuthorization(repoFactory)) + authorizer.NewDefaultAuthorization(repoFactory), + requestRecoder.NewDefaultRequestRecoder()) cache := gcache.New(5*time.Minute, 10*time.Minute) @@ -74,137 +77,136 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa authHandler := delivery.NewAuthHandler(usecase.NewAuthUsecase(repoFactory, kc)) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/login", authHandler.Login).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/ping", authHandler.PingToken).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/auth/logout", authMiddleware.Handle(http.HandlerFunc(authHandler.Logout))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/auth/refresh", authMiddleware.Handle(http.HandlerFunc(authHandler.RefreshToken))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/auth/logout", customMiddleware.Handle(internalApi.Logout, http.HandlerFunc(authHandler.Logout))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/auth/refresh", customMiddleware.Handle(internalApi.RefreshToken, http.HandlerFunc(authHandler.RefreshToken))).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-id/verification", authHandler.FindId).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-password/verification", authHandler.FindPassword).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-id/code", authHandler.VerifyIdentityForLostId).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-password/code", authHandler.VerifyIdentityForLostPassword).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/auth/verify-token", authMiddleware.Handle(http.HandlerFunc(authHandler.VerifyToken))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/auth/verify-token", customMiddleware.Handle(internalApi.VerifyToken, http.HandlerFunc(authHandler.VerifyToken))).Methods(http.MethodGet) //r.HandleFunc(API_PREFIX+API_VERSION+"/cookie-test", authHandler.CookieTest).Methods(http.MethodPost) //r.HandleFunc(API_PREFIX+API_VERSION+"/auth/callback", authHandler.CookieTestCallback).Methods(http.MethodGet) userHandler := delivery.NewUserHandler(usecase.NewUserUsecase(repoFactory, kc)) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", authMiddleware.Handle(http.HandlerFunc(userHandler.Create))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", authMiddleware.Handle(http.HandlerFunc(userHandler.List))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", authMiddleware.Handle(http.HandlerFunc(userHandler.Get))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", authMiddleware.Handle(http.HandlerFunc(userHandler.Update))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/reset-password", authMiddleware.Handle(http.HandlerFunc(userHandler.ResetPassword))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", authMiddleware.Handle(http.HandlerFunc(userHandler.Delete))).Methods(http.MethodDelete) - - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", authMiddleware.Handle(http.HandlerFunc(userHandler.GetMyProfile))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", authMiddleware.Handle(http.HandlerFunc(userHandler.UpdateMyProfile))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/password", authMiddleware.Handle(http.HandlerFunc(userHandler.UpdateMyPassword))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/next-password-change", authMiddleware.Handle(http.HandlerFunc(userHandler.RenewPasswordExpiredDate))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", authMiddleware.Handle(http.HandlerFunc(userHandler.DeleteMyProfile))).Methods(http.MethodDelete) - - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/account-id/{accountId}/existence", authMiddleware.Handle(http.HandlerFunc(userHandler.CheckId))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/email/{email}/existence", authMiddleware.Handle(http.HandlerFunc(userHandler.CheckEmail))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.CreateUser, http.HandlerFunc(userHandler.Create))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.ListUser, http.HandlerFunc(userHandler.List))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.GetUser, http.HandlerFunc(userHandler.Get))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.UpdateUser, http.HandlerFunc(userHandler.Update))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/reset-password", customMiddleware.Handle(internalApi.ResetPassword, http.HandlerFunc(userHandler.ResetPassword))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.DeleteUser, http.HandlerFunc(userHandler.Delete))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/account-id/{accountId}/existence", customMiddleware.Handle(internalApi.CheckId, http.HandlerFunc(userHandler.CheckId))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/email/{email}/existence", customMiddleware.Handle(internalApi.CheckEmail, http.HandlerFunc(userHandler.CheckEmail))).Methods(http.MethodGet) + + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.GetMyProfile, http.HandlerFunc(userHandler.GetMyProfile))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.UpdateMyProfile, http.HandlerFunc(userHandler.UpdateMyProfile))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/password", customMiddleware.Handle(internalApi.UpdateMyPassword, http.HandlerFunc(userHandler.UpdateMyPassword))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/next-password-change", customMiddleware.Handle(internalApi.RenewPasswordExpiredDate, http.HandlerFunc(userHandler.RenewPasswordExpiredDate))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.DeleteMyProfile, http.HandlerFunc(userHandler.DeleteMyProfile))).Methods(http.MethodDelete) organizationHandler := delivery.NewOrganizationHandler(usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), usecase.NewUserUsecase(repoFactory, kc)) - r.Handle(API_PREFIX+API_VERSION+"/organizations", authMiddleware.Handle(http.HandlerFunc(organizationHandler.CreateOrganization))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations", authMiddleware.Handle(http.HandlerFunc(organizationHandler.GetOrganizations))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", authMiddleware.Handle(http.HandlerFunc(organizationHandler.GetOrganization))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", authMiddleware.Handle(http.HandlerFunc(organizationHandler.DeleteOrganization))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", authMiddleware.Handle(http.HandlerFunc(organizationHandler.UpdateOrganization))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/primary-cluster", authMiddleware.Handle(http.HandlerFunc(organizationHandler.UpdatePrimaryCluster))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.CreateOrganization, http.HandlerFunc(organizationHandler.CreateOrganization))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.GetOrganizations, http.HandlerFunc(organizationHandler.GetOrganizations))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.GetOrganization, http.HandlerFunc(organizationHandler.GetOrganization))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.DeleteOrganization, http.HandlerFunc(organizationHandler.DeleteOrganization))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.UpdateOrganization, http.HandlerFunc(organizationHandler.UpdateOrganization))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/primary-cluster", customMiddleware.Handle(internalApi.UpdatePrimaryCluster, http.HandlerFunc(organizationHandler.UpdatePrimaryCluster))).Methods(http.MethodPatch) clusterHandler := delivery.NewClusterHandler(usecase.NewClusterUsecase(repoFactory, argoClient, cache)) - r.Handle(API_PREFIX+API_VERSION+"/clusters", authMiddleware.Handle(http.HandlerFunc(clusterHandler.CreateCluster))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/clusters", authMiddleware.Handle(http.HandlerFunc(clusterHandler.GetClusters))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/clusters/import", authMiddleware.Handle(http.HandlerFunc(clusterHandler.ImportCluster))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}", authMiddleware.Handle(http.HandlerFunc(clusterHandler.GetCluster))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}", authMiddleware.Handle(http.HandlerFunc(clusterHandler.DeleteCluster))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/site-values", authMiddleware.Handle(http.HandlerFunc(clusterHandler.GetClusterSiteValues))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/install", authMiddleware.Handle(http.HandlerFunc(clusterHandler.InstallCluster))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/bootstrap-kubeconfig", authMiddleware.Handle(http.HandlerFunc(clusterHandler.CreateBootstrapKubeconfig))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/bootstrap-kubeconfig", authMiddleware.Handle(http.HandlerFunc(clusterHandler.GetBootstrapKubeconfig))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/nodes", authMiddleware.Handle(http.HandlerFunc(clusterHandler.GetNodes))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters", customMiddleware.Handle(internalApi.CreateCluster, http.HandlerFunc(clusterHandler.CreateCluster))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/clusters", customMiddleware.Handle(internalApi.GetClusters, http.HandlerFunc(clusterHandler.GetClusters))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/import", customMiddleware.Handle(internalApi.ImportCluster, http.HandlerFunc(clusterHandler.ImportCluster))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}", customMiddleware.Handle(internalApi.GetCluster, http.HandlerFunc(clusterHandler.GetCluster))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}", customMiddleware.Handle(internalApi.DeleteCluster, http.HandlerFunc(clusterHandler.DeleteCluster))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/site-values", customMiddleware.Handle(internalApi.GetClusterSiteValues, http.HandlerFunc(clusterHandler.GetClusterSiteValues))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/install", customMiddleware.Handle(internalApi.InstallCluster, http.HandlerFunc(clusterHandler.InstallCluster))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/bootstrap-kubeconfig", customMiddleware.Handle(internalApi.CreateBootstrapKubeconfig, http.HandlerFunc(clusterHandler.CreateBootstrapKubeconfig))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/bootstrap-kubeconfig", customMiddleware.Handle(internalApi.GetBootstrapKubeconfig, http.HandlerFunc(clusterHandler.GetBootstrapKubeconfig))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/nodes", customMiddleware.Handle(internalApi.GetNodes, http.HandlerFunc(clusterHandler.GetNodes))).Methods(http.MethodGet) appGroupHandler := delivery.NewAppGroupHandler(usecase.NewAppGroupUsecase(repoFactory, argoClient)) - r.Handle(API_PREFIX+API_VERSION+"/app-groups", authMiddleware.Handle(http.HandlerFunc(appGroupHandler.CreateAppGroup))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/app-groups", authMiddleware.Handle(http.HandlerFunc(appGroupHandler.GetAppGroups))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}", authMiddleware.Handle(http.HandlerFunc(appGroupHandler.GetAppGroup))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}", authMiddleware.Handle(http.HandlerFunc(appGroupHandler.DeleteAppGroup))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}/applications", authMiddleware.Handle(http.HandlerFunc(appGroupHandler.GetApplications))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}/applications", authMiddleware.Handle(http.HandlerFunc(appGroupHandler.CreateApplication))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/app-groups", customMiddleware.Handle(internalApi.CreateAppgroup, http.HandlerFunc(appGroupHandler.CreateAppGroup))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/app-groups", customMiddleware.Handle(internalApi.GetAppgroups, http.HandlerFunc(appGroupHandler.GetAppGroups))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}", customMiddleware.Handle(internalApi.GetAppgroup, http.HandlerFunc(appGroupHandler.GetAppGroup))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}", customMiddleware.Handle(internalApi.DeleteAppgroup, http.HandlerFunc(appGroupHandler.DeleteAppGroup))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}/applications", customMiddleware.Handle(internalApi.GetApplications, http.HandlerFunc(appGroupHandler.GetApplications))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}/applications", customMiddleware.Handle(internalApi.CreateApplication, http.HandlerFunc(appGroupHandler.CreateApplication))).Methods(http.MethodPost) appServeAppHandler := delivery.NewAppServeAppHandler(usecase.NewAppServeAppUsecase(repoFactory, argoClient)) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.CreateAppServeApp))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.GetAppServeApps))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/count", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.GetNumOfAppsOnStack))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.GetAppServeApp))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps", customMiddleware.Handle(internalApi.CreateAppServeApp, http.HandlerFunc(appServeAppHandler.CreateAppServeApp))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApps))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/count", customMiddleware.Handle(internalApi.GetNumOfAppsOnStack, http.HandlerFunc(appServeAppHandler.GetNumOfAppsOnStack))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApp))).Methods(http.MethodGet) // TODO: To be implemented - // r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/tasks/{taskId}", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.GetAppServeAppTask))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/latest-task", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.GetAppServeAppLatestTask))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/exist", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.IsAppServeAppExist))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/name/{name}/existence", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.IsAppServeAppNameExist))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.DeleteAppServeApp))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.UpdateAppServeApp))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/status", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.UpdateAppServeAppStatus))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/endpoint", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.UpdateAppServeAppEndpoint))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/rollback", authMiddleware.Handle(http.HandlerFunc(appServeAppHandler.RollbackAppServeApp))).Methods(http.MethodPost) + // r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/tasks/{taskId}", customMiddleware.Handle(http.HandlerFunc(appServeAppHandler.GetAppServeAppTask))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/latest-task", customMiddleware.Handle(internalApi.GetAppServeAppLatestTask, http.HandlerFunc(appServeAppHandler.GetAppServeAppLatestTask))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/exist", customMiddleware.Handle(internalApi.IsAppServeAppExist, http.HandlerFunc(appServeAppHandler.IsAppServeAppExist))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/name/{name}/existence", customMiddleware.Handle(internalApi.IsAppServeAppNameExist, http.HandlerFunc(appServeAppHandler.IsAppServeAppNameExist))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.DeleteAppServeApp, http.HandlerFunc(appServeAppHandler.DeleteAppServeApp))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.UpdateAppServeApp, http.HandlerFunc(appServeAppHandler.UpdateAppServeApp))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/status", customMiddleware.Handle(internalApi.UpdateAppServeAppStatus, http.HandlerFunc(appServeAppHandler.UpdateAppServeAppStatus))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/endpoint", customMiddleware.Handle(internalApi.UpdateAppServeAppEndpoint, http.HandlerFunc(appServeAppHandler.UpdateAppServeAppEndpoint))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/rollback", customMiddleware.Handle(internalApi.RollbackAppServeApp, http.HandlerFunc(appServeAppHandler.RollbackAppServeApp))).Methods(http.MethodPost) cloudAccountHandler := delivery.NewCloudAccountHandler(usecase.NewCloudAccountUsecase(repoFactory, argoClient)) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.GetCloudAccounts))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.CreateCloudAccount))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/name/{name}/existence", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.CheckCloudAccountName))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.CheckAwsAccountId))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.GetCloudAccount))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.UpdateCloudAccount))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.DeleteCloudAccount))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.DeleteForceCloudAccount))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quotas", authMiddleware.Handle(http.HandlerFunc(cloudAccountHandler.GetResourceQuota))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts", customMiddleware.Handle(internalApi.GetCloudAccounts, http.HandlerFunc(cloudAccountHandler.GetCloudAccounts))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts", customMiddleware.Handle(internalApi.CreateCloudAccount, http.HandlerFunc(cloudAccountHandler.CreateCloudAccount))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/name/{name}/existence", customMiddleware.Handle(internalApi.CheckCloudAccountName, http.HandlerFunc(cloudAccountHandler.CheckCloudAccountName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence", customMiddleware.Handle(internalApi.CheckAwsAccountId, http.HandlerFunc(cloudAccountHandler.CheckAwsAccountId))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}", customMiddleware.Handle(internalApi.GetCloudAccount, http.HandlerFunc(cloudAccountHandler.GetCloudAccount))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}", customMiddleware.Handle(internalApi.UpdateCloudAccount, http.HandlerFunc(cloudAccountHandler.UpdateCloudAccount))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}", customMiddleware.Handle(internalApi.DeleteCloudAccount, http.HandlerFunc(cloudAccountHandler.DeleteCloudAccount))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error", customMiddleware.Handle(internalApi.DeleteForceCloudAccount, http.HandlerFunc(cloudAccountHandler.DeleteForceCloudAccount))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quotas", customMiddleware.Handle(internalApi.GetResourceQuota, http.HandlerFunc(cloudAccountHandler.GetResourceQuota))).Methods(http.MethodGet) stackTemplateHandler := delivery.NewStackTemplateHandler(usecase.NewStackTemplateUsecase(repoFactory)) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates", authMiddleware.Handle(http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates", authMiddleware.Handle(http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", authMiddleware.Handle(http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", authMiddleware.Handle(http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", authMiddleware.Handle(http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/stack-templates", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/stack-templates", customMiddleware.Handle(internalApi.CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetStackTemplate, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) dashboardHandler := delivery.NewDashboardHandler(usecase.NewDashboardUsecase(repoFactory, cache)) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", authMiddleware.Handle(http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts/{chartType}", authMiddleware.Handle(http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/stacks", authMiddleware.Handle(http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", authMiddleware.Handle(http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts/{chartType}", customMiddleware.Handle(internalApi.GetChartDashboard, http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) alertHandler := delivery.NewAlertHandler(usecase.NewAlertUsecase(repoFactory)) r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/alerts", alertHandler.CreateAlert).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts", authMiddleware.Handle(http.HandlerFunc(alertHandler.GetAlerts))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", authMiddleware.Handle(http.HandlerFunc(alertHandler.GetAlert))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", authMiddleware.Handle(http.HandlerFunc(alertHandler.DeleteAlert))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", authMiddleware.Handle(http.HandlerFunc(alertHandler.UpdateAlert))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}/actions", authMiddleware.Handle(http.HandlerFunc(alertHandler.CreateAlertAction))).Methods(http.MethodPost) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}/actions/status", authMiddleware.Handle(http.HandlerFunc(alertHandler.UpdateAlertActionStatus))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts", customMiddleware.Handle(internalApi.GetAlerts, http.HandlerFunc(alertHandler.GetAlerts))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", customMiddleware.Handle(internalApi.GetAlert, http.HandlerFunc(alertHandler.GetAlert))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", customMiddleware.Handle(internalApi.DeleteAlert, http.HandlerFunc(alertHandler.DeleteAlert))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", customMiddleware.Handle(internalApi.UpdateAlert, http.HandlerFunc(alertHandler.UpdateAlert))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}/actions", customMiddleware.Handle(internalApi.CreateAlertAction, http.HandlerFunc(alertHandler.CreateAlertAction))).Methods(http.MethodPost) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}/actions/status", customMiddleware.Handle(http.HandlerFunc(alertHandler.UpdateAlertActionStatus))).Methods(http.MethodPatch) stackHandler := delivery.NewStackHandler(usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache))) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", authMiddleware.Handle(http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", authMiddleware.Handle(http.HandlerFunc(stackHandler.CreateStack))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/name/{name}/existence", authMiddleware.Handle(http.HandlerFunc(stackHandler.CheckStackName))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", authMiddleware.Handle(http.HandlerFunc(stackHandler.GetStack))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", authMiddleware.Handle(http.HandlerFunc(stackHandler.UpdateStack))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", authMiddleware.Handle(http.HandlerFunc(stackHandler.DeleteStack))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/kube-config", authMiddleware.Handle(http.HandlerFunc(stackHandler.GetStackKubeConfig))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/status", authMiddleware.Handle(http.HandlerFunc(stackHandler.GetStackStatus))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", authMiddleware.Handle(http.HandlerFunc(stackHandler.SetFavorite))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", authMiddleware.Handle(http.HandlerFunc(stackHandler.DeleteFavorite))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/install", authMiddleware.Handle(http.HandlerFunc(stackHandler.InstallStack))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.CreateStack, http.HandlerFunc(stackHandler.CreateStack))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/name/{name}/existence", customMiddleware.Handle(internalApi.CheckStackName, http.HandlerFunc(stackHandler.CheckStackName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetStack, http.HandlerFunc(stackHandler.GetStack))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateStack, http.HandlerFunc(stackHandler.UpdateStack))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteStack, http.HandlerFunc(stackHandler.DeleteStack))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/kube-config", customMiddleware.Handle(internalApi.GetStackKubeConfig, http.HandlerFunc(stackHandler.GetStackKubeConfig))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/status", customMiddleware.Handle(internalApi.GetStackStatus, http.HandlerFunc(stackHandler.GetStackStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", customMiddleware.Handle(internalApi.SetFavoriteStack, http.HandlerFunc(stackHandler.SetFavorite))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", customMiddleware.Handle(internalApi.DeleteFavoriteStack, http.HandlerFunc(stackHandler.DeleteFavorite))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/install", customMiddleware.Handle(internalApi.InstallStack, http.HandlerFunc(stackHandler.InstallStack))).Methods(http.MethodPost) projectHandler := delivery.NewProjectHandler(usecase.NewProjectUsecase(repoFactory)) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", authMiddleware.Handle(http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProjectMembers))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", authMiddleware.Handle(http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{accountId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{accountId}/role", authMiddleware.Handle(http.HandlerFunc(projectHandler.UpdateProjectMemberRole))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", authMiddleware.Handle(http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", authMiddleware.Handle(http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.CreateProject, http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.DeleteProject, http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.AddProjectMember, http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMembers))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{accountId}", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{accountId}/role", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMemberRole))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets diff --git a/pkg/log/log.go b/pkg/log/log.go index 7bd6adb1..1983ad67 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -6,6 +6,7 @@ import ( "os" "path" "runtime" + "strconv" "strings" "github.com/openinfradev/tks-api/internal" @@ -108,7 +109,7 @@ func WarnWithContext(ctx context.Context, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, + "file": file + ":" + strconv.Itoa(line), "line": line, string(internal.ContextKeyRequestID): reqID, }).Warn(v...) From 19f7d049ef3bb533e80e906f2b429a5ab339d566 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Jan 2024 13:39:17 +0900 Subject: [PATCH 006/502] audit logic --- internal/middleware/audit/audit.go | 28 +++++++++++++++++++ internal/middleware/auth/request/context.go | 10 +++++++ internal/middleware/middleware.go | 30 +++++++++++++++++---- internal/route/route.go | 4 ++- 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 6fd56fbc..4b2058c5 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -1 +1,29 @@ package audit + +import ( + "github.com/openinfradev/tks-api/internal/repository" + "net/http" +) + +type Interface interface { + WithAudit(handler http.Handler) http.Handler +} + +type defaultAudit struct { + repo repository.Repository +} + +func NewDefaultAudit(repo repository.Repository) *defaultAudit { + return &defaultAudit{ + repo: repo, + } +} + +// TODO: implement audit logic +func (a *defaultAudit) WithAudit(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // TODO: implement audit logic + + handler.ServeHTTP(w, r) + }) +} diff --git a/internal/middleware/auth/request/context.go b/internal/middleware/auth/request/context.go index 0fadfa1e..61efecfa 100644 --- a/internal/middleware/auth/request/context.go +++ b/internal/middleware/auth/request/context.go @@ -13,6 +13,7 @@ const ( userToken sessionKey endpointKey + auditKey ) func WithValue(parent context.Context, key, val interface{}) context.Context { @@ -54,3 +55,12 @@ func EndpointFrom(ctx context.Context) (internalApi.Endpoint, bool) { endpoint, ok := ctx.Value(endpointKey).(internalApi.Endpoint) return endpoint, ok } + +func WithAudit(parent context.Context, audit string) context.Context { + return WithValue(parent, auditKey, audit) +} + +func AuditFrom(ctx context.Context) (string, bool) { + audit, ok := ctx.Value(auditKey).(string) + return audit, ok +} diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go index f9bd3098..86e8899c 100644 --- a/internal/middleware/middleware.go +++ b/internal/middleware/middleware.go @@ -2,6 +2,7 @@ package middleware import ( internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" @@ -12,22 +13,41 @@ type Middleware struct { authenticator authenticator.Interface authorizer authorizer.Interface requestRecoder requestRecoder.Interface + audit audit.Interface } func NewMiddleware(authenticator authenticator.Interface, authorizer authorizer.Interface, - requestRecoder requestRecoder.Interface) *Middleware { + requestRecoder requestRecoder.Interface, + audit audit.Interface) *Middleware { ret := &Middleware{ authenticator: authenticator, authorizer: authorizer, requestRecoder: requestRecoder, + audit: audit, } return ret } func (m *Middleware) Handle(endpoint internalApi.Endpoint, handle http.Handler) http.Handler { - handler := m.authorizer.WithAuthorization(handle) - handler = m.requestRecoder.WithRequestRecoder(endpoint, handler) - handler = m.authenticator.WithAuthentication(handler) - return handler + + // pre-handler + preHandler := m.authorizer.WithAuthorization(handle) + // TODO: this is a temporary solution. check if this is the right place to put audit middleware + preHandler = m.audit.WithAudit(preHandler) + preHandler = m.requestRecoder.WithRequestRecoder(endpoint, preHandler) + preHandler = m.authenticator.WithAuthentication(preHandler) + + // post-handler + emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + + // append post-handler below + // TODO: this is a temporary solution. check if this is the right place to put audit middleware + postHandler := m.audit.WithAudit(emptyHandler) + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + preHandler.ServeHTTP(w, r) + + postHandler.ServeHTTP(w, r) + }) } diff --git a/internal/route/route.go b/internal/route/route.go index 6cbd1522..9f5ef5e4 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -5,6 +5,7 @@ import ( "context" "fmt" internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" "io" "net/http" @@ -65,7 +66,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa customMiddleware := internalMiddleware.NewMiddleware( authenticator.NewAuthenticator(authKeycloak.NewKeycloakAuthenticator(kc)), authorizer.NewDefaultAuthorization(repoFactory), - requestRecoder.NewDefaultRequestRecoder()) + requestRecoder.NewDefaultRequestRecoder(), + audit.NewDefaultAudit(repoFactory)) cache := gcache.New(5*time.Minute, 10*time.Minute) From e05662564594cb19d673f738d91615ff9e0e86c2 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Jan 2024 15:03:20 +0900 Subject: [PATCH 007/502] trimming --- api/swagger/docs.go | 2 +- cmd/server/main.go | 2 +- internal/delivery/api/api.go | 51 --------------------- internal/delivery/api/group.go | 9 ---- internal/delivery/api/project.go | 28 ------------ pkg/log/log.go | 77 +++++++++++++++++++------------- 6 files changed, 47 insertions(+), 122 deletions(-) delete mode 100644 internal/delivery/api/api.go delete mode 100644 internal/delivery/api/group.go delete mode 100644 internal/delivery/api/project.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 27273773..ff2be9e4 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -21,7 +21,7 @@ const docTemplate = `{ "version": "{{.Version}}" }, "host": "{{.Host}}", - "basePath": "{{.Path}}", + "basePath": "{{.BasePath}}", "paths": { "/app-groups": { "get": { diff --git a/cmd/server/main.go b/cmd/server/main.go index 7e644142..eea9f26d 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -92,7 +92,7 @@ func init() { // @name Authorization // @host tks-api-ft.taco-cat.xyz -// @Path /api/1.0/ +// @BasePath /api/1.0/ func main() { log.Info("*** Arguments *** ") for i, s := range viper.AllSettings() { diff --git a/internal/delivery/api/api.go b/internal/delivery/api/api.go deleted file mode 100644 index 10f42603..00000000 --- a/internal/delivery/api/api.go +++ /dev/null @@ -1,51 +0,0 @@ -package api - -// -//import ( -// "github.com/gorilla/mux" -// "net/http" -//) -// -//type IApi interface { -// //SetPath() -// API() Api -// //SetMethod() -// //GetMethod() string -// //SetHandler() -// //GetHandler() http.Handler -// // -// //RegisterApi(router *mux.Router) -//} -//type Api struct { -// Path string -// Method string -// Handler http.Handler -//} -// -//func (a Api) GetPath() string { -// return a.Path -//} -// -//func (a Api) GetMethod() string { -// return a.Method -//} -// -//func (a Api) GetHandler() http.Handler { -// return a.Handler -//} -// -//func (a Api) SetBasePath(path string) { -// a.Path = path -//} -// -//func (a Api) SetMethod(method string) { -// a.Method = method -//} -// -//func (a Api) SetHandler(handler http.Handler) { -// a.Handler = handler -//} -// -//func (a Api) RegisterApi(router *mux.Router) { -// router.Handle(a.GetPath(), a.GetHandler()) -//} diff --git a/internal/delivery/api/group.go b/internal/delivery/api/group.go deleted file mode 100644 index 9b6362e0..00000000 --- a/internal/delivery/api/group.go +++ /dev/null @@ -1,9 +0,0 @@ -package api - -var ProjectEndpoints = []Endpoint{ - CreateProject, - UpdateProject, - DeleteProject, - GetProject, - GetProjects, -} diff --git a/internal/delivery/api/project.go b/internal/delivery/api/project.go deleted file mode 100644 index 13786557..00000000 --- a/internal/delivery/api/project.go +++ /dev/null @@ -1,28 +0,0 @@ -package api - -// -//var ProjectApis []IApi = []IApi{ -// &ProjectApi{ -// name: "CreateProject", -// Api: Api{ -// Path: "", -// Method: "", -// Handler: nil, -// }, -// }, -//} -// -//type ProjectApi struct { -// name string -// Api -//} -// -////func NewProjectApi(path string, method string) IApi { -//// return &ProjectApi{ -//// Api: Api{Path: path, Method: method}, -//// } -////} -// -//func (a ProjectApi) API() Api { -// return a.Api -//} diff --git a/pkg/log/log.go b/pkg/log/log.go index 1983ad67..2a5bf3bc 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -4,7 +4,6 @@ import ( "context" "io" "os" - "path" "runtime" "strconv" "strings" @@ -59,8 +58,7 @@ func (f *CustomFormatter) Format(entry *logrus.Entry) ([]byte, error) { func Info(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": path.Base(file), - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Info(v...) } else { logger.Info(v...) @@ -69,8 +67,7 @@ func Info(v ...interface{}) { func Infof(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": path.Base(file), - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Infof(format, v...) } else { logger.Infof(format, v...) @@ -78,18 +75,31 @@ func Infof(format string, v ...interface{}) { } func InfoWithContext(ctx context.Context, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) - logger.WithField(string(internal.ContextKeyRequestID), reqID).Info(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file + ":" + strconv.Itoa(line), + string(internal.ContextKeyRequestID): reqID, + }).Info(v...) + } else { + logger.WithField(string(internal.ContextKeyRequestID), reqID).Info(v...) + } } func InfofWithContext(ctx context.Context, format string, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) - logger.WithField(string(internal.ContextKeyRequestID), reqID).Infof(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file + ":" + strconv.Itoa(line), + string(internal.ContextKeyRequestID): reqID, + }).Infof(format, v...) + } else { + logger.WithField(string(internal.ContextKeyRequestID), reqID).Infof(format, v...) + } } func Warn(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Warn(v...) } else { logger.Warn(v...) @@ -98,8 +108,7 @@ func Warn(v ...interface{}) { func Warnf(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Warnf(format, v...) } else { logger.Warnf(format, v...) @@ -110,7 +119,6 @@ func WarnWithContext(ctx context.Context, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ "file": file + ":" + strconv.Itoa(line), - "line": line, string(internal.ContextKeyRequestID): reqID, }).Warn(v...) } else { @@ -121,8 +129,7 @@ func WarnfWithContext(ctx context.Context, format string, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), string(internal.ContextKeyRequestID): reqID, }).Warnf(format, v...) } else { @@ -133,8 +140,7 @@ func WarnfWithContext(ctx context.Context, format string, v ...interface{}) { func Debug(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Debug(v...) } else { logger.Debug(v...) @@ -143,8 +149,7 @@ func Debug(v ...interface{}) { func Debugf(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Debugf(format, v...) } else { logger.Debugf(format, v...) @@ -152,18 +157,31 @@ func Debugf(format string, v ...interface{}) { } func DebugWithContext(ctx context.Context, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) - logger.WithField(string(internal.ContextKeyRequestID), reqID).Debug(v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file + ":" + strconv.Itoa(line), + string(internal.ContextKeyRequestID): reqID, + }).Debug(v...) + } else { + logger.WithField(string(internal.ContextKeyRequestID), reqID).Debug(v...) + } } func DebugfWithContext(ctx context.Context, format string, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) - logger.WithField(string(internal.ContextKeyRequestID), reqID).Debugf(format, v...) + if _, file, line, ok := runtime.Caller(1); ok { + logger.WithFields(logrus.Fields{ + "file": file + ":" + strconv.Itoa(line), + string(internal.ContextKeyRequestID): reqID, + }).Debugf(format, v...) + } else { + logger.WithField(string(internal.ContextKeyRequestID), reqID).Debugf(format, v...) + } } func Error(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Error(v...) } else { logger.Error(v...) @@ -172,8 +190,7 @@ func Error(v ...interface{}) { func Errorf(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Errorf(format, v...) } else { logger.Errorf(format, v...) @@ -183,8 +200,7 @@ func ErrorWithContext(ctx context.Context, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), string(internal.ContextKeyRequestID): reqID, }).Error(v...) } else { @@ -195,8 +211,7 @@ func ErrorfWithContext(ctx context.Context, format string, v ...interface{}) { reqID := ctx.Value(internal.ContextKeyRequestID) if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), string(internal.ContextKeyRequestID): reqID, }).Errorf(format, v...) } else { @@ -207,8 +222,7 @@ func ErrorfWithContext(ctx context.Context, format string, v ...interface{}) { func Fatal(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Fatal(v...) } else { logger.Fatal(v...) @@ -217,8 +231,7 @@ func Fatal(v ...interface{}) { func Fatalf(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { logger.WithFields(logrus.Fields{ - "file": file, - "line": line, + "file": file + ":" + strconv.Itoa(line), }).Fatalf(format, v...) } else { logger.Fatalf(format, v...) From 94eb30273e8d25de52a138a9f4b4c0d900ce6a6d Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Jan 2024 15:13:12 +0900 Subject: [PATCH 008/502] remove panic code in project API --- internal/delivery/http/project.go | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 2c2b2bf5..550a6313 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1,7 +1,6 @@ package http import ( - "fmt" "github.com/openinfradev/tks-api/internal/usecase" "net/http" ) @@ -35,88 +34,70 @@ type ProjectHandler struct { func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { //TODO implement me - fmt.Println("print test") - //panic("implement me") } func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) SetFavoriteProject(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) SetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) UnSetFavoriteProject(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) { //TODO implement me - panic("implement me") } func NewProjectHandler(u usecase.IProjectUsecase) IProjectHandler { From 15b19b94e1b944789b1d8fa5b65b94d7eb77c885 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Jan 2024 15:16:13 +0900 Subject: [PATCH 009/502] minor fix: lint fix --- .../middleware/auth/authorizer/password.go | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/middleware/auth/authorizer/password.go b/internal/middleware/auth/authorizer/password.go index fec862b7..4fd9b980 100644 --- a/internal/middleware/auth/authorizer/password.go +++ b/internal/middleware/auth/authorizer/password.go @@ -2,7 +2,6 @@ package authorizer import ( "fmt" - internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "net/http" "github.com/openinfradev/tks-api/internal" @@ -55,15 +54,16 @@ func urlContains(urls []string, url string) bool { return false } -func isBypassEndpoint(endpoint internalApi.Endpoint) bool { - switch endpoint { - case internalApi.Login: - case internalApi.PingToken: - case internalApi.FindId: - case internalApi.FindPassword: - case internalApi.VerifyIdentityForLostId: - case internalApi.VerifyIdentityForLostPassword: - return true - } - return false -} +// +//func isBypassEndpoint(endpoint internalApi.Endpoint) bool { +// switch endpoint { +// case internalApi.Login: +// case internalApi.PingToken: +// case internalApi.FindId: +// case internalApi.FindPassword: +// case internalApi.VerifyIdentityForLostId: +// case internalApi.VerifyIdentityForLostPassword: +// return true +// } +// return false +//} From 3e8c181296dfb828458b710c36d6962326a14be2 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Jan 2024 15:17:27 +0900 Subject: [PATCH 010/502] increase lint t/o 5m to 10m --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5df838e9..c9514afe 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,7 +23,7 @@ jobs: with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version version: v1.51.0 - args: --timeout=5m + args: --timeout=10m # Optional: working directory, useful for monorepos # working-directory: somedir From b650eb8e83c35fbffe397027e927e741550ffd25 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Jan 2024 11:18:41 +0900 Subject: [PATCH 011/502] feature. implementation filter & pagination --- api/swagger/docs.go | 6 + api/swagger/swagger.json | 6 + api/swagger/swagger.yaml | 4 + go.mod | 29 +- go.sum | 60 ++++ go.work.sum | 31 +- internal/delivery/http/stack-template.go | 2 +- internal/filter/filter.go | 70 +++++ internal/filter/join.go | 246 ++++++++++++++++ internal/filter/operator.go | 162 +++++++++++ internal/filter/search.go | 67 +++++ internal/filter/settings.go | 346 +++++++++++++++++++++++ internal/filter/sort.go | 60 ++++ internal/filter/util.go | 246 ++++++++++++++++ internal/filter/validation.go | 213 ++++++++++++++ internal/pagination/pagination.go | 149 ++++++++-- internal/repository/stack-template.go | 35 ++- pkg/domain/pagination.go | 6 +- scripts/init_postgres.sql | 12 +- 19 files changed, 1699 insertions(+), 51 deletions(-) create mode 100644 internal/filter/filter.go create mode 100644 internal/filter/join.go create mode 100644 internal/filter/operator.go create mode 100644 internal/filter/search.go create mode 100644 internal/filter/settings.go create mode 100644 internal/filter/sort.go create mode 100644 internal/filter/util.go create mode 100644 internal/filter/validation.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index ff2be9e4..3b595793 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -5282,6 +5282,12 @@ const docTemplate = `{ "column": { "type": "string" }, + "operator": { + "type": "string" + }, + "releation": { + "type": "string" + }, "values": { "type": "array", "items": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 9392836c..fa98668f 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -5275,6 +5275,12 @@ "column": { "type": "string" }, + "operator": { + "type": "string" + }, + "releation": { + "type": "string" + }, "values": { "type": "array", "items": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index e5915d23..dfbf2f9f 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -962,6 +962,10 @@ definitions: properties: column: type: string + operator: + type: string + releation: + type: string values: items: type: string diff --git a/go.mod b/go.mod index ff813bc2..8e79f74d 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/google/uuid v1.3.0 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 - github.com/gorilla/websocket v1.4.2 + github.com/gorilla/websocket v1.5.0 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 @@ -34,20 +34,21 @@ require ( github.com/swaggo/swag v1.8.5 github.com/thoas/go-funk v0.9.3 github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.4.0 - golang.org/x/crypto v0.7.0 - golang.org/x/net v0.8.0 + golang.org/x/crypto v0.9.0 + golang.org/x/net v0.10.0 golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 gorm.io/datatypes v1.1.1 - gorm.io/driver/postgres v1.4.5 - gorm.io/gorm v1.25.0 + gorm.io/driver/postgres v1.5.0 + gorm.io/gorm v1.25.1 k8s.io/apimachinery v0.25.4 k8s.io/client-go v0.25.2 k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed ) require ( + github.com/Code-Hex/uniseg v0.2.0 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 // indirect @@ -71,7 +72,7 @@ require ( github.com/go-openapi/spec v0.20.6 // indirect github.com/go-openapi/swag v0.19.15 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -80,13 +81,13 @@ require ( github.com/google/go-cmp v0.5.8 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect + github.com/imdario/mergo v0.3.15 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.13.0 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgproto3/v2 v2.3.1 // indirect - github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgtype v1.12.0 // indirect github.com/jackc/pgx/v4 v4.17.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect @@ -105,6 +106,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect @@ -113,11 +115,12 @@ require ( github.com/spf13/afero v1.8.2 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/stretchr/testify v1.8.2 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect @@ -127,7 +130,9 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gorm.io/driver/mysql v1.4.7 // indirect + gorm.io/driver/mysql v1.5.0 // indirect + goyave.dev/filter v0.6.0 // indirect + goyave.dev/goyave/v4 v4.4.11 // indirect k8s.io/api v0.25.4 // indirect k8s.io/apiextensions-apiserver v0.23.5 // indirect k8s.io/component-base v0.25.2 // indirect diff --git a/go.sum b/go.sum index 4150f430..372a677f 100644 --- a/go.sum +++ b/go.sum @@ -51,6 +51,8 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Code-Hex/uniseg v0.2.0 h1:QB/2UJFvEuRLSZqe+Sb1XQBTWjqGVbZoC6oSWzQRKws= +github.com/Code-Hex/uniseg v0.2.0/go.mod h1:/ndS2tP+X1lk2HUOcXWGtVTxVq0lWilwgMa4CbzdRsg= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= @@ -238,6 +240,8 @@ github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPr github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/flect v0.2.4 h1:BSYA8+T60cdyq+vynaSUjqSVI9mDEg9ZfQUXKmfjo4I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -345,6 +349,7 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= @@ -378,6 +383,10 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -410,6 +419,8 @@ github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= @@ -422,10 +433,12 @@ github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQ github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= +github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= @@ -462,7 +475,9 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -497,6 +512,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/microsoft/go-mssqldb v0.21.0 h1:p2rpHIL7TlSv1QrbXJUAcbyRKnIT0C9rRkH2E4OjLn8= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -594,6 +610,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= @@ -655,6 +672,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -679,6 +697,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -743,10 +762,14 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -782,6 +805,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -835,8 +859,12 @@ golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -864,6 +892,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -935,15 +965,23 @@ golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -953,8 +991,11 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1027,6 +1068,7 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1159,6 +1201,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= @@ -1188,22 +1232,38 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/datatypes v1.1.1 h1:XAjO7NNfUKVUvnS3+BkqMrPXxCAcxDlpOYbjnizxNCw= gorm.io/datatypes v1.1.1/go.mod h1:u8GEgFjJ+GpsGfgHmBUcQqHm/937t3sj/SO9dvbndTg= gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y= gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc= +gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM= +gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo= gorm.io/driver/postgres v1.4.5 h1:mTeXTTtHAgnS9PgmhN2YeUbazYpLhUI1doLnw42XUZc= gorm.io/driver/postgres v1.4.5/go.mod h1:GKNQYSJ14qvWkvPwXljMGehpKrhlDNsqYRr5HnYGncg= +gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= +gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU= +gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= +gorm.io/driver/sqlserver v1.4.3 h1:ji91Zb/zS7NWrMRJBfoM9C0gyxCSh9anQoJApqEkiV8= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.24.1-0.20221019064659-5dd2bb482755/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= +gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU= gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64= +gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +goyave.dev/filter v0.6.0 h1:uAOHbV9rnylDyJmjBy8qsBoRRD9rZt0TEe8YrwYWOts= +goyave.dev/filter v0.6.0/go.mod h1:IKw7y3F8SFq3ZRzq/V31UboQfDYbSTzqBrQZTqIwJro= +goyave.dev/goyave/v4 v4.4.5 h1:pqNQTMMx4XImjpDZ890Yz4nTW0t5o3zpmdPfmXuXSF4= +goyave.dev/goyave/v4 v4.4.5/go.mod h1:lZCUx5ln6k+CWNop2vLU9295LNaOm7FUqpJbk6hqGVU= +goyave.dev/goyave/v4 v4.4.11 h1:HdJJ82ZWrkB7sBsituVRgQhcDvmAavfVbd6xynaUN8Y= +goyave.dev/goyave/v4 v4.4.11/go.mod h1:kMbB3bf7ZhUD4Cq1Zy6nM4fHBHYO5mPSkTF6WStf4ik= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/go.work.sum b/go.work.sum index dfaaf3a0..375ce61a 100644 --- a/go.work.sum +++ b/go.work.sum @@ -203,6 +203,10 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= @@ -241,6 +245,7 @@ github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd h1:efcJu2Vzz6DoS github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= +github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= github.com/jackpal/gateway v1.0.7 h1:7tIFeCGmpyrMx9qvT0EgYUi7cxVW48a0mMvnIL17bPM= github.com/jackpal/gateway v1.0.7/go.mod h1:aRcO0UFKt+MgIZmRmvOmnejdDT4Y1DNiNOsSd1AcIbA= @@ -274,7 +279,31 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= +github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= +github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc h1:m7rJJJeXrYCFpsxXYapkDW53wJCDmf9bsIXUg0HoeQY= +github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc/go.mod h1:eOj1DDj3NAZ6yv+WafaKzY37MFZ58TdfIhQ+8nQbiis= +github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE= +github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= +github.com/mdlayher/ndp v0.10.0 h1:Zdwol2bq1EHY8xSnejIYkq6LEj7dLjLymJX0o/2tjGw= +github.com/mdlayher/ndp v0.10.0/go.mod h1:Uv6IWvgvqirNUu2N3ZXJEB86xu6foyUsG0NrClSSfek= +github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0= +github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= +github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b h1:MHcTarUMC4sFA7eiyR8IEJ6j2PgmgXR+B9X2IIMjh7A= +github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= +github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM= +github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= +github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc h1:m7rJJJeXrYCFpsxXYapkDW53wJCDmf9bsIXUg0HoeQY= diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 29b4af18..92c0237f 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -81,7 +81,7 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/filter/filter.go b/internal/filter/filter.go new file mode 100644 index 00000000..e8d8cf52 --- /dev/null +++ b/internal/filter/filter.go @@ -0,0 +1,70 @@ +package filter + +import ( + "fmt" + "strings" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" +) + +type Filter struct { + Field string + Operator *Operator + Args []string + Or bool +} + +func (f *Filter) Scope(settings *Settings, sch *schema.Schema) (func(*gorm.DB) *gorm.DB, func(*gorm.DB) *gorm.DB) { + field, s, joinName := getField(f.Field, sch, &settings.Blacklist) + if field == nil { + return nil, nil + } + + dataType := getDataType(field) + + joinScope := func(tx *gorm.DB) *gorm.DB { + if dataType == DataTypeUnsupported { + return tx + } + if joinName != "" { + if err := tx.Statement.Parse(tx.Statement.Model); err != nil { + _ = tx.AddError(err) + return tx + } + tx = join(tx, joinName, sch) + } + + return tx + } + + computed := field.StructField.Tag.Get("computed") + + conditionScope := func(tx *gorm.DB) *gorm.DB { + if dataType == DataTypeUnsupported { + return tx + } + + table := tx.Statement.Quote(tableFromJoinName(s.Table, joinName)) + var fieldExpr string + if computed != "" { + fieldExpr = fmt.Sprintf("(%s)", strings.ReplaceAll(computed, clause.CurrentTable, table)) + } else { + fieldExpr = table + "." + tx.Statement.Quote(field.DBName) + } + + return f.Operator.Function(tx, f, fieldExpr, dataType) + } + + return joinScope, conditionScope +} + +// Where applies a condition to given transaction, automatically taking the "Or" +// filter value into account. +func (f *Filter) Where(tx *gorm.DB, query string, args ...interface{}) *gorm.DB { + if f.Or { + return tx.Or(query, args...) + } + return tx.Where(query, args...) +} diff --git a/internal/filter/join.go b/internal/filter/join.go new file mode 100644 index 00000000..72240709 --- /dev/null +++ b/internal/filter/join.go @@ -0,0 +1,246 @@ +package filter + +import ( + "bytes" + "fmt" + "regexp" + "strings" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + "goyave.dev/goyave/v4/util/sliceutil" +) + +var ( + joinRegex = regexp.MustCompile("(?i)((LEFT|RIGHT|FULL)\\s+)?((OUTER|INNER)\\s+)?JOIN\\s+[\"'`]?(?P\\w+)[\"'`]?\\s+((AS\\s+)?[\"'`]?(?P\\w+)[\"'`]?)?\\s*ON") +) + +type Join struct { + selectCache map[string][]string + Relation string + Fields []string +} + +func (j *Join) Scopes(settings *Settings, schema *schema.Schema) []func(*gorm.DB) *gorm.DB { + scopes := j.applyRelation(schema, &settings.Blacklist, j.Relation, 0, make([]func(*gorm.DB) *gorm.DB, 0, strings.Count(j.Relation, ".")+1)) + if scopes != nil { + return scopes + } + return nil +} + +func (j *Join) applyRelation(schema *schema.Schema, blacklist *Blacklist, relationName string, startIndex int, scopes []func(*gorm.DB) *gorm.DB) []func(*gorm.DB) *gorm.DB { + if blacklist != nil && blacklist.IsFinal { + return nil + } + trimmedRelationName := relationName[startIndex:] + i := strings.Index(trimmedRelationName, ".") + if i == -1 { + if blacklist != nil { + if sliceutil.ContainsStr(blacklist.RelationsBlacklist, trimmedRelationName) { + return nil + } + blacklist = blacklist.Relations[trimmedRelationName] + } + + r, ok := schema.Relationships.Relations[trimmedRelationName] + if !ok { + return nil + } + + j.selectCache[relationName] = j.Fields + return append(scopes, joinScope(relationName, r, j.Fields, blacklist)) + } + + if startIndex+i+1 >= len(relationName) { + return nil + } + + name := trimmedRelationName[:i] + var b *Blacklist + if blacklist != nil { + if sliceutil.ContainsStr(blacklist.RelationsBlacklist, name) { + return nil + } + b = blacklist.Relations[name] + } + r, ok := schema.Relationships.Relations[name] + if !ok { + return nil + } + n := relationName[:startIndex+i] + fields := []string{} + if f, ok := j.selectCache[n]; ok { + fields = f + } + scopes = append(scopes, joinScope(n, r, fields, b)) + + return j.applyRelation(r.FieldSchema, b, relationName, startIndex+i+1, scopes) +} + +func joinScope(relationName string, rel *schema.Relationship, fields []string, blacklist *Blacklist) func(*gorm.DB) *gorm.DB { + var columns []*schema.Field + if fields == nil { + columns = getSelectableFields(blacklist, rel.FieldSchema) + } else { + var b []string + if blacklist != nil { + b = blacklist.FieldsBlacklist + } + columns = cleanColumns(rel.FieldSchema, fields, b) + } + + return func(tx *gorm.DB) *gorm.DB { + if rel.FieldSchema.Table == "" { + _ = tx.AddError(fmt.Errorf("Relation %q is anonymous, could not get table name", relationName)) + return tx + } + if columns != nil { + for _, primaryField := range rel.FieldSchema.PrimaryFields { + if !columnsContain(columns, primaryField) && (blacklist == nil || !sliceutil.ContainsStr(blacklist.FieldsBlacklist, primaryField.DBName)) { + columns = append(columns, primaryField) + } + } + for _, backwardsRelation := range rel.FieldSchema.Relationships.Relations { + if backwardsRelation.FieldSchema == rel.Schema && backwardsRelation.Type == schema.BelongsTo { + for _, ref := range backwardsRelation.References { + if !columnsContain(columns, ref.ForeignKey) && (blacklist == nil || !sliceutil.ContainsStr(blacklist.FieldsBlacklist, ref.ForeignKey.DBName)) { + columns = append(columns, ref.ForeignKey) + } + } + } + } + } + + return tx.Preload(relationName, selectScope(rel.FieldSchema.Table, columns, true)) + } +} + +func join(tx *gorm.DB, joinName string, sch *schema.Schema) *gorm.DB { + + var lastTable string + var relation *schema.Relationship + joins := make([]clause.Join, 0, strings.Count(joinName, ".")+1) + for _, rel := range strings.Split(joinName, ".") { + lastTable = sch.Table + if relation != nil { + lastTable = relation.Name + } + relation = sch.Relationships.Relations[rel] + sch = relation.FieldSchema + exprs := make([]clause.Expression, len(relation.References)) + for idx, ref := range relation.References { + if ref.OwnPrimaryKey { + exprs[idx] = clause.Eq{ + Column: clause.Column{Table: lastTable, Name: ref.PrimaryKey.DBName}, + Value: clause.Column{Table: relation.Name, Name: ref.ForeignKey.DBName}, + } + } else { + if ref.PrimaryValue == "" { + exprs[idx] = clause.Eq{ + Column: clause.Column{Table: lastTable, Name: ref.ForeignKey.DBName}, + Value: clause.Column{Table: relation.Name, Name: ref.PrimaryKey.DBName}, + } + } else { + exprs[idx] = clause.Eq{ + Column: clause.Column{Table: relation.Name, Name: ref.ForeignKey.DBName}, + Value: ref.PrimaryValue, + } + } + } + } + j := clause.Join{ + Type: clause.LeftJoin, + Table: clause.Table{Name: sch.Table, Alias: relation.Name}, + ON: clause.Where{Exprs: exprs}, + } + if !joinExists(tx.Statement, j) && !findStatementJoin(tx.Statement, &j) { + joins = append(joins, j) + } + } + if c, ok := tx.Statement.Clauses["FROM"]; ok { + from, _ := c.Expression.(clause.From) + from.Joins = append(from.Joins, joins...) + c.Expression = from + tx.Statement.Clauses["FROM"] = c + return tx + } + return tx.Clauses(clause.From{Joins: joins}) +} + +func joinExists(stmt *gorm.Statement, join clause.Join) bool { + if c, ok := stmt.Clauses["FROM"]; ok { + from, _ := c.Expression.(clause.From) + c.Expression = from + for _, j := range from.Joins { + if j.Table == join.Table { + return true + } + } + } + for _, j := range stmt.Joins { + groups := joinRegex.FindStringSubmatch(j.Name) + if groups != nil { + tableName := groups[joinRegex.SubexpIndex("TableName")] + aliasName := groups[joinRegex.SubexpIndex("Alias")] + tableMatch := tableName == join.Table.Name + aliasMatch := aliasName == "" || aliasName == join.Table.Alias + if tableMatch && aliasMatch { + return true + } + } + } + return false +} + +func findStatementJoin(stmt *gorm.Statement, join *clause.Join) bool { + for _, j := range stmt.Joins { + if j.Name == join.Table.Alias { + return true + } + } + + return false +} + +func quoteString(stmt *gorm.Statement, str string) string { + writer := bytes.NewBufferString("") + stmt.DB.Dialector.QuoteTo(writer, str) + return writer.String() +} + +func processJoinsComputedColumns(stmt *gorm.Statement, sch *schema.Schema) { + for i, j := range stmt.Joins { + rel, ok := sch.Relationships.Relations[j.Name] + if !ok { + continue + } + + columnStmt := gorm.Statement{ + Table: j.Name, + Schema: rel.FieldSchema, + Selects: j.Selects, + Omits: j.Omits, + } + if len(columnStmt.Selects) == 0 { + columnStmt.Selects = []string{"*"} + } + + selectColumns, restricted := columnStmt.SelectAndOmitColumns(false, false) + j.Selects = nil + j.Omits = []string{"*"} + for _, s := range rel.FieldSchema.DBNames { + if v, ok := selectColumns[s]; (ok && v) || (!ok && !restricted) { + field := rel.FieldSchema.FieldsByDBName[s] + computed := field.StructField.Tag.Get("computed") + if computed != "" { + stmt.Selects = append(stmt.Selects, fmt.Sprintf("(%s) %s", strings.ReplaceAll(computed, clause.CurrentTable, quoteString(stmt, j.Name)), quoteString(stmt, j.Name+"__"+s))) + continue + } + stmt.Selects = append(stmt.Selects, fmt.Sprintf("%s.%s %s", quoteString(stmt, j.Name), quoteString(stmt, s), quoteString(stmt, j.Name+"__"+s))) + } + } + stmt.Joins[i] = j + } +} diff --git a/internal/filter/operator.go b/internal/filter/operator.go new file mode 100644 index 00000000..de992369 --- /dev/null +++ b/internal/filter/operator.go @@ -0,0 +1,162 @@ +package filter + +import ( + "fmt" + + "gorm.io/gorm" + "goyave.dev/goyave/v4/util/sqlutil" +) + +// Operator used by filters to build the SQL query. +// The operator function modifies the GORM statement (most of the time by adding +// a WHERE condition) then returns the modified statement. +// +// Operators may need arguments (e.g. "$eq", equals needs a value to compare the field to); +// RequiredArguments define the minimum number of arguments a client must send in order to +// use this operator in a filter. RequiredArguments is checked during Filter parsing. +// +// Operators may return the given tx without change if they don't support the given dataType or +// add a condition that will always be false. +type Operator struct { + Function func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB + RequiredArguments uint8 +} + +var ( + Operators = map[string]*Operator{ + "$eq": {Function: basicComparison("="), RequiredArguments: 1}, + "$ne": {Function: basicComparison("<>"), RequiredArguments: 1}, + "$gt": {Function: basicComparison(">"), RequiredArguments: 1}, + "$lt": {Function: basicComparison("<"), RequiredArguments: 1}, + "$gte": {Function: basicComparison(">="), RequiredArguments: 1}, + "$lte": {Function: basicComparison("<="), RequiredArguments: 1}, + "$starts": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType != DataTypeText && dataType != DataTypeEnum { + return filter.Where(tx, "FALSE") + } + query := castEnumAsText(column, dataType) + " LIKE ?" + value := sqlutil.EscapeLike(filter.Args[0]) + "%" + return filter.Where(tx, query, value) + }, + RequiredArguments: 1, + }, + "$ends": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType != DataTypeText && dataType != DataTypeEnum { + return filter.Where(tx, "FALSE") + } + query := castEnumAsText(column, dataType) + " LIKE ?" + value := "%" + sqlutil.EscapeLike(filter.Args[0]) + return filter.Where(tx, query, value) + }, + RequiredArguments: 1, + }, + "$cont": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType != DataTypeText && dataType != DataTypeEnum { + return filter.Where(tx, "FALSE") + } + query := castEnumAsText(column, dataType) + " LIKE ?" + value := "%" + sqlutil.EscapeLike(filter.Args[0]) + "%" + return filter.Where(tx, query, value) + }, + RequiredArguments: 1, + }, + "$excl": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType != DataTypeText && dataType != DataTypeEnum { + return filter.Where(tx, "FALSE") + } + query := castEnumAsText(column, dataType) + " NOT LIKE ?" + value := "%" + sqlutil.EscapeLike(filter.Args[0]) + "%" + return filter.Where(tx, query, value) + }, + RequiredArguments: 1, + }, + "$in": {Function: multiComparison("IN"), RequiredArguments: 1}, + "$notin": {Function: multiComparison("NOT IN"), RequiredArguments: 1}, + "$isnull": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + return filter.Where(tx, column+" IS NULL") + }, + RequiredArguments: 0, + }, + "$istrue": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType != DataTypeBool { + return filter.Where(tx, "FALSE") + } + return filter.Where(tx, column+" IS TRUE") + }, + RequiredArguments: 0, + }, + "$isfalse": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType != DataTypeBool { + return filter.Where(tx, "FALSE") + } + return filter.Where(tx, column+" IS FALSE") + }, + RequiredArguments: 0, + }, + "$notnull": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + return filter.Where(tx, column+" IS NOT NULL") + }, + RequiredArguments: 0, + }, + "$between": { + Function: func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType.IsArray() { + return filter.Where(tx, "FALSE") + } + + args, ok := ConvertArgsToSafeType(filter.Args[:2], dataType) + if !ok { + return filter.Where(tx, "FALSE") + } + query := castEnumAsText(column, dataType) + " BETWEEN ? AND ?" + return filter.Where(tx, query, args...) + }, + RequiredArguments: 2, + }, + } +) + +func castEnumAsText(column string, dataType DataType) string { + if dataType == DataTypeEnum || dataType == DataTypeEnumArray { + return fmt.Sprintf("CAST(%s AS TEXT)", column) + } + return column +} + +func basicComparison(op string) func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + return func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType.IsArray() { + return filter.Where(tx, "FALSE") + } + arg, ok := ConvertToSafeType(filter.Args[0], dataType) + if !ok { + return filter.Where(tx, "FALSE") + } + + query := fmt.Sprintf("%s %s ?", castEnumAsText(column, dataType), op) + return filter.Where(tx, query, arg) + } +} + +func multiComparison(op string) func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + return func(tx *gorm.DB, filter *Filter, column string, dataType DataType) *gorm.DB { + if dataType.IsArray() { + return filter.Where(tx, "FALSE") + } + args, ok := ConvertArgsToSafeType(filter.Args, dataType) + if !ok { + return filter.Where(tx, "FALSE") + } + + query := fmt.Sprintf("%s %s ?", castEnumAsText(column, dataType), op) + return filter.Where(tx, query, args) + } +} diff --git a/internal/filter/search.go b/internal/filter/search.go new file mode 100644 index 00000000..47f56d6d --- /dev/null +++ b/internal/filter/search.go @@ -0,0 +1,67 @@ +package filter + +import ( + "fmt" + "strings" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" +) + +type Search struct { + Query string + Operator *Operator + Fields []string +} + +func (s *Search) Scope(schema *schema.Schema) func(*gorm.DB) *gorm.DB { + if len(s.Fields) == 0 { + return nil + } + + return func(tx *gorm.DB) *gorm.DB { + searchQuery := tx.Session(&gorm.Session{NewDB: true}) + + for _, field := range s.Fields { + + f, sch, joinName := getField(field, schema, nil) + if f == nil { + continue + } + dataType := getDataType(f) + if dataType == DataTypeUnsupported { + continue + } + + if joinName != "" { + if err := tx.Statement.Parse(tx.Statement.Model); err != nil { + _ = tx.AddError(err) + return tx + } + tx = join(tx, joinName, schema) + } + + filter := &Filter{ + Field: f.DBName, + Operator: s.Operator, + Args: []string{s.Query}, + Or: true, + } + + table := tx.Statement.Quote(tableFromJoinName(sch.Table, joinName)) + + computed := f.StructField.Tag.Get("computed") + var fieldExpr string + if computed != "" { + fieldExpr = fmt.Sprintf("(%s)", strings.ReplaceAll(computed, clause.CurrentTable, table)) + } else { + fieldExpr = table + "." + tx.Statement.Quote(f.DBName) + } + + searchQuery = s.Operator.Function(searchQuery, filter, fieldExpr, dataType) + } + + return tx.Where(searchQuery) + } +} diff --git a/internal/filter/settings.go b/internal/filter/settings.go new file mode 100644 index 00000000..ac2a31a8 --- /dev/null +++ b/internal/filter/settings.go @@ -0,0 +1,346 @@ +package filter + +import ( + "fmt" + "strings" + "sync" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + "goyave.dev/goyave/v4" + "goyave.dev/goyave/v4/database" + "goyave.dev/goyave/v4/util/sliceutil" +) + +type Settings struct { + FieldsSearch []string + SearchOperator *Operator + + Blacklist + + DisableFields bool + DisableFilter bool + DisableSort bool + DisableJoin bool + DisableSearch bool +} + +type Blacklist struct { + Relations map[string]*Blacklist + FieldsBlacklist []string + RelationsBlacklist []string + IsFinal bool +} + +var ( + DefaultPageSize = 10 + modelCache = &sync.Map{} +) + +func parseModel(db *gorm.DB, model interface{}) (*schema.Schema, error) { + return schema.Parse(model, modelCache, db.NamingStrategy) +} + +func Scope(db *gorm.DB, request *goyave.Request, dest interface{}) (*database.Paginator, *gorm.DB) { + return (&Settings{}).Scope(db, request, dest) +} + +func ScopeUnpaginated(db *gorm.DB, request *goyave.Request, dest interface{}) *gorm.DB { + return (&Settings{}).ScopeUnpaginated(db, request, dest) +} + +func (s *Settings) Scope(db *gorm.DB, request *goyave.Request, dest interface{}) (*database.Paginator, *gorm.DB) { + db, schema, hasJoins := s.scopeCommon(db, request, dest) + + page := 1 + if request.Has("page") { + page = request.Integer("page") + } + pageSize := DefaultPageSize + if request.Has("per_page") { + pageSize = request.Integer("per_page") + } + + paginator := database.NewPaginator(db, page, pageSize, dest) + paginator.UpdatePageInfo() + + paginator.DB = s.scopeSort(paginator.DB, request, schema) + if fieldsDB := s.scopeFields(paginator.DB, request, schema, hasJoins); fieldsDB != nil { + paginator.DB = fieldsDB + } else { + return nil, paginator.DB + } + + return paginator, paginator.Find() +} + +func (s *Settings) ScopeUnpaginated(db *gorm.DB, request *goyave.Request, dest interface{}) *gorm.DB { + db, schema, hasJoins := s.scopeCommon(db, request, dest) + db = s.scopeSort(db, request, schema) + if fieldsDB := s.scopeFields(db, request, schema, hasJoins); fieldsDB != nil { + db = fieldsDB + } else { + return db + } + return db.Find(dest) +} + +func (s *Settings) scopeCommon(db *gorm.DB, request *goyave.Request, dest interface{}) (*gorm.DB, *schema.Schema, bool) { + schema, err := parseModel(db, dest) + if err != nil { + panic(err) + } + + db = db.Model(dest) + db = s.applyFilters(db, request, schema) + + hasJoins := false + if !s.DisableJoin && request.Has("join") { + joins, ok := request.Data["join"].([]*Join) + if ok { + selectCache := map[string][]string{} + for _, j := range joins { + hasJoins = true + j.selectCache = selectCache + if s := j.Scopes(s, schema); s != nil { + db = db.Scopes(s...) + } + } + } + } + + if !s.DisableSearch && request.Has("search") { + if search := s.applySearch(request, schema); search != nil { + if scope := search.Scope(schema); scope != nil { + db = db.Scopes(scope) + } + } + } + + db.Scopes(func(tx *gorm.DB) *gorm.DB { + processJoinsComputedColumns(tx.Statement, schema) + return tx + }) + + return db, schema, hasJoins +} + +func (s *Settings) scopeFields(db *gorm.DB, request *goyave.Request, schema *schema.Schema, hasJoins bool) *gorm.DB { + if !s.DisableFields && request.Has("fields") { + fields := strings.Split(request.String("fields"), ",") + if hasJoins { + if len(schema.PrimaryFieldDBNames) == 0 { + _ = db.AddError(fmt.Errorf("Could not find primary key. Add `gorm:\"primaryKey\"` to your model")) + return nil + } + fields = addPrimaryKeys(schema, fields) + fields = addForeignKeys(schema, fields) + } + return db.Scopes(selectScope(schema.Table, cleanColumns(schema, fields, s.FieldsBlacklist), false)) + } + return db.Scopes(selectScope(schema.Table, getSelectableFields(&s.Blacklist, schema), false)) +} + +func (s *Settings) scopeSort(db *gorm.DB, request *goyave.Request, schema *schema.Schema) *gorm.DB { + if !s.DisableSort && request.Has("sort") { + sorts, ok := request.Data["sort"].([]*Sort) + if ok { + for _, sort := range sorts { + if scope := sort.Scope(s, schema); scope != nil { + db = db.Scopes(scope) + } + } + } + } + return db +} + +func (s *Settings) applyFilters(db *gorm.DB, request *goyave.Request, schema *schema.Schema) *gorm.DB { + if s.DisableFilter { + return db + } + filterScopes := make([]func(*gorm.DB) *gorm.DB, 0, 2) + joinScopes := make([]func(*gorm.DB) *gorm.DB, 0, 2) + + andLen := filterLen(request, "filter") + orLen := filterLen(request, "or") + mixed := orLen > 1 && andLen > 0 + + for _, queryParam := range []string{"filter", "or"} { + if request.Has(queryParam) { + filters, ok := request.Data[queryParam].([]*Filter) + if ok { + group := make([]func(*gorm.DB) *gorm.DB, 0, 4) + for _, f := range filters { + if mixed { + f = &Filter{ + Field: f.Field, + Operator: f.Operator, + Args: f.Args, + Or: false, + } + } + joinScope, conditionScope := f.Scope(s, schema) + if conditionScope != nil { + group = append(group, conditionScope) + } + if joinScope != nil { + joinScopes = append(joinScopes, joinScope) + } + } + filterScopes = append(filterScopes, groupFilters(group, false)) + } + } + } + if len(joinScopes) > 0 { + db = db.Scopes(joinScopes...) + } + if len(filterScopes) > 0 { + db = db.Scopes(groupFilters(filterScopes, true)) + } + return db +} + +func filterLen(request *goyave.Request, name string) int { + count := 0 + if data, ok := request.Data[name]; ok { + if filters, ok := data.([]*Filter); ok { + count = len(filters) + } + } + return count +} + +func groupFilters(scopes []func(*gorm.DB) *gorm.DB, and bool) func(*gorm.DB) *gorm.DB { + return func(tx *gorm.DB) *gorm.DB { + processedFilters := tx.Session(&gorm.Session{NewDB: true}) + for _, f := range scopes { + processedFilters = f(processedFilters) + } + if and { + return tx.Where(processedFilters) + } + return tx.Or(processedFilters) + } +} + +func (s *Settings) applySearch(request *goyave.Request, schema *schema.Schema) *Search { + // Note: the search condition is not in a group condition (parenthesis) + query, ok := request.Data["search"].(string) + if ok { + fields := s.FieldsSearch + if fields == nil { + for _, f := range getSelectableFields(&s.Blacklist, schema) { + fields = append(fields, f.DBName) + } + } + + operator := s.SearchOperator + if operator == nil { + operator = Operators["$cont"] + } + + search := &Search{ + Query: query, + Operator: operator, + Fields: fields, + } + + return search + } + + return nil +} + +func getSelectableFields(blacklist *Blacklist, sch *schema.Schema) []*schema.Field { + b := []string{} + if blacklist != nil && blacklist.FieldsBlacklist != nil { + b = blacklist.FieldsBlacklist + } + columns := make([]*schema.Field, 0, len(sch.DBNames)) + for _, f := range sch.DBNames { + if !sliceutil.ContainsStr(b, f) { + columns = append(columns, sch.FieldsByDBName[f]) + } + } + + return columns +} + +func selectScope(table string, fields []*schema.Field, override bool) func(*gorm.DB) *gorm.DB { + return func(tx *gorm.DB) *gorm.DB { + + if fields == nil { + return tx + } + + var fieldsWithTableName []string + if len(fields) == 0 { + fieldsWithTableName = []string{"1"} + } else { + fieldsWithTableName = make([]string, 0, len(fields)) + tableName := tx.Statement.Quote(table) + for _, f := range fields { + computed := f.StructField.Tag.Get("computed") + var fieldExpr string + if computed != "" { + fieldExpr = fmt.Sprintf("(%s) %s", strings.ReplaceAll(computed, clause.CurrentTable, tableName), tx.Statement.Quote(f.DBName)) + } else { + fieldExpr = tableName + "." + tx.Statement.Quote(f.DBName) + } + + fieldsWithTableName = append(fieldsWithTableName, fieldExpr) + } + } + + if override { + return tx.Select(fieldsWithTableName) + } + + return tx.Select(tx.Statement.Selects, fieldsWithTableName) + } +} + +func getField(field string, sch *schema.Schema, blacklist *Blacklist) (*schema.Field, *schema.Schema, string) { + joinName := "" + s := sch + if i := strings.LastIndex(field, "."); i != -1 && i+1 < len(field) { + rel := field[:i] + field = field[i+1:] + for _, v := range strings.Split(rel, ".") { + if blacklist != nil && (sliceutil.ContainsStr(blacklist.RelationsBlacklist, v) || blacklist.IsFinal) { + return nil, nil, "" + } + relation, ok := s.Relationships.Relations[v] + if !ok || (relation.Type != schema.HasOne && relation.Type != schema.BelongsTo) { + return nil, nil, "" + } + s = relation.FieldSchema + if blacklist != nil { + blacklist = blacklist.Relations[v] + } + } + joinName = rel + } + if blacklist != nil && sliceutil.ContainsStr(blacklist.FieldsBlacklist, field) { + return nil, nil, "" + } + col, ok := s.FieldsByDBName[field] + if !ok { + return nil, nil, "" + } + return col, s, joinName +} + +func tableFromJoinName(table string, joinName string) string { + if joinName != "" { + i := strings.LastIndex(joinName, ".") + if i != -1 { + table = joinName[i+1:] + } else { + table = joinName + } + } + return table +} diff --git a/internal/filter/sort.go b/internal/filter/sort.go new file mode 100644 index 00000000..958e32d6 --- /dev/null +++ b/internal/filter/sort.go @@ -0,0 +1,60 @@ +package filter + +import ( + "fmt" + "strings" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" +) + +type Sort struct { + Field string + Order SortOrder +} + +type SortOrder string + +const ( + SortAscending SortOrder = "ASC" + SortDescending SortOrder = "DESC" +) + +func (s *Sort) Scope(settings *Settings, schema *schema.Schema) func(*gorm.DB) *gorm.DB { + field, sch, joinName := getField(s.Field, schema, &settings.Blacklist) + if field == nil { + return nil + } + + computed := field.StructField.Tag.Get("computed") + + return func(tx *gorm.DB) *gorm.DB { + if joinName != "" { + if err := tx.Statement.Parse(tx.Statement.Model); err != nil { + _ = tx.AddError(err) + return tx + } + tx = join(tx, joinName, schema) + } + + table := tableFromJoinName(sch.Table, joinName) + var column clause.Column + if computed != "" { + column = clause.Column{ + Raw: true, + Name: fmt.Sprintf("(%s)", strings.ReplaceAll(computed, clause.CurrentTable, tx.Statement.Quote(table))), + } + } else { + column = clause.Column{ + Table: tableFromJoinName(sch.Table, joinName), + Name: field.DBName, + } + } + c := clause.OrderByColumn{ + Column: column, + Desc: s.Order == SortDescending, + } + return tx.Order(c) + } +} diff --git a/internal/filter/util.go b/internal/filter/util.go new file mode 100644 index 00000000..68b9bcc4 --- /dev/null +++ b/internal/filter/util.go @@ -0,0 +1,246 @@ +package filter + +import ( + "strconv" + "strings" + "time" + + "github.com/openinfradev/tks-api/pkg/log" + "gorm.io/gorm/schema" + "goyave.dev/goyave/v4/util/sliceutil" +) + +type DataType string + +func (d DataType) IsArray() bool { + return strings.HasSuffix(string(d), "[]") +} + +const ( + DataTypeText DataType = "text" + DataTypeTextArray DataType = "text[]" + + DataTypeEnum DataType = "enum" + DataTypeEnumArray DataType = "enum[]" + + DataTypeBool DataType = "bool" + DataTypeBoolArray DataType = "bool[]" + + DataTypeInt8 DataType = "int8" + DataTypeInt8Array DataType = "int8[]" + DataTypeInt16 DataType = "int16" + DataTypeInt16Array DataType = "int16[]" + DataTypeInt32 DataType = "int32" + DataTypeInt32Array DataType = "int32[]" + DataTypeInt64 DataType = "int64" + DataTypeInt64Array DataType = "int64[]" + + DataTypeUint8 DataType = "uint8" + DataTypeUint8Array DataType = "uint8[]" + DataTypeUint16 DataType = "uint16" + DataTypeUint16Array DataType = "uint16[]" + DataTypeUint32 DataType = "uint32" + DataTypeUint32Array DataType = "uint32[]" + DataTypeUint64 DataType = "uint64" + DataTypeUint64Array DataType = "uint64[]" + + DataTypeFloat32 DataType = "float32" + DataTypeFloat32Array DataType = "float32[]" + DataTypeFloat64 DataType = "float64" + DataTypeFloat64Array DataType = "float64[]" + + DataTypeTime DataType = "time" + DataTypeTimeArray DataType = "time[]" + + DataTypeUnsupported DataType = "-" +) + +func cleanColumns(sch *schema.Schema, columns []string, blacklist []string) []*schema.Field { + fields := make([]*schema.Field, 0, len(columns)) + for _, c := range columns { + f, ok := sch.FieldsByDBName[c] + if ok && !sliceutil.ContainsStr(blacklist, c) { + fields = append(fields, f) + } + } + + return fields +} + +func addPrimaryKeys(schema *schema.Schema, fields []string) []string { + for _, k := range schema.PrimaryFieldDBNames { + if !sliceutil.ContainsStr(fields, k) { + fields = append(fields, k) + } + } + return fields +} + +func addForeignKeys(sch *schema.Schema, fields []string) []string { + for _, r := range sch.Relationships.Relations { + if r.Type == schema.HasOne || r.Type == schema.BelongsTo { + for _, ref := range r.References { + if !sliceutil.ContainsStr(fields, ref.ForeignKey.DBName) { + fields = append(fields, ref.ForeignKey.DBName) + } + } + } + } + return fields +} + +func columnsContain(fields []*schema.Field, field *schema.Field) bool { + for _, f := range fields { + if f.DBName == field.DBName { + return true + } + } + return false +} + +func getDataType(field *schema.Field) DataType { + fromTag := DataType(strings.ToLower(field.Tag.Get("filterType"))) + switch fromTag { + case DataTypeText, DataTypeTextArray, + DataTypeEnum, DataTypeEnumArray, + DataTypeBool, DataTypeBoolArray, + DataTypeFloat32, DataTypeFloat32Array, + DataTypeFloat64, DataTypeFloat64Array, + DataTypeInt8, DataTypeInt16, DataTypeInt32, DataTypeInt64, + DataTypeInt8Array, DataTypeInt16Array, DataTypeInt32Array, DataTypeInt64Array, + DataTypeUint8, DataTypeUint16, DataTypeUint32, DataTypeUint64, + DataTypeUint8Array, DataTypeUint16Array, DataTypeUint32Array, DataTypeUint64Array, + DataTypeTime, DataTypeTimeArray, + DataTypeUnsupported: + return fromTag + case "": + switch field.GORMDataType { + case schema.String: + return DataTypeText + case schema.Bool: + return DataTypeBool + case schema.Float: + switch field.Size { + case 32: + return DataTypeFloat32 + case 64: + return DataTypeFloat64 + } + case schema.Int: + switch field.Size { + case 8: + return DataTypeInt8 + case 16: + return DataTypeInt16 + case 32: + return DataTypeInt32 + case 64: + return DataTypeInt64 + } + case schema.Uint: + switch field.Size { + case 8: + return DataTypeUint8 + case 16: + return DataTypeUint16 + case 32: + return DataTypeUint32 + case 64: + return DataTypeUint64 + } + case schema.Time: + return DataTypeTime + } + } + return DataTypeUnsupported +} + +func ConvertToSafeType(arg string, dataType DataType) (interface{}, bool) { + log.Info(arg) + log.Info(dataType) + + switch dataType { + case DataTypeText, DataTypeTextArray, DataTypeEnum, DataTypeEnumArray: + return arg, true + case DataTypeBool, DataTypeBoolArray: + switch arg { + case "1", "on", "true", "yes": + return true, true + case "0", "off", "false", "no": + return false, true + } + return nil, false + case DataTypeFloat32, DataTypeFloat32Array: + return validateFloat(arg, 32) + case DataTypeFloat64, DataTypeFloat64Array: + return validateFloat(arg, 64) + case DataTypeInt8, DataTypeInt8Array: + return validateInt(arg, 8) + case DataTypeInt16, DataTypeInt16Array: + return validateInt(arg, 16) + case DataTypeInt32, DataTypeInt32Array: + return validateInt(arg, 32) + case DataTypeInt64, DataTypeInt64Array: + return validateInt(arg, 64) + case DataTypeUint8, DataTypeUint8Array: + return validateUint(arg, 8) + case DataTypeUint16, DataTypeUint16Array: + return validateUint(arg, 16) + case DataTypeUint32, DataTypeUint32Array: + return validateUint(arg, 32) + case DataTypeUint64, DataTypeUint64Array: + return validateUint(arg, 64) + case DataTypeTime, DataTypeTimeArray: + if validateTime(arg) { + return arg, true + } + } + return nil, false +} + +func validateInt(arg string, bitSize int) (int64, bool) { + i, err := strconv.ParseInt(arg, 10, bitSize) + if err != nil { + return 0, false + } + return i, true +} + +func validateUint(arg string, bitSize int) (uint64, bool) { + i, err := strconv.ParseUint(arg, 10, bitSize) + if err != nil { + return 0, false + } + return i, true +} + +func validateFloat(arg string, bitSize int) (float64, bool) { + i, err := strconv.ParseFloat(arg, bitSize) + if err != nil { + return 0, false + } + return i, true +} + +func validateTime(timeStr string) bool { + for _, format := range []string{time.RFC3339, time.RFC3339Nano, "2006-01-02 15:04:05", "2006-01-02"} { + _, err := time.Parse(format, timeStr) + if err == nil { + return true + } + } + + return false +} + +func ConvertArgsToSafeType(args []string, dataType DataType) ([]interface{}, bool) { + result := make([]interface{}, 0, len(args)) + for _, arg := range args { + a, ok := ConvertToSafeType(arg, dataType) + if !ok { + return nil, false + } + result = append(result, a) + } + return result, true +} diff --git a/internal/filter/validation.go b/internal/filter/validation.go new file mode 100644 index 00000000..90fb385f --- /dev/null +++ b/internal/filter/validation.go @@ -0,0 +1,213 @@ +package filter + +import ( + "fmt" + "strings" + + "goyave.dev/goyave/v4/lang" + "goyave.dev/goyave/v4/validation" +) + +var Separator = "||" + +func init() { + validation.AddRule("filter", &validation.RuleDefinition{ + Function: validateFilter, + }) + validation.AddRule("sort", &validation.RuleDefinition{ + Function: validateSort, + }) + validation.AddRule("join", &validation.RuleDefinition{ + Function: validateJoin, + }) + lang.SetDefaultValidationRule("filter.array", "The filter format is invalid.") + lang.SetDefaultValidationRule("join.array", "The join format is invalid.") + lang.SetDefaultValidationRule("sort.array", "The sort format is invalid.") +} + +func validateFilter(ctx *validation.Context) bool { + if _, ok := ctx.Value.(*Filter); ok { + return true + } + str, ok := ctx.Value.(string) + if !ok { + return false + } + f, err := ParseFilter(str) + if err != nil { + return false + } + if len(ctx.Rule.Params) > 0 && ctx.Rule.Params[0] == "or" { + f.Or = true + } + ctx.Value = f + return true +} + +func validateSort(ctx *validation.Context) bool { + if _, ok := ctx.Value.(*Sort); ok { + return true + } + str, ok := ctx.Value.(string) + if !ok { + return false + } + sort, err := ParseSort(str) + if err != nil { + return false + } + ctx.Value = sort + return true +} + +func validateJoin(ctx *validation.Context) bool { + if _, ok := ctx.Value.(*Join); ok { + return true + } + str, ok := ctx.Value.(string) + if !ok { + return false + } + join, err := ParseJoin(str) + if err != nil { + return false + } + ctx.Value = join + return true +} + +func ApplyValidation(set validation.RuleSet) { + set["filter"] = validation.List{"array"} + set["filter[]"] = validation.List{"filter"} + set["or"] = validation.List{"array"} + set["or[]"] = validation.List{"filter:or"} + set["sort"] = validation.List{"array"} + set["sort[]"] = validation.List{"sort"} + set["join"] = validation.List{"array"} + set["join[]"] = validation.List{"join"} + set["fields"] = validation.List{"string"} + set["page"] = validation.List{"integer", "min:1"} + set["per_page"] = validation.List{"integer", "between:1,500"} + set["search"] = validation.List{"string"} +} + +func ApplyValidationRules(set *validation.Rules) { + set.Fields["filter"] = &validation.Field{Rules: []*validation.Rule{{Name: "array"}}} + set.Fields["filter[]"] = &validation.Field{Rules: []*validation.Rule{{Name: "filter"}}} + set.Fields["or"] = &validation.Field{Rules: []*validation.Rule{{Name: "array"}}} + set.Fields["or[]"] = &validation.Field{Rules: []*validation.Rule{{Name: "filter", Params: []string{"or"}}}} + set.Fields["sort"] = &validation.Field{Rules: []*validation.Rule{{Name: "array"}}} + set.Fields["sort[]"] = &validation.Field{Rules: []*validation.Rule{{Name: "sort"}}} + set.Fields["join"] = &validation.Field{Rules: []*validation.Rule{{Name: "array"}}} + set.Fields["join[]"] = &validation.Field{Rules: []*validation.Rule{{Name: "join"}}} + set.Fields["fields"] = &validation.Field{Rules: []*validation.Rule{{Name: "string"}}} + set.Fields["page"] = &validation.Field{Rules: []*validation.Rule{{Name: "integer"}, {Name: "min", Params: []string{"1"}}}} + set.Fields["per_page"] = &validation.Field{Rules: []*validation.Rule{{Name: "integer"}, {Name: "between", Params: []string{"1", "500"}}}} + set.Fields["search"] = &validation.Field{Rules: []*validation.Rule{{Name: "string"}}} +} + +func ParseFilter(filter string) (*Filter, error) { + res := &Filter{} + f := filter + op := "" + + index := strings.Index(f, Separator) + if index == -1 { + return nil, fmt.Errorf("Missing operator") + } + res.Field = strings.TrimSpace(f[:index]) + if res.Field == "" { + return nil, fmt.Errorf("Invalid filter syntax") + } + f = f[index+2:] + + index = strings.Index(f, Separator) + if index == -1 { + index = len(f) + } + op = strings.TrimSpace(f[:index]) + operator, ok := Operators[op] + if !ok { + return nil, fmt.Errorf("Unknown operator: %q", f[:index]) + } + res.Operator = operator + + if index < len(f) { + f = f[index+2:] + for paramIndex := strings.Index(f, ","); paramIndex < len(f); paramIndex = strings.Index(f, ",") { + if paramIndex == -1 { + paramIndex = len(f) + } + p := strings.TrimSpace(f[:paramIndex]) + if p == "" { + return nil, fmt.Errorf("Invalid filter syntax") + } + res.Args = append(res.Args, p) + if paramIndex+1 >= len(f) { + break + } + f = f[paramIndex+1:] + } + } + + if len(res.Args) < int(res.Operator.RequiredArguments) { + return nil, fmt.Errorf("Operator %q requires at least %d argument(s)", op, res.Operator.RequiredArguments) + } + + return res, nil +} + +func ParseSort(sort string) (*Sort, error) { + commaIndex := strings.Index(sort, ",") + if commaIndex == -1 { + return nil, fmt.Errorf("Invalid sort syntax") + } + + fieldName := strings.TrimSpace(sort[:commaIndex]) + order := strings.TrimSpace(strings.ToUpper(sort[commaIndex+1:])) + if fieldName == "" || order == "" { + return nil, fmt.Errorf("Invalid sort syntax") + } + + if order != string(SortAscending) && order != string(SortDescending) { + return nil, fmt.Errorf("Invalid sort order %q", order) + } + + s := &Sort{ + Field: fieldName, + Order: SortOrder(order), + } + return s, nil +} + +func ParseJoin(join string) (*Join, error) { + separatorIndex := strings.Index(join, Separator) + if separatorIndex == -1 { + separatorIndex = len(join) + } + + relation := strings.TrimSpace(join[:separatorIndex]) + if relation == "" { + return nil, fmt.Errorf("Invalid join syntax") + } + + var fields []string + if separatorIndex+2 < len(join) { + fields = strings.Split(join[separatorIndex+2:], ",") + for i, f := range fields { + f = strings.TrimSpace(f) + if f == "" { + return nil, fmt.Errorf("Invalid join syntax") + } + fields[i] = f + } + } else { + fields = nil + } + + j := &Join{ + Relation: relation, + Fields: fields, + } + return j, nil +} diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 287da518..73b58c9f 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -6,29 +6,45 @@ import ( "strconv" "strings" + filter "github.com/openinfradev/tks-api/internal/filter" "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" + "gorm.io/gorm" + + "goyave.dev/goyave/v4" + "goyave.dev/goyave/v4/database" ) const SORT_COLUMN = "sortColumn" const SORT_ORDER = "sortOrder" const PAGE_NUMBER = "pageNumber" const PAGE_SIZE = "pageSize" +const FILTER = "filter" const COMBINED_FILTER = "combinedFilter" +var DEFAULT_LIMIT = 10 + type Pagination struct { Limit int Page int SortColumn string SortOrder string Filters []Filter - CombinedFilter CombinedFilter + CombinedFilter CombinedFilter // deprecated TotalRows int64 TotalPages int + + PaginationRequest *goyave.Request + Paginator *database.Paginator } type Filter struct { - Column string - Values []string + Relation string + Column string + Operator string + Values []string } type CombinedFilter struct { @@ -36,9 +52,6 @@ type CombinedFilter struct { Value string } -var DEFAULT_LIMIT = 10 -var MAX_LIMIT = 1000 - func (p *Pagination) GetOffset() int { return (p.GetPage() - 1) * p.GetLimit() } @@ -69,33 +82,91 @@ func (p *Pagination) GetFilters() []Filter { return p.Filters } +func (p *Pagination) MakePaginationRequest() { + if p.PaginationRequest == nil { + p.PaginationRequest = &goyave.Request{} + } + + pgFilters := make([]*filter.Filter, 0) + pgSorts := make([]*filter.Sort, 0) + + for _, f := range p.Filters { + field := f.Column + if f.Relation != "" { + field = f.Relation + "." + f.Column + } + + pgFilter := filter.Filter{ + Field: field, + Operator: convertOperator(f.Operator), + Args: f.Values, + Or: false, + } + + pgFilters = append(pgFilters, &pgFilter) + } + + pgSort := filter.Sort{ + Field: p.SortColumn, + Order: filter.SortOrder(p.SortOrder), + } + pgSorts = append(pgSorts, &pgSort) + + p.PaginationRequest.Data = map[string]interface{}{ + "filter": pgFilters, + //"join": pgJoins, + "page": p.Page, + "per_page": p.Limit, + "sort": pgSorts, + } +} + +func (p *Pagination) Fetch(db *gorm.DB, dest interface{}) (*database.Paginator, *gorm.DB) { + paginator, db := filter.Scope(db, p.PaginationRequest, dest) + + p.Paginator = paginator + + p.Page = paginator.CurrentPage + p.TotalPages = int(paginator.MaxPage) + p.TotalRows = paginator.Total + p.Limit = int(paginator.PageSize) + + return paginator, db +} + +func (p *Pagination) Response() (out domain.PaginationResponse, err error) { + if err := serializer.Map(*p, &out); err != nil { + return out, err + } + out.Filters = make([]domain.FilterResponse, len(p.Filters)) + for i, f := range p.Filters { + if err := serializer.Map(f, &out.Filters[i]); err != nil { + continue + } + } + + return out, err +} + func NewPagination(urlParams *url.Values) (*Pagination, error) { pg := NewDefaultPagination() for key, value := range *urlParams { switch key { case SORT_COLUMN: - if value[0] == "" { - pg.SortColumn = "created_at" - } else { + if value[0] != "" { pg.SortColumn = value[0] } case SORT_ORDER: - if value[0] == "" { - pg.SortOrder = "DESC" - } else { + if value[0] != "" { pg.SortOrder = value[0] } case PAGE_NUMBER: - if value[0] == "" { - pg.Page = 1 - } else { + if value[0] != "" { pg.Page, _ = strconv.Atoi(value[0]) } case PAGE_SIZE: if value[0] == "" { - pg.Page = DEFAULT_LIMIT - } else { if limitNum, err := strconv.Atoi(value[0]); err == nil { pg.Limit = limitNum } @@ -116,14 +187,39 @@ func NewPagination(urlParams *url.Values) (*Pagination, error) { return nil, fmt.Errorf("Invalid query string : combinedFilter ") } } - default: - pg.Filters = append(pg.Filters, Filter{ - Column: helper.ToSnakeCase(strings.Replace(key, "[]", "", -1)), - Values: value, - }) + case FILTER: + for _, filterValue := range value { + log.Debug("filterValue : ", filterValue) + arr := strings.Split(filterValue, "|") + + column := arr[0] + releation := "" + arrColumns := strings.Split(column, ".") + if len(arrColumns) > 1 { + releation = arrColumns[0] + column = arrColumns[1] + } + + trimmedStr := strings.Trim(arr[1], "[]") + values := strings.Split(trimmedStr, ",") + + op := "$cont" + if len(arr) == 3 { + op = arr[2] + } + + pg.Filters = append(pg.Filters, Filter{ + Column: helper.ToSnakeCase(strings.Replace(column, "[]", "", -1)), + Relation: releation, + Operator: op, + Values: values, + }) + } } } + pg.MakePaginationRequest() + return pg, nil } @@ -132,6 +228,13 @@ func NewDefaultPagination() *Pagination { SortColumn: "created_at", SortOrder: "DESC", Page: 1, - Limit: MAX_LIMIT, + Limit: DEFAULT_LIMIT, + } +} + +func convertOperator(op string) *filter.Operator { + if _, ok := filter.Operators[op]; ok { + return filter.Operators[op] } + return filter.Operators["$cont"] } diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 7f8da72c..dd7be17f 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -1,14 +1,12 @@ package repository import ( - "fmt" - "math" - "github.com/google/uuid" "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -76,17 +74,30 @@ func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out domain.Sta // [TODO] organizationId 별로 생성하지 않고, 하나의 stackTemplate 을 모든 organization 에서 재사용한다. ( 5월 한정, 추후 rearchitecture 필요) func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain.StackTemplate, err error) { var stackTemplates []StackTemplate + if pg == nil { pg = pagination.NewDefaultPagination() } - filterFunc := CombinedGormFilter("stack_templates", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&StackTemplate{})) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order("kube_type DESC,template_type ASC").Order(orderQuery).Find(&stackTemplates) + /* + filterFunc := CombinedGormFilter("stack_templates", pg.GetFilters(), pg.CombinedFilter) + db := filterFunc(r.db.Model(&StackTemplate{})) + db.Count(&pg.TotalRows) + + pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) + orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) + res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order("kube_type DESC,template_type ASC").Order(orderQuery).Find(&stackTemplates) + if res.Error != nil { + return nil, res.Error + } + + for _, stackTemplate := range stackTemplates { + out = append(out, reflectStackTemplate(stackTemplate)) + } + */ + + // paginator, res := filter.Scope(r.db.Order("kube_type DESC,template_type ASC"), pg.GetPaginationRequest(), &stackTemplates) + paginator, res := pg.Fetch(r.db, &stackTemplates) if res.Error != nil { return nil, res.Error } @@ -94,6 +105,10 @@ func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain for _, stackTemplate := range stackTemplates { out = append(out, reflectStackTemplate(stackTemplate)) } + + log.Info(helper.ModelToJson(paginator.Total)) + //log.Info(helper.ModelToJson(stackTemplates)) + return } diff --git a/pkg/domain/pagination.go b/pkg/domain/pagination.go index 33efaef7..21f9c1ba 100644 --- a/pkg/domain/pagination.go +++ b/pkg/domain/pagination.go @@ -11,6 +11,8 @@ type PaginationResponse struct { } type FilterResponse struct { - Column string `json:"column"` - Values []string `json:"values"` + Column string `json:"column"` + Values []string `json:"values"` + Operator string `json:"operator"` + Relation string `json:"releation"` } diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index 17e33296..6797c355 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -36,6 +36,14 @@ values ( '92f5e5ce-7ffd-4c3e-aff6-9b7fb03dd881', 'master', 'BYOH MSA Standard', insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) values ( '2526ec49-28a2-4be9-8d18-2c39fc0993fd', 'master', 'BYOH Admin Standard (BTV)', 'included LMA', 'v1', 'BYOH', 'x86', 'tks-admin', 'STANDARD', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( 'a76b5c97-7d55-46d8-9248-9952bfaff62c', 'master', 'BYOH Standard (BTV SSU)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-ssu-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); +values ( 'a76b5c97-7d55-46d8-9248-9952bfaff62c', 'master', 'BYOH MSA Standard (BTV SSU)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-ssu-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( 'b5bbd6ea-5bf3-4d88-bb06-4a4c64c73c15', 'master', 'BYOH Standard (BTV SUY)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-suy-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); +values ( 'b5bbd6ea-5bf3-4d88-bb06-4a4c64c73c15', 'master', 'BYOH MSA Standard (BTV SUY)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-suy-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); + +# PSNM +insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( 'c3396c68-03ec-4d41-991c-69e4a2ac16aa', 'master', 'psnm-backend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-backend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); +insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '23b07a65-1cb3-4609-9bba-e88c15e2e192', 'master', 'psnm-frontend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-frontend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); + + From 9ddd8ba94e5bb5503199413dc890567ab8ab7dc6 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Jan 2024 11:24:27 +0900 Subject: [PATCH 012/502] trivial. update golangci-lint version --- .github/workflows/lint.yml | 38 ++++------ go.mod | 11 +-- go.sum | 144 ++----------------------------------- 3 files changed, 21 insertions(+), 172 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c9514afe..4545b2b5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,27 +17,19 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: golangci-lint - uses: golangci/golangci-lint-action@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: - # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.51.0 - args: --timeout=10m - # Optional: working directory, useful for monorepos - # working-directory: somedir - - # Optional: golangci-lint command line arguments. - # args: --issues-exit-code=0 - - # Optional: show only new issues if it's a pull request. The default value is `false`. - # only-new-issues: true - - # Optional: if set to true then the action will use pre-installed Go. - # skip-go-installation: true - - # Optional: if set to true then the action don't cache or restore ~/go/pkg. - # skip-pkg-cache: true - - # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. - # skip-build-cache: true + go-version: "1.18" + cache: false + - name: Install golangci-lint + # Install golangci-lint from source instead of using + # golangci-lint-action to ensure the golangci-lint binary is built with + # the same Go version we're targeting. + # Avoids incompatibility issues such as: + # - https://github.com/golangci/golangci-lint/issues/2922 + # - https://github.com/golangci/golangci-lint/issues/2673 + # - https://github.com/golangci/golangci-lint-action/issues/442 + run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0 + - name: Run golangci-lint + run: golangci-lint run --version --verbose --out-format=github-actions diff --git a/go.mod b/go.mod index 8e79f74d..d9b1afe1 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,7 @@ require ( gorm.io/datatypes v1.1.1 gorm.io/driver/postgres v1.5.0 gorm.io/gorm v1.25.1 + goyave.dev/goyave/v4 v4.4.11 k8s.io/apimachinery v0.25.4 k8s.io/client-go v0.25.2 k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed @@ -82,21 +83,15 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.15 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.13.0 // indirect - github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.1 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgtype v1.12.0 // indirect - github.com/jackc/pgx/v4 v4.17.2 // indirect + github.com/jackc/pgx/v5 v5.3.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.3 // indirect - github.com/lib/pq v1.10.4 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -131,8 +126,6 @@ require ( gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.5.0 // indirect - goyave.dev/filter v0.6.0 // indirect - goyave.dev/goyave/v4 v4.4.11 // indirect k8s.io/api v0.25.4 // indirect k8s.io/apiextensions-apiserver v0.23.5 // indirect k8s.io/component-base v0.25.2 // indirect diff --git a/go.sum b/go.sum index 372a677f..f9e03911 100644 --- a/go.sum +++ b/go.sum @@ -55,8 +55,6 @@ github.com/Code-Hex/uniseg v0.2.0 h1:QB/2UJFvEuRLSZqe+Sb1XQBTWjqGVbZoC6oSWzQRKws github.com/Code-Hex/uniseg v0.2.0/go.mod h1:/ndS2tP+X1lk2HUOcXWGtVTxVq0lWilwgMa4CbzdRsg= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/Nerzal/gocloak/v13 v13.1.0 h1:ret4pZTIsSQGZHURDMJ4jXnUmHyEoRykBqDTsAKoj8c= @@ -146,8 +144,6 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= @@ -156,11 +152,9 @@ github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -238,15 +232,12 @@ github.com/go-playground/validator/v10 v10.13.0 h1:cFRQdfaSMCOSfGCCLB20MHvuoHb/s github.com/go-playground/validator/v10 v10.13.0/go.mod h1:dwu7+CG8/CtBiJFZDz4e+5Upb6OLw04gtBYw0mcG/z4= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/flect v0.2.4 h1:BSYA8+T60cdyq+vynaSUjqSVI9mDEg9ZfQUXKmfjo4I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -347,8 +338,8 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -381,68 +372,20 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= -github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= -github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= -github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= -github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= +github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -469,7 +412,6 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -479,18 +421,11 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA= github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= -github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= @@ -500,18 +435,12 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= github.com/microsoft/go-mssqldb v0.21.0 h1:p2rpHIL7TlSv1QrbXJUAcbyRKnIT0C9rRkH2E4OjLn8= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -540,7 +469,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -611,21 +539,13 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -661,7 +581,6 @@ github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiu github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -698,7 +617,6 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -727,47 +645,32 @@ go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -825,7 +728,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -856,13 +758,10 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -902,9 +801,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -912,7 +809,6 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -922,7 +818,6 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -969,17 +864,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -992,8 +882,6 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1013,7 +901,6 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -1021,11 +908,8 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1035,7 +919,6 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1071,8 +954,6 @@ golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpd golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1199,7 +1080,6 @@ gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -1207,7 +1087,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1232,36 +1111,21 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/datatypes v1.1.1 h1:XAjO7NNfUKVUvnS3+BkqMrPXxCAcxDlpOYbjnizxNCw= gorm.io/datatypes v1.1.1/go.mod h1:u8GEgFjJ+GpsGfgHmBUcQqHm/937t3sj/SO9dvbndTg= -gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y= -gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc= gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM= gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo= -gorm.io/driver/postgres v1.4.5 h1:mTeXTTtHAgnS9PgmhN2YeUbazYpLhUI1doLnw42XUZc= -gorm.io/driver/postgres v1.4.5/go.mod h1:GKNQYSJ14qvWkvPwXljMGehpKrhlDNsqYRr5HnYGncg= gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= -gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU= gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= -gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= gorm.io/driver/sqlserver v1.4.3 h1:ji91Zb/zS7NWrMRJBfoM9C0gyxCSh9anQoJApqEkiV8= -gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.24.1-0.20221019064659-5dd2bb482755/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU= -gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64= gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -goyave.dev/filter v0.6.0 h1:uAOHbV9rnylDyJmjBy8qsBoRRD9rZt0TEe8YrwYWOts= -goyave.dev/filter v0.6.0/go.mod h1:IKw7y3F8SFq3ZRzq/V31UboQfDYbSTzqBrQZTqIwJro= -goyave.dev/goyave/v4 v4.4.5 h1:pqNQTMMx4XImjpDZ890Yz4nTW0t5o3zpmdPfmXuXSF4= -goyave.dev/goyave/v4 v4.4.5/go.mod h1:lZCUx5ln6k+CWNop2vLU9295LNaOm7FUqpJbk6hqGVU= goyave.dev/goyave/v4 v4.4.11 h1:HdJJ82ZWrkB7sBsituVRgQhcDvmAavfVbd6xynaUN8Y= goyave.dev/goyave/v4 v4.4.11/go.mod h1:kMbB3bf7ZhUD4Cq1Zy6nM4fHBHYO5mPSkTF6WStf4ik= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 40df6c4423c5b73f6cba36442aa5d412d7dd2a69 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Jan 2024 15:55:58 +0900 Subject: [PATCH 013/502] swagger automation --- Dockerfile | 5 +- api/swagger/docs.go | 6874 -------------------------------------- api/swagger/swagger.json | 6851 ------------------------------------- api/swagger/swagger.yaml | 4453 ------------------------ go.work | 5 - go.work.sum | 503 --- 6 files changed, 4 insertions(+), 18687 deletions(-) delete mode 100644 api/swagger/docs.go delete mode 100644 api/swagger/swagger.json delete mode 100644 api/swagger/swagger.yaml delete mode 100644 go.work delete mode 100644 go.work.sum diff --git a/Dockerfile b/Dockerfile index f1d1e192..68d504c1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,13 @@ # Build - backend FROM --platform=linux/amd64 docker.io/library/golang:1.18-buster AS backend-build RUN DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata -RUN wget https://github.com/swaggo/swag/releases/download/v1.7.1/swag_linux_amd64.tar.gz -O - | tar -xz -C /tmp && cp /tmp/swag_linux_amd64/swag /usr/local/bin +RUN wget https://github.com/swaggo/swag/releases/download/v1.8.5/swag_1.8.5_Linux_x86_64.tar.gz -O - | tar -xz -C /tmp && cp /tmp/swag /usr/local/bin WORKDIR /app/backend COPY ./ . + +RUN swag init -g ./cmd/server/main.go -o ./api/swagger + RUN go mod tidy RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/server ./cmd/server/main.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go deleted file mode 100644 index 3b595793..00000000 --- a/api/swagger/docs.go +++ /dev/null @@ -1,6874 +0,0 @@ -// Package swagger GENERATED BY SWAG; DO NOT EDIT -// This file was generated by swaggo/swag -package swagger - -import "github.com/swaggo/swag" - -const docTemplate = `{ - "schemes": {{ marshal .Schemes }}, - "swagger": "2.0", - "info": { - "description": "{{escape .Description}}", - "title": "{{.Title}}", - "contact": { - "name": "taekyu.kang@sk.com", - "email": "taekyu.kang@sk.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "{{.Version}}" - }, - "host": "{{.Host}}", - "basePath": "{{.BasePath}}", - "paths": { - "/app-groups": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appGroup list by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Get appGroup list", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppGroupsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Install appGroup", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Install appGroup", - "parameters": [ - { - "description": "create appgroup request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateAppGroupRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateAppGroupResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Uninstall appGroup", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Uninstall appGroup", - "parameters": [ - { - "description": "body", - "name": "object", - "in": "body", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/app-groups/{appGroupId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appGroup detail by appGroupId", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Get appGroup detail", - "parameters": [ - { - "type": "string", - "description": "appGroupId", - "name": "appGroupId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppGroupResponse" - } - } - } - } - }, - "/app-groups/{appGroupId}/applications": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get applications", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Get applications", - "parameters": [ - { - "type": "string", - "description": "appGroupId", - "name": "appGroupId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "applicationType", - "name": "applicationType", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetApplicationsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create application", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Create application", - "parameters": [ - { - "description": "body", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateApplicationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/find-id/code": { - "post": { - "description": "This API allows users to verify their identity for lost id by submitting required information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "Request to verify identity for lost id", - "parameters": [ - { - "description": "Request body for verifying identity for lost id including {organization ID, email, username}", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostIdRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostIdResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/auth/find-id/verification": { - "post": { - "description": "This API allows users to find their account ID by submitting required information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "Request to find forgotten ID", - "parameters": [ - { - "description": "Request body for finding the account ID including {organization ID, email, username, 6 digit code}", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.FindIdRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.FindIdResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/auth/find-password/code": { - "post": { - "description": "This API allows users to verify their identity for lost password by submitting required information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "Request to verify identity for lost password", - "parameters": [ - { - "description": "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/auth/find-password/verification": { - "post": { - "description": "This API allows users to reset their forgotten password by submitting required information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "Request to find forgotten password", - "parameters": [ - { - "description": "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.FindPasswordRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/auth/login": { - "post": { - "description": "login", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "login", - "parameters": [ - { - "description": "account info", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.LoginRequest" - } - } - ], - "responses": { - "200": { - "description": "user detail", - "schema": { - "$ref": "#/definitions/domain.LoginResponse" - } - } - } - } - }, - "/auth/logout": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "logout", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "logout", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.LogoutResponse" - } - } - } - } - }, - "/auth/ping": { - "post": { - "description": "ping with token", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "ping with token", - "parameters": [ - { - "description": "token info", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.PingTokenRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/clusters": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get cluster list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get clusters", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetClustersResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Create cluster", - "parameters": [ - { - "description": "create cluster request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateClusterRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateClusterResponse" - } - } - } - } - }, - "/clusters/import": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Import cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Import cluster", - "parameters": [ - { - "description": "import cluster request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.ImportClusterRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.ImportClusterResponse" - } - } - } - } - }, - "/clusters/{clusterId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get cluster detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get cluster", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.Cluster" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Delete cluster", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.Cluster" - } - } - } - } - }, - "/clusters/{clusterId}/bootstrap-kubeconfig": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get bootstrap kubeconfig for BYOH", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get bootstrap kubeconfig for BYOH", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetBootstrapKubeconfigResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create bootstrap kubeconfig for BYOH", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Create bootstrap kubeconfig for BYOH", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateBootstrapKubeconfigResponse" - } - } - } - } - }, - "/clusters/{clusterId}/install": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Install cluster on tks cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Install cluster on tks cluster", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/clusters/{clusterId}/nodes": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get nodes information for BYOH", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get nodes information for BYOH", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetClusterNodesResponse" - } - } - } - } - }, - "/clusters/{clusterId}/site-values": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get cluster site values for creating", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get cluster site values for creating", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.ClusterSiteValuesResponse" - } - } - } - } - }, - "/organizations": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get organization list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Get organization list", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ListOrganizationBody" - } - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create organization", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Create organization", - "parameters": [ - { - "description": "create organization request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateOrganizationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object" - } - } - } - } - }, - "/organizations/{organizationId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get organization detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Get organization detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetOrganizationResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update organization detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Update organization detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "update organization request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateOrganizationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.UpdateOrganizationResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete organization", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Delete organization", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.Organization" - } - } - } - } - }, - "/organizations/{organizationId}/alerts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Alerts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Get Alerts", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAlertsResponse" - } - } - } - } - }, - "/organizations/{organizationId}/alerts/{alertId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Get Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "alertId", - "name": "alertId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAlertResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Update Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAlertRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Delete Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "alertId", - "name": "alertId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/alerts/{alertId}/actions": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create alert action", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Create alert action", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp list by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp list", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "boolean", - "description": "Show all apps including deleted apps", - "name": "showAll", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AppServeApp" - } - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Install appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Install appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Request body to create app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/count": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get number of apps on given stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get number of apps on given stack", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "integer" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check duplicate appServeAppName by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Check duplicate appServeAppName", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppServeAppResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Uninstall appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Uninstall appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/endpoint": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update app endpoint", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update app endpoint", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "appId", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app endpoint", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/exist": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/latest-task": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get latest task from appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get latest task from appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/rollback": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Rollback appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Rollback appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to rollback app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.RollbackAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/status": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update app status", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update app status", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app status", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get CloudAccounts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Get CloudAccounts", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetCloudAccountsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Create CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateCloudAccountRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateCloudAccountResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check awsAccountId for cloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Check awsAccountId for cloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "awsAccountId", - "name": "awsAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CheckCloudAccountAwsAccountIdResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check name for cloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Check name for cloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CheckCloudAccountNameResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Get CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "cloudAccountId", - "name": "cloudAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetCloudAccountResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Update CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateCloudAccountRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Delete CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Delete cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.DeleteCloudAccountRequest" - } - }, - { - "type": "string", - "description": "cloudAccountId", - "name": "cloudAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Force CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Delete Force CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "cloudAccountId", - "name": "cloudAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get resource quota by cloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Get resource quota by cloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "cloudAccountId", - "name": "cloudAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetCloudAccountResourceQuotaResponse" - } - } - } - } - }, - "/organizations/{organizationId}/dashboard/charts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get charts data", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get charts data", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "chartType", - "name": "chartType", - "in": "query" - }, - { - "type": "string", - "description": "duration", - "name": "duration", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetDashboardChartsResponse" - } - } - } - } - }, - "/organizations/{organizationId}/dashboard/charts/{chartType}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get chart data", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get chart data", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "chartType", - "name": "chartType", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "duration", - "name": "duration", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetDashboardChartResponse" - } - } - } - } - }, - "/organizations/{organizationId}/dashboard/resources": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get resources", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get resources", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetDashboardResourcesResponse" - } - } - } - } - }, - "/organizations/{organizationId}/dashboard/stacks": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get stacks", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get stacks", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetDashboardStacksResponse" - } - } - } - } - }, - "/organizations/{organizationId}/my-profile": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get my profile detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Get my profile detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetMyProfileResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update my profile detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Update my profile detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Required fields: password due to double-check", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateMyProfileRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.UpdateMyProfileResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete myProfile", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Delete myProfile", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/organizations/{organizationId}/my-profile/next-password-change": { - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update user's password expired date to current date", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Update user's password expired date to current date", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/organizations/{organizationId}/my-profile/password": { - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update user password detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Update user password detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "update user password request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdatePasswordRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/primary-cluster": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update primary cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Update primary cluster", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "update primary cluster request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdatePrimaryClusterRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/stacks": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Stacks", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Get Stacks", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStacksResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Create Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateStackRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateStackResponse" - } - } - } - } - }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check name for stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Check name for stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/stacks/{stackId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Get Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Update Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateStackRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Delete Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/favorite": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Set favorite stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Set favorite stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete favorite stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Delete favorite stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/kube-config": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get KubeConfig by stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Get KubeConfig by stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "organizationId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackKubeConfigResponse" - } - } - } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Stack Status", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Get Stack Status", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackStatusResponse" - } - } - } - } - }, - "/organizations/{organizationId}/users": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get user list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Get user list", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ListUserBody" - } - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Create user", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create user request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateUserRequest" - } - } - ], - "responses": { - "200": { - "description": "create user response", - "schema": { - "$ref": "#/definitions/domain.CreateUserResponse" - } - } - } - } - }, - "/organizations/{organizationId}/users/account-id/{accountId}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "return true when accountId exists", - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Get user id existence", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" - } - } - } - } - }, - "/organizations/{organizationId}/users/email/{email}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "return true when email exists", - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Get user email existence", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "email", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" - } - } - } - } - }, - "/organizations/{organizationId}/users/{accountId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get user detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Get user detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetUserResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Update user", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - }, - { - "description": "input", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateUserRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.UpdateUserResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Delete user", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.User" - } - } - } - } - }, - "/organizations/{organizationId}/users/{accountId}/reset-password": { - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Reset user's password as temporary password by admin and send email to user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Reset user's password as temporary password by admin", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/stack-templates": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get StackTemplates", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplates", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackTemplatesResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "description": "create stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateStackTemplateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateStackTemplateResponse" - } - } - } - } - }, - "/stack-templates/{stackTemplateId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplate", - "parameters": [ - { - "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackTemplateResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "description": "Update stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateStackTemplateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/system-api/organizations/{organizationId}/alerts": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create alert. ADMIN ONLY", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Create alert. ADMIN ONLY", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - } - }, - "definitions": { - "domain.ActionResponse": { - "type": "object", - "properties": { - "body": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "method": { - "type": "string" - }, - "name": { - "description": "ENDPOINT (화면보기), PREVIEW (미리보기), PROMOTE (배포), ABORT (중단)", - "type": "string" - }, - "type": { - "description": "LINK, API", - "type": "string" - }, - "uri": { - "type": "string" - } - } - }, - "domain.AlertActionResponse": { - "type": "object", - "properties": { - "alertId": { - "type": "string" - }, - "content": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "taker": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.AlertResponse": { - "type": "object", - "properties": { - "alertActions": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AlertActionResponse" - } - }, - "closedAt": { - "type": "string" - }, - "cluster": { - "$ref": "#/definitions/domain.SimpleClusterResponse" - }, - "code": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "firedAt": { - "type": "string" - }, - "grade": { - "type": "string" - }, - "grafanaUrl": { - "type": "string" - }, - "id": { - "type": "string" - }, - "lastTaker": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "node": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "processingSec": { - "type": "integer" - }, - "rawData": { - "type": "string" - }, - "status": { - "type": "string" - }, - "takedAt": { - "type": "string" - }, - "takedSec": { - "type": "integer" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.AppGroupResponse": { - "type": "object", - "properties": { - "appGroupType": { - "type": "integer" - }, - "clusterId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "workflowId": { - "type": "string" - } - } - }, - "domain.AppServeApp": { - "type": "object", - "properties": { - "appServeAppTasks": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AppServeAppTask" - } - }, - "appType": { - "description": "appType (spring/springboot)", - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "endpointUrl": { - "description": "endpoint URL of deployed app", - "type": "string" - }, - "grafanaUrl": { - "description": "grafana dashboard URL for deployed app", - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "description": "application name", - "type": "string" - }, - "namespace": { - "description": "application namespace", - "type": "string" - }, - "organizationId": { - "description": "contractId is a contract ID which this app belongs to", - "type": "string" - }, - "previewEndpointUrl": { - "description": "preview svc endpoint URL in B/G deployment", - "type": "string" - }, - "status": { - "description": "status is status of deployed app", - "type": "string" - }, - "targetClusterId": { - "description": "target cluster to which the app is deployed", - "type": "string" - }, - "targetClusterName": { - "description": "target cluster name", - "type": "string" - }, - "type": { - "description": "type (build/deploy/all)", - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.AppServeAppTask": { - "type": "object", - "properties": { - "appConfig": { - "description": "java app config", - "type": "string" - }, - "appSecret": { - "description": "java app secret", - "type": "string" - }, - "appServeAppId": { - "description": "ID for appServeApp that this task belongs to", - "type": "string" - }, - "artifactUrl": { - "description": "URL of java app artifact (Eg, Jar)", - "type": "string" - }, - "availableRollback": { - "type": "boolean" - }, - "createdAt": { - "description": "createdAt is a creation timestamp for the application", - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "executablePath": { - "description": "Executable path of app image", - "type": "string" - }, - "extraEnv": { - "description": "env variable list for java app", - "type": "string" - }, - "helmRevision": { - "description": "revision of deployed helm release", - "type": "integer" - }, - "id": { - "type": "string" - }, - "imageUrl": { - "description": "URL of built image for app", - "type": "string" - }, - "output": { - "description": "output for task result", - "type": "string" - }, - "port": { - "description": "java app port", - "type": "string" - }, - "profile": { - "description": "java app profile", - "type": "string" - }, - "pvAccessMode": { - "type": "string" - }, - "pvEnabled": { - "type": "boolean" - }, - "pvMountPath": { - "type": "string" - }, - "pvSize": { - "type": "string" - }, - "pvStorageClass": { - "type": "string" - }, - "resourceSpec": { - "description": "resource spec of app pod", - "type": "string" - }, - "rollbackVersion": { - "description": "rollback target version", - "type": "string" - }, - "status": { - "description": "status is app status", - "type": "string" - }, - "strategy": { - "description": "deployment strategy (eg, rolling-update)", - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "description": "application version", - "type": "string" - } - } - }, - "domain.ApplicationResponse": { - "type": "object", - "properties": { - "appGroupId": { - "type": "string" - }, - "applicationType": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "endpoint": { - "type": "string" - }, - "id": { - "type": "string" - }, - "metadata": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.Axis": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "domain.BootstrapKubeconfig": { - "type": "object", - "properties": { - "expiration": { - "type": "integer" - } - } - }, - "domain.ChartData": { - "type": "object", - "properties": { - "podCounts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.PodCount" - } - }, - "series": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.Unit" - } - }, - "xAxis": { - "$ref": "#/definitions/domain.Axis" - }, - "yAxis": { - "$ref": "#/definitions/domain.Axis" - } - } - }, - "domain.CheckCloudAccountAwsAccountIdResponse": { - "type": "object", - "properties": { - "existed": { - "type": "boolean" - } - } - }, - "domain.CheckCloudAccountNameResponse": { - "type": "object", - "properties": { - "existed": { - "type": "boolean" - } - } - }, - "domain.CheckExistedResponse": { - "type": "object", - "properties": { - "existed": { - "type": "boolean" - } - } - }, - "domain.CloudAccount": { - "type": "object", - "properties": { - "accessKeyId": { - "type": "string" - }, - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusters": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "createdIAM": { - "type": "boolean" - }, - "creator": { - "$ref": "#/definitions/domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "secretAccessKey": { - "type": "string" - }, - "sessionToken": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, - "domain.CloudAccountResponse": { - "type": "object", - "properties": { - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusters": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "createdIAM": { - "type": "boolean" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - } - } - }, - "domain.Cluster": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccount": { - "$ref": "#/definitions/domain.CloudAccount" - }, - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "integer" - }, - "conf": { - "$ref": "#/definitions/domain.ClusterConf" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "favorited": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "isStack": { - "type": "boolean" - }, - "kubeconfig": { - "type": "array", - "items": { - "type": "integer" - } - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplate": { - "$ref": "#/definitions/domain.StackTemplate" - }, - "stackTemplateId": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, - "domain.ClusterConf": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.ClusterConfResponse": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.ClusterHost": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "domain.ClusterNode": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "hosts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ClusterHost" - } - }, - "registered": { - "type": "integer" - }, - "registering": { - "type": "integer" - }, - "status": { - "type": "string" - }, - "targeted": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "validity": { - "type": "integer" - } - } - }, - "domain.ClusterResponse": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccount": { - "$ref": "#/definitions/domain.SimpleCloudAccountResponse" - }, - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "string" - }, - "conf": { - "$ref": "#/definitions/domain.ClusterConfResponse" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "isStack": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplate": { - "$ref": "#/definitions/domain.SimpleStackTemplateResponse" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - } - } - }, - "domain.ClusterSiteValuesResponse": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "clusterRegion": { - "type": "string" - }, - "clusterType": { - "type": "string" - }, - "sshKeyName": { - "type": "string" - }, - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.CreateAppGroupRequest": { - "type": "object", - "required": [ - "clusterId", - "name" - ], - "properties": { - "appGroupType": { - "type": "string", - "enum": [ - "LMA", - "SERVICE_MESH" - ] - }, - "clusterId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "domain.CreateAppGroupResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateAppServeAppRequest": { - "type": "object", - "required": [ - "name", - "targetClusterId" - ], - "properties": { - "appConfig": { - "type": "string" - }, - "appSecret": { - "type": "string" - }, - "appType": { - "description": "springboot spring", - "type": "string" - }, - "artifactUrl": { - "type": "string" - }, - "executablePath": { - "type": "string" - }, - "extraEnv": { - "type": "string" - }, - "imageUrl": { - "type": "string" - }, - "name": { - "description": "App", - "type": "string" - }, - "namespace": { - "type": "string" - }, - "port": { - "type": "string" - }, - "profile": { - "type": "string" - }, - "pvAccessMode": { - "type": "string" - }, - "pvEnabled": { - "type": "boolean" - }, - "pvMountPath": { - "type": "string" - }, - "pvSize": { - "type": "string" - }, - "pvStorageClass": { - "type": "string" - }, - "resourceSpec": { - "description": "tiny medium large", - "type": "string" - }, - "strategy": { - "description": "rolling-update blue-green canary", - "type": "string" - }, - "targetClusterId": { - "type": "string" - }, - "type": { - "description": "build deploy all", - "type": "string" - }, - "version": { - "description": "Task", - "type": "string" - } - } - }, - "domain.CreateApplicationRequest": { - "type": "object", - "properties": { - "applicationType": { - "type": "string" - }, - "endpoint": { - "type": "string" - }, - "metadata": { - "type": "string" - } - } - }, - "domain.CreateBootstrapKubeconfigResponse": { - "type": "object", - "properties": { - "kubeconfig": { - "$ref": "#/definitions/domain.BootstrapKubeconfig" - } - } - }, - "domain.CreateCloudAccountRequest": { - "type": "object", - "required": [ - "accessKeyId", - "awsAccountId", - "name", - "secretAccessKey" - ], - "properties": { - "accessKeyId": { - "type": "string", - "maxLength": 128, - "minLength": 16 - }, - "awsAccountId": { - "type": "string", - "maxLength": 12, - "minLength": 12 - }, - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "AZZURE", - "GCP" - ] - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "secretAccessKey": { - "type": "string", - "maxLength": 128, - "minLength": 16 - }, - "sessionToken": { - "type": "string", - "maxLength": 2000 - } - } - }, - "domain.CreateCloudAccountResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateClusterRequest": { - "type": "object", - "required": [ - "cloudService", - "name", - "organizationId", - "stackTemplateId" - ], - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "BYOH" - ] - }, - "clusterType": { - "type": "string" - }, - "description": { - "type": "string" - }, - "isStack": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplateId": { - "type": "string" - }, - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.CreateClusterResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateOrganizationRequest": { - "type": "object", - "required": [ - "Email", - "name" - ], - "properties": { - "Email": { - "type": "string" - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - } - } - }, - "domain.CreateStackRequest": { - "type": "object", - "required": [ - "cloudService", - "name", - "stackTemplateId" - ], - "properties": { - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "BYOH" - ] - }, - "clusterId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "stackTemplateId": { - "type": "string" - }, - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - }, - "userClusterEndpoint": { - "type": "string" - } - } - }, - "domain.CreateStackResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateStackTemplateRequest": { - "type": "object", - "required": [ - "name", - "platform", - "template", - "version" - ], - "properties": { - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "AZZURE", - "GCP" - ] - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string", - "enum": [ - "STANDARD", - "MSA" - ] - }, - "version": { - "type": "string" - } - } - }, - "domain.CreateStackTemplateResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateUserRequest": { - "type": "object", - "required": [ - "accountId", - "email", - "password", - "role" - ], - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] - } - } - }, - "domain.CreateUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - } - } - } - } - }, - "domain.DashboardChartResponse": { - "type": "object", - "properties": { - "chartData": { - "$ref": "#/definitions/domain.ChartData" - }, - "chartType": { - "type": "string" - }, - "description": { - "type": "string" - }, - "duration": { - "type": "string" - }, - "interval": { - "type": "string" - }, - "month": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "year": { - "type": "string" - } - } - }, - "domain.DashboardResource": { - "type": "object", - "properties": { - "cpu": { - "type": "string" - }, - "memory": { - "type": "string" - }, - "stack": { - "type": "string" - }, - "storage": { - "type": "string" - } - } - }, - "domain.DashboardStackResponse": { - "type": "object", - "properties": { - "cpu": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "memory": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "storage": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.DeleteCloudAccountRequest": { - "type": "object", - "required": [ - "accessKeyId", - "secretAccessKey" - ], - "properties": { - "accessKeyId": { - "type": "string", - "maxLength": 128, - "minLength": 16 - }, - "secretAccessKey": { - "type": "string", - "maxLength": 128, - "minLength": 16 - }, - "sessionToken": { - "type": "string", - "maxLength": 2000 - } - } - }, - "domain.FilterResponse": { - "type": "object", - "properties": { - "column": { - "type": "string" - }, - "operator": { - "type": "string" - }, - "releation": { - "type": "string" - }, - "values": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "domain.FindIdRequest": { - "type": "object", - "required": [ - "code", - "email", - "organizationId", - "userName" - ], - "properties": { - "code": { - "type": "string" - }, - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, - "domain.FindIdResponse": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - } - } - }, - "domain.FindPasswordRequest": { - "type": "object", - "required": [ - "accountId", - "code", - "email", - "organizationId", - "userName" - ], - "properties": { - "accountId": { - "type": "string" - }, - "code": { - "type": "string" - }, - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, - "domain.GetAlertResponse": { - "type": "object", - "properties": { - "alert": { - "$ref": "#/definitions/domain.AlertResponse" - } - } - }, - "domain.GetAlertsResponse": { - "type": "object", - "properties": { - "alerts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AlertResponse" - } - }, - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - } - } - }, - "domain.GetAppGroupResponse": { - "type": "object", - "properties": { - "appGroup": { - "$ref": "#/definitions/domain.AppGroupResponse" - } - } - }, - "domain.GetAppGroupsResponse": { - "type": "object", - "properties": { - "appGroups": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AppGroupResponse" - } - }, - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - } - } - }, - "domain.GetAppServeAppResponse": { - "type": "object", - "properties": { - "appServeApp": { - "$ref": "#/definitions/domain.AppServeApp" - }, - "stages": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StageResponse" - } - } - } - }, - "domain.GetAppServeAppTaskResponse": { - "type": "object", - "properties": { - "appServeAppTask": { - "$ref": "#/definitions/domain.AppServeAppTask" - } - } - }, - "domain.GetApplicationsResponse": { - "type": "object", - "properties": { - "applications": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ApplicationResponse" - } - } - } - }, - "domain.GetBootstrapKubeconfigResponse": { - "type": "object", - "properties": { - "kubeconfig": { - "$ref": "#/definitions/domain.BootstrapKubeconfig" - } - } - }, - "domain.GetCloudAccountResourceQuotaResponse": { - "type": "object", - "properties": { - "available": { - "type": "boolean" - }, - "resourceQuota": { - "$ref": "#/definitions/domain.ResourceQuota" - } - } - }, - "domain.GetCloudAccountResponse": { - "type": "object", - "properties": { - "cloudAccount": { - "$ref": "#/definitions/domain.CloudAccountResponse" - } - } - }, - "domain.GetCloudAccountsResponse": { - "type": "object", - "properties": { - "cloudAccounts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.CloudAccountResponse" - } - }, - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - } - } - }, - "domain.GetClusterNodesResponse": { - "type": "object", - "properties": { - "nodes": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ClusterNode" - } - } - } - }, - "domain.GetClustersResponse": { - "type": "object", - "properties": { - "clusters": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ClusterResponse" - } - }, - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - } - } - }, - "domain.GetDashboardChartResponse": { - "type": "object", - "properties": { - "chart": { - "$ref": "#/definitions/domain.DashboardChartResponse" - } - } - }, - "domain.GetDashboardChartsResponse": { - "type": "object", - "properties": { - "charts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.DashboardChartResponse" - } - } - } - }, - "domain.GetDashboardResourcesResponse": { - "type": "object", - "properties": { - "resources": { - "$ref": "#/definitions/domain.DashboardResource" - } - } - }, - "domain.GetDashboardStacksResponse": { - "type": "object", - "properties": { - "stacks": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.DashboardStackResponse" - } - } - } - }, - "domain.GetMyProfileResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - } - } - } - } - }, - "domain.GetOrganizationResponse": { - "type": "object", - "properties": { - "organization": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, - "domain.GetStackKubeConfigResponse": { - "type": "object", - "properties": { - "kubeConfig": { - "type": "string" - } - } - }, - "domain.GetStackResponse": { - "type": "object", - "properties": { - "stack": { - "$ref": "#/definitions/domain.StackResponse" - } - } - }, - "domain.GetStackStatusResponse": { - "type": "object", - "properties": { - "stackStatus": { - "type": "string" - }, - "stepStatus": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackStepStatus" - } - } - } - }, - "domain.GetStackTemplateResponse": { - "type": "object", - "properties": { - "stackTemplate": { - "$ref": "#/definitions/domain.StackTemplateResponse" - } - } - }, - "domain.GetStackTemplatesResponse": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - }, - "stackTemplates": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackTemplateResponse" - } - } - } - }, - "domain.GetStacksResponse": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - }, - "stacks": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackResponse" - } - } - } - }, - "domain.GetUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, - "domain.ImportClusterRequest": { - "type": "object", - "required": [ - "name", - "organizationId", - "stackTemplateId" - ], - "properties": { - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "string" - }, - "description": { - "type": "string" - }, - "kubeconfig": { - "type": "array", - "items": { - "type": "integer" - } - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplateId": { - "type": "string" - } - } - }, - "domain.ImportClusterResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.ListOrganizationBody": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.ListUserBody": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.LoginRequest": { - "type": "object", - "required": [ - "accountId", - "organizationId", - "password" - ], - "properties": { - "accountId": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "domain.LoginResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "passwordExpired": { - "type": "boolean" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "token": { - "type": "string" - } - } - } - } - }, - "domain.LogoutResponse": { - "type": "object", - "properties": { - "ssoUrls": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "domain.Organization": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.PaginationResponse": { - "type": "object", - "properties": { - "filters": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.FilterResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "sortColumn": { - "type": "string" - }, - "sortOrder": { - "type": "string" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" - } - } - }, - "domain.PingTokenRequest": { - "type": "object", - "required": [ - "organizationId", - "token" - ], - "properties": { - "organizationId": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, - "domain.PodCount": { - "type": "object", - "properties": { - "day": { - "type": "integer" - }, - "value": { - "type": "integer" - } - } - }, - "domain.ResourceQuota": { - "type": "object", - "properties": { - "quotas": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ResourceQuotaAttr" - } - } - } - }, - "domain.ResourceQuotaAttr": { - "type": "object", - "properties": { - "quota": { - "type": "integer" - }, - "required": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "usage": { - "type": "integer" - } - } - }, - "domain.Role": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.RollbackAppServeAppRequest": { - "type": "object", - "properties": { - "taskId": { - "type": "string" - } - } - }, - "domain.SimpleCloudAccountResponse": { - "type": "object", - "properties": { - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusters": { - "type": "integer" - }, - "createdIAM": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - } - } - }, - "domain.SimpleClusterResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - } - } - }, - "domain.SimpleStackTemplateResponse": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "services": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackTemplateServiceResponse" - } - }, - "template": { - "type": "string" - } - } - }, - "domain.SimpleUserResponse": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "domain.StackConfResponse": { - "type": "object", - "required": [ - "tksInfraNode", - "tksUserNode" - ], - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer", - "maximum": 3, - "minimum": 1 - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer", - "maximum": 100, - "minimum": 0 - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.StackResponse": { - "type": "object", - "properties": { - "cloudAccount": { - "$ref": "#/definitions/domain.SimpleCloudAccountResponse" - }, - "conf": { - "$ref": "#/definitions/domain.StackConfResponse" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "favorited": { - "type": "boolean" - }, - "grafanaUrl": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "primaryCluster": { - "type": "boolean" - }, - "resource": { - "$ref": "#/definitions/domain.DashboardStackResponse" - }, - "stackTemplate": { - "$ref": "#/definitions/domain.SimpleStackTemplateResponse" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "userClusterEndpoint": { - "type": "string" - } - } - }, - "domain.StackStepStatus": { - "type": "object", - "properties": { - "maxStep": { - "type": "integer" - }, - "stage": { - "type": "string" - }, - "status": { - "type": "string" - }, - "step": { - "type": "integer" - } - } - }, - "domain.StackTemplate": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "services": { - "type": "array", - "items": { - "type": "integer" - } - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.User" - }, - "updatorId": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "domain.StackTemplateResponse": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "services": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackTemplateServiceResponse" - } - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "version": { - "type": "string" - } - } - }, - "domain.StackTemplateServiceApplicationResponse": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "domain.StackTemplateServiceResponse": { - "type": "object", - "properties": { - "applications": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackTemplateServiceApplicationResponse" - } - }, - "type": { - "type": "string" - } - } - }, - "domain.StageResponse": { - "type": "object", - "properties": { - "actions": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ActionResponse" - } - }, - "name": { - "description": "BUILD (빌드), DEPLOY (배포), PROMOTE (프로모트), ROLLBACK (롤백)", - "type": "string" - }, - "result": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "domain.Unit": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - } - } - }, - "domain.UpdateAlertRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "domain.UpdateAppServeAppEndpointRequest": { - "type": "object", - "required": [ - "taskId" - ], - "properties": { - "endpointUrl": { - "type": "string" - }, - "helmRevision": { - "type": "integer" - }, - "previewEndpointUrl": { - "type": "string" - }, - "taskId": { - "type": "string" - } - } - }, - "domain.UpdateAppServeAppRequest": { - "type": "object", - "properties": { - "abort": { - "type": "boolean" - }, - "appConfig": { - "type": "string" - }, - "appSecret": { - "type": "string" - }, - "artifactUrl": { - "type": "string" - }, - "executablePath": { - "type": "string" - }, - "extraEnv": { - "type": "string" - }, - "imageUrl": { - "type": "string" - }, - "port": { - "type": "string" - }, - "profile": { - "type": "string" - }, - "promote": { - "description": "Update Strategy", - "type": "boolean" - }, - "resourceSpec": { - "type": "string" - }, - "strategy": { - "description": "Task", - "type": "string" - } - } - }, - "domain.UpdateAppServeAppStatusRequest": { - "type": "object", - "required": [ - "status", - "taskId" - ], - "properties": { - "output": { - "type": "string" - }, - "status": { - "type": "string" - }, - "taskId": { - "type": "string" - } - } - }, - "domain.UpdateCloudAccountRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "domain.UpdateMyProfileRequest": { - "type": "object", - "required": [ - "password" - ], - "properties": { - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "password": { - "type": "string" - } - } - }, - "domain.UpdateMyProfileResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - } - } - } - } - }, - "domain.UpdateOrganizationRequest": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - } - } - }, - "domain.UpdateOrganizationResponse": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - } - } - }, - "domain.UpdatePasswordRequest": { - "type": "object", - "required": [ - "newPassword", - "originPassword" - ], - "properties": { - "newPassword": { - "type": "string" - }, - "originPassword": { - "type": "string" - } - } - }, - "domain.UpdatePrimaryClusterRequest": { - "type": "object", - "properties": { - "primaryClusterId": { - "type": "string" - } - } - }, - "domain.UpdateStackRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "domain.UpdateStackTemplateRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "domain.UpdateUserRequest": { - "type": "object", - "properties": { - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] - } - } - }, - "domain.UpdateUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, - "domain.User": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "password": { - "type": "string" - }, - "passwordExpired": { - "type": "boolean" - }, - "passwordUpdatedAt": { - "type": "string" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "token": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.VerifyIdentityForLostIdRequest": { - "type": "object", - "required": [ - "email", - "organizationId", - "userName" - ], - "properties": { - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, - "domain.VerifyIdentityForLostIdResponse": { - "type": "object", - "properties": { - "validityPeriod": { - "type": "string" - } - } - }, - "domain.VerifyIdentityForLostPasswordRequest": { - "type": "object", - "required": [ - "accountId", - "email", - "organizationId", - "userName" - ], - "properties": { - "accountId": { - "type": "string" - }, - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, - "domain.VerifyIdentityForLostPasswordResponse": { - "type": "object", - "properties": { - "validityPeriod": { - "type": "string" - } - } - }, - "httpErrors.RestError": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "message": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "text": { - "type": "string" - } - } - } - }, - "securityDefinitions": { - "JWT": { - "type": "apiKey", - "name": "Authorization", - "in": "header" - } - } -}` - -// SwaggerInfo holds exported Swagger Info so clients can modify it -var SwaggerInfo = &swag.Spec{ - Version: "1.0", - Host: "tks-api-ft.taco-cat.xyz", - BasePath: "/api/1.0/", - Schemes: []string{}, - Title: "tks-api service", - Description: "This is backend api service for tks platform", - InfoInstanceName: "swagger", - SwaggerTemplate: docTemplate, -} - -func init() { - swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) -} diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json deleted file mode 100644 index fa98668f..00000000 --- a/api/swagger/swagger.json +++ /dev/null @@ -1,6851 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "This is backend api service for tks platform", - "title": "tks-api service", - "contact": { - "name": "taekyu.kang@sk.com", - "email": "taekyu.kang@sk.com" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "tks-api-ft.taco-cat.xyz", - "basePath": "/api/1.0/", - "paths": { - "/app-groups": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appGroup list by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Get appGroup list", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppGroupsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Install appGroup", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Install appGroup", - "parameters": [ - { - "description": "create appgroup request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateAppGroupRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateAppGroupResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Uninstall appGroup", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Uninstall appGroup", - "parameters": [ - { - "description": "body", - "name": "object", - "in": "body", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/app-groups/{appGroupId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appGroup detail by appGroupId", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Get appGroup detail", - "parameters": [ - { - "type": "string", - "description": "appGroupId", - "name": "appGroupId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppGroupResponse" - } - } - } - } - }, - "/app-groups/{appGroupId}/applications": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get applications", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Get applications", - "parameters": [ - { - "type": "string", - "description": "appGroupId", - "name": "appGroupId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "applicationType", - "name": "applicationType", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetApplicationsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create application", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppGroups" - ], - "summary": "Create application", - "parameters": [ - { - "description": "body", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateApplicationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/auth/find-id/code": { - "post": { - "description": "This API allows users to verify their identity for lost id by submitting required information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "Request to verify identity for lost id", - "parameters": [ - { - "description": "Request body for verifying identity for lost id including {organization ID, email, username}", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostIdRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostIdResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/auth/find-id/verification": { - "post": { - "description": "This API allows users to find their account ID by submitting required information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "Request to find forgotten ID", - "parameters": [ - { - "description": "Request body for finding the account ID including {organization ID, email, username, 6 digit code}", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.FindIdRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.FindIdResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/auth/find-password/code": { - "post": { - "description": "This API allows users to verify their identity for lost password by submitting required information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "Request to verify identity for lost password", - "parameters": [ - { - "description": "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/auth/find-password/verification": { - "post": { - "description": "This API allows users to reset their forgotten password by submitting required information", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "Request to find forgotten password", - "parameters": [ - { - "description": "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.FindPasswordRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/auth/login": { - "post": { - "description": "login", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "login", - "parameters": [ - { - "description": "account info", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.LoginRequest" - } - } - ], - "responses": { - "200": { - "description": "user detail", - "schema": { - "$ref": "#/definitions/domain.LoginResponse" - } - } - } - } - }, - "/auth/logout": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "logout", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "logout", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.LogoutResponse" - } - } - } - } - }, - "/auth/ping": { - "post": { - "description": "ping with token", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "ping with token", - "parameters": [ - { - "description": "token info", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.PingTokenRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/clusters": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get cluster list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get clusters", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetClustersResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Create cluster", - "parameters": [ - { - "description": "create cluster request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateClusterRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateClusterResponse" - } - } - } - } - }, - "/clusters/import": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Import cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Import cluster", - "parameters": [ - { - "description": "import cluster request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.ImportClusterRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.ImportClusterResponse" - } - } - } - } - }, - "/clusters/{clusterId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get cluster detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get cluster", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.Cluster" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Delete cluster", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.Cluster" - } - } - } - } - }, - "/clusters/{clusterId}/bootstrap-kubeconfig": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get bootstrap kubeconfig for BYOH", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get bootstrap kubeconfig for BYOH", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetBootstrapKubeconfigResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create bootstrap kubeconfig for BYOH", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Create bootstrap kubeconfig for BYOH", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateBootstrapKubeconfigResponse" - } - } - } - } - }, - "/clusters/{clusterId}/install": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Install cluster on tks cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Install cluster on tks cluster", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/clusters/{clusterId}/nodes": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get nodes information for BYOH", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get nodes information for BYOH", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetClusterNodesResponse" - } - } - } - } - }, - "/clusters/{clusterId}/site-values": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get cluster site values for creating", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Clusters" - ], - "summary": "Get cluster site values for creating", - "parameters": [ - { - "type": "string", - "description": "clusterId", - "name": "clusterId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.ClusterSiteValuesResponse" - } - } - } - } - }, - "/organizations": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get organization list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Get organization list", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ListOrganizationBody" - } - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create organization", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Create organization", - "parameters": [ - { - "description": "create organization request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateOrganizationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object" - } - } - } - } - }, - "/organizations/{organizationId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get organization detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Get organization detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetOrganizationResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update organization detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Update organization detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "update organization request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateOrganizationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.UpdateOrganizationResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete organization", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Delete organization", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.Organization" - } - } - } - } - }, - "/organizations/{organizationId}/alerts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Alerts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Get Alerts", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAlertsResponse" - } - } - } - } - }, - "/organizations/{organizationId}/alerts/{alertId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Get Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "alertId", - "name": "alertId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAlertResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Update Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAlertRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Delete Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "alertId", - "name": "alertId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/alerts/{alertId}/actions": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create alert action", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Create alert action", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp list by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp list", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "boolean", - "description": "Show all apps including deleted apps", - "name": "showAll", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AppServeApp" - } - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Install appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Install appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Request body to create app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/count": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get number of apps on given stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get number of apps on given stack", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "integer" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check duplicate appServeAppName by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Check duplicate appServeAppName", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppServeAppResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Uninstall appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Uninstall appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/endpoint": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update app endpoint", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update app endpoint", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "appId", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app endpoint", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/exist": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/latest-task": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get latest task from appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get latest task from appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/rollback": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Rollback appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Rollback appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to rollback app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.RollbackAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/status": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update app status", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update app status", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app status", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get CloudAccounts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Get CloudAccounts", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetCloudAccountsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Create CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateCloudAccountRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateCloudAccountResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check awsAccountId for cloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Check awsAccountId for cloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "awsAccountId", - "name": "awsAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CheckCloudAccountAwsAccountIdResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check name for cloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Check name for cloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CheckCloudAccountNameResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Get CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "cloudAccountId", - "name": "cloudAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetCloudAccountResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Update CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateCloudAccountRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Delete CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Delete cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.DeleteCloudAccountRequest" - } - }, - { - "type": "string", - "description": "cloudAccountId", - "name": "cloudAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Force CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Delete Force CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "cloudAccountId", - "name": "cloudAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get resource quota by cloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Get resource quota by cloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "cloudAccountId", - "name": "cloudAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetCloudAccountResourceQuotaResponse" - } - } - } - } - }, - "/organizations/{organizationId}/dashboard/charts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get charts data", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get charts data", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "chartType", - "name": "chartType", - "in": "query" - }, - { - "type": "string", - "description": "duration", - "name": "duration", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetDashboardChartsResponse" - } - } - } - } - }, - "/organizations/{organizationId}/dashboard/charts/{chartType}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get chart data", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get chart data", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "chartType", - "name": "chartType", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "duration", - "name": "duration", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetDashboardChartResponse" - } - } - } - } - }, - "/organizations/{organizationId}/dashboard/resources": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get resources", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get resources", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetDashboardResourcesResponse" - } - } - } - } - }, - "/organizations/{organizationId}/dashboard/stacks": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get stacks", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get stacks", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetDashboardStacksResponse" - } - } - } - } - }, - "/organizations/{organizationId}/my-profile": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get my profile detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Get my profile detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetMyProfileResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update my profile detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Update my profile detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Required fields: password due to double-check", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateMyProfileRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.UpdateMyProfileResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete myProfile", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Delete myProfile", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request" - } - } - } - }, - "/organizations/{organizationId}/my-profile/next-password-change": { - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update user's password expired date to current date", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Update user's password expired date to current date", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/httpErrors.RestError" - } - } - } - } - }, - "/organizations/{organizationId}/my-profile/password": { - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update user password detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "My-profile" - ], - "summary": "Update user password detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "update user password request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdatePasswordRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/primary-cluster": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update primary cluster", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Update primary cluster", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "update primary cluster request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdatePrimaryClusterRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/stacks": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Stacks", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Get Stacks", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStacksResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Create Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateStackRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateStackResponse" - } - } - } - } - }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check name for stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Check name for stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/stacks/{stackId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Get Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Update Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateStackRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Delete Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/favorite": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Set favorite stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Set favorite stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete favorite stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Delete favorite stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/kube-config": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get KubeConfig by stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Get KubeConfig by stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "organizationId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackKubeConfigResponse" - } - } - } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Stack Status", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Get Stack Status", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackStatusResponse" - } - } - } - } - }, - "/organizations/{organizationId}/users": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get user list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Get user list", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ListUserBody" - } - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Create user", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create user request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateUserRequest" - } - } - ], - "responses": { - "200": { - "description": "create user response", - "schema": { - "$ref": "#/definitions/domain.CreateUserResponse" - } - } - } - } - }, - "/organizations/{organizationId}/users/account-id/{accountId}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "return true when accountId exists", - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Get user id existence", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" - } - } - } - } - }, - "/organizations/{organizationId}/users/email/{email}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "return true when email exists", - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Get user email existence", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "email", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" - } - } - } - } - }, - "/organizations/{organizationId}/users/{accountId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get user detail", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Get user detail", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetUserResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Update user", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - }, - { - "description": "input", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateUserRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.UpdateUserResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Delete user", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.User" - } - } - } - } - }, - "/organizations/{organizationId}/users/{accountId}/reset-password": { - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Reset user's password as temporary password by admin and send email to user", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "Reset user's password as temporary password by admin", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/stack-templates": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get StackTemplates", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplates", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackTemplatesResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "description": "create stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateStackTemplateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.CreateStackTemplateResponse" - } - } - } - } - }, - "/stack-templates/{stackTemplateId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplate", - "parameters": [ - { - "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetStackTemplateResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "description": "Update stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateStackTemplateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/system-api/organizations/{organizationId}/alerts": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create alert. ADMIN ONLY", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Create alert. ADMIN ONLY", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - } - }, - "definitions": { - "domain.ActionResponse": { - "type": "object", - "properties": { - "body": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "method": { - "type": "string" - }, - "name": { - "description": "ENDPOINT (화면보기), PREVIEW (미리보기), PROMOTE (배포), ABORT (중단)", - "type": "string" - }, - "type": { - "description": "LINK, API", - "type": "string" - }, - "uri": { - "type": "string" - } - } - }, - "domain.AlertActionResponse": { - "type": "object", - "properties": { - "alertId": { - "type": "string" - }, - "content": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "taker": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.AlertResponse": { - "type": "object", - "properties": { - "alertActions": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AlertActionResponse" - } - }, - "closedAt": { - "type": "string" - }, - "cluster": { - "$ref": "#/definitions/domain.SimpleClusterResponse" - }, - "code": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "firedAt": { - "type": "string" - }, - "grade": { - "type": "string" - }, - "grafanaUrl": { - "type": "string" - }, - "id": { - "type": "string" - }, - "lastTaker": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "node": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "processingSec": { - "type": "integer" - }, - "rawData": { - "type": "string" - }, - "status": { - "type": "string" - }, - "takedAt": { - "type": "string" - }, - "takedSec": { - "type": "integer" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.AppGroupResponse": { - "type": "object", - "properties": { - "appGroupType": { - "type": "integer" - }, - "clusterId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "workflowId": { - "type": "string" - } - } - }, - "domain.AppServeApp": { - "type": "object", - "properties": { - "appServeAppTasks": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AppServeAppTask" - } - }, - "appType": { - "description": "appType (spring/springboot)", - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "endpointUrl": { - "description": "endpoint URL of deployed app", - "type": "string" - }, - "grafanaUrl": { - "description": "grafana dashboard URL for deployed app", - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "description": "application name", - "type": "string" - }, - "namespace": { - "description": "application namespace", - "type": "string" - }, - "organizationId": { - "description": "contractId is a contract ID which this app belongs to", - "type": "string" - }, - "previewEndpointUrl": { - "description": "preview svc endpoint URL in B/G deployment", - "type": "string" - }, - "status": { - "description": "status is status of deployed app", - "type": "string" - }, - "targetClusterId": { - "description": "target cluster to which the app is deployed", - "type": "string" - }, - "targetClusterName": { - "description": "target cluster name", - "type": "string" - }, - "type": { - "description": "type (build/deploy/all)", - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.AppServeAppTask": { - "type": "object", - "properties": { - "appConfig": { - "description": "java app config", - "type": "string" - }, - "appSecret": { - "description": "java app secret", - "type": "string" - }, - "appServeAppId": { - "description": "ID for appServeApp that this task belongs to", - "type": "string" - }, - "artifactUrl": { - "description": "URL of java app artifact (Eg, Jar)", - "type": "string" - }, - "availableRollback": { - "type": "boolean" - }, - "createdAt": { - "description": "createdAt is a creation timestamp for the application", - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "executablePath": { - "description": "Executable path of app image", - "type": "string" - }, - "extraEnv": { - "description": "env variable list for java app", - "type": "string" - }, - "helmRevision": { - "description": "revision of deployed helm release", - "type": "integer" - }, - "id": { - "type": "string" - }, - "imageUrl": { - "description": "URL of built image for app", - "type": "string" - }, - "output": { - "description": "output for task result", - "type": "string" - }, - "port": { - "description": "java app port", - "type": "string" - }, - "profile": { - "description": "java app profile", - "type": "string" - }, - "pvAccessMode": { - "type": "string" - }, - "pvEnabled": { - "type": "boolean" - }, - "pvMountPath": { - "type": "string" - }, - "pvSize": { - "type": "string" - }, - "pvStorageClass": { - "type": "string" - }, - "resourceSpec": { - "description": "resource spec of app pod", - "type": "string" - }, - "rollbackVersion": { - "description": "rollback target version", - "type": "string" - }, - "status": { - "description": "status is app status", - "type": "string" - }, - "strategy": { - "description": "deployment strategy (eg, rolling-update)", - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "description": "application version", - "type": "string" - } - } - }, - "domain.ApplicationResponse": { - "type": "object", - "properties": { - "appGroupId": { - "type": "string" - }, - "applicationType": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "endpoint": { - "type": "string" - }, - "id": { - "type": "string" - }, - "metadata": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.Axis": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "domain.BootstrapKubeconfig": { - "type": "object", - "properties": { - "expiration": { - "type": "integer" - } - } - }, - "domain.ChartData": { - "type": "object", - "properties": { - "podCounts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.PodCount" - } - }, - "series": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.Unit" - } - }, - "xAxis": { - "$ref": "#/definitions/domain.Axis" - }, - "yAxis": { - "$ref": "#/definitions/domain.Axis" - } - } - }, - "domain.CheckCloudAccountAwsAccountIdResponse": { - "type": "object", - "properties": { - "existed": { - "type": "boolean" - } - } - }, - "domain.CheckCloudAccountNameResponse": { - "type": "object", - "properties": { - "existed": { - "type": "boolean" - } - } - }, - "domain.CheckExistedResponse": { - "type": "object", - "properties": { - "existed": { - "type": "boolean" - } - } - }, - "domain.CloudAccount": { - "type": "object", - "properties": { - "accessKeyId": { - "type": "string" - }, - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusters": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "createdIAM": { - "type": "boolean" - }, - "creator": { - "$ref": "#/definitions/domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "secretAccessKey": { - "type": "string" - }, - "sessionToken": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, - "domain.CloudAccountResponse": { - "type": "object", - "properties": { - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusters": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "createdIAM": { - "type": "boolean" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - } - } - }, - "domain.Cluster": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccount": { - "$ref": "#/definitions/domain.CloudAccount" - }, - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "integer" - }, - "conf": { - "$ref": "#/definitions/domain.ClusterConf" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "favorited": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "isStack": { - "type": "boolean" - }, - "kubeconfig": { - "type": "array", - "items": { - "type": "integer" - } - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplate": { - "$ref": "#/definitions/domain.StackTemplate" - }, - "stackTemplateId": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, - "domain.ClusterConf": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.ClusterConfResponse": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.ClusterHost": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "domain.ClusterNode": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "hosts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ClusterHost" - } - }, - "registered": { - "type": "integer" - }, - "registering": { - "type": "integer" - }, - "status": { - "type": "string" - }, - "targeted": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "validity": { - "type": "integer" - } - } - }, - "domain.ClusterResponse": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccount": { - "$ref": "#/definitions/domain.SimpleCloudAccountResponse" - }, - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "string" - }, - "conf": { - "$ref": "#/definitions/domain.ClusterConfResponse" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "isStack": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplate": { - "$ref": "#/definitions/domain.SimpleStackTemplateResponse" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - } - } - }, - "domain.ClusterSiteValuesResponse": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "clusterRegion": { - "type": "string" - }, - "clusterType": { - "type": "string" - }, - "sshKeyName": { - "type": "string" - }, - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.CreateAppGroupRequest": { - "type": "object", - "required": [ - "clusterId", - "name" - ], - "properties": { - "appGroupType": { - "type": "string", - "enum": [ - "LMA", - "SERVICE_MESH" - ] - }, - "clusterId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "domain.CreateAppGroupResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateAppServeAppRequest": { - "type": "object", - "required": [ - "name", - "targetClusterId" - ], - "properties": { - "appConfig": { - "type": "string" - }, - "appSecret": { - "type": "string" - }, - "appType": { - "description": "springboot spring", - "type": "string" - }, - "artifactUrl": { - "type": "string" - }, - "executablePath": { - "type": "string" - }, - "extraEnv": { - "type": "string" - }, - "imageUrl": { - "type": "string" - }, - "name": { - "description": "App", - "type": "string" - }, - "namespace": { - "type": "string" - }, - "port": { - "type": "string" - }, - "profile": { - "type": "string" - }, - "pvAccessMode": { - "type": "string" - }, - "pvEnabled": { - "type": "boolean" - }, - "pvMountPath": { - "type": "string" - }, - "pvSize": { - "type": "string" - }, - "pvStorageClass": { - "type": "string" - }, - "resourceSpec": { - "description": "tiny medium large", - "type": "string" - }, - "strategy": { - "description": "rolling-update blue-green canary", - "type": "string" - }, - "targetClusterId": { - "type": "string" - }, - "type": { - "description": "build deploy all", - "type": "string" - }, - "version": { - "description": "Task", - "type": "string" - } - } - }, - "domain.CreateApplicationRequest": { - "type": "object", - "properties": { - "applicationType": { - "type": "string" - }, - "endpoint": { - "type": "string" - }, - "metadata": { - "type": "string" - } - } - }, - "domain.CreateBootstrapKubeconfigResponse": { - "type": "object", - "properties": { - "kubeconfig": { - "$ref": "#/definitions/domain.BootstrapKubeconfig" - } - } - }, - "domain.CreateCloudAccountRequest": { - "type": "object", - "required": [ - "accessKeyId", - "awsAccountId", - "name", - "secretAccessKey" - ], - "properties": { - "accessKeyId": { - "type": "string", - "maxLength": 128, - "minLength": 16 - }, - "awsAccountId": { - "type": "string", - "maxLength": 12, - "minLength": 12 - }, - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "AZZURE", - "GCP" - ] - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "secretAccessKey": { - "type": "string", - "maxLength": 128, - "minLength": 16 - }, - "sessionToken": { - "type": "string", - "maxLength": 2000 - } - } - }, - "domain.CreateCloudAccountResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateClusterRequest": { - "type": "object", - "required": [ - "cloudService", - "name", - "organizationId", - "stackTemplateId" - ], - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "BYOH" - ] - }, - "clusterType": { - "type": "string" - }, - "description": { - "type": "string" - }, - "isStack": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplateId": { - "type": "string" - }, - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.CreateClusterResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateOrganizationRequest": { - "type": "object", - "required": [ - "Email", - "name" - ], - "properties": { - "Email": { - "type": "string" - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - } - } - }, - "domain.CreateStackRequest": { - "type": "object", - "required": [ - "cloudService", - "name", - "stackTemplateId" - ], - "properties": { - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "BYOH" - ] - }, - "clusterId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "stackTemplateId": { - "type": "string" - }, - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - }, - "userClusterEndpoint": { - "type": "string" - } - } - }, - "domain.CreateStackResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateStackTemplateRequest": { - "type": "object", - "required": [ - "name", - "platform", - "template", - "version" - ], - "properties": { - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "AZZURE", - "GCP" - ] - }, - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string", - "enum": [ - "STANDARD", - "MSA" - ] - }, - "version": { - "type": "string" - } - } - }, - "domain.CreateStackTemplateResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.CreateUserRequest": { - "type": "object", - "required": [ - "accountId", - "email", - "password", - "role" - ], - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] - } - } - }, - "domain.CreateUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - } - } - } - } - }, - "domain.DashboardChartResponse": { - "type": "object", - "properties": { - "chartData": { - "$ref": "#/definitions/domain.ChartData" - }, - "chartType": { - "type": "string" - }, - "description": { - "type": "string" - }, - "duration": { - "type": "string" - }, - "interval": { - "type": "string" - }, - "month": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "year": { - "type": "string" - } - } - }, - "domain.DashboardResource": { - "type": "object", - "properties": { - "cpu": { - "type": "string" - }, - "memory": { - "type": "string" - }, - "stack": { - "type": "string" - }, - "storage": { - "type": "string" - } - } - }, - "domain.DashboardStackResponse": { - "type": "object", - "properties": { - "cpu": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "memory": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "storage": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.DeleteCloudAccountRequest": { - "type": "object", - "required": [ - "accessKeyId", - "secretAccessKey" - ], - "properties": { - "accessKeyId": { - "type": "string", - "maxLength": 128, - "minLength": 16 - }, - "secretAccessKey": { - "type": "string", - "maxLength": 128, - "minLength": 16 - }, - "sessionToken": { - "type": "string", - "maxLength": 2000 - } - } - }, - "domain.FilterResponse": { - "type": "object", - "properties": { - "column": { - "type": "string" - }, - "operator": { - "type": "string" - }, - "releation": { - "type": "string" - }, - "values": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "domain.FindIdRequest": { - "type": "object", - "required": [ - "code", - "email", - "organizationId", - "userName" - ], - "properties": { - "code": { - "type": "string" - }, - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, - "domain.FindIdResponse": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - } - } - }, - "domain.FindPasswordRequest": { - "type": "object", - "required": [ - "accountId", - "code", - "email", - "organizationId", - "userName" - ], - "properties": { - "accountId": { - "type": "string" - }, - "code": { - "type": "string" - }, - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, - "domain.GetAlertResponse": { - "type": "object", - "properties": { - "alert": { - "$ref": "#/definitions/domain.AlertResponse" - } - } - }, - "domain.GetAlertsResponse": { - "type": "object", - "properties": { - "alerts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AlertResponse" - } - }, - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - } - } - }, - "domain.GetAppGroupResponse": { - "type": "object", - "properties": { - "appGroup": { - "$ref": "#/definitions/domain.AppGroupResponse" - } - } - }, - "domain.GetAppGroupsResponse": { - "type": "object", - "properties": { - "appGroups": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AppGroupResponse" - } - }, - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - } - } - }, - "domain.GetAppServeAppResponse": { - "type": "object", - "properties": { - "appServeApp": { - "$ref": "#/definitions/domain.AppServeApp" - }, - "stages": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StageResponse" - } - } - } - }, - "domain.GetAppServeAppTaskResponse": { - "type": "object", - "properties": { - "appServeAppTask": { - "$ref": "#/definitions/domain.AppServeAppTask" - } - } - }, - "domain.GetApplicationsResponse": { - "type": "object", - "properties": { - "applications": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ApplicationResponse" - } - } - } - }, - "domain.GetBootstrapKubeconfigResponse": { - "type": "object", - "properties": { - "kubeconfig": { - "$ref": "#/definitions/domain.BootstrapKubeconfig" - } - } - }, - "domain.GetCloudAccountResourceQuotaResponse": { - "type": "object", - "properties": { - "available": { - "type": "boolean" - }, - "resourceQuota": { - "$ref": "#/definitions/domain.ResourceQuota" - } - } - }, - "domain.GetCloudAccountResponse": { - "type": "object", - "properties": { - "cloudAccount": { - "$ref": "#/definitions/domain.CloudAccountResponse" - } - } - }, - "domain.GetCloudAccountsResponse": { - "type": "object", - "properties": { - "cloudAccounts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.CloudAccountResponse" - } - }, - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - } - } - }, - "domain.GetClusterNodesResponse": { - "type": "object", - "properties": { - "nodes": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ClusterNode" - } - } - } - }, - "domain.GetClustersResponse": { - "type": "object", - "properties": { - "clusters": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ClusterResponse" - } - }, - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - } - } - }, - "domain.GetDashboardChartResponse": { - "type": "object", - "properties": { - "chart": { - "$ref": "#/definitions/domain.DashboardChartResponse" - } - } - }, - "domain.GetDashboardChartsResponse": { - "type": "object", - "properties": { - "charts": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.DashboardChartResponse" - } - } - } - }, - "domain.GetDashboardResourcesResponse": { - "type": "object", - "properties": { - "resources": { - "$ref": "#/definitions/domain.DashboardResource" - } - } - }, - "domain.GetDashboardStacksResponse": { - "type": "object", - "properties": { - "stacks": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.DashboardStackResponse" - } - } - } - }, - "domain.GetMyProfileResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - } - } - } - } - }, - "domain.GetOrganizationResponse": { - "type": "object", - "properties": { - "organization": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, - "domain.GetStackKubeConfigResponse": { - "type": "object", - "properties": { - "kubeConfig": { - "type": "string" - } - } - }, - "domain.GetStackResponse": { - "type": "object", - "properties": { - "stack": { - "$ref": "#/definitions/domain.StackResponse" - } - } - }, - "domain.GetStackStatusResponse": { - "type": "object", - "properties": { - "stackStatus": { - "type": "string" - }, - "stepStatus": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackStepStatus" - } - } - } - }, - "domain.GetStackTemplateResponse": { - "type": "object", - "properties": { - "stackTemplate": { - "$ref": "#/definitions/domain.StackTemplateResponse" - } - } - }, - "domain.GetStackTemplatesResponse": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - }, - "stackTemplates": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackTemplateResponse" - } - } - } - }, - "domain.GetStacksResponse": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" - }, - "stacks": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackResponse" - } - } - } - }, - "domain.GetUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, - "domain.ImportClusterRequest": { - "type": "object", - "required": [ - "name", - "organizationId", - "stackTemplateId" - ], - "properties": { - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "string" - }, - "description": { - "type": "string" - }, - "kubeconfig": { - "type": "array", - "items": { - "type": "integer" - } - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplateId": { - "type": "string" - } - } - }, - "domain.ImportClusterResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "domain.ListOrganizationBody": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.ListUserBody": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.LoginRequest": { - "type": "object", - "required": [ - "accountId", - "organizationId", - "password" - ], - "properties": { - "accountId": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "domain.LoginResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "passwordExpired": { - "type": "boolean" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "token": { - "type": "string" - } - } - } - } - }, - "domain.LogoutResponse": { - "type": "object", - "properties": { - "ssoUrls": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "domain.Organization": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.PaginationResponse": { - "type": "object", - "properties": { - "filters": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.FilterResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "sortColumn": { - "type": "string" - }, - "sortOrder": { - "type": "string" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" - } - } - }, - "domain.PingTokenRequest": { - "type": "object", - "required": [ - "organizationId", - "token" - ], - "properties": { - "organizationId": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, - "domain.PodCount": { - "type": "object", - "properties": { - "day": { - "type": "integer" - }, - "value": { - "type": "integer" - } - } - }, - "domain.ResourceQuota": { - "type": "object", - "properties": { - "quotas": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ResourceQuotaAttr" - } - } - } - }, - "domain.ResourceQuotaAttr": { - "type": "object", - "properties": { - "quota": { - "type": "integer" - }, - "required": { - "type": "integer" - }, - "type": { - "type": "string" - }, - "usage": { - "type": "integer" - } - } - }, - "domain.Role": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.RollbackAppServeAppRequest": { - "type": "object", - "properties": { - "taskId": { - "type": "string" - } - } - }, - "domain.SimpleCloudAccountResponse": { - "type": "object", - "properties": { - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusters": { - "type": "integer" - }, - "createdIAM": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - } - } - }, - "domain.SimpleClusterResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - } - } - }, - "domain.SimpleStackTemplateResponse": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "services": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackTemplateServiceResponse" - } - }, - "template": { - "type": "string" - } - } - }, - "domain.SimpleUserResponse": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "domain.StackConfResponse": { - "type": "object", - "required": [ - "tksInfraNode", - "tksUserNode" - ], - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer", - "maximum": 3, - "minimum": 1 - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer", - "maximum": 100, - "minimum": 0 - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "domain.StackResponse": { - "type": "object", - "properties": { - "cloudAccount": { - "$ref": "#/definitions/domain.SimpleCloudAccountResponse" - }, - "conf": { - "$ref": "#/definitions/domain.StackConfResponse" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "favorited": { - "type": "boolean" - }, - "grafanaUrl": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "primaryCluster": { - "type": "boolean" - }, - "resource": { - "$ref": "#/definitions/domain.DashboardStackResponse" - }, - "stackTemplate": { - "$ref": "#/definitions/domain.SimpleStackTemplateResponse" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "userClusterEndpoint": { - "type": "string" - } - } - }, - "domain.StackStepStatus": { - "type": "object", - "properties": { - "maxStep": { - "type": "integer" - }, - "stage": { - "type": "string" - }, - "status": { - "type": "string" - }, - "step": { - "type": "integer" - } - } - }, - "domain.StackTemplate": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "services": { - "type": "array", - "items": { - "type": "integer" - } - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.User" - }, - "updatorId": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "domain.StackTemplateResponse": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "platform": { - "type": "string" - }, - "services": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackTemplateServiceResponse" - } - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" - }, - "version": { - "type": "string" - } - } - }, - "domain.StackTemplateServiceApplicationResponse": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "domain.StackTemplateServiceResponse": { - "type": "object", - "properties": { - "applications": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.StackTemplateServiceApplicationResponse" - } - }, - "type": { - "type": "string" - } - } - }, - "domain.StageResponse": { - "type": "object", - "properties": { - "actions": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ActionResponse" - } - }, - "name": { - "description": "BUILD (빌드), DEPLOY (배포), PROMOTE (프로모트), ROLLBACK (롤백)", - "type": "string" - }, - "result": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "domain.Unit": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - } - } - }, - "domain.UpdateAlertRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "domain.UpdateAppServeAppEndpointRequest": { - "type": "object", - "required": [ - "taskId" - ], - "properties": { - "endpointUrl": { - "type": "string" - }, - "helmRevision": { - "type": "integer" - }, - "previewEndpointUrl": { - "type": "string" - }, - "taskId": { - "type": "string" - } - } - }, - "domain.UpdateAppServeAppRequest": { - "type": "object", - "properties": { - "abort": { - "type": "boolean" - }, - "appConfig": { - "type": "string" - }, - "appSecret": { - "type": "string" - }, - "artifactUrl": { - "type": "string" - }, - "executablePath": { - "type": "string" - }, - "extraEnv": { - "type": "string" - }, - "imageUrl": { - "type": "string" - }, - "port": { - "type": "string" - }, - "profile": { - "type": "string" - }, - "promote": { - "description": "Update Strategy", - "type": "boolean" - }, - "resourceSpec": { - "type": "string" - }, - "strategy": { - "description": "Task", - "type": "string" - } - } - }, - "domain.UpdateAppServeAppStatusRequest": { - "type": "object", - "required": [ - "status", - "taskId" - ], - "properties": { - "output": { - "type": "string" - }, - "status": { - "type": "string" - }, - "taskId": { - "type": "string" - } - } - }, - "domain.UpdateCloudAccountRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "domain.UpdateMyProfileRequest": { - "type": "object", - "required": [ - "password" - ], - "properties": { - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "password": { - "type": "string" - } - } - }, - "domain.UpdateMyProfileResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - } - } - } - } - }, - "domain.UpdateOrganizationRequest": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - } - } - }, - "domain.UpdateOrganizationResponse": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - } - } - }, - "domain.UpdatePasswordRequest": { - "type": "object", - "required": [ - "newPassword", - "originPassword" - ], - "properties": { - "newPassword": { - "type": "string" - }, - "originPassword": { - "type": "string" - } - } - }, - "domain.UpdatePrimaryClusterRequest": { - "type": "object", - "properties": { - "primaryClusterId": { - "type": "string" - } - } - }, - "domain.UpdateStackRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "domain.UpdateStackTemplateRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "domain.UpdateUserRequest": { - "type": "object", - "properties": { - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] - } - } - }, - "domain.UpdateUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, - "domain.User": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/domain.Organization" - }, - "password": { - "type": "string" - }, - "passwordExpired": { - "type": "boolean" - }, - "passwordUpdatedAt": { - "type": "string" - }, - "role": { - "$ref": "#/definitions/domain.Role" - }, - "token": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "domain.VerifyIdentityForLostIdRequest": { - "type": "object", - "required": [ - "email", - "organizationId", - "userName" - ], - "properties": { - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, - "domain.VerifyIdentityForLostIdResponse": { - "type": "object", - "properties": { - "validityPeriod": { - "type": "string" - } - } - }, - "domain.VerifyIdentityForLostPasswordRequest": { - "type": "object", - "required": [ - "accountId", - "email", - "organizationId", - "userName" - ], - "properties": { - "accountId": { - "type": "string" - }, - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "userName": { - "type": "string" - } - } - }, - "domain.VerifyIdentityForLostPasswordResponse": { - "type": "object", - "properties": { - "validityPeriod": { - "type": "string" - } - } - }, - "httpErrors.RestError": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "message": { - "type": "string" - }, - "status": { - "type": "integer" - }, - "text": { - "type": "string" - } - } - } - }, - "securityDefinitions": { - "JWT": { - "type": "apiKey", - "name": "Authorization", - "in": "header" - } - } -} \ No newline at end of file diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml deleted file mode 100644 index dfbf2f9f..00000000 --- a/api/swagger/swagger.yaml +++ /dev/null @@ -1,4453 +0,0 @@ -basePath: /api/1.0/ -definitions: - domain.ActionResponse: - properties: - body: - additionalProperties: - type: string - type: object - method: - type: string - name: - description: ENDPOINT (화면보기), PREVIEW (미리보기), PROMOTE (배포), ABORT (중단) - type: string - type: - description: LINK, API - type: string - uri: - type: string - type: object - domain.AlertActionResponse: - properties: - alertId: - type: string - content: - type: string - createdAt: - type: string - id: - type: string - status: - type: string - taker: - $ref: '#/definitions/domain.SimpleUserResponse' - updatedAt: - type: string - type: object - domain.AlertResponse: - properties: - alertActions: - items: - $ref: '#/definitions/domain.AlertActionResponse' - type: array - closedAt: - type: string - cluster: - $ref: '#/definitions/domain.SimpleClusterResponse' - code: - type: string - createdAt: - type: string - description: - type: string - firedAt: - type: string - grade: - type: string - grafanaUrl: - type: string - id: - type: string - lastTaker: - $ref: '#/definitions/domain.SimpleUserResponse' - message: - type: string - name: - type: string - node: - type: string - organizationId: - type: string - processingSec: - type: integer - rawData: - type: string - status: - type: string - takedAt: - type: string - takedSec: - type: integer - updatedAt: - type: string - type: object - domain.AppGroupResponse: - properties: - appGroupType: - type: integer - clusterId: - type: string - createdAt: - type: string - creator: - $ref: '#/definitions/domain.SimpleUserResponse' - description: - type: string - id: - type: string - name: - type: string - status: - type: integer - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/domain.SimpleUserResponse' - workflowId: - type: string - type: object - domain.AppServeApp: - properties: - appServeAppTasks: - items: - $ref: '#/definitions/domain.AppServeAppTask' - type: array - appType: - description: appType (spring/springboot) - type: string - createdAt: - type: string - deletedAt: - type: string - endpointUrl: - description: endpoint URL of deployed app - type: string - grafanaUrl: - description: grafana dashboard URL for deployed app - type: string - id: - type: string - name: - description: application name - type: string - namespace: - description: application namespace - type: string - organizationId: - description: contractId is a contract ID which this app belongs to - type: string - previewEndpointUrl: - description: preview svc endpoint URL in B/G deployment - type: string - status: - description: status is status of deployed app - type: string - targetClusterId: - description: target cluster to which the app is deployed - type: string - targetClusterName: - description: target cluster name - type: string - type: - description: type (build/deploy/all) - type: string - updatedAt: - type: string - type: object - domain.AppServeAppTask: - properties: - appConfig: - description: java app config - type: string - appSecret: - description: java app secret - type: string - appServeAppId: - description: ID for appServeApp that this task belongs to - type: string - artifactUrl: - description: URL of java app artifact (Eg, Jar) - type: string - availableRollback: - type: boolean - createdAt: - description: createdAt is a creation timestamp for the application - type: string - deletedAt: - type: string - executablePath: - description: Executable path of app image - type: string - extraEnv: - description: env variable list for java app - type: string - helmRevision: - description: revision of deployed helm release - type: integer - id: - type: string - imageUrl: - description: URL of built image for app - type: string - output: - description: output for task result - type: string - port: - description: java app port - type: string - profile: - description: java app profile - type: string - pvAccessMode: - type: string - pvEnabled: - type: boolean - pvMountPath: - type: string - pvSize: - type: string - pvStorageClass: - type: string - resourceSpec: - description: resource spec of app pod - type: string - rollbackVersion: - description: rollback target version - type: string - status: - description: status is app status - type: string - strategy: - description: deployment strategy (eg, rolling-update) - type: string - updatedAt: - type: string - version: - description: application version - type: string - type: object - domain.ApplicationResponse: - properties: - appGroupId: - type: string - applicationType: - type: integer - createdAt: - type: string - endpoint: - type: string - id: - type: string - metadata: - type: string - updatedAt: - type: string - type: object - domain.Axis: - properties: - data: - items: - type: string - type: array - type: object - domain.BootstrapKubeconfig: - properties: - expiration: - type: integer - type: object - domain.ChartData: - properties: - podCounts: - items: - $ref: '#/definitions/domain.PodCount' - type: array - series: - items: - $ref: '#/definitions/domain.Unit' - type: array - xAxis: - $ref: '#/definitions/domain.Axis' - yAxis: - $ref: '#/definitions/domain.Axis' - type: object - domain.CheckCloudAccountAwsAccountIdResponse: - properties: - existed: - type: boolean - type: object - domain.CheckCloudAccountNameResponse: - properties: - existed: - type: boolean - type: object - domain.CheckExistedResponse: - properties: - existed: - type: boolean - type: object - domain.CloudAccount: - properties: - accessKeyId: - type: string - awsAccountId: - type: string - cloudService: - type: string - clusters: - type: integer - createdAt: - type: string - createdIAM: - type: boolean - creator: - $ref: '#/definitions/domain.User' - creatorId: - type: string - description: - type: string - id: - type: string - name: - type: string - organizationId: - type: string - resource: - type: string - secretAccessKey: - type: string - sessionToken: - type: string - status: - type: integer - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/domain.User' - updatorId: - type: string - type: object - domain.CloudAccountResponse: - properties: - awsAccountId: - type: string - cloudService: - type: string - clusters: - type: integer - createdAt: - type: string - createdIAM: - type: boolean - creator: - $ref: '#/definitions/domain.SimpleUserResponse' - description: - type: string - id: - type: string - name: - type: string - organizationId: - type: string - resource: - type: string - status: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/domain.SimpleUserResponse' - type: object - domain.Cluster: - properties: - byoClusterEndpointHost: - type: string - byoClusterEndpointPort: - type: integer - cloudAccount: - $ref: '#/definitions/domain.CloudAccount' - cloudAccountId: - type: string - cloudService: - type: string - clusterType: - type: integer - conf: - $ref: '#/definitions/domain.ClusterConf' - createdAt: - type: string - creator: - $ref: '#/definitions/domain.User' - creatorId: - type: string - description: - type: string - favorited: - type: boolean - id: - type: string - isStack: - type: boolean - kubeconfig: - items: - type: integer - type: array - name: - type: string - organizationId: - type: string - stackTemplate: - $ref: '#/definitions/domain.StackTemplate' - stackTemplateId: - type: string - status: - type: integer - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/domain.User' - updatorId: - type: string - type: object - domain.ClusterConf: - properties: - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - type: object - domain.ClusterConfResponse: - properties: - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - type: object - domain.ClusterHost: - properties: - name: - type: string - status: - type: string - type: object - domain.ClusterNode: - properties: - command: - type: string - hosts: - items: - $ref: '#/definitions/domain.ClusterHost' - type: array - registered: - type: integer - registering: - type: integer - status: - type: string - targeted: - type: integer - type: - type: string - validity: - type: integer - type: object - domain.ClusterResponse: - properties: - byoClusterEndpointHost: - type: string - byoClusterEndpointPort: - type: integer - cloudAccount: - $ref: '#/definitions/domain.SimpleCloudAccountResponse' - cloudService: - type: string - clusterType: - type: string - conf: - $ref: '#/definitions/domain.ClusterConfResponse' - createdAt: - type: string - creator: - $ref: '#/definitions/domain.SimpleUserResponse' - description: - type: string - id: - type: string - isStack: - type: boolean - name: - type: string - organizationId: - type: string - stackTemplate: - $ref: '#/definitions/domain.SimpleStackTemplateResponse' - status: - type: string - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/domain.SimpleUserResponse' - type: object - domain.ClusterSiteValuesResponse: - properties: - byoClusterEndpointHost: - type: string - byoClusterEndpointPort: - type: integer - clusterRegion: - type: string - clusterType: - type: string - sshKeyName: - type: string - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - type: object - domain.CreateAppGroupRequest: - properties: - appGroupType: - enum: - - LMA - - SERVICE_MESH - type: string - clusterId: - type: string - description: - type: string - name: - type: string - required: - - clusterId - - name - type: object - domain.CreateAppGroupResponse: - properties: - id: - type: string - type: object - domain.CreateAppServeAppRequest: - properties: - appConfig: - type: string - appSecret: - type: string - appType: - description: springboot spring - type: string - artifactUrl: - type: string - executablePath: - type: string - extraEnv: - type: string - imageUrl: - type: string - name: - description: App - type: string - namespace: - type: string - port: - type: string - profile: - type: string - pvAccessMode: - type: string - pvEnabled: - type: boolean - pvMountPath: - type: string - pvSize: - type: string - pvStorageClass: - type: string - resourceSpec: - description: tiny medium large - type: string - strategy: - description: rolling-update blue-green canary - type: string - targetClusterId: - type: string - type: - description: build deploy all - type: string - version: - description: Task - type: string - required: - - name - - targetClusterId - type: object - domain.CreateApplicationRequest: - properties: - applicationType: - type: string - endpoint: - type: string - metadata: - type: string - type: object - domain.CreateBootstrapKubeconfigResponse: - properties: - kubeconfig: - $ref: '#/definitions/domain.BootstrapKubeconfig' - type: object - domain.CreateCloudAccountRequest: - properties: - accessKeyId: - maxLength: 128 - minLength: 16 - type: string - awsAccountId: - maxLength: 12 - minLength: 12 - type: string - cloudService: - enum: - - AWS - - AZZURE - - GCP - type: string - description: - type: string - name: - type: string - secretAccessKey: - maxLength: 128 - minLength: 16 - type: string - sessionToken: - maxLength: 2000 - type: string - required: - - accessKeyId - - awsAccountId - - name - - secretAccessKey - type: object - domain.CreateCloudAccountResponse: - properties: - id: - type: string - type: object - domain.CreateClusterRequest: - properties: - byoClusterEndpointHost: - type: string - byoClusterEndpointPort: - type: integer - cloudAccountId: - type: string - cloudService: - enum: - - AWS - - BYOH - type: string - clusterType: - type: string - description: - type: string - isStack: - type: boolean - name: - type: string - organizationId: - type: string - stackTemplateId: - type: string - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - required: - - cloudService - - name - - organizationId - - stackTemplateId - type: object - domain.CreateClusterResponse: - properties: - id: - type: string - type: object - domain.CreateOrganizationRequest: - properties: - Email: - type: string - description: - maxLength: 100 - minLength: 0 - type: string - name: - type: string - phone: - type: string - required: - - Email - - name - type: object - domain.CreateStackRequest: - properties: - cloudAccountId: - type: string - cloudService: - enum: - - AWS - - BYOH - type: string - clusterId: - type: string - description: - type: string - name: - type: string - stackTemplateId: - type: string - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - userClusterEndpoint: - type: string - required: - - cloudService - - name - - stackTemplateId - type: object - domain.CreateStackResponse: - properties: - id: - type: string - type: object - domain.CreateStackTemplateRequest: - properties: - cloudService: - enum: - - AWS - - AZZURE - - GCP - type: string - description: - type: string - name: - type: string - platform: - type: string - template: - type: string - templateType: - enum: - - STANDARD - - MSA - type: string - version: - type: string - required: - - name - - platform - - template - - version - type: object - domain.CreateStackTemplateResponse: - properties: - id: - type: string - type: object - domain.CreateUserRequest: - properties: - accountId: - type: string - department: - maxLength: 50 - minLength: 0 - type: string - description: - maxLength: 100 - minLength: 0 - type: string - email: - type: string - name: - type: string - password: - type: string - role: - enum: - - admin - - user - type: string - required: - - accountId - - email - - password - - role - type: object - domain.CreateUserResponse: - properties: - user: - properties: - accountId: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/domain.Organization' - role: - $ref: '#/definitions/domain.Role' - type: object - type: object - domain.DashboardChartResponse: - properties: - chartData: - $ref: '#/definitions/domain.ChartData' - chartType: - type: string - description: - type: string - duration: - type: string - interval: - type: string - month: - type: string - name: - type: string - organizationId: - type: string - updatedAt: - type: string - year: - type: string - type: object - domain.DashboardResource: - properties: - cpu: - type: string - memory: - type: string - stack: - type: string - storage: - type: string - type: object - domain.DashboardStackResponse: - properties: - cpu: - type: string - createdAt: - type: string - description: - type: string - id: - type: string - memory: - type: string - name: - type: string - status: - type: string - statusDesc: - type: string - storage: - type: string - updatedAt: - type: string - type: object - domain.DeleteCloudAccountRequest: - properties: - accessKeyId: - maxLength: 128 - minLength: 16 - type: string - secretAccessKey: - maxLength: 128 - minLength: 16 - type: string - sessionToken: - maxLength: 2000 - type: string - required: - - accessKeyId - - secretAccessKey - type: object - domain.FilterResponse: - properties: - column: - type: string - operator: - type: string - releation: - type: string - values: - items: - type: string - type: array - type: object - domain.FindIdRequest: - properties: - code: - type: string - email: - type: string - organizationId: - type: string - userName: - type: string - required: - - code - - email - - organizationId - - userName - type: object - domain.FindIdResponse: - properties: - accountId: - type: string - type: object - domain.FindPasswordRequest: - properties: - accountId: - type: string - code: - type: string - email: - type: string - organizationId: - type: string - userName: - type: string - required: - - accountId - - code - - email - - organizationId - - userName - type: object - domain.GetAlertResponse: - properties: - alert: - $ref: '#/definitions/domain.AlertResponse' - type: object - domain.GetAlertsResponse: - properties: - alerts: - items: - $ref: '#/definitions/domain.AlertResponse' - type: array - pagination: - $ref: '#/definitions/domain.PaginationResponse' - type: object - domain.GetAppGroupResponse: - properties: - appGroup: - $ref: '#/definitions/domain.AppGroupResponse' - type: object - domain.GetAppGroupsResponse: - properties: - appGroups: - items: - $ref: '#/definitions/domain.AppGroupResponse' - type: array - pagination: - $ref: '#/definitions/domain.PaginationResponse' - type: object - domain.GetAppServeAppResponse: - properties: - appServeApp: - $ref: '#/definitions/domain.AppServeApp' - stages: - items: - $ref: '#/definitions/domain.StageResponse' - type: array - type: object - domain.GetAppServeAppTaskResponse: - properties: - appServeAppTask: - $ref: '#/definitions/domain.AppServeAppTask' - type: object - domain.GetApplicationsResponse: - properties: - applications: - items: - $ref: '#/definitions/domain.ApplicationResponse' - type: array - type: object - domain.GetBootstrapKubeconfigResponse: - properties: - kubeconfig: - $ref: '#/definitions/domain.BootstrapKubeconfig' - type: object - domain.GetCloudAccountResourceQuotaResponse: - properties: - available: - type: boolean - resourceQuota: - $ref: '#/definitions/domain.ResourceQuota' - type: object - domain.GetCloudAccountResponse: - properties: - cloudAccount: - $ref: '#/definitions/domain.CloudAccountResponse' - type: object - domain.GetCloudAccountsResponse: - properties: - cloudAccounts: - items: - $ref: '#/definitions/domain.CloudAccountResponse' - type: array - pagination: - $ref: '#/definitions/domain.PaginationResponse' - type: object - domain.GetClusterNodesResponse: - properties: - nodes: - items: - $ref: '#/definitions/domain.ClusterNode' - type: array - type: object - domain.GetClustersResponse: - properties: - clusters: - items: - $ref: '#/definitions/domain.ClusterResponse' - type: array - pagination: - $ref: '#/definitions/domain.PaginationResponse' - type: object - domain.GetDashboardChartResponse: - properties: - chart: - $ref: '#/definitions/domain.DashboardChartResponse' - type: object - domain.GetDashboardChartsResponse: - properties: - charts: - items: - $ref: '#/definitions/domain.DashboardChartResponse' - type: array - type: object - domain.GetDashboardResourcesResponse: - properties: - resources: - $ref: '#/definitions/domain.DashboardResource' - type: object - domain.GetDashboardStacksResponse: - properties: - stacks: - items: - $ref: '#/definitions/domain.DashboardStackResponse' - type: array - type: object - domain.GetMyProfileResponse: - properties: - user: - properties: - accountId: - type: string - department: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/domain.Organization' - role: - $ref: '#/definitions/domain.Role' - type: object - type: object - domain.GetOrganizationResponse: - properties: - organization: - properties: - createdAt: - type: string - creator: - type: string - description: - type: string - id: - type: string - name: - type: string - phone: - type: string - primaryClusterId: - type: string - status: - type: string - statusDesc: - type: string - updatedAt: - type: string - type: object - type: object - domain.GetStackKubeConfigResponse: - properties: - kubeConfig: - type: string - type: object - domain.GetStackResponse: - properties: - stack: - $ref: '#/definitions/domain.StackResponse' - type: object - domain.GetStackStatusResponse: - properties: - stackStatus: - type: string - stepStatus: - items: - $ref: '#/definitions/domain.StackStepStatus' - type: array - type: object - domain.GetStackTemplateResponse: - properties: - stackTemplate: - $ref: '#/definitions/domain.StackTemplateResponse' - type: object - domain.GetStackTemplatesResponse: - properties: - pagination: - $ref: '#/definitions/domain.PaginationResponse' - stackTemplates: - items: - $ref: '#/definitions/domain.StackTemplateResponse' - type: array - type: object - domain.GetStacksResponse: - properties: - pagination: - $ref: '#/definitions/domain.PaginationResponse' - stacks: - items: - $ref: '#/definitions/domain.StackResponse' - type: array - type: object - domain.GetUserResponse: - properties: - user: - properties: - accountId: - type: string - createdAt: - type: string - creator: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/domain.Organization' - role: - $ref: '#/definitions/domain.Role' - updatedAt: - type: string - type: object - type: object - domain.ImportClusterRequest: - properties: - cloudService: - type: string - clusterType: - type: string - description: - type: string - kubeconfig: - items: - type: integer - type: array - name: - type: string - organizationId: - type: string - stackTemplateId: - type: string - required: - - name - - organizationId - - stackTemplateId - type: object - domain.ImportClusterResponse: - properties: - id: - type: string - type: object - domain.ListOrganizationBody: - properties: - createdAt: - type: string - description: - type: string - id: - type: string - name: - type: string - phone: - type: string - primaryClusterId: - type: string - status: - type: string - updatedAt: - type: string - type: object - domain.ListUserBody: - properties: - accountId: - type: string - createdAt: - type: string - creator: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/domain.Organization' - role: - $ref: '#/definitions/domain.Role' - updatedAt: - type: string - type: object - domain.LoginRequest: - properties: - accountId: - type: string - organizationId: - type: string - password: - type: string - required: - - accountId - - organizationId - - password - type: object - domain.LoginResponse: - properties: - user: - properties: - accountId: - type: string - department: - type: string - name: - type: string - organization: - $ref: '#/definitions/domain.Organization' - passwordExpired: - type: boolean - role: - $ref: '#/definitions/domain.Role' - token: - type: string - type: object - type: object - domain.LogoutResponse: - properties: - ssoUrls: - additionalProperties: - items: - type: string - type: array - type: object - type: object - domain.Organization: - properties: - createdAt: - type: string - creator: - type: string - description: - type: string - id: - type: string - name: - type: string - phone: - type: string - primaryClusterId: - type: string - status: - type: integer - statusDesc: - type: string - updatedAt: - type: string - type: object - domain.PaginationResponse: - properties: - filters: - items: - $ref: '#/definitions/domain.FilterResponse' - type: array - pageNumber: - type: integer - pageSize: - type: integer - sortColumn: - type: string - sortOrder: - type: string - totalPages: - type: integer - totalRows: - type: integer - type: object - domain.PingTokenRequest: - properties: - organizationId: - type: string - token: - type: string - required: - - organizationId - - token - type: object - domain.PodCount: - properties: - day: - type: integer - value: - type: integer - type: object - domain.ResourceQuota: - properties: - quotas: - items: - $ref: '#/definitions/domain.ResourceQuotaAttr' - type: array - type: object - domain.ResourceQuotaAttr: - properties: - quota: - type: integer - required: - type: integer - type: - type: string - usage: - type: integer - type: object - domain.Role: - properties: - createdAt: - type: string - creator: - type: string - description: - type: string - id: - type: string - name: - type: string - updatedAt: - type: string - type: object - domain.RollbackAppServeAppRequest: - properties: - taskId: - type: string - type: object - domain.SimpleCloudAccountResponse: - properties: - awsAccountId: - type: string - cloudService: - type: string - clusters: - type: integer - createdIAM: - type: boolean - description: - type: string - id: - type: string - name: - type: string - organizationId: - type: string - type: object - domain.SimpleClusterResponse: - properties: - id: - type: string - name: - type: string - organizationId: - type: string - type: object - domain.SimpleStackTemplateResponse: - properties: - cloudService: - type: string - description: - type: string - id: - type: string - kubeType: - type: string - kubeVersion: - type: string - name: - type: string - services: - items: - $ref: '#/definitions/domain.StackTemplateServiceResponse' - type: array - template: - type: string - type: object - domain.SimpleUserResponse: - properties: - accountId: - type: string - id: - type: string - name: - type: string - type: object - domain.StackConfResponse: - properties: - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - maximum: 3 - minimum: 1 - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - maximum: 100 - minimum: 0 - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - required: - - tksInfraNode - - tksUserNode - type: object - domain.StackResponse: - properties: - cloudAccount: - $ref: '#/definitions/domain.SimpleCloudAccountResponse' - conf: - $ref: '#/definitions/domain.StackConfResponse' - createdAt: - type: string - creator: - $ref: '#/definitions/domain.SimpleUserResponse' - description: - type: string - favorited: - type: boolean - grafanaUrl: - type: string - id: - type: string - name: - type: string - organizationId: - type: string - primaryCluster: - type: boolean - resource: - $ref: '#/definitions/domain.DashboardStackResponse' - stackTemplate: - $ref: '#/definitions/domain.SimpleStackTemplateResponse' - status: - type: string - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/domain.SimpleUserResponse' - userClusterEndpoint: - type: string - type: object - domain.StackStepStatus: - properties: - maxStep: - type: integer - stage: - type: string - status: - type: string - step: - type: integer - type: object - domain.StackTemplate: - properties: - cloudService: - type: string - createdAt: - type: string - creator: - $ref: '#/definitions/domain.User' - creatorId: - type: string - description: - type: string - id: - type: string - kubeType: - type: string - kubeVersion: - type: string - name: - type: string - organizationId: - type: string - platform: - type: string - services: - items: - type: integer - type: array - template: - type: string - templateType: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/domain.User' - updatorId: - type: string - version: - type: string - type: object - domain.StackTemplateResponse: - properties: - cloudService: - type: string - createdAt: - type: string - creator: - $ref: '#/definitions/domain.SimpleUserResponse' - description: - type: string - id: - type: string - kubeType: - type: string - kubeVersion: - type: string - name: - type: string - platform: - type: string - services: - items: - $ref: '#/definitions/domain.StackTemplateServiceResponse' - type: array - template: - type: string - templateType: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/domain.SimpleUserResponse' - version: - type: string - type: object - domain.StackTemplateServiceApplicationResponse: - properties: - description: - type: string - name: - type: string - version: - type: string - type: object - domain.StackTemplateServiceResponse: - properties: - applications: - items: - $ref: '#/definitions/domain.StackTemplateServiceApplicationResponse' - type: array - type: - type: string - type: object - domain.StageResponse: - properties: - actions: - items: - $ref: '#/definitions/domain.ActionResponse' - type: array - name: - description: BUILD (빌드), DEPLOY (배포), PROMOTE (프로모트), ROLLBACK (롤백) - type: string - result: - type: string - status: - type: string - type: object - domain.Unit: - properties: - data: - items: - type: string - type: array - name: - type: string - type: object - domain.UpdateAlertRequest: - properties: - description: - type: string - type: object - domain.UpdateAppServeAppEndpointRequest: - properties: - endpointUrl: - type: string - helmRevision: - type: integer - previewEndpointUrl: - type: string - taskId: - type: string - required: - - taskId - type: object - domain.UpdateAppServeAppRequest: - properties: - abort: - type: boolean - appConfig: - type: string - appSecret: - type: string - artifactUrl: - type: string - executablePath: - type: string - extraEnv: - type: string - imageUrl: - type: string - port: - type: string - profile: - type: string - promote: - description: Update Strategy - type: boolean - resourceSpec: - type: string - strategy: - description: Task - type: string - type: object - domain.UpdateAppServeAppStatusRequest: - properties: - output: - type: string - status: - type: string - taskId: - type: string - required: - - status - - taskId - type: object - domain.UpdateCloudAccountRequest: - properties: - description: - type: string - type: object - domain.UpdateMyProfileRequest: - properties: - department: - maxLength: 50 - minLength: 0 - type: string - email: - type: string - name: - maxLength: 30 - minLength: 1 - type: string - password: - type: string - required: - - password - type: object - domain.UpdateMyProfileResponse: - properties: - user: - properties: - accountId: - type: string - department: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/domain.Organization' - role: - $ref: '#/definitions/domain.Role' - type: object - type: object - domain.UpdateOrganizationRequest: - properties: - description: - maxLength: 100 - minLength: 0 - type: string - name: - maxLength: 30 - minLength: 1 - type: string - phone: - type: string - primaryClusterId: - type: string - required: - - name - type: object - domain.UpdateOrganizationResponse: - properties: - description: - type: string - id: - type: string - name: - type: string - phone: - type: string - type: object - domain.UpdatePasswordRequest: - properties: - newPassword: - type: string - originPassword: - type: string - required: - - newPassword - - originPassword - type: object - domain.UpdatePrimaryClusterRequest: - properties: - primaryClusterId: - type: string - type: object - domain.UpdateStackRequest: - properties: - description: - type: string - type: object - domain.UpdateStackTemplateRequest: - properties: - description: - type: string - type: object - domain.UpdateUserRequest: - properties: - department: - maxLength: 50 - minLength: 0 - type: string - description: - maxLength: 100 - minLength: 0 - type: string - email: - type: string - name: - maxLength: 30 - minLength: 1 - type: string - role: - enum: - - admin - - user - type: string - type: object - domain.UpdateUserResponse: - properties: - user: - properties: - accountId: - type: string - createdAt: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/domain.Organization' - role: - $ref: '#/definitions/domain.Role' - updatedAt: - type: string - type: object - type: object - domain.User: - properties: - accountId: - type: string - createdAt: - type: string - creator: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/domain.Organization' - password: - type: string - passwordExpired: - type: boolean - passwordUpdatedAt: - type: string - role: - $ref: '#/definitions/domain.Role' - token: - type: string - updatedAt: - type: string - type: object - domain.VerifyIdentityForLostIdRequest: - properties: - email: - type: string - organizationId: - type: string - userName: - type: string - required: - - email - - organizationId - - userName - type: object - domain.VerifyIdentityForLostIdResponse: - properties: - validityPeriod: - type: string - type: object - domain.VerifyIdentityForLostPasswordRequest: - properties: - accountId: - type: string - email: - type: string - organizationId: - type: string - userName: - type: string - required: - - accountId - - email - - organizationId - - userName - type: object - domain.VerifyIdentityForLostPasswordResponse: - properties: - validityPeriod: - type: string - type: object - httpErrors.RestError: - properties: - code: - type: string - message: - type: string - status: - type: integer - text: - type: string - type: object -host: tks-api-ft.taco-cat.xyz -info: - contact: - email: taekyu.kang@sk.com - name: taekyu.kang@sk.com - description: This is backend api service for tks platform - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - title: tks-api service - version: "1.0" -paths: - /app-groups: - delete: - consumes: - - application/json - description: Uninstall appGroup - parameters: - - description: body - in: body - name: object - required: true - schema: - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Uninstall appGroup - tags: - - AppGroups - get: - consumes: - - application/json - description: Get appGroup list by giving params - parameters: - - description: clusterId - in: query - name: clusterId - type: string - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetAppGroupsResponse' - security: - - JWT: [] - summary: Get appGroup list - tags: - - AppGroups - post: - consumes: - - application/json - description: Install appGroup - parameters: - - description: create appgroup request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.CreateAppGroupRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CreateAppGroupResponse' - security: - - JWT: [] - summary: Install appGroup - tags: - - AppGroups - /app-groups/{appGroupId}: - get: - consumes: - - application/json - description: Get appGroup detail by appGroupId - parameters: - - description: appGroupId - in: path - name: appGroupId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetAppGroupResponse' - security: - - JWT: [] - summary: Get appGroup detail - tags: - - AppGroups - /app-groups/{appGroupId}/applications: - get: - consumes: - - application/json - description: Get applications - parameters: - - description: appGroupId - in: path - name: appGroupId - required: true - type: string - - description: applicationType - in: query - name: applicationType - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetApplicationsResponse' - security: - - JWT: [] - summary: Get applications - tags: - - AppGroups - post: - consumes: - - application/json - description: Create application - parameters: - - description: body - in: body - name: object - required: true - schema: - $ref: '#/definitions/domain.CreateApplicationRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Create application - tags: - - AppGroups - /auth/find-id/code: - post: - consumes: - - application/json - description: This API allows users to verify their identity for lost id by submitting - required information - parameters: - - description: Request body for verifying identity for lost id including {organization - ID, email, username} - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.VerifyIdentityForLostIdRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.VerifyIdentityForLostIdResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/httpErrors.RestError' - summary: Request to verify identity for lost id - tags: - - Auth - /auth/find-id/verification: - post: - consumes: - - application/json - description: This API allows users to find their account ID by submitting required - information - parameters: - - description: Request body for finding the account ID including {organization - ID, email, username, 6 digit code} - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.FindIdRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.FindIdResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/httpErrors.RestError' - summary: Request to find forgotten ID - tags: - - Auth - /auth/find-password/code: - post: - consumes: - - application/json - description: This API allows users to verify their identity for lost password - by submitting required information - parameters: - - description: Request body for verifying identity for lost password including - {organization ID, email, username, Account ID} - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.VerifyIdentityForLostPasswordRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.VerifyIdentityForLostPasswordResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/httpErrors.RestError' - summary: Request to verify identity for lost password - tags: - - Auth - /auth/find-password/verification: - post: - consumes: - - application/json - description: This API allows users to reset their forgotten password by submitting - required information - parameters: - - description: Request body for finding the password including {organization - ID, email, username, Account ID, 6 digit code} - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.FindPasswordRequest' - produces: - - application/json - responses: - "200": - description: OK - "400": - description: Bad Request - schema: - $ref: '#/definitions/httpErrors.RestError' - summary: Request to find forgotten password - tags: - - Auth - /auth/login: - post: - consumes: - - application/json - description: login - parameters: - - description: account info - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.LoginRequest' - produces: - - application/json - responses: - "200": - description: user detail - schema: - $ref: '#/definitions/domain.LoginResponse' - summary: login - tags: - - Auth - /auth/logout: - post: - consumes: - - application/json - description: logout - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.LogoutResponse' - security: - - JWT: [] - summary: logout - tags: - - Auth - /auth/ping: - post: - consumes: - - application/json - description: ping with token - parameters: - - description: token info - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.PingTokenRequest' - produces: - - application/json - responses: - "200": - description: OK - summary: ping with token - tags: - - Auth - /clusters: - get: - consumes: - - application/json - description: Get cluster list - parameters: - - description: organizationId - in: query - name: organizationId - type: string - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetClustersResponse' - security: - - JWT: [] - summary: Get clusters - tags: - - Clusters - post: - consumes: - - application/json - description: Create cluster - parameters: - - description: create cluster request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.CreateClusterRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CreateClusterResponse' - security: - - JWT: [] - summary: Create cluster - tags: - - Clusters - /clusters/{clusterId}: - delete: - consumes: - - application/json - description: Delete cluster - parameters: - - description: clusterId - in: path - name: clusterId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.Cluster' - security: - - JWT: [] - summary: Delete cluster - tags: - - Clusters - get: - consumes: - - application/json - description: Get cluster detail - parameters: - - description: clusterId - in: path - name: clusterId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.Cluster' - security: - - JWT: [] - summary: Get cluster - tags: - - Clusters - /clusters/{clusterId}/bootstrap-kubeconfig: - get: - consumes: - - application/json - description: Get bootstrap kubeconfig for BYOH - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetBootstrapKubeconfigResponse' - security: - - JWT: [] - summary: Get bootstrap kubeconfig for BYOH - tags: - - Clusters - post: - consumes: - - application/json - description: Create bootstrap kubeconfig for BYOH - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CreateBootstrapKubeconfigResponse' - security: - - JWT: [] - summary: Create bootstrap kubeconfig for BYOH - tags: - - Clusters - /clusters/{clusterId}/install: - post: - consumes: - - application/json - description: Install cluster on tks cluster - parameters: - - description: clusterId - in: path - name: clusterId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Install cluster on tks cluster - tags: - - Clusters - /clusters/{clusterId}/nodes: - get: - consumes: - - application/json - description: Get nodes information for BYOH - parameters: - - description: clusterId - in: path - name: clusterId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetClusterNodesResponse' - security: - - JWT: [] - summary: Get nodes information for BYOH - tags: - - Clusters - /clusters/{clusterId}/site-values: - get: - consumes: - - application/json - description: Get cluster site values for creating - parameters: - - description: clusterId - in: path - name: clusterId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.ClusterSiteValuesResponse' - security: - - JWT: [] - summary: Get cluster site values for creating - tags: - - Clusters - /clusters/import: - post: - consumes: - - application/json - description: Import cluster - parameters: - - description: import cluster request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.ImportClusterRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.ImportClusterResponse' - security: - - JWT: [] - summary: Import cluster - tags: - - Clusters - /organizations: - get: - consumes: - - application/json - description: Get organization list - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/domain.ListOrganizationBody' - type: array - security: - - JWT: [] - summary: Get organization list - tags: - - Organizations - post: - consumes: - - application/json - description: Create organization - parameters: - - description: create organization request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.CreateOrganizationRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: object - security: - - JWT: [] - summary: Create organization - tags: - - Organizations - /organizations/{organizationId}: - delete: - consumes: - - application/json - description: Delete organization - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.Organization' - security: - - JWT: [] - summary: Delete organization - tags: - - Organizations - get: - consumes: - - application/json - description: Get organization detail - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetOrganizationResponse' - security: - - JWT: [] - summary: Get organization detail - tags: - - Organizations - put: - consumes: - - application/json - description: Update organization detail - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: update organization request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateOrganizationRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.UpdateOrganizationResponse' - security: - - JWT: [] - summary: Update organization detail - tags: - - Organizations - /organizations/{organizationId}/alerts: - get: - consumes: - - application/json - description: Get Alerts - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetAlertsResponse' - security: - - JWT: [] - summary: Get Alerts - tags: - - Alerts - /organizations/{organizationId}/alerts/{alertId}: - delete: - consumes: - - application/json - description: Delete Alert - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: alertId - in: path - name: alertId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete Alert - tags: - - Alerts - get: - consumes: - - application/json - description: Get Alert - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: alertId - in: path - name: alertId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetAlertResponse' - security: - - JWT: [] - summary: Get Alert - tags: - - Alerts - put: - consumes: - - application/json - description: Update Alert - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: Update cloud setting request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateAlertRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update Alert - tags: - - Alerts - /organizations/{organizationId}/alerts/{alertId}/actions: - post: - consumes: - - application/json - description: Create alert action - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Create alert action - tags: - - Alerts - /organizations/{organizationId}/app-serve-apps: - get: - consumes: - - application/json - description: Get appServeApp list by giving params - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: Show all apps including deleted apps - in: query - name: showAll - type: boolean - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/domain.AppServeApp' - type: array - security: - - JWT: [] - summary: Get appServeApp list - tags: - - AppServeApps - post: - consumes: - - application/json - description: Install appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: Request body to create app - in: body - name: object - required: true - schema: - $ref: '#/definitions/domain.CreateAppServeAppRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Install appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}: - delete: - consumes: - - application/json - description: Uninstall appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Uninstall appServeApp - tags: - - AppServeApps - get: - consumes: - - application/json - description: Get appServeApp by giving params - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetAppServeAppResponse' - security: - - JWT: [] - summary: Get appServeApp - tags: - - AppServeApps - put: - consumes: - - application/json - description: Update appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - - description: Request body to update app - in: body - name: object - required: true - schema: - $ref: '#/definitions/domain.UpdateAppServeAppRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Update appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/endpoint: - patch: - consumes: - - application/json - description: Update app endpoint - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: appId - in: path - name: appId - required: true - type: string - - description: Request body to update app endpoint - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateAppServeAppEndpointRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Update app endpoint - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/exist: - get: - consumes: - - application/json - description: Get appServeApp by giving params - produces: - - application/json - responses: - "200": - description: OK - schema: - type: boolean - security: - - JWT: [] - summary: Get appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/latest-task: - get: - consumes: - - application/json - description: Get latest task from appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetAppServeAppTaskResponse' - security: - - JWT: [] - summary: Get latest task from appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/rollback: - post: - consumes: - - application/json - description: Rollback appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - - description: Request body to rollback app - in: body - name: object - required: true - schema: - $ref: '#/definitions/domain.RollbackAppServeAppRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Rollback appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/status: - patch: - consumes: - - application/json - description: Update app status - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - - description: Request body to update app status - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateAppServeAppStatusRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Update app status - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/count: - get: - consumes: - - application/json - description: Get number of apps on given stack - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: Stack ID - in: query - name: stackId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - type: integer - security: - - JWT: [] - summary: Get number of apps on given stack - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/name/{name}/existence: - get: - consumes: - - application/json - description: Check duplicate appServeAppName by giving params - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: name - in: path - name: name - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - type: boolean - security: - - JWT: [] - summary: Check duplicate appServeAppName - tags: - - AppServeApps - /organizations/{organizationId}/cloud-accounts: - get: - consumes: - - application/json - description: Get CloudAccounts - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetCloudAccountsResponse' - security: - - JWT: [] - summary: Get CloudAccounts - tags: - - CloudAccounts - post: - consumes: - - application/json - description: Create CloudAccount - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: create cloud setting request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.CreateCloudAccountRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CreateCloudAccountResponse' - security: - - JWT: [] - summary: Create CloudAccount - tags: - - CloudAccounts - /organizations/{organizationId}/cloud-accounts/{cloudAccountId}: - delete: - consumes: - - application/json - description: Delete CloudAccount - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: Delete cloud setting request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.DeleteCloudAccountRequest' - - description: cloudAccountId - in: path - name: cloudAccountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete CloudAccount - tags: - - CloudAccounts - get: - consumes: - - application/json - description: Get CloudAccount - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: cloudAccountId - in: path - name: cloudAccountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetCloudAccountResponse' - security: - - JWT: [] - summary: Get CloudAccount - tags: - - CloudAccounts - put: - consumes: - - application/json - description: Update CloudAccount - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: Update cloud setting request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateCloudAccountRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update CloudAccount - tags: - - CloudAccounts - /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error: - delete: - consumes: - - application/json - description: Delete Force CloudAccount - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: cloudAccountId - in: path - name: cloudAccountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete Force CloudAccount - tags: - - CloudAccounts - /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota: - get: - consumes: - - application/json - description: Get resource quota by cloudAccount - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: cloudAccountId - in: path - name: cloudAccountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetCloudAccountResourceQuotaResponse' - security: - - JWT: [] - summary: Get resource quota by cloudAccount - tags: - - CloudAccounts - /organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence: - get: - consumes: - - application/json - description: Check awsAccountId for cloudAccount - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: awsAccountId - in: path - name: awsAccountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CheckCloudAccountAwsAccountIdResponse' - security: - - JWT: [] - summary: Check awsAccountId for cloudAccount - tags: - - CloudAccounts - /organizations/{organizationId}/cloud-accounts/name/{name}/existence: - get: - consumes: - - application/json - description: Check name for cloudAccount - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: name - in: path - name: name - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CheckCloudAccountNameResponse' - security: - - JWT: [] - summary: Check name for cloudAccount - tags: - - CloudAccounts - /organizations/{organizationId}/dashboard/charts: - get: - consumes: - - application/json - description: Get charts data - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: chartType - in: query - name: chartType - type: string - - description: duration - in: query - name: duration - required: true - type: string - - description: interval - in: query - name: interval - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetDashboardChartsResponse' - security: - - JWT: [] - summary: Get charts data - tags: - - Dashboards - /organizations/{organizationId}/dashboard/charts/{chartType}: - get: - consumes: - - application/json - description: Get chart data - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: chartType - in: path - name: chartType - required: true - type: string - - description: duration - in: query - name: duration - required: true - type: string - - description: interval - in: query - name: interval - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetDashboardChartResponse' - security: - - JWT: [] - summary: Get chart data - tags: - - Dashboards - /organizations/{organizationId}/dashboard/resources: - get: - consumes: - - application/json - description: Get resources - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetDashboardResourcesResponse' - security: - - JWT: [] - summary: Get resources - tags: - - Dashboards - /organizations/{organizationId}/dashboard/stacks: - get: - consumes: - - application/json - description: Get stacks - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetDashboardStacksResponse' - security: - - JWT: [] - summary: Get stacks - tags: - - Dashboards - /organizations/{organizationId}/my-profile: - delete: - consumes: - - application/json - description: Delete myProfile - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - "400": - description: Bad Request - security: - - JWT: [] - summary: Delete myProfile - tags: - - My-profile - get: - consumes: - - application/json - description: Get my profile detail - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetMyProfileResponse' - security: - - JWT: [] - summary: Get my profile detail - tags: - - My-profile - put: - consumes: - - application/json - description: Update my profile detail - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: 'Required fields: password due to double-check' - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateMyProfileRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.UpdateMyProfileResponse' - security: - - JWT: [] - summary: Update my profile detail - tags: - - My-profile - /organizations/{organizationId}/my-profile/next-password-change: - put: - consumes: - - application/json - description: Update user's password expired date to current date - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - "400": - description: Bad Request - schema: - $ref: '#/definitions/httpErrors.RestError' - security: - - JWT: [] - summary: Update user's password expired date to current date - tags: - - My-profile - /organizations/{organizationId}/my-profile/password: - put: - consumes: - - application/json - description: Update user password detail - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: update user password request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdatePasswordRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update user password detail - tags: - - My-profile - /organizations/{organizationId}/primary-cluster: - patch: - consumes: - - application/json - description: Update primary cluster - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: update primary cluster request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdatePrimaryClusterRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update primary cluster - tags: - - Organizations - /organizations/{organizationId}/stacks: - get: - consumes: - - application/json - description: Get Stacks - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: combinedFilter - in: query - name: combinedFilter - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetStacksResponse' - security: - - JWT: [] - summary: Get Stacks - tags: - - Stacks - post: - consumes: - - application/json - description: Create Stack - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: create cloud setting request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.CreateStackRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CreateStackResponse' - security: - - JWT: [] - summary: Create Stack - tags: - - Stacks - /organizations/{organizationId}/stacks/{stackId}: - delete: - consumes: - - application/json - description: Delete Stack - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: stackId - in: path - name: stackId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete Stack - tags: - - Stacks - get: - consumes: - - application/json - description: Get Stack - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: stackId - in: path - name: stackId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetStackResponse' - security: - - JWT: [] - summary: Get Stack - tags: - - Stacks - put: - consumes: - - application/json - description: Update Stack - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: stackId - in: path - name: stackId - required: true - type: string - - description: Update cloud setting request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateStackRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update Stack - tags: - - Stacks - /organizations/{organizationId}/stacks/{stackId}/favorite: - delete: - consumes: - - application/json - description: Delete favorite stack - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: stackId - in: path - name: stackId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete favorite stack - tags: - - Stacks - post: - consumes: - - application/json - description: Set favorite stack - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: stackId - in: path - name: stackId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Set favorite stack - tags: - - Stacks - /organizations/{organizationId}/stacks/{stackId}/kube-config: - get: - consumes: - - application/json - description: Get KubeConfig by stack - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: organizationId - in: path - name: stackId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetStackKubeConfigResponse' - security: - - JWT: [] - summary: Get KubeConfig by stack - tags: - - Stacks - /organizations/{organizationId}/stacks/{stackId}/status: - get: - consumes: - - application/json - description: Get Stack Status - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: stackId - in: path - name: stackId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetStackStatusResponse' - security: - - JWT: [] - summary: Get Stack Status - tags: - - Stacks - /organizations/{organizationId}/stacks/name/{name}/existence: - get: - consumes: - - application/json - description: Check name for stack - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: stackId - in: path - name: stackId - required: true - type: string - - description: name - in: path - name: name - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Check name for stack - tags: - - Stacks - /organizations/{organizationId}/users: - get: - consumes: - - application/json - description: Get user list - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/domain.ListUserBody' - type: array - security: - - JWT: [] - summary: Get user list - tags: - - Users - post: - consumes: - - application/json - description: Create user - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: create user request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.CreateUserRequest' - produces: - - application/json - responses: - "200": - description: create user response - schema: - $ref: '#/definitions/domain.CreateUserResponse' - security: - - JWT: [] - summary: Create user - tags: - - Users - /organizations/{organizationId}/users/{accountId}: - delete: - consumes: - - application/json - description: Delete user - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: accountId - in: path - name: accountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.User' - security: - - JWT: [] - summary: Delete user - tags: - - Users - get: - consumes: - - application/json - description: Get user detail - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: accountId - in: path - name: accountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetUserResponse' - security: - - JWT: [] - summary: Get user detail - tags: - - Users - put: - consumes: - - application/json - description: Update user - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: accountId - in: path - name: accountId - required: true - type: string - - description: input - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateUserRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.UpdateUserResponse' - security: - - JWT: [] - summary: Update user - tags: - - Users - /organizations/{organizationId}/users/{accountId}/reset-password: - put: - consumes: - - application/json - description: Reset user's password as temporary password by admin and send email - to user - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: accountId - in: path - name: accountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Reset user's password as temporary password by admin - tags: - - Users - /organizations/{organizationId}/users/account-id/{accountId}/existence: - get: - description: return true when accountId exists - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: accountId - in: path - name: accountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CheckExistedResponse' - security: - - JWT: [] - summary: Get user id existence - tags: - - Users - /organizations/{organizationId}/users/email/{email}/existence: - get: - description: return true when email exists - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: email - in: path - name: accountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CheckExistedResponse' - security: - - JWT: [] - summary: Get user email existence - tags: - - Users - /stack-templates: - get: - consumes: - - application/json - description: Get StackTemplates - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetStackTemplatesResponse' - security: - - JWT: [] - summary: Get StackTemplates - tags: - - StackTemplates - post: - consumes: - - application/json - description: Create StackTemplate - parameters: - - description: create stack template request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.CreateStackTemplateRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.CreateStackTemplateResponse' - security: - - JWT: [] - summary: Create StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates - /stack-templates/{stackTemplateId}: - delete: - consumes: - - application/json - description: Delete StackTemplate - parameters: - - description: stackTemplateId - in: path - name: stackTemplateId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates - get: - consumes: - - application/json - description: Get StackTemplate - parameters: - - description: stackTemplateId - in: path - name: stackTemplateId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetStackTemplateResponse' - security: - - JWT: [] - summary: Get StackTemplate - tags: - - StackTemplates - put: - consumes: - - application/json - description: Update StackTemplate - parameters: - - description: Update stack template request - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateStackTemplateRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates - /system-api/organizations/{organizationId}/alerts: - post: - consumes: - - application/json - description: Create alert. ADMIN ONLY - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Create alert. ADMIN ONLY - tags: - - Alerts -securityDefinitions: - JWT: - in: header - name: Authorization - type: apiKey -swagger: "2.0" diff --git a/go.work b/go.work deleted file mode 100644 index 9a21ec73..00000000 --- a/go.work +++ /dev/null @@ -1,5 +0,0 @@ -go 1.18 - -use ( - . -) diff --git a/go.work.sum b/go.work.sum deleted file mode 100644 index 375ce61a..00000000 --- a/go.work.sum +++ /dev/null @@ -1,503 +0,0 @@ -cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= -cloud.google.com/go/compute v1.6.1 h1:2sMmt8prCn7DPaG4Pmh0N3Inmc8cT8ae5k1M6VJ9Wqc= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= -cloud.google.com/go/firestore v1.6.1 h1:8rBq3zRjnHx8UtBvaOWqBB1xq9jH6/wltfQLlTMh2Fw= -cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= -cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= -cloud.google.com/go/storage v1.14.0 h1:6RRlFMv1omScs6iq2hfE3IvgE+l6RfJPampq8UZc5TU= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= -github.com/Azure/azure-sdk-for-go v43.0.0+incompatible h1:/wSNCu0e6EsHFR4Qa3vBEBbicaprEHMyyga9g8RTULI= -github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= -github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= -github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= -github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= -github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= -github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= -github.com/Azure/go-autorest/autorest/to v0.3.0 h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8= -github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= -github.com/Azure/go-autorest/autorest/validation v0.1.0 h1:ISSNzGUh+ZSzizJWOWzs8bwpXIePbGLW4z/AmUFGH5A= -github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= -github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= -github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/hcsshim v0.9.6 h1:VwnDOgLeoi2du6dAznfmspNqTiwczvjv4K7NxuY9jsY= -github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= -github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 h1:4SPQljF/GJ8Q+QlCWMWxRBepub4DresnOm4eI2ebFGc= -github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 h1:AUNCr9CiJuwrRYS3XieqF+Z9B9gNxo/eANAJCF2eiN4= -github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= -github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= -github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e h1:GCzyKMDDjSGnlpl3clrdAK7I1AaVoaiKDOYkUzChZzg= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= -github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= -github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= -github.com/aws/aws-sdk-go v1.35.24 h1:U3GNTg8+7xSM6OAJ8zksiSM4bRqxBWmVwwehvOSNG3A= -github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= -github.com/bketelsen/crypt v0.0.4 h1:w/jqZtC9YD4DS/Vp9GhWfWcCpuAL58oTnLoI8vE9YHU= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= -github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= -github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= -github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= -github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= -github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns= -github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= -github.com/containerd/stargz-snapshotter/estargz v0.7.0 h1:1d/rydzTywc76lnjJb6qbPCiTiCwts49AzKps/Ecblw= -github.com/containerd/stargz-snapshotter/estargz v0.7.0/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw= -github.com/coredns/caddy v1.1.0 h1:ezvsPrT/tA/7pYDBZxu0cT0VmWk75AfIaf6GSYCNMf0= -github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= -github.com/coredns/corefile-migration v1.0.17 h1:tNwh8+4WOANV6NjSljwgW7qViJfhvPUt1kosj4rR8yg= -github.com/coredns/corefile-migration v1.0.17/go.mod h1:XnhgULOEouimnzgn0t4WPuFDN2/PJQcTxdWKC5eXNGE= -github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= -github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= -github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= -github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= -github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= -github.com/cppforlife/cobrautil v0.0.0-20200514214827-bb86e6965d72 h1:rPWcUBgMb1ox2eCohCuZ8gsZVe0aB5qBbYaBpdoxfCE= -github.com/cppforlife/cobrautil v0.0.0-20200514214827-bb86e6965d72/go.mod h1:2w+qxVu2KSGW78Ex/XaIqfh/OvBgjEsmN53S4T8vEyA= -github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835 h1:mYQweUIBD+TBRjIeQnJmXr0GSVMpI6O0takyb/aaOgo= -github.com/cppforlife/color v1.9.1-0.20200716202919-6706ac40b835/go.mod h1:dYeVsKp1vvK8XjdTPR1gF+uk+9doxKeO3hqQTOCr7T4= -github.com/cppforlife/go-cli-ui v0.0.0-20200716203538-1e47f820817f h1:yVW0v4zDXzJo1i8G9G3vtvNpyzhvtLalO34BsN/K88E= -github.com/cppforlife/go-cli-ui v0.0.0-20200716203538-1e47f820817f/go.mod h1:L18TqO77ci8i+hFtlMC4zSFz/D3O8lf84TyVU+zFF8E= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4= -github.com/docker/cli v20.10.21+incompatible h1:qVkgyYUnOLQ98LtXBrwd/duVqPT2X4SHndOuGsfwyhU= -github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= -github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= -github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= -github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= -github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= -github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0= -github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= -github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 h1:dulLQAYQFYtG5MTplgNGHWuV2D+OBD+Z8lmDBmbLg+s= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= -github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/flatcar-linux/container-linux-config-transpiler v0.9.2 h1:EZKQ25jmhNfj+VAvdhPLLc4jmnSnRwFrI4x4dlPWXqE= -github.com/flatcar-linux/container-linux-config-transpiler v0.9.2/go.mod h1:AGVTulMzeIKwurV9ExYH3UiokET1Ur65g+EIeRDMwzM= -github.com/flatcar-linux/ignition v0.36.1 h1:yNvS9sQvm9HJ8VgxXskx88DsF73qdF35ALJkbTwcYhY= -github.com/flatcar-linux/ignition v0.36.1/go.mod h1:0jS5n4AopgOdwgi7QDo5MFgkMx/fQUDYjuxlGJC1Txg= -github.com/florianl/go-conntrack v0.3.0 h1:DUY84Mce+/lE9dJi2EWvGYacQtX2X96J9aVWV99l8UE= -github.com/florianl/go-conntrack v0.3.0/go.mod h1:Q+Um4J/nWUXSbnyzQRMOP4eweSeEQ2G8sfCO5gMz6Pw= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= -github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/getkin/kin-openapi v0.76.0 h1:j77zg3Ec+k+r+GA3d8hBoXpAc6KX9TbBPrwQGBIy2sY= -github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= -github.com/go-kit/log v0.1.0 h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ= -github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gobuffalo/flect v0.2.4/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= -github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= -github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/cel-go v0.9.0 h1:u1hg7lcZ/XWw2d3aV1jFS30ijQQ6q0/h1C2ZBeBD1gY= -github.com/google/cel-spec v0.6.0 h1:xuthJSiJGoSzq+lVEBIW1MTpaaZXknMCYC4WzVAWOsE= -github.com/google/go-containerregistry v0.6.0 h1:niQ+8XD//kKgArIFwDVBXsWVWbde16LPdHMyNwSC8h4= -github.com/google/go-containerregistry v0.6.0/go.mod h1:euCCtNbZ6tKqi1E72vwDj2xZcN5ttKpZLfa/wSo5iLw= -github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM= -github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= -github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 h1:zIaiqGYDQwa4HVx5wGRTXbx38Pqxjemn4BP98wpzpXo= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/googleapis/gax-go/v2 v2.4.0 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= -github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= -github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/hashicorp/consul/api v1.12.0 h1:k3y1FYv6nuKyNTqj6w9gXOx5r5CfLj/k/euUeBXj1OY= -github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= -github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= -github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= -github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= -github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= -github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= -github.com/hashicorp/serf v0.9.7 h1:hkdgbqizGQHuU5IPqYM1JdSMV8nKfpuOnZYXssk9muY= -github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= -github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd h1:efcJu2Vzz6DoSq245deWNzTz6l/gsqdphm3FjmI88/g= -github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= -github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= -github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= -github.com/jackpal/gateway v1.0.7 h1:7tIFeCGmpyrMx9qvT0EgYUi7cxVW48a0mMvnIL17bPM= -github.com/jackpal/gateway v1.0.7/go.mod h1:aRcO0UFKt+MgIZmRmvOmnejdDT4Y1DNiNOsSd1AcIbA= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= -github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/k14s/imgpkg v0.21.0 h1:zQvLI0PT9oH9emfAq7gXsyuKEF1MYdaSqO/012/QqQs= -github.com/k14s/imgpkg v0.21.0/go.mod h1:p2hsjGOtiIQlqO1+1TJ4PnCsK3SjnZgqmjoDMPewtlY= -github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= -github.com/klauspost/compress v1.13.0 h1:2T7tUoQrQT+fQWdaY5rjWztFGAFwbGD04iPJg90ZiOs= -github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= -github.com/kube-vip/kube-vip v0.5.5 h1:ZtCp3417IaZtI6JLKqf3mciERyopouyW5eB5QjVQ3Bk= -github.com/kube-vip/kube-vip v0.5.5/go.mod h1:60rF7LtNs7RopdOB8LYk+2X/SF5cT56Gb2n8a3ik4qQ= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= -github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc h1:m7rJJJeXrYCFpsxXYapkDW53wJCDmf9bsIXUg0HoeQY= -github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc/go.mod h1:eOj1DDj3NAZ6yv+WafaKzY37MFZ58TdfIhQ+8nQbiis= -github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE= -github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= -github.com/mdlayher/ndp v0.10.0 h1:Zdwol2bq1EHY8xSnejIYkq6LEj7dLjLymJX0o/2tjGw= -github.com/mdlayher/ndp v0.10.0/go.mod h1:Uv6IWvgvqirNUu2N3ZXJEB86xu6foyUsG0NrClSSfek= -github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0= -github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= -github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b h1:MHcTarUMC4sFA7eiyR8IEJ6j2PgmgXR+B9X2IIMjh7A= -github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= -github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM= -github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= -github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= -github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= -github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= -github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc h1:m7rJJJeXrYCFpsxXYapkDW53wJCDmf9bsIXUg0HoeQY= -github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc/go.mod h1:eOj1DDj3NAZ6yv+WafaKzY37MFZ58TdfIhQ+8nQbiis= -github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE= -github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= -github.com/mdlayher/ndp v0.10.0 h1:Zdwol2bq1EHY8xSnejIYkq6LEj7dLjLymJX0o/2tjGw= -github.com/mdlayher/ndp v0.10.0/go.mod h1:Uv6IWvgvqirNUu2N3ZXJEB86xu6foyUsG0NrClSSfek= -github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0= -github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= -github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b h1:MHcTarUMC4sFA7eiyR8IEJ6j2PgmgXR+B9X2IIMjh7A= -github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= -github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM= -github.com/mdlayher/socket v0.2.3/go.mod h1:bz12/FozYNH/VbvC3q7TRIK/Y6dH1kCKsXaUeXi/FmY= -github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= -github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= -github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= -github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= -github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= -github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= -github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= -github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= -github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 h1:0XM1XL/OFFJjXsYXlG30spTkV/E9+gmd5GD1w2HE8xM= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= -github.com/rs/zerolog v1.15.0 h1:uPRuwkWF4J6fGsJ2R0Gn2jB1EQiav9k3S6CSdygQJXY= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f h1:UFr9zpz4xgTnIE5yIMtWAMngCdZ9p/+q6lTbgelo80M= -github.com/sagikazarmark/crypt v0.6.0 h1:REOEXCs/NFY/1jOCEouMuT4zEniE5YoXbvpC5X/TLF8= -github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= -github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= -github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME= -github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= -github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc= -github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= -github.com/vdemeester/k8s-pkg-credentialprovider v1.21.0-1 h1:7Ajl3rjeYoB5V47jPknnLbyxYlhMXTTJiQsye5aT7f0= -github.com/vdemeester/k8s-pkg-credentialprovider v1.21.0-1/go.mod h1:l4LxiP0cmEcc5q4BTDE8tZSyIiyXe0T28x37yHpMzoM= -github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= -github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= -github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA= -github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec h1:Klu98tQ9Z1t23gvC7p7sCmvxkZxLhBHLNyrUPsWsYFg= -github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec/go.mod h1:wPlfmglZmRWMYv/qJy3P+fK/UnoQB5ISk4txfNd9tDo= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zenazn/goji v0.9.0 h1:RSQQAbXGArQ0dIDEq+PI6WqN6if+5KHu6x2Cx/GXLTQ= -gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f h1:Wku8eEdeJqIOFHtrfkYUByc4bCaTeA6fL0UJgfEiFMI= -gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:Tiuhl+njh/JIg0uS/sOJVYi0x2HEa5rc1OAaVsb5tAs= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= -go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= -go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= -go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.4 h1:Dcx3/MYyfKcPNLpR4VVQUP5KgYrBeJtktBwEKkw08Ao= -go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= -go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4= -go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= -go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= -go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= -go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= -go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= -go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= -go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= -go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go4.org v0.0.0-20201209231011-d4a079459e60 h1:iqAGo78tVOJXELHQFRjR6TMwItrvXH4hrGJ32I/NFF8= -go4.org v0.0.0-20201209231011-d4a079459e60/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.81.0 h1:o8WF5AvfidafWbFjsRyupxyEQJNUWxLZJCK5NXrxZZ8= -google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= -google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I= -google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ= -google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec h1:RlWgLqCMMIYYEVcAR5MDsuHlVkaIPDAF+5Dehzg8L5A= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= -gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA= -gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= -gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= -honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= -k8s.io/apiserver v0.23.5 h1:2Ly8oUjz5cnZRn1YwYr+aFgDZzUmEVL9RscXbnIeDSE= -k8s.io/cli-runtime v0.23.0 h1:UONt0BV2+edjUVAXuR1nnOAL2CB9r+Gl9yk4UBQpKfs= -k8s.io/cli-runtime v0.23.0/go.mod h1:B5N3YH0KP1iKr6gEuJ/RRmGjO0mJQ/f/JrsmEiPQAlU= -k8s.io/cloud-provider v0.21.0 h1:NSTS+czpv6LQAaIpY/VUghsT4oj62hYmQPErkDKTzKU= -k8s.io/cloud-provider v0.21.0/go.mod h1:z17TQgu3JgUFjcgby8sj5X86YdVK5Pbt+jm/eYMZU9M= -k8s.io/cluster-bootstrap v0.25.4 h1:m50ICwMsEW13N7Z/tdTmLwELGHt4SJEJaeriPdQRxs0= -k8s.io/cluster-bootstrap v0.25.4/go.mod h1:q6XZzStf/uGcXUZhMHmRB8ael1k+bv8//AajQ6FPJag= -k8s.io/code-generator v0.23.5 h1:xn3a6J5pUL49AoH6SPrOFtnB5cvdMl76f/bEY176R3c= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c h1:GohjlNKauSai7gN4wsJkeZ3WAJx4Sh+oT/b5IYn5suA= -k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg= -k8s.io/legacy-cloud-providers v0.21.0 h1:iWf5xaX9yvYT5mkz8UB96UtISQ5IkrWeuMPMhRp01ZY= -k8s.io/legacy-cloud-providers v0.21.0/go.mod h1:bNxo7gDg+PGkBmT/MFZswLTWdSWK9kAlS1s8DJca5q4= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= -rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 h1:dUk62HQ3ZFhD48Qr8MIXCiKA8wInBQCtuE4QGfFW7yA= -sigs.k8s.io/cluster-api/test v1.1.5 h1:jukMEA50R3V6G7VcJMR7dMZJPd3Tuf0Orc/6CKuS9Ek= -sigs.k8s.io/cluster-api/test v1.1.5/go.mod h1:NXFioUFKruk/PgpUt4QrprV9bN1rVUcm7OWao9dfesg= -sigs.k8s.io/kind v0.14.0 h1:cNmI3jGBvp7UegEGbC5we8plDtCUmaNRL+bod7JoSCE= -sigs.k8s.io/kind v0.14.0/go.mod h1:UrFRPHG+2a5j0Q7qiR4gtJ4rEyn8TuMQwuOPf+m4oHg= -sigs.k8s.io/kustomize/api v0.10.1 h1:KgU7hfYoscuqag84kxtzKdEC3mKMb99DPI3a0eaV1d0= -sigs.k8s.io/kustomize/api v0.10.1/go.mod h1:2FigT1QN6xKdcnGS2Ppp1uIWrtWN28Ms8A3OZUZhwr8= -sigs.k8s.io/kustomize/kyaml v0.13.0 h1:9c+ETyNfSrVhxvphs+K2dzT3dh5oVPPEqPOE/cUpScY= -sigs.k8s.io/kustomize/kyaml v0.13.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E= From acdf0d8c7b4f376e06bb5b122d357d0ef1d2699b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Jan 2024 17:12:47 +0900 Subject: [PATCH 014/502] resotre generated files for local environment --- api/swagger/docs.go | 6874 ++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.json | 6851 +++++++++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 4453 ++++++++++++++++++++++++ 3 files changed, 18178 insertions(+) create mode 100644 api/swagger/docs.go create mode 100644 api/swagger/swagger.json create mode 100644 api/swagger/swagger.yaml diff --git a/api/swagger/docs.go b/api/swagger/docs.go new file mode 100644 index 00000000..3b595793 --- /dev/null +++ b/api/swagger/docs.go @@ -0,0 +1,6874 @@ +// Package swagger GENERATED BY SWAG; DO NOT EDIT +// This file was generated by swaggo/swag +package swagger + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": { + "name": "taekyu.kang@sk.com", + "email": "taekyu.kang@sk.com" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/app-groups": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appGroup list by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Get appGroup list", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "query" + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppGroupsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install appGroup", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Install appGroup", + "parameters": [ + { + "description": "create appgroup request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateAppGroupRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateAppGroupResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Uninstall appGroup", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Uninstall appGroup", + "parameters": [ + { + "description": "body", + "name": "object", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/app-groups/{appGroupId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appGroup detail by appGroupId", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Get appGroup detail", + "parameters": [ + { + "type": "string", + "description": "appGroupId", + "name": "appGroupId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppGroupResponse" + } + } + } + } + }, + "/app-groups/{appGroupId}/applications": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get applications", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Get applications", + "parameters": [ + { + "type": "string", + "description": "appGroupId", + "name": "appGroupId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "applicationType", + "name": "applicationType", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetApplicationsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create application", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Create application", + "parameters": [ + { + "description": "body", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateApplicationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/auth/find-id/code": { + "post": { + "description": "This API allows users to verify their identity for lost id by submitting required information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "Request to verify identity for lost id", + "parameters": [ + { + "description": "Request body for verifying identity for lost id including {organization ID, email, username}", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.VerifyIdentityForLostIdRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.VerifyIdentityForLostIdResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/auth/find-id/verification": { + "post": { + "description": "This API allows users to find their account ID by submitting required information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "Request to find forgotten ID", + "parameters": [ + { + "description": "Request body for finding the account ID including {organization ID, email, username, 6 digit code}", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.FindIdRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.FindIdResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/auth/find-password/code": { + "post": { + "description": "This API allows users to verify their identity for lost password by submitting required information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "Request to verify identity for lost password", + "parameters": [ + { + "description": "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/auth/find-password/verification": { + "post": { + "description": "This API allows users to reset their forgotten password by submitting required information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "Request to find forgotten password", + "parameters": [ + { + "description": "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.FindPasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/auth/login": { + "post": { + "description": "login", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "login", + "parameters": [ + { + "description": "account info", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.LoginRequest" + } + } + ], + "responses": { + "200": { + "description": "user detail", + "schema": { + "$ref": "#/definitions/domain.LoginResponse" + } + } + } + } + }, + "/auth/logout": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "logout", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "logout", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.LogoutResponse" + } + } + } + } + }, + "/auth/ping": { + "post": { + "description": "ping with token", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "ping with token", + "parameters": [ + { + "description": "token info", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.PingTokenRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/clusters": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get cluster list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get clusters", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "query" + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetClustersResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Create cluster", + "parameters": [ + { + "description": "create cluster request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateClusterRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateClusterResponse" + } + } + } + } + }, + "/clusters/import": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Import cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Import cluster", + "parameters": [ + { + "description": "import cluster request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.ImportClusterRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.ImportClusterResponse" + } + } + } + } + }, + "/clusters/{clusterId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get cluster detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get cluster", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.Cluster" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Delete cluster", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.Cluster" + } + } + } + } + }, + "/clusters/{clusterId}/bootstrap-kubeconfig": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get bootstrap kubeconfig for BYOH", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get bootstrap kubeconfig for BYOH", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetBootstrapKubeconfigResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create bootstrap kubeconfig for BYOH", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Create bootstrap kubeconfig for BYOH", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateBootstrapKubeconfigResponse" + } + } + } + } + }, + "/clusters/{clusterId}/install": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install cluster on tks cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Install cluster on tks cluster", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/clusters/{clusterId}/nodes": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get nodes information for BYOH", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get nodes information for BYOH", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetClusterNodesResponse" + } + } + } + } + }, + "/clusters/{clusterId}/site-values": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get cluster site values for creating", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get cluster site values for creating", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.ClusterSiteValuesResponse" + } + } + } + } + }, + "/organizations": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get organization list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Get organization list", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ListOrganizationBody" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create organization", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Create organization", + "parameters": [ + { + "description": "create organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + } + } + } + }, + "/organizations/{organizationId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get organization detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Get organization detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetOrganizationResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update organization detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Update organization detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.UpdateOrganizationResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete organization", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Delete organization", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.Organization" + } + } + } + } + }, + "/organizations/{organizationId}/alerts": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Alerts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Get Alerts", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAlertsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/alerts/{alertId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Alert", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Get Alert", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "alertId", + "name": "alertId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAlertResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update Alert", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Update Alert", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAlertRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Alert", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Delete Alert", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "alertId", + "name": "alertId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/alerts/{alertId}/actions": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create alert action", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Create alert action", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp list by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp list", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "boolean", + "description": "Show all apps including deleted apps", + "name": "showAll", + "in": "query" + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppServeApp" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Install appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to create app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/count": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get number of apps on given stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get number of apps on given stack", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check duplicate appServeAppName by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Check duplicate appServeAppName", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Uninstall appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Uninstall appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/endpoint": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update app endpoint", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update app endpoint", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "appId", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app endpoint", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/exist": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/latest-task": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get latest task from appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get latest task from appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/rollback": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Rollback appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Rollback appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to rollback app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.RollbackAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/status": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update app status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update app status", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app status", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get CloudAccounts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Get CloudAccounts", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetCloudAccountsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Create CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateCloudAccountRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateCloudAccountResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check awsAccountId for cloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Check awsAccountId for cloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "awsAccountId", + "name": "awsAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckCloudAccountAwsAccountIdResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for cloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Check name for cloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckCloudAccountNameResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Get CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cloudAccountId", + "name": "cloudAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetCloudAccountResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Update CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateCloudAccountRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Delete CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Delete cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.DeleteCloudAccountRequest" + } + }, + { + "type": "string", + "description": "cloudAccountId", + "name": "cloudAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Force CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Delete Force CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cloudAccountId", + "name": "cloudAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get resource quota by cloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Get resource quota by cloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cloudAccountId", + "name": "cloudAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetCloudAccountResourceQuotaResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboard/charts": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get charts data", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get charts data", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "chartType", + "name": "chartType", + "in": "query" + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetDashboardChartsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboard/charts/{chartType}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get chart data", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get chart data", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "chartType", + "name": "chartType", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetDashboardChartResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboard/resources": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get resources", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get resources", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetDashboardResourcesResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboard/stacks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get stacks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get stacks", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetDashboardStacksResponse" + } + } + } + } + }, + "/organizations/{organizationId}/my-profile": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get my profile detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Get my profile detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetMyProfileResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update my profile detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update my profile detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Required fields: password due to double-check", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateMyProfileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.UpdateMyProfileResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete myProfile", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Delete myProfile", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request" + } + } + } + }, + "/organizations/{organizationId}/my-profile/next-password-change": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user's password expired date to current date", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update user's password expired date to current date", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/organizations/{organizationId}/my-profile/password": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user password detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update user password detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update user password request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdatePasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/primary-cluster": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update primary cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Update primary cluster", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update primary cluster request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdatePrimaryClusterRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stacks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stacks", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "string", + "description": "combinedFilter", + "name": "combinedFilter", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStacksResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Create Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateStackResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Check name for stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Update Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Delete Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/favorite": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Set favorite stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Set favorite stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete favorite stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Delete favorite stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get KubeConfig by stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get KubeConfig by stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "organizationId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackKubeConfigResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack Status", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user list", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ListUserBody" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create user request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "create user response", + "schema": { + "$ref": "#/definitions/domain.CreateUserResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "return true when accountId exists", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user id existence", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/email/{email}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "return true when email exists", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user email existence", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "email", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetUserResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.UpdateUserResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.User" + } + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}/reset-password": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Reset user's password as temporary password by admin and send email to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Reset user's password as temporary password by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/stack-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackTemplatesResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "description": "create stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateStackTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateStackTemplateResponse" + } + } + } + } + }, + "/stack-templates/{stackTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplate", + "parameters": [ + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackTemplateResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "description": "Update stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateStackTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/system-api/organizations/{organizationId}/alerts": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create alert. ADMIN ONLY", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Create alert. ADMIN ONLY", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "definitions": { + "domain.ActionResponse": { + "type": "object", + "properties": { + "body": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "method": { + "type": "string" + }, + "name": { + "description": "ENDPOINT (화면보기), PREVIEW (미리보기), PROMOTE (배포), ABORT (중단)", + "type": "string" + }, + "type": { + "description": "LINK, API", + "type": "string" + }, + "uri": { + "type": "string" + } + } + }, + "domain.AlertActionResponse": { + "type": "object", + "properties": { + "alertId": { + "type": "string" + }, + "content": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "taker": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.AlertResponse": { + "type": "object", + "properties": { + "alertActions": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AlertActionResponse" + } + }, + "closedAt": { + "type": "string" + }, + "cluster": { + "$ref": "#/definitions/domain.SimpleClusterResponse" + }, + "code": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "firedAt": { + "type": "string" + }, + "grade": { + "type": "string" + }, + "grafanaUrl": { + "type": "string" + }, + "id": { + "type": "string" + }, + "lastTaker": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "message": { + "type": "string" + }, + "name": { + "type": "string" + }, + "node": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "processingSec": { + "type": "integer" + }, + "rawData": { + "type": "string" + }, + "status": { + "type": "string" + }, + "takedAt": { + "type": "string" + }, + "takedSec": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.AppGroupResponse": { + "type": "object", + "properties": { + "appGroupType": { + "type": "integer" + }, + "clusterId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "workflowId": { + "type": "string" + } + } + }, + "domain.AppServeApp": { + "type": "object", + "properties": { + "appServeAppTasks": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppServeAppTask" + } + }, + "appType": { + "description": "appType (spring/springboot)", + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "endpointUrl": { + "description": "endpoint URL of deployed app", + "type": "string" + }, + "grafanaUrl": { + "description": "grafana dashboard URL for deployed app", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "description": "application name", + "type": "string" + }, + "namespace": { + "description": "application namespace", + "type": "string" + }, + "organizationId": { + "description": "contractId is a contract ID which this app belongs to", + "type": "string" + }, + "previewEndpointUrl": { + "description": "preview svc endpoint URL in B/G deployment", + "type": "string" + }, + "status": { + "description": "status is status of deployed app", + "type": "string" + }, + "targetClusterId": { + "description": "target cluster to which the app is deployed", + "type": "string" + }, + "targetClusterName": { + "description": "target cluster name", + "type": "string" + }, + "type": { + "description": "type (build/deploy/all)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.AppServeAppTask": { + "type": "object", + "properties": { + "appConfig": { + "description": "java app config", + "type": "string" + }, + "appSecret": { + "description": "java app secret", + "type": "string" + }, + "appServeAppId": { + "description": "ID for appServeApp that this task belongs to", + "type": "string" + }, + "artifactUrl": { + "description": "URL of java app artifact (Eg, Jar)", + "type": "string" + }, + "availableRollback": { + "type": "boolean" + }, + "createdAt": { + "description": "createdAt is a creation timestamp for the application", + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "executablePath": { + "description": "Executable path of app image", + "type": "string" + }, + "extraEnv": { + "description": "env variable list for java app", + "type": "string" + }, + "helmRevision": { + "description": "revision of deployed helm release", + "type": "integer" + }, + "id": { + "type": "string" + }, + "imageUrl": { + "description": "URL of built image for app", + "type": "string" + }, + "output": { + "description": "output for task result", + "type": "string" + }, + "port": { + "description": "java app port", + "type": "string" + }, + "profile": { + "description": "java app profile", + "type": "string" + }, + "pvAccessMode": { + "type": "string" + }, + "pvEnabled": { + "type": "boolean" + }, + "pvMountPath": { + "type": "string" + }, + "pvSize": { + "type": "string" + }, + "pvStorageClass": { + "type": "string" + }, + "resourceSpec": { + "description": "resource spec of app pod", + "type": "string" + }, + "rollbackVersion": { + "description": "rollback target version", + "type": "string" + }, + "status": { + "description": "status is app status", + "type": "string" + }, + "strategy": { + "description": "deployment strategy (eg, rolling-update)", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "version": { + "description": "application version", + "type": "string" + } + } + }, + "domain.ApplicationResponse": { + "type": "object", + "properties": { + "appGroupId": { + "type": "string" + }, + "applicationType": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "id": { + "type": "string" + }, + "metadata": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.Axis": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "domain.BootstrapKubeconfig": { + "type": "object", + "properties": { + "expiration": { + "type": "integer" + } + } + }, + "domain.ChartData": { + "type": "object", + "properties": { + "podCounts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.PodCount" + } + }, + "series": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.Unit" + } + }, + "xAxis": { + "$ref": "#/definitions/domain.Axis" + }, + "yAxis": { + "$ref": "#/definitions/domain.Axis" + } + } + }, + "domain.CheckCloudAccountAwsAccountIdResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "domain.CheckCloudAccountNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "domain.CheckExistedResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "domain.CloudAccount": { + "type": "object", + "properties": { + "accessKeyId": { + "type": "string" + }, + "awsAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusters": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "createdIAM": { + "type": "boolean" + }, + "creator": { + "$ref": "#/definitions/domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "secretAccessKey": { + "type": "string" + }, + "sessionToken": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.User" + }, + "updatorId": { + "type": "string" + } + } + }, + "domain.CloudAccountResponse": { + "type": "object", + "properties": { + "awsAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusters": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "createdIAM": { + "type": "boolean" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + } + } + }, + "domain.Cluster": { + "type": "object", + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "cloudAccount": { + "$ref": "#/definitions/domain.CloudAccount" + }, + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusterType": { + "type": "integer" + }, + "conf": { + "$ref": "#/definitions/domain.ClusterConf" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "favorited": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "isStack": { + "type": "boolean" + }, + "kubeconfig": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplate": { + "$ref": "#/definitions/domain.StackTemplate" + }, + "stackTemplateId": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.User" + }, + "updatorId": { + "type": "string" + } + } + }, + "domain.ClusterConf": { + "type": "object", + "properties": { + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.ClusterConfResponse": { + "type": "object", + "properties": { + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.ClusterHost": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "domain.ClusterNode": { + "type": "object", + "properties": { + "command": { + "type": "string" + }, + "hosts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ClusterHost" + } + }, + "registered": { + "type": "integer" + }, + "registering": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "targeted": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "validity": { + "type": "integer" + } + } + }, + "domain.ClusterResponse": { + "type": "object", + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "cloudAccount": { + "$ref": "#/definitions/domain.SimpleCloudAccountResponse" + }, + "cloudService": { + "type": "string" + }, + "clusterType": { + "type": "string" + }, + "conf": { + "$ref": "#/definitions/domain.ClusterConfResponse" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "isStack": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplate": { + "$ref": "#/definitions/domain.SimpleStackTemplateResponse" + }, + "status": { + "type": "string" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + } + } + }, + "domain.ClusterSiteValuesResponse": { + "type": "object", + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "clusterRegion": { + "type": "string" + }, + "clusterType": { + "type": "string" + }, + "sshKeyName": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.CreateAppGroupRequest": { + "type": "object", + "required": [ + "clusterId", + "name" + ], + "properties": { + "appGroupType": { + "type": "string", + "enum": [ + "LMA", + "SERVICE_MESH" + ] + }, + "clusterId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "domain.CreateAppGroupResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateAppServeAppRequest": { + "type": "object", + "required": [ + "name", + "targetClusterId" + ], + "properties": { + "appConfig": { + "type": "string" + }, + "appSecret": { + "type": "string" + }, + "appType": { + "description": "springboot spring", + "type": "string" + }, + "artifactUrl": { + "type": "string" + }, + "executablePath": { + "type": "string" + }, + "extraEnv": { + "type": "string" + }, + "imageUrl": { + "type": "string" + }, + "name": { + "description": "App", + "type": "string" + }, + "namespace": { + "type": "string" + }, + "port": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "pvAccessMode": { + "type": "string" + }, + "pvEnabled": { + "type": "boolean" + }, + "pvMountPath": { + "type": "string" + }, + "pvSize": { + "type": "string" + }, + "pvStorageClass": { + "type": "string" + }, + "resourceSpec": { + "description": "tiny medium large", + "type": "string" + }, + "strategy": { + "description": "rolling-update blue-green canary", + "type": "string" + }, + "targetClusterId": { + "type": "string" + }, + "type": { + "description": "build deploy all", + "type": "string" + }, + "version": { + "description": "Task", + "type": "string" + } + } + }, + "domain.CreateApplicationRequest": { + "type": "object", + "properties": { + "applicationType": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "metadata": { + "type": "string" + } + } + }, + "domain.CreateBootstrapKubeconfigResponse": { + "type": "object", + "properties": { + "kubeconfig": { + "$ref": "#/definitions/domain.BootstrapKubeconfig" + } + } + }, + "domain.CreateCloudAccountRequest": { + "type": "object", + "required": [ + "accessKeyId", + "awsAccountId", + "name", + "secretAccessKey" + ], + "properties": { + "accessKeyId": { + "type": "string", + "maxLength": 128, + "minLength": 16 + }, + "awsAccountId": { + "type": "string", + "maxLength": 12, + "minLength": 12 + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "AZZURE", + "GCP" + ] + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "secretAccessKey": { + "type": "string", + "maxLength": 128, + "minLength": 16 + }, + "sessionToken": { + "type": "string", + "maxLength": 2000 + } + } + }, + "domain.CreateCloudAccountResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateClusterRequest": { + "type": "object", + "required": [ + "cloudService", + "name", + "organizationId", + "stackTemplateId" + ], + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "BYOH" + ] + }, + "clusterType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "isStack": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplateId": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.CreateClusterResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateOrganizationRequest": { + "type": "object", + "required": [ + "Email", + "name" + ], + "properties": { + "Email": { + "type": "string" + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "domain.CreateStackRequest": { + "type": "object", + "required": [ + "cloudService", + "name", + "stackTemplateId" + ], + "properties": { + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "BYOH" + ] + }, + "clusterId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "stackTemplateId": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + }, + "userClusterEndpoint": { + "type": "string" + } + } + }, + "domain.CreateStackResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateStackTemplateRequest": { + "type": "object", + "required": [ + "name", + "platform", + "template", + "version" + ], + "properties": { + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "AZZURE", + "GCP" + ] + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string", + "enum": [ + "STANDARD", + "MSA" + ] + }, + "version": { + "type": "string" + } + } + }, + "domain.CreateStackTemplateResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateUserRequest": { + "type": "object", + "required": [ + "accountId", + "email", + "password", + "role" + ], + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "password": { + "type": "string" + }, + "role": { + "type": "string", + "enum": [ + "admin", + "user" + ] + } + } + }, + "domain.CreateUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + } + } + } + } + }, + "domain.DashboardChartResponse": { + "type": "object", + "properties": { + "chartData": { + "$ref": "#/definitions/domain.ChartData" + }, + "chartType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "string" + }, + "interval": { + "type": "string" + }, + "month": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "year": { + "type": "string" + } + } + }, + "domain.DashboardResource": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + }, + "stack": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, + "domain.DashboardStackResponse": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "memory": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string" + }, + "statusDesc": { + "type": "string" + }, + "storage": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.DeleteCloudAccountRequest": { + "type": "object", + "required": [ + "accessKeyId", + "secretAccessKey" + ], + "properties": { + "accessKeyId": { + "type": "string", + "maxLength": 128, + "minLength": 16 + }, + "secretAccessKey": { + "type": "string", + "maxLength": 128, + "minLength": 16 + }, + "sessionToken": { + "type": "string", + "maxLength": 2000 + } + } + }, + "domain.FilterResponse": { + "type": "object", + "properties": { + "column": { + "type": "string" + }, + "operator": { + "type": "string" + }, + "releation": { + "type": "string" + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "domain.FindIdRequest": { + "type": "object", + "required": [ + "code", + "email", + "organizationId", + "userName" + ], + "properties": { + "code": { + "type": "string" + }, + "email": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, + "domain.FindIdResponse": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + } + } + }, + "domain.FindPasswordRequest": { + "type": "object", + "required": [ + "accountId", + "code", + "email", + "organizationId", + "userName" + ], + "properties": { + "accountId": { + "type": "string" + }, + "code": { + "type": "string" + }, + "email": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, + "domain.GetAlertResponse": { + "type": "object", + "properties": { + "alert": { + "$ref": "#/definitions/domain.AlertResponse" + } + } + }, + "domain.GetAlertsResponse": { + "type": "object", + "properties": { + "alerts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AlertResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, + "domain.GetAppGroupResponse": { + "type": "object", + "properties": { + "appGroup": { + "$ref": "#/definitions/domain.AppGroupResponse" + } + } + }, + "domain.GetAppGroupsResponse": { + "type": "object", + "properties": { + "appGroups": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppGroupResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, + "domain.GetAppServeAppResponse": { + "type": "object", + "properties": { + "appServeApp": { + "$ref": "#/definitions/domain.AppServeApp" + }, + "stages": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StageResponse" + } + } + } + }, + "domain.GetAppServeAppTaskResponse": { + "type": "object", + "properties": { + "appServeAppTask": { + "$ref": "#/definitions/domain.AppServeAppTask" + } + } + }, + "domain.GetApplicationsResponse": { + "type": "object", + "properties": { + "applications": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ApplicationResponse" + } + } + } + }, + "domain.GetBootstrapKubeconfigResponse": { + "type": "object", + "properties": { + "kubeconfig": { + "$ref": "#/definitions/domain.BootstrapKubeconfig" + } + } + }, + "domain.GetCloudAccountResourceQuotaResponse": { + "type": "object", + "properties": { + "available": { + "type": "boolean" + }, + "resourceQuota": { + "$ref": "#/definitions/domain.ResourceQuota" + } + } + }, + "domain.GetCloudAccountResponse": { + "type": "object", + "properties": { + "cloudAccount": { + "$ref": "#/definitions/domain.CloudAccountResponse" + } + } + }, + "domain.GetCloudAccountsResponse": { + "type": "object", + "properties": { + "cloudAccounts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.CloudAccountResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, + "domain.GetClusterNodesResponse": { + "type": "object", + "properties": { + "nodes": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ClusterNode" + } + } + } + }, + "domain.GetClustersResponse": { + "type": "object", + "properties": { + "clusters": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ClusterResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, + "domain.GetDashboardChartResponse": { + "type": "object", + "properties": { + "chart": { + "$ref": "#/definitions/domain.DashboardChartResponse" + } + } + }, + "domain.GetDashboardChartsResponse": { + "type": "object", + "properties": { + "charts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.DashboardChartResponse" + } + } + } + }, + "domain.GetDashboardResourcesResponse": { + "type": "object", + "properties": { + "resources": { + "$ref": "#/definitions/domain.DashboardResource" + } + } + }, + "domain.GetDashboardStacksResponse": { + "type": "object", + "properties": { + "stacks": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.DashboardStackResponse" + } + } + } + }, + "domain.GetMyProfileResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + } + } + } + } + }, + "domain.GetOrganizationResponse": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "primaryClusterId": { + "type": "string" + }, + "status": { + "type": "string" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "domain.GetStackKubeConfigResponse": { + "type": "object", + "properties": { + "kubeConfig": { + "type": "string" + } + } + }, + "domain.GetStackResponse": { + "type": "object", + "properties": { + "stack": { + "$ref": "#/definitions/domain.StackResponse" + } + } + }, + "domain.GetStackStatusResponse": { + "type": "object", + "properties": { + "stackStatus": { + "type": "string" + }, + "stepStatus": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackStepStatus" + } + } + } + }, + "domain.GetStackTemplateResponse": { + "type": "object", + "properties": { + "stackTemplate": { + "$ref": "#/definitions/domain.StackTemplateResponse" + } + } + }, + "domain.GetStackTemplatesResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + }, + "stackTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackTemplateResponse" + } + } + } + }, + "domain.GetStacksResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + }, + "stacks": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackResponse" + } + } + } + }, + "domain.GetUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "domain.ImportClusterRequest": { + "type": "object", + "required": [ + "name", + "organizationId", + "stackTemplateId" + ], + "properties": { + "cloudService": { + "type": "string" + }, + "clusterType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "kubeconfig": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplateId": { + "type": "string" + } + } + }, + "domain.ImportClusterResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.ListOrganizationBody": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "primaryClusterId": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.ListUserBody": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.LoginRequest": { + "type": "object", + "required": [ + "accountId", + "organizationId", + "password" + ], + "properties": { + "accountId": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "domain.LoginResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "passwordExpired": { + "type": "boolean" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "token": { + "type": "string" + } + } + } + } + }, + "domain.LogoutResponse": { + "type": "object", + "properties": { + "ssoUrls": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "domain.Organization": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "primaryClusterId": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.PaginationResponse": { + "type": "object", + "properties": { + "filters": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.FilterResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "sortColumn": { + "type": "string" + }, + "sortOrder": { + "type": "string" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" + } + } + }, + "domain.PingTokenRequest": { + "type": "object", + "required": [ + "organizationId", + "token" + ], + "properties": { + "organizationId": { + "type": "string" + }, + "token": { + "type": "string" + } + } + }, + "domain.PodCount": { + "type": "object", + "properties": { + "day": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "domain.ResourceQuota": { + "type": "object", + "properties": { + "quotas": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ResourceQuotaAttr" + } + } + } + }, + "domain.ResourceQuotaAttr": { + "type": "object", + "properties": { + "quota": { + "type": "integer" + }, + "required": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "usage": { + "type": "integer" + } + } + }, + "domain.Role": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.RollbackAppServeAppRequest": { + "type": "object", + "properties": { + "taskId": { + "type": "string" + } + } + }, + "domain.SimpleCloudAccountResponse": { + "type": "object", + "properties": { + "awsAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusters": { + "type": "integer" + }, + "createdIAM": { + "type": "boolean" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + } + } + }, + "domain.SimpleClusterResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + } + } + }, + "domain.SimpleStackTemplateResponse": { + "type": "object", + "properties": { + "cloudService": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "services": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackTemplateServiceResponse" + } + }, + "template": { + "type": "string" + } + } + }, + "domain.SimpleUserResponse": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "domain.StackConfResponse": { + "type": "object", + "required": [ + "tksInfraNode", + "tksUserNode" + ], + "properties": { + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer", + "maximum": 3, + "minimum": 1 + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer", + "maximum": 100, + "minimum": 0 + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.StackResponse": { + "type": "object", + "properties": { + "cloudAccount": { + "$ref": "#/definitions/domain.SimpleCloudAccountResponse" + }, + "conf": { + "$ref": "#/definitions/domain.StackConfResponse" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "favorited": { + "type": "boolean" + }, + "grafanaUrl": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "primaryCluster": { + "type": "boolean" + }, + "resource": { + "$ref": "#/definitions/domain.DashboardStackResponse" + }, + "stackTemplate": { + "$ref": "#/definitions/domain.SimpleStackTemplateResponse" + }, + "status": { + "type": "string" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "userClusterEndpoint": { + "type": "string" + } + } + }, + "domain.StackStepStatus": { + "type": "object", + "properties": { + "maxStep": { + "type": "integer" + }, + "stage": { + "type": "string" + }, + "status": { + "type": "string" + }, + "step": { + "type": "integer" + } + } + }, + "domain.StackTemplate": { + "type": "object", + "properties": { + "cloudService": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "services": { + "type": "array", + "items": { + "type": "integer" + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.User" + }, + "updatorId": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "domain.StackTemplateResponse": { + "type": "object", + "properties": { + "cloudService": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "services": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackTemplateServiceResponse" + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "version": { + "type": "string" + } + } + }, + "domain.StackTemplateServiceApplicationResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "domain.StackTemplateServiceResponse": { + "type": "object", + "properties": { + "applications": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackTemplateServiceApplicationResponse" + } + }, + "type": { + "type": "string" + } + } + }, + "domain.StageResponse": { + "type": "object", + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ActionResponse" + } + }, + "name": { + "description": "BUILD (빌드), DEPLOY (배포), PROMOTE (프로모트), ROLLBACK (롤백)", + "type": "string" + }, + "result": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "domain.Unit": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "domain.UpdateAlertRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "domain.UpdateAppServeAppEndpointRequest": { + "type": "object", + "required": [ + "taskId" + ], + "properties": { + "endpointUrl": { + "type": "string" + }, + "helmRevision": { + "type": "integer" + }, + "previewEndpointUrl": { + "type": "string" + }, + "taskId": { + "type": "string" + } + } + }, + "domain.UpdateAppServeAppRequest": { + "type": "object", + "properties": { + "abort": { + "type": "boolean" + }, + "appConfig": { + "type": "string" + }, + "appSecret": { + "type": "string" + }, + "artifactUrl": { + "type": "string" + }, + "executablePath": { + "type": "string" + }, + "extraEnv": { + "type": "string" + }, + "imageUrl": { + "type": "string" + }, + "port": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "promote": { + "description": "Update Strategy", + "type": "boolean" + }, + "resourceSpec": { + "type": "string" + }, + "strategy": { + "description": "Task", + "type": "string" + } + } + }, + "domain.UpdateAppServeAppStatusRequest": { + "type": "object", + "required": [ + "status", + "taskId" + ], + "properties": { + "output": { + "type": "string" + }, + "status": { + "type": "string" + }, + "taskId": { + "type": "string" + } + } + }, + "domain.UpdateCloudAccountRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "domain.UpdateMyProfileRequest": { + "type": "object", + "required": [ + "password" + ], + "properties": { + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "password": { + "type": "string" + } + } + }, + "domain.UpdateMyProfileResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + } + } + } + } + }, + "domain.UpdateOrganizationRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "phone": { + "type": "string" + }, + "primaryClusterId": { + "type": "string" + } + } + }, + "domain.UpdateOrganizationResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "domain.UpdatePasswordRequest": { + "type": "object", + "required": [ + "newPassword", + "originPassword" + ], + "properties": { + "newPassword": { + "type": "string" + }, + "originPassword": { + "type": "string" + } + } + }, + "domain.UpdatePrimaryClusterRequest": { + "type": "object", + "properties": { + "primaryClusterId": { + "type": "string" + } + } + }, + "domain.UpdateStackRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "domain.UpdateStackTemplateRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "domain.UpdateUserRequest": { + "type": "object", + "properties": { + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "role": { + "type": "string", + "enum": [ + "admin", + "user" + ] + } + } + }, + "domain.UpdateUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "domain.User": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "password": { + "type": "string" + }, + "passwordExpired": { + "type": "boolean" + }, + "passwordUpdatedAt": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "token": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.VerifyIdentityForLostIdRequest": { + "type": "object", + "required": [ + "email", + "organizationId", + "userName" + ], + "properties": { + "email": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, + "domain.VerifyIdentityForLostIdResponse": { + "type": "object", + "properties": { + "validityPeriod": { + "type": "string" + } + } + }, + "domain.VerifyIdentityForLostPasswordRequest": { + "type": "object", + "required": [ + "accountId", + "email", + "organizationId", + "userName" + ], + "properties": { + "accountId": { + "type": "string" + }, + "email": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, + "domain.VerifyIdentityForLostPasswordResponse": { + "type": "object", + "properties": { + "validityPeriod": { + "type": "string" + } + } + }, + "httpErrors.RestError": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "text": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "JWT": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "1.0", + Host: "tks-api-ft.taco-cat.xyz", + BasePath: "/api/1.0/", + Schemes: []string{}, + Title: "tks-api service", + Description: "This is backend api service for tks platform", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json new file mode 100644 index 00000000..fa98668f --- /dev/null +++ b/api/swagger/swagger.json @@ -0,0 +1,6851 @@ +{ + "swagger": "2.0", + "info": { + "description": "This is backend api service for tks platform", + "title": "tks-api service", + "contact": { + "name": "taekyu.kang@sk.com", + "email": "taekyu.kang@sk.com" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0" + }, + "host": "tks-api-ft.taco-cat.xyz", + "basePath": "/api/1.0/", + "paths": { + "/app-groups": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appGroup list by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Get appGroup list", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "query" + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppGroupsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install appGroup", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Install appGroup", + "parameters": [ + { + "description": "create appgroup request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateAppGroupRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateAppGroupResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Uninstall appGroup", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Uninstall appGroup", + "parameters": [ + { + "description": "body", + "name": "object", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/app-groups/{appGroupId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appGroup detail by appGroupId", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Get appGroup detail", + "parameters": [ + { + "type": "string", + "description": "appGroupId", + "name": "appGroupId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppGroupResponse" + } + } + } + } + }, + "/app-groups/{appGroupId}/applications": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get applications", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Get applications", + "parameters": [ + { + "type": "string", + "description": "appGroupId", + "name": "appGroupId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "applicationType", + "name": "applicationType", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetApplicationsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create application", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppGroups" + ], + "summary": "Create application", + "parameters": [ + { + "description": "body", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateApplicationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/auth/find-id/code": { + "post": { + "description": "This API allows users to verify their identity for lost id by submitting required information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "Request to verify identity for lost id", + "parameters": [ + { + "description": "Request body for verifying identity for lost id including {organization ID, email, username}", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.VerifyIdentityForLostIdRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.VerifyIdentityForLostIdResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/auth/find-id/verification": { + "post": { + "description": "This API allows users to find their account ID by submitting required information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "Request to find forgotten ID", + "parameters": [ + { + "description": "Request body for finding the account ID including {organization ID, email, username, 6 digit code}", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.FindIdRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.FindIdResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/auth/find-password/code": { + "post": { + "description": "This API allows users to verify their identity for lost password by submitting required information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "Request to verify identity for lost password", + "parameters": [ + { + "description": "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/auth/find-password/verification": { + "post": { + "description": "This API allows users to reset their forgotten password by submitting required information", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "Request to find forgotten password", + "parameters": [ + { + "description": "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.FindPasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/auth/login": { + "post": { + "description": "login", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "login", + "parameters": [ + { + "description": "account info", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.LoginRequest" + } + } + ], + "responses": { + "200": { + "description": "user detail", + "schema": { + "$ref": "#/definitions/domain.LoginResponse" + } + } + } + } + }, + "/auth/logout": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "logout", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "logout", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.LogoutResponse" + } + } + } + } + }, + "/auth/ping": { + "post": { + "description": "ping with token", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "ping with token", + "parameters": [ + { + "description": "token info", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.PingTokenRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/clusters": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get cluster list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get clusters", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "query" + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetClustersResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Create cluster", + "parameters": [ + { + "description": "create cluster request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateClusterRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateClusterResponse" + } + } + } + } + }, + "/clusters/import": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Import cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Import cluster", + "parameters": [ + { + "description": "import cluster request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.ImportClusterRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.ImportClusterResponse" + } + } + } + } + }, + "/clusters/{clusterId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get cluster detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get cluster", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.Cluster" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Delete cluster", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.Cluster" + } + } + } + } + }, + "/clusters/{clusterId}/bootstrap-kubeconfig": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get bootstrap kubeconfig for BYOH", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get bootstrap kubeconfig for BYOH", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetBootstrapKubeconfigResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create bootstrap kubeconfig for BYOH", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Create bootstrap kubeconfig for BYOH", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateBootstrapKubeconfigResponse" + } + } + } + } + }, + "/clusters/{clusterId}/install": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install cluster on tks cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Install cluster on tks cluster", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/clusters/{clusterId}/nodes": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get nodes information for BYOH", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get nodes information for BYOH", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetClusterNodesResponse" + } + } + } + } + }, + "/clusters/{clusterId}/site-values": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get cluster site values for creating", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Get cluster site values for creating", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.ClusterSiteValuesResponse" + } + } + } + } + }, + "/organizations": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get organization list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Get organization list", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ListOrganizationBody" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create organization", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Create organization", + "parameters": [ + { + "description": "create organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + } + } + } + }, + "/organizations/{organizationId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get organization detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Get organization detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetOrganizationResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update organization detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Update organization detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.UpdateOrganizationResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete organization", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Delete organization", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.Organization" + } + } + } + } + }, + "/organizations/{organizationId}/alerts": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Alerts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Get Alerts", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAlertsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/alerts/{alertId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Alert", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Get Alert", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "alertId", + "name": "alertId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAlertResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update Alert", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Update Alert", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAlertRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Alert", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Delete Alert", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "alertId", + "name": "alertId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/alerts/{alertId}/actions": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create alert action", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Create alert action", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp list by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp list", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "boolean", + "description": "Show all apps including deleted apps", + "name": "showAll", + "in": "query" + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppServeApp" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Install appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to create app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/count": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get number of apps on given stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get number of apps on given stack", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check duplicate appServeAppName by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Check duplicate appServeAppName", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Uninstall appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Uninstall appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/endpoint": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update app endpoint", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update app endpoint", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "appId", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app endpoint", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/exist": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/latest-task": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get latest task from appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get latest task from appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/rollback": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Rollback appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Rollback appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to rollback app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.RollbackAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/app-serve-apps/{appId}/status": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update app status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update app status", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app status", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get CloudAccounts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Get CloudAccounts", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetCloudAccountsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Create CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateCloudAccountRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateCloudAccountResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check awsAccountId for cloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Check awsAccountId for cloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "awsAccountId", + "name": "awsAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckCloudAccountAwsAccountIdResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for cloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Check name for cloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckCloudAccountNameResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Get CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cloudAccountId", + "name": "cloudAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetCloudAccountResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Update CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateCloudAccountRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Delete CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Delete cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.DeleteCloudAccountRequest" + } + }, + { + "type": "string", + "description": "cloudAccountId", + "name": "cloudAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Force CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Delete Force CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cloudAccountId", + "name": "cloudAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get resource quota by cloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Get resource quota by cloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "cloudAccountId", + "name": "cloudAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetCloudAccountResourceQuotaResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboard/charts": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get charts data", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get charts data", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "chartType", + "name": "chartType", + "in": "query" + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetDashboardChartsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboard/charts/{chartType}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get chart data", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get chart data", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "chartType", + "name": "chartType", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetDashboardChartResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboard/resources": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get resources", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get resources", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetDashboardResourcesResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboard/stacks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get stacks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get stacks", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetDashboardStacksResponse" + } + } + } + } + }, + "/organizations/{organizationId}/my-profile": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get my profile detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Get my profile detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetMyProfileResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update my profile detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update my profile detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Required fields: password due to double-check", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateMyProfileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.UpdateMyProfileResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete myProfile", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Delete myProfile", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request" + } + } + } + }, + "/organizations/{organizationId}/my-profile/next-password-change": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user's password expired date to current date", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update user's password expired date to current date", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/httpErrors.RestError" + } + } + } + } + }, + "/organizations/{organizationId}/my-profile/password": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user password detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update user password detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update user password request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdatePasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/primary-cluster": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update primary cluster", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Update primary cluster", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update primary cluster request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdatePrimaryClusterRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stacks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stacks", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "string", + "description": "combinedFilter", + "name": "combinedFilter", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStacksResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Create Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateStackResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Check name for stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Update Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Delete Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/favorite": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Set favorite stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Set favorite stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete favorite stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Delete favorite stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get KubeConfig by stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get KubeConfig by stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "organizationId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackKubeConfigResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack Status", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user list", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ListUserBody" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create user request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "create user response", + "schema": { + "$ref": "#/definitions/domain.CreateUserResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "return true when accountId exists", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user id existence", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/email/{email}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "return true when email exists", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user email existence", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "email", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetUserResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.UpdateUserResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.User" + } + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}/reset-password": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Reset user's password as temporary password by admin and send email to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Reset user's password as temporary password by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/stack-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackTemplatesResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "description": "create stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateStackTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateStackTemplateResponse" + } + } + } + } + }, + "/stack-templates/{stackTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplate", + "parameters": [ + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetStackTemplateResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "description": "Update stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateStackTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/system-api/organizations/{organizationId}/alerts": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create alert. ADMIN ONLY", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Alerts" + ], + "summary": "Create alert. ADMIN ONLY", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "definitions": { + "domain.ActionResponse": { + "type": "object", + "properties": { + "body": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "method": { + "type": "string" + }, + "name": { + "description": "ENDPOINT (화면보기), PREVIEW (미리보기), PROMOTE (배포), ABORT (중단)", + "type": "string" + }, + "type": { + "description": "LINK, API", + "type": "string" + }, + "uri": { + "type": "string" + } + } + }, + "domain.AlertActionResponse": { + "type": "object", + "properties": { + "alertId": { + "type": "string" + }, + "content": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "taker": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.AlertResponse": { + "type": "object", + "properties": { + "alertActions": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AlertActionResponse" + } + }, + "closedAt": { + "type": "string" + }, + "cluster": { + "$ref": "#/definitions/domain.SimpleClusterResponse" + }, + "code": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "firedAt": { + "type": "string" + }, + "grade": { + "type": "string" + }, + "grafanaUrl": { + "type": "string" + }, + "id": { + "type": "string" + }, + "lastTaker": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "message": { + "type": "string" + }, + "name": { + "type": "string" + }, + "node": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "processingSec": { + "type": "integer" + }, + "rawData": { + "type": "string" + }, + "status": { + "type": "string" + }, + "takedAt": { + "type": "string" + }, + "takedSec": { + "type": "integer" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.AppGroupResponse": { + "type": "object", + "properties": { + "appGroupType": { + "type": "integer" + }, + "clusterId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "workflowId": { + "type": "string" + } + } + }, + "domain.AppServeApp": { + "type": "object", + "properties": { + "appServeAppTasks": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppServeAppTask" + } + }, + "appType": { + "description": "appType (spring/springboot)", + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "endpointUrl": { + "description": "endpoint URL of deployed app", + "type": "string" + }, + "grafanaUrl": { + "description": "grafana dashboard URL for deployed app", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "description": "application name", + "type": "string" + }, + "namespace": { + "description": "application namespace", + "type": "string" + }, + "organizationId": { + "description": "contractId is a contract ID which this app belongs to", + "type": "string" + }, + "previewEndpointUrl": { + "description": "preview svc endpoint URL in B/G deployment", + "type": "string" + }, + "status": { + "description": "status is status of deployed app", + "type": "string" + }, + "targetClusterId": { + "description": "target cluster to which the app is deployed", + "type": "string" + }, + "targetClusterName": { + "description": "target cluster name", + "type": "string" + }, + "type": { + "description": "type (build/deploy/all)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.AppServeAppTask": { + "type": "object", + "properties": { + "appConfig": { + "description": "java app config", + "type": "string" + }, + "appSecret": { + "description": "java app secret", + "type": "string" + }, + "appServeAppId": { + "description": "ID for appServeApp that this task belongs to", + "type": "string" + }, + "artifactUrl": { + "description": "URL of java app artifact (Eg, Jar)", + "type": "string" + }, + "availableRollback": { + "type": "boolean" + }, + "createdAt": { + "description": "createdAt is a creation timestamp for the application", + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "executablePath": { + "description": "Executable path of app image", + "type": "string" + }, + "extraEnv": { + "description": "env variable list for java app", + "type": "string" + }, + "helmRevision": { + "description": "revision of deployed helm release", + "type": "integer" + }, + "id": { + "type": "string" + }, + "imageUrl": { + "description": "URL of built image for app", + "type": "string" + }, + "output": { + "description": "output for task result", + "type": "string" + }, + "port": { + "description": "java app port", + "type": "string" + }, + "profile": { + "description": "java app profile", + "type": "string" + }, + "pvAccessMode": { + "type": "string" + }, + "pvEnabled": { + "type": "boolean" + }, + "pvMountPath": { + "type": "string" + }, + "pvSize": { + "type": "string" + }, + "pvStorageClass": { + "type": "string" + }, + "resourceSpec": { + "description": "resource spec of app pod", + "type": "string" + }, + "rollbackVersion": { + "description": "rollback target version", + "type": "string" + }, + "status": { + "description": "status is app status", + "type": "string" + }, + "strategy": { + "description": "deployment strategy (eg, rolling-update)", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "version": { + "description": "application version", + "type": "string" + } + } + }, + "domain.ApplicationResponse": { + "type": "object", + "properties": { + "appGroupId": { + "type": "string" + }, + "applicationType": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "id": { + "type": "string" + }, + "metadata": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.Axis": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "domain.BootstrapKubeconfig": { + "type": "object", + "properties": { + "expiration": { + "type": "integer" + } + } + }, + "domain.ChartData": { + "type": "object", + "properties": { + "podCounts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.PodCount" + } + }, + "series": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.Unit" + } + }, + "xAxis": { + "$ref": "#/definitions/domain.Axis" + }, + "yAxis": { + "$ref": "#/definitions/domain.Axis" + } + } + }, + "domain.CheckCloudAccountAwsAccountIdResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "domain.CheckCloudAccountNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "domain.CheckExistedResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "domain.CloudAccount": { + "type": "object", + "properties": { + "accessKeyId": { + "type": "string" + }, + "awsAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusters": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "createdIAM": { + "type": "boolean" + }, + "creator": { + "$ref": "#/definitions/domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "secretAccessKey": { + "type": "string" + }, + "sessionToken": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.User" + }, + "updatorId": { + "type": "string" + } + } + }, + "domain.CloudAccountResponse": { + "type": "object", + "properties": { + "awsAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusters": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "createdIAM": { + "type": "boolean" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + } + } + }, + "domain.Cluster": { + "type": "object", + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "cloudAccount": { + "$ref": "#/definitions/domain.CloudAccount" + }, + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusterType": { + "type": "integer" + }, + "conf": { + "$ref": "#/definitions/domain.ClusterConf" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "favorited": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "isStack": { + "type": "boolean" + }, + "kubeconfig": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplate": { + "$ref": "#/definitions/domain.StackTemplate" + }, + "stackTemplateId": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.User" + }, + "updatorId": { + "type": "string" + } + } + }, + "domain.ClusterConf": { + "type": "object", + "properties": { + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.ClusterConfResponse": { + "type": "object", + "properties": { + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.ClusterHost": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "domain.ClusterNode": { + "type": "object", + "properties": { + "command": { + "type": "string" + }, + "hosts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ClusterHost" + } + }, + "registered": { + "type": "integer" + }, + "registering": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "targeted": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "validity": { + "type": "integer" + } + } + }, + "domain.ClusterResponse": { + "type": "object", + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "cloudAccount": { + "$ref": "#/definitions/domain.SimpleCloudAccountResponse" + }, + "cloudService": { + "type": "string" + }, + "clusterType": { + "type": "string" + }, + "conf": { + "$ref": "#/definitions/domain.ClusterConfResponse" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "isStack": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplate": { + "$ref": "#/definitions/domain.SimpleStackTemplateResponse" + }, + "status": { + "type": "string" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + } + } + }, + "domain.ClusterSiteValuesResponse": { + "type": "object", + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "clusterRegion": { + "type": "string" + }, + "clusterType": { + "type": "string" + }, + "sshKeyName": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.CreateAppGroupRequest": { + "type": "object", + "required": [ + "clusterId", + "name" + ], + "properties": { + "appGroupType": { + "type": "string", + "enum": [ + "LMA", + "SERVICE_MESH" + ] + }, + "clusterId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "domain.CreateAppGroupResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateAppServeAppRequest": { + "type": "object", + "required": [ + "name", + "targetClusterId" + ], + "properties": { + "appConfig": { + "type": "string" + }, + "appSecret": { + "type": "string" + }, + "appType": { + "description": "springboot spring", + "type": "string" + }, + "artifactUrl": { + "type": "string" + }, + "executablePath": { + "type": "string" + }, + "extraEnv": { + "type": "string" + }, + "imageUrl": { + "type": "string" + }, + "name": { + "description": "App", + "type": "string" + }, + "namespace": { + "type": "string" + }, + "port": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "pvAccessMode": { + "type": "string" + }, + "pvEnabled": { + "type": "boolean" + }, + "pvMountPath": { + "type": "string" + }, + "pvSize": { + "type": "string" + }, + "pvStorageClass": { + "type": "string" + }, + "resourceSpec": { + "description": "tiny medium large", + "type": "string" + }, + "strategy": { + "description": "rolling-update blue-green canary", + "type": "string" + }, + "targetClusterId": { + "type": "string" + }, + "type": { + "description": "build deploy all", + "type": "string" + }, + "version": { + "description": "Task", + "type": "string" + } + } + }, + "domain.CreateApplicationRequest": { + "type": "object", + "properties": { + "applicationType": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "metadata": { + "type": "string" + } + } + }, + "domain.CreateBootstrapKubeconfigResponse": { + "type": "object", + "properties": { + "kubeconfig": { + "$ref": "#/definitions/domain.BootstrapKubeconfig" + } + } + }, + "domain.CreateCloudAccountRequest": { + "type": "object", + "required": [ + "accessKeyId", + "awsAccountId", + "name", + "secretAccessKey" + ], + "properties": { + "accessKeyId": { + "type": "string", + "maxLength": 128, + "minLength": 16 + }, + "awsAccountId": { + "type": "string", + "maxLength": 12, + "minLength": 12 + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "AZZURE", + "GCP" + ] + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "secretAccessKey": { + "type": "string", + "maxLength": 128, + "minLength": 16 + }, + "sessionToken": { + "type": "string", + "maxLength": 2000 + } + } + }, + "domain.CreateCloudAccountResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateClusterRequest": { + "type": "object", + "required": [ + "cloudService", + "name", + "organizationId", + "stackTemplateId" + ], + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "BYOH" + ] + }, + "clusterType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "isStack": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplateId": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.CreateClusterResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateOrganizationRequest": { + "type": "object", + "required": [ + "Email", + "name" + ], + "properties": { + "Email": { + "type": "string" + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "domain.CreateStackRequest": { + "type": "object", + "required": [ + "cloudService", + "name", + "stackTemplateId" + ], + "properties": { + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "BYOH" + ] + }, + "clusterId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "stackTemplateId": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + }, + "userClusterEndpoint": { + "type": "string" + } + } + }, + "domain.CreateStackResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateStackTemplateRequest": { + "type": "object", + "required": [ + "name", + "platform", + "template", + "version" + ], + "properties": { + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "AZZURE", + "GCP" + ] + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string", + "enum": [ + "STANDARD", + "MSA" + ] + }, + "version": { + "type": "string" + } + } + }, + "domain.CreateStackTemplateResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.CreateUserRequest": { + "type": "object", + "required": [ + "accountId", + "email", + "password", + "role" + ], + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "password": { + "type": "string" + }, + "role": { + "type": "string", + "enum": [ + "admin", + "user" + ] + } + } + }, + "domain.CreateUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + } + } + } + } + }, + "domain.DashboardChartResponse": { + "type": "object", + "properties": { + "chartData": { + "$ref": "#/definitions/domain.ChartData" + }, + "chartType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "string" + }, + "interval": { + "type": "string" + }, + "month": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "year": { + "type": "string" + } + } + }, + "domain.DashboardResource": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + }, + "stack": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, + "domain.DashboardStackResponse": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "memory": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string" + }, + "statusDesc": { + "type": "string" + }, + "storage": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.DeleteCloudAccountRequest": { + "type": "object", + "required": [ + "accessKeyId", + "secretAccessKey" + ], + "properties": { + "accessKeyId": { + "type": "string", + "maxLength": 128, + "minLength": 16 + }, + "secretAccessKey": { + "type": "string", + "maxLength": 128, + "minLength": 16 + }, + "sessionToken": { + "type": "string", + "maxLength": 2000 + } + } + }, + "domain.FilterResponse": { + "type": "object", + "properties": { + "column": { + "type": "string" + }, + "operator": { + "type": "string" + }, + "releation": { + "type": "string" + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "domain.FindIdRequest": { + "type": "object", + "required": [ + "code", + "email", + "organizationId", + "userName" + ], + "properties": { + "code": { + "type": "string" + }, + "email": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, + "domain.FindIdResponse": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + } + } + }, + "domain.FindPasswordRequest": { + "type": "object", + "required": [ + "accountId", + "code", + "email", + "organizationId", + "userName" + ], + "properties": { + "accountId": { + "type": "string" + }, + "code": { + "type": "string" + }, + "email": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, + "domain.GetAlertResponse": { + "type": "object", + "properties": { + "alert": { + "$ref": "#/definitions/domain.AlertResponse" + } + } + }, + "domain.GetAlertsResponse": { + "type": "object", + "properties": { + "alerts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AlertResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, + "domain.GetAppGroupResponse": { + "type": "object", + "properties": { + "appGroup": { + "$ref": "#/definitions/domain.AppGroupResponse" + } + } + }, + "domain.GetAppGroupsResponse": { + "type": "object", + "properties": { + "appGroups": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppGroupResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, + "domain.GetAppServeAppResponse": { + "type": "object", + "properties": { + "appServeApp": { + "$ref": "#/definitions/domain.AppServeApp" + }, + "stages": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StageResponse" + } + } + } + }, + "domain.GetAppServeAppTaskResponse": { + "type": "object", + "properties": { + "appServeAppTask": { + "$ref": "#/definitions/domain.AppServeAppTask" + } + } + }, + "domain.GetApplicationsResponse": { + "type": "object", + "properties": { + "applications": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ApplicationResponse" + } + } + } + }, + "domain.GetBootstrapKubeconfigResponse": { + "type": "object", + "properties": { + "kubeconfig": { + "$ref": "#/definitions/domain.BootstrapKubeconfig" + } + } + }, + "domain.GetCloudAccountResourceQuotaResponse": { + "type": "object", + "properties": { + "available": { + "type": "boolean" + }, + "resourceQuota": { + "$ref": "#/definitions/domain.ResourceQuota" + } + } + }, + "domain.GetCloudAccountResponse": { + "type": "object", + "properties": { + "cloudAccount": { + "$ref": "#/definitions/domain.CloudAccountResponse" + } + } + }, + "domain.GetCloudAccountsResponse": { + "type": "object", + "properties": { + "cloudAccounts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.CloudAccountResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, + "domain.GetClusterNodesResponse": { + "type": "object", + "properties": { + "nodes": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ClusterNode" + } + } + } + }, + "domain.GetClustersResponse": { + "type": "object", + "properties": { + "clusters": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ClusterResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, + "domain.GetDashboardChartResponse": { + "type": "object", + "properties": { + "chart": { + "$ref": "#/definitions/domain.DashboardChartResponse" + } + } + }, + "domain.GetDashboardChartsResponse": { + "type": "object", + "properties": { + "charts": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.DashboardChartResponse" + } + } + } + }, + "domain.GetDashboardResourcesResponse": { + "type": "object", + "properties": { + "resources": { + "$ref": "#/definitions/domain.DashboardResource" + } + } + }, + "domain.GetDashboardStacksResponse": { + "type": "object", + "properties": { + "stacks": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.DashboardStackResponse" + } + } + } + }, + "domain.GetMyProfileResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + } + } + } + } + }, + "domain.GetOrganizationResponse": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "primaryClusterId": { + "type": "string" + }, + "status": { + "type": "string" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "domain.GetStackKubeConfigResponse": { + "type": "object", + "properties": { + "kubeConfig": { + "type": "string" + } + } + }, + "domain.GetStackResponse": { + "type": "object", + "properties": { + "stack": { + "$ref": "#/definitions/domain.StackResponse" + } + } + }, + "domain.GetStackStatusResponse": { + "type": "object", + "properties": { + "stackStatus": { + "type": "string" + }, + "stepStatus": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackStepStatus" + } + } + } + }, + "domain.GetStackTemplateResponse": { + "type": "object", + "properties": { + "stackTemplate": { + "$ref": "#/definitions/domain.StackTemplateResponse" + } + } + }, + "domain.GetStackTemplatesResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + }, + "stackTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackTemplateResponse" + } + } + } + }, + "domain.GetStacksResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + }, + "stacks": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackResponse" + } + } + } + }, + "domain.GetUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "domain.ImportClusterRequest": { + "type": "object", + "required": [ + "name", + "organizationId", + "stackTemplateId" + ], + "properties": { + "cloudService": { + "type": "string" + }, + "clusterType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "kubeconfig": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplateId": { + "type": "string" + } + } + }, + "domain.ImportClusterResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "domain.ListOrganizationBody": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "primaryClusterId": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.ListUserBody": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.LoginRequest": { + "type": "object", + "required": [ + "accountId", + "organizationId", + "password" + ], + "properties": { + "accountId": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "domain.LoginResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "passwordExpired": { + "type": "boolean" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "token": { + "type": "string" + } + } + } + } + }, + "domain.LogoutResponse": { + "type": "object", + "properties": { + "ssoUrls": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "domain.Organization": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "primaryClusterId": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.PaginationResponse": { + "type": "object", + "properties": { + "filters": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.FilterResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "sortColumn": { + "type": "string" + }, + "sortOrder": { + "type": "string" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" + } + } + }, + "domain.PingTokenRequest": { + "type": "object", + "required": [ + "organizationId", + "token" + ], + "properties": { + "organizationId": { + "type": "string" + }, + "token": { + "type": "string" + } + } + }, + "domain.PodCount": { + "type": "object", + "properties": { + "day": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "domain.ResourceQuota": { + "type": "object", + "properties": { + "quotas": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ResourceQuotaAttr" + } + } + } + }, + "domain.ResourceQuotaAttr": { + "type": "object", + "properties": { + "quota": { + "type": "integer" + }, + "required": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "usage": { + "type": "integer" + } + } + }, + "domain.Role": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.RollbackAppServeAppRequest": { + "type": "object", + "properties": { + "taskId": { + "type": "string" + } + } + }, + "domain.SimpleCloudAccountResponse": { + "type": "object", + "properties": { + "awsAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusters": { + "type": "integer" + }, + "createdIAM": { + "type": "boolean" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + } + } + }, + "domain.SimpleClusterResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + } + } + }, + "domain.SimpleStackTemplateResponse": { + "type": "object", + "properties": { + "cloudService": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "services": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackTemplateServiceResponse" + } + }, + "template": { + "type": "string" + } + } + }, + "domain.SimpleUserResponse": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "domain.StackConfResponse": { + "type": "object", + "required": [ + "tksInfraNode", + "tksUserNode" + ], + "properties": { + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer", + "maximum": 3, + "minimum": 1 + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer", + "maximum": 100, + "minimum": 0 + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "domain.StackResponse": { + "type": "object", + "properties": { + "cloudAccount": { + "$ref": "#/definitions/domain.SimpleCloudAccountResponse" + }, + "conf": { + "$ref": "#/definitions/domain.StackConfResponse" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "favorited": { + "type": "boolean" + }, + "grafanaUrl": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "primaryCluster": { + "type": "boolean" + }, + "resource": { + "$ref": "#/definitions/domain.DashboardStackResponse" + }, + "stackTemplate": { + "$ref": "#/definitions/domain.SimpleStackTemplateResponse" + }, + "status": { + "type": "string" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "userClusterEndpoint": { + "type": "string" + } + } + }, + "domain.StackStepStatus": { + "type": "object", + "properties": { + "maxStep": { + "type": "integer" + }, + "stage": { + "type": "string" + }, + "status": { + "type": "string" + }, + "step": { + "type": "integer" + } + } + }, + "domain.StackTemplate": { + "type": "object", + "properties": { + "cloudService": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "services": { + "type": "array", + "items": { + "type": "integer" + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.User" + }, + "updatorId": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "domain.StackTemplateResponse": { + "type": "object", + "properties": { + "cloudService": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "services": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackTemplateServiceResponse" + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "version": { + "type": "string" + } + } + }, + "domain.StackTemplateServiceApplicationResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "domain.StackTemplateServiceResponse": { + "type": "object", + "properties": { + "applications": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StackTemplateServiceApplicationResponse" + } + }, + "type": { + "type": "string" + } + } + }, + "domain.StageResponse": { + "type": "object", + "properties": { + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ActionResponse" + } + }, + "name": { + "description": "BUILD (빌드), DEPLOY (배포), PROMOTE (프로모트), ROLLBACK (롤백)", + "type": "string" + }, + "result": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "domain.Unit": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "string" + } + }, + "name": { + "type": "string" + } + } + }, + "domain.UpdateAlertRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "domain.UpdateAppServeAppEndpointRequest": { + "type": "object", + "required": [ + "taskId" + ], + "properties": { + "endpointUrl": { + "type": "string" + }, + "helmRevision": { + "type": "integer" + }, + "previewEndpointUrl": { + "type": "string" + }, + "taskId": { + "type": "string" + } + } + }, + "domain.UpdateAppServeAppRequest": { + "type": "object", + "properties": { + "abort": { + "type": "boolean" + }, + "appConfig": { + "type": "string" + }, + "appSecret": { + "type": "string" + }, + "artifactUrl": { + "type": "string" + }, + "executablePath": { + "type": "string" + }, + "extraEnv": { + "type": "string" + }, + "imageUrl": { + "type": "string" + }, + "port": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "promote": { + "description": "Update Strategy", + "type": "boolean" + }, + "resourceSpec": { + "type": "string" + }, + "strategy": { + "description": "Task", + "type": "string" + } + } + }, + "domain.UpdateAppServeAppStatusRequest": { + "type": "object", + "required": [ + "status", + "taskId" + ], + "properties": { + "output": { + "type": "string" + }, + "status": { + "type": "string" + }, + "taskId": { + "type": "string" + } + } + }, + "domain.UpdateCloudAccountRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "domain.UpdateMyProfileRequest": { + "type": "object", + "required": [ + "password" + ], + "properties": { + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "password": { + "type": "string" + } + } + }, + "domain.UpdateMyProfileResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + } + } + } + } + }, + "domain.UpdateOrganizationRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "phone": { + "type": "string" + }, + "primaryClusterId": { + "type": "string" + } + } + }, + "domain.UpdateOrganizationResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "domain.UpdatePasswordRequest": { + "type": "object", + "required": [ + "newPassword", + "originPassword" + ], + "properties": { + "newPassword": { + "type": "string" + }, + "originPassword": { + "type": "string" + } + } + }, + "domain.UpdatePrimaryClusterRequest": { + "type": "object", + "properties": { + "primaryClusterId": { + "type": "string" + } + } + }, + "domain.UpdateStackRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "domain.UpdateStackTemplateRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "domain.UpdateUserRequest": { + "type": "object", + "properties": { + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "role": { + "type": "string", + "enum": [ + "admin", + "user" + ] + } + } + }, + "domain.UpdateUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "domain.User": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.Organization" + }, + "password": { + "type": "string" + }, + "passwordExpired": { + "type": "boolean" + }, + "passwordUpdatedAt": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/domain.Role" + }, + "token": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.VerifyIdentityForLostIdRequest": { + "type": "object", + "required": [ + "email", + "organizationId", + "userName" + ], + "properties": { + "email": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, + "domain.VerifyIdentityForLostIdResponse": { + "type": "object", + "properties": { + "validityPeriod": { + "type": "string" + } + } + }, + "domain.VerifyIdentityForLostPasswordRequest": { + "type": "object", + "required": [ + "accountId", + "email", + "organizationId", + "userName" + ], + "properties": { + "accountId": { + "type": "string" + }, + "email": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "userName": { + "type": "string" + } + } + }, + "domain.VerifyIdentityForLostPasswordResponse": { + "type": "object", + "properties": { + "validityPeriod": { + "type": "string" + } + } + }, + "httpErrors.RestError": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "status": { + "type": "integer" + }, + "text": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "JWT": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +} \ No newline at end of file diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml new file mode 100644 index 00000000..dfbf2f9f --- /dev/null +++ b/api/swagger/swagger.yaml @@ -0,0 +1,4453 @@ +basePath: /api/1.0/ +definitions: + domain.ActionResponse: + properties: + body: + additionalProperties: + type: string + type: object + method: + type: string + name: + description: ENDPOINT (화면보기), PREVIEW (미리보기), PROMOTE (배포), ABORT (중단) + type: string + type: + description: LINK, API + type: string + uri: + type: string + type: object + domain.AlertActionResponse: + properties: + alertId: + type: string + content: + type: string + createdAt: + type: string + id: + type: string + status: + type: string + taker: + $ref: '#/definitions/domain.SimpleUserResponse' + updatedAt: + type: string + type: object + domain.AlertResponse: + properties: + alertActions: + items: + $ref: '#/definitions/domain.AlertActionResponse' + type: array + closedAt: + type: string + cluster: + $ref: '#/definitions/domain.SimpleClusterResponse' + code: + type: string + createdAt: + type: string + description: + type: string + firedAt: + type: string + grade: + type: string + grafanaUrl: + type: string + id: + type: string + lastTaker: + $ref: '#/definitions/domain.SimpleUserResponse' + message: + type: string + name: + type: string + node: + type: string + organizationId: + type: string + processingSec: + type: integer + rawData: + type: string + status: + type: string + takedAt: + type: string + takedSec: + type: integer + updatedAt: + type: string + type: object + domain.AppGroupResponse: + properties: + appGroupType: + type: integer + clusterId: + type: string + createdAt: + type: string + creator: + $ref: '#/definitions/domain.SimpleUserResponse' + description: + type: string + id: + type: string + name: + type: string + status: + type: integer + statusDesc: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/domain.SimpleUserResponse' + workflowId: + type: string + type: object + domain.AppServeApp: + properties: + appServeAppTasks: + items: + $ref: '#/definitions/domain.AppServeAppTask' + type: array + appType: + description: appType (spring/springboot) + type: string + createdAt: + type: string + deletedAt: + type: string + endpointUrl: + description: endpoint URL of deployed app + type: string + grafanaUrl: + description: grafana dashboard URL for deployed app + type: string + id: + type: string + name: + description: application name + type: string + namespace: + description: application namespace + type: string + organizationId: + description: contractId is a contract ID which this app belongs to + type: string + previewEndpointUrl: + description: preview svc endpoint URL in B/G deployment + type: string + status: + description: status is status of deployed app + type: string + targetClusterId: + description: target cluster to which the app is deployed + type: string + targetClusterName: + description: target cluster name + type: string + type: + description: type (build/deploy/all) + type: string + updatedAt: + type: string + type: object + domain.AppServeAppTask: + properties: + appConfig: + description: java app config + type: string + appSecret: + description: java app secret + type: string + appServeAppId: + description: ID for appServeApp that this task belongs to + type: string + artifactUrl: + description: URL of java app artifact (Eg, Jar) + type: string + availableRollback: + type: boolean + createdAt: + description: createdAt is a creation timestamp for the application + type: string + deletedAt: + type: string + executablePath: + description: Executable path of app image + type: string + extraEnv: + description: env variable list for java app + type: string + helmRevision: + description: revision of deployed helm release + type: integer + id: + type: string + imageUrl: + description: URL of built image for app + type: string + output: + description: output for task result + type: string + port: + description: java app port + type: string + profile: + description: java app profile + type: string + pvAccessMode: + type: string + pvEnabled: + type: boolean + pvMountPath: + type: string + pvSize: + type: string + pvStorageClass: + type: string + resourceSpec: + description: resource spec of app pod + type: string + rollbackVersion: + description: rollback target version + type: string + status: + description: status is app status + type: string + strategy: + description: deployment strategy (eg, rolling-update) + type: string + updatedAt: + type: string + version: + description: application version + type: string + type: object + domain.ApplicationResponse: + properties: + appGroupId: + type: string + applicationType: + type: integer + createdAt: + type: string + endpoint: + type: string + id: + type: string + metadata: + type: string + updatedAt: + type: string + type: object + domain.Axis: + properties: + data: + items: + type: string + type: array + type: object + domain.BootstrapKubeconfig: + properties: + expiration: + type: integer + type: object + domain.ChartData: + properties: + podCounts: + items: + $ref: '#/definitions/domain.PodCount' + type: array + series: + items: + $ref: '#/definitions/domain.Unit' + type: array + xAxis: + $ref: '#/definitions/domain.Axis' + yAxis: + $ref: '#/definitions/domain.Axis' + type: object + domain.CheckCloudAccountAwsAccountIdResponse: + properties: + existed: + type: boolean + type: object + domain.CheckCloudAccountNameResponse: + properties: + existed: + type: boolean + type: object + domain.CheckExistedResponse: + properties: + existed: + type: boolean + type: object + domain.CloudAccount: + properties: + accessKeyId: + type: string + awsAccountId: + type: string + cloudService: + type: string + clusters: + type: integer + createdAt: + type: string + createdIAM: + type: boolean + creator: + $ref: '#/definitions/domain.User' + creatorId: + type: string + description: + type: string + id: + type: string + name: + type: string + organizationId: + type: string + resource: + type: string + secretAccessKey: + type: string + sessionToken: + type: string + status: + type: integer + statusDesc: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/domain.User' + updatorId: + type: string + type: object + domain.CloudAccountResponse: + properties: + awsAccountId: + type: string + cloudService: + type: string + clusters: + type: integer + createdAt: + type: string + createdIAM: + type: boolean + creator: + $ref: '#/definitions/domain.SimpleUserResponse' + description: + type: string + id: + type: string + name: + type: string + organizationId: + type: string + resource: + type: string + status: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/domain.SimpleUserResponse' + type: object + domain.Cluster: + properties: + byoClusterEndpointHost: + type: string + byoClusterEndpointPort: + type: integer + cloudAccount: + $ref: '#/definitions/domain.CloudAccount' + cloudAccountId: + type: string + cloudService: + type: string + clusterType: + type: integer + conf: + $ref: '#/definitions/domain.ClusterConf' + createdAt: + type: string + creator: + $ref: '#/definitions/domain.User' + creatorId: + type: string + description: + type: string + favorited: + type: boolean + id: + type: string + isStack: + type: boolean + kubeconfig: + items: + type: integer + type: array + name: + type: string + organizationId: + type: string + stackTemplate: + $ref: '#/definitions/domain.StackTemplate' + stackTemplateId: + type: string + status: + type: integer + statusDesc: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/domain.User' + updatorId: + type: string + type: object + domain.ClusterConf: + properties: + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + type: object + domain.ClusterConfResponse: + properties: + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + type: object + domain.ClusterHost: + properties: + name: + type: string + status: + type: string + type: object + domain.ClusterNode: + properties: + command: + type: string + hosts: + items: + $ref: '#/definitions/domain.ClusterHost' + type: array + registered: + type: integer + registering: + type: integer + status: + type: string + targeted: + type: integer + type: + type: string + validity: + type: integer + type: object + domain.ClusterResponse: + properties: + byoClusterEndpointHost: + type: string + byoClusterEndpointPort: + type: integer + cloudAccount: + $ref: '#/definitions/domain.SimpleCloudAccountResponse' + cloudService: + type: string + clusterType: + type: string + conf: + $ref: '#/definitions/domain.ClusterConfResponse' + createdAt: + type: string + creator: + $ref: '#/definitions/domain.SimpleUserResponse' + description: + type: string + id: + type: string + isStack: + type: boolean + name: + type: string + organizationId: + type: string + stackTemplate: + $ref: '#/definitions/domain.SimpleStackTemplateResponse' + status: + type: string + statusDesc: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/domain.SimpleUserResponse' + type: object + domain.ClusterSiteValuesResponse: + properties: + byoClusterEndpointHost: + type: string + byoClusterEndpointPort: + type: integer + clusterRegion: + type: string + clusterType: + type: string + sshKeyName: + type: string + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + type: object + domain.CreateAppGroupRequest: + properties: + appGroupType: + enum: + - LMA + - SERVICE_MESH + type: string + clusterId: + type: string + description: + type: string + name: + type: string + required: + - clusterId + - name + type: object + domain.CreateAppGroupResponse: + properties: + id: + type: string + type: object + domain.CreateAppServeAppRequest: + properties: + appConfig: + type: string + appSecret: + type: string + appType: + description: springboot spring + type: string + artifactUrl: + type: string + executablePath: + type: string + extraEnv: + type: string + imageUrl: + type: string + name: + description: App + type: string + namespace: + type: string + port: + type: string + profile: + type: string + pvAccessMode: + type: string + pvEnabled: + type: boolean + pvMountPath: + type: string + pvSize: + type: string + pvStorageClass: + type: string + resourceSpec: + description: tiny medium large + type: string + strategy: + description: rolling-update blue-green canary + type: string + targetClusterId: + type: string + type: + description: build deploy all + type: string + version: + description: Task + type: string + required: + - name + - targetClusterId + type: object + domain.CreateApplicationRequest: + properties: + applicationType: + type: string + endpoint: + type: string + metadata: + type: string + type: object + domain.CreateBootstrapKubeconfigResponse: + properties: + kubeconfig: + $ref: '#/definitions/domain.BootstrapKubeconfig' + type: object + domain.CreateCloudAccountRequest: + properties: + accessKeyId: + maxLength: 128 + minLength: 16 + type: string + awsAccountId: + maxLength: 12 + minLength: 12 + type: string + cloudService: + enum: + - AWS + - AZZURE + - GCP + type: string + description: + type: string + name: + type: string + secretAccessKey: + maxLength: 128 + minLength: 16 + type: string + sessionToken: + maxLength: 2000 + type: string + required: + - accessKeyId + - awsAccountId + - name + - secretAccessKey + type: object + domain.CreateCloudAccountResponse: + properties: + id: + type: string + type: object + domain.CreateClusterRequest: + properties: + byoClusterEndpointHost: + type: string + byoClusterEndpointPort: + type: integer + cloudAccountId: + type: string + cloudService: + enum: + - AWS + - BYOH + type: string + clusterType: + type: string + description: + type: string + isStack: + type: boolean + name: + type: string + organizationId: + type: string + stackTemplateId: + type: string + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + required: + - cloudService + - name + - organizationId + - stackTemplateId + type: object + domain.CreateClusterResponse: + properties: + id: + type: string + type: object + domain.CreateOrganizationRequest: + properties: + Email: + type: string + description: + maxLength: 100 + minLength: 0 + type: string + name: + type: string + phone: + type: string + required: + - Email + - name + type: object + domain.CreateStackRequest: + properties: + cloudAccountId: + type: string + cloudService: + enum: + - AWS + - BYOH + type: string + clusterId: + type: string + description: + type: string + name: + type: string + stackTemplateId: + type: string + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + userClusterEndpoint: + type: string + required: + - cloudService + - name + - stackTemplateId + type: object + domain.CreateStackResponse: + properties: + id: + type: string + type: object + domain.CreateStackTemplateRequest: + properties: + cloudService: + enum: + - AWS + - AZZURE + - GCP + type: string + description: + type: string + name: + type: string + platform: + type: string + template: + type: string + templateType: + enum: + - STANDARD + - MSA + type: string + version: + type: string + required: + - name + - platform + - template + - version + type: object + domain.CreateStackTemplateResponse: + properties: + id: + type: string + type: object + domain.CreateUserRequest: + properties: + accountId: + type: string + department: + maxLength: 50 + minLength: 0 + type: string + description: + maxLength: 100 + minLength: 0 + type: string + email: + type: string + name: + type: string + password: + type: string + role: + enum: + - admin + - user + type: string + required: + - accountId + - email + - password + - role + type: object + domain.CreateUserResponse: + properties: + user: + properties: + accountId: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/domain.Organization' + role: + $ref: '#/definitions/domain.Role' + type: object + type: object + domain.DashboardChartResponse: + properties: + chartData: + $ref: '#/definitions/domain.ChartData' + chartType: + type: string + description: + type: string + duration: + type: string + interval: + type: string + month: + type: string + name: + type: string + organizationId: + type: string + updatedAt: + type: string + year: + type: string + type: object + domain.DashboardResource: + properties: + cpu: + type: string + memory: + type: string + stack: + type: string + storage: + type: string + type: object + domain.DashboardStackResponse: + properties: + cpu: + type: string + createdAt: + type: string + description: + type: string + id: + type: string + memory: + type: string + name: + type: string + status: + type: string + statusDesc: + type: string + storage: + type: string + updatedAt: + type: string + type: object + domain.DeleteCloudAccountRequest: + properties: + accessKeyId: + maxLength: 128 + minLength: 16 + type: string + secretAccessKey: + maxLength: 128 + minLength: 16 + type: string + sessionToken: + maxLength: 2000 + type: string + required: + - accessKeyId + - secretAccessKey + type: object + domain.FilterResponse: + properties: + column: + type: string + operator: + type: string + releation: + type: string + values: + items: + type: string + type: array + type: object + domain.FindIdRequest: + properties: + code: + type: string + email: + type: string + organizationId: + type: string + userName: + type: string + required: + - code + - email + - organizationId + - userName + type: object + domain.FindIdResponse: + properties: + accountId: + type: string + type: object + domain.FindPasswordRequest: + properties: + accountId: + type: string + code: + type: string + email: + type: string + organizationId: + type: string + userName: + type: string + required: + - accountId + - code + - email + - organizationId + - userName + type: object + domain.GetAlertResponse: + properties: + alert: + $ref: '#/definitions/domain.AlertResponse' + type: object + domain.GetAlertsResponse: + properties: + alerts: + items: + $ref: '#/definitions/domain.AlertResponse' + type: array + pagination: + $ref: '#/definitions/domain.PaginationResponse' + type: object + domain.GetAppGroupResponse: + properties: + appGroup: + $ref: '#/definitions/domain.AppGroupResponse' + type: object + domain.GetAppGroupsResponse: + properties: + appGroups: + items: + $ref: '#/definitions/domain.AppGroupResponse' + type: array + pagination: + $ref: '#/definitions/domain.PaginationResponse' + type: object + domain.GetAppServeAppResponse: + properties: + appServeApp: + $ref: '#/definitions/domain.AppServeApp' + stages: + items: + $ref: '#/definitions/domain.StageResponse' + type: array + type: object + domain.GetAppServeAppTaskResponse: + properties: + appServeAppTask: + $ref: '#/definitions/domain.AppServeAppTask' + type: object + domain.GetApplicationsResponse: + properties: + applications: + items: + $ref: '#/definitions/domain.ApplicationResponse' + type: array + type: object + domain.GetBootstrapKubeconfigResponse: + properties: + kubeconfig: + $ref: '#/definitions/domain.BootstrapKubeconfig' + type: object + domain.GetCloudAccountResourceQuotaResponse: + properties: + available: + type: boolean + resourceQuota: + $ref: '#/definitions/domain.ResourceQuota' + type: object + domain.GetCloudAccountResponse: + properties: + cloudAccount: + $ref: '#/definitions/domain.CloudAccountResponse' + type: object + domain.GetCloudAccountsResponse: + properties: + cloudAccounts: + items: + $ref: '#/definitions/domain.CloudAccountResponse' + type: array + pagination: + $ref: '#/definitions/domain.PaginationResponse' + type: object + domain.GetClusterNodesResponse: + properties: + nodes: + items: + $ref: '#/definitions/domain.ClusterNode' + type: array + type: object + domain.GetClustersResponse: + properties: + clusters: + items: + $ref: '#/definitions/domain.ClusterResponse' + type: array + pagination: + $ref: '#/definitions/domain.PaginationResponse' + type: object + domain.GetDashboardChartResponse: + properties: + chart: + $ref: '#/definitions/domain.DashboardChartResponse' + type: object + domain.GetDashboardChartsResponse: + properties: + charts: + items: + $ref: '#/definitions/domain.DashboardChartResponse' + type: array + type: object + domain.GetDashboardResourcesResponse: + properties: + resources: + $ref: '#/definitions/domain.DashboardResource' + type: object + domain.GetDashboardStacksResponse: + properties: + stacks: + items: + $ref: '#/definitions/domain.DashboardStackResponse' + type: array + type: object + domain.GetMyProfileResponse: + properties: + user: + properties: + accountId: + type: string + department: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/domain.Organization' + role: + $ref: '#/definitions/domain.Role' + type: object + type: object + domain.GetOrganizationResponse: + properties: + organization: + properties: + createdAt: + type: string + creator: + type: string + description: + type: string + id: + type: string + name: + type: string + phone: + type: string + primaryClusterId: + type: string + status: + type: string + statusDesc: + type: string + updatedAt: + type: string + type: object + type: object + domain.GetStackKubeConfigResponse: + properties: + kubeConfig: + type: string + type: object + domain.GetStackResponse: + properties: + stack: + $ref: '#/definitions/domain.StackResponse' + type: object + domain.GetStackStatusResponse: + properties: + stackStatus: + type: string + stepStatus: + items: + $ref: '#/definitions/domain.StackStepStatus' + type: array + type: object + domain.GetStackTemplateResponse: + properties: + stackTemplate: + $ref: '#/definitions/domain.StackTemplateResponse' + type: object + domain.GetStackTemplatesResponse: + properties: + pagination: + $ref: '#/definitions/domain.PaginationResponse' + stackTemplates: + items: + $ref: '#/definitions/domain.StackTemplateResponse' + type: array + type: object + domain.GetStacksResponse: + properties: + pagination: + $ref: '#/definitions/domain.PaginationResponse' + stacks: + items: + $ref: '#/definitions/domain.StackResponse' + type: array + type: object + domain.GetUserResponse: + properties: + user: + properties: + accountId: + type: string + createdAt: + type: string + creator: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/domain.Organization' + role: + $ref: '#/definitions/domain.Role' + updatedAt: + type: string + type: object + type: object + domain.ImportClusterRequest: + properties: + cloudService: + type: string + clusterType: + type: string + description: + type: string + kubeconfig: + items: + type: integer + type: array + name: + type: string + organizationId: + type: string + stackTemplateId: + type: string + required: + - name + - organizationId + - stackTemplateId + type: object + domain.ImportClusterResponse: + properties: + id: + type: string + type: object + domain.ListOrganizationBody: + properties: + createdAt: + type: string + description: + type: string + id: + type: string + name: + type: string + phone: + type: string + primaryClusterId: + type: string + status: + type: string + updatedAt: + type: string + type: object + domain.ListUserBody: + properties: + accountId: + type: string + createdAt: + type: string + creator: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/domain.Organization' + role: + $ref: '#/definitions/domain.Role' + updatedAt: + type: string + type: object + domain.LoginRequest: + properties: + accountId: + type: string + organizationId: + type: string + password: + type: string + required: + - accountId + - organizationId + - password + type: object + domain.LoginResponse: + properties: + user: + properties: + accountId: + type: string + department: + type: string + name: + type: string + organization: + $ref: '#/definitions/domain.Organization' + passwordExpired: + type: boolean + role: + $ref: '#/definitions/domain.Role' + token: + type: string + type: object + type: object + domain.LogoutResponse: + properties: + ssoUrls: + additionalProperties: + items: + type: string + type: array + type: object + type: object + domain.Organization: + properties: + createdAt: + type: string + creator: + type: string + description: + type: string + id: + type: string + name: + type: string + phone: + type: string + primaryClusterId: + type: string + status: + type: integer + statusDesc: + type: string + updatedAt: + type: string + type: object + domain.PaginationResponse: + properties: + filters: + items: + $ref: '#/definitions/domain.FilterResponse' + type: array + pageNumber: + type: integer + pageSize: + type: integer + sortColumn: + type: string + sortOrder: + type: string + totalPages: + type: integer + totalRows: + type: integer + type: object + domain.PingTokenRequest: + properties: + organizationId: + type: string + token: + type: string + required: + - organizationId + - token + type: object + domain.PodCount: + properties: + day: + type: integer + value: + type: integer + type: object + domain.ResourceQuota: + properties: + quotas: + items: + $ref: '#/definitions/domain.ResourceQuotaAttr' + type: array + type: object + domain.ResourceQuotaAttr: + properties: + quota: + type: integer + required: + type: integer + type: + type: string + usage: + type: integer + type: object + domain.Role: + properties: + createdAt: + type: string + creator: + type: string + description: + type: string + id: + type: string + name: + type: string + updatedAt: + type: string + type: object + domain.RollbackAppServeAppRequest: + properties: + taskId: + type: string + type: object + domain.SimpleCloudAccountResponse: + properties: + awsAccountId: + type: string + cloudService: + type: string + clusters: + type: integer + createdIAM: + type: boolean + description: + type: string + id: + type: string + name: + type: string + organizationId: + type: string + type: object + domain.SimpleClusterResponse: + properties: + id: + type: string + name: + type: string + organizationId: + type: string + type: object + domain.SimpleStackTemplateResponse: + properties: + cloudService: + type: string + description: + type: string + id: + type: string + kubeType: + type: string + kubeVersion: + type: string + name: + type: string + services: + items: + $ref: '#/definitions/domain.StackTemplateServiceResponse' + type: array + template: + type: string + type: object + domain.SimpleUserResponse: + properties: + accountId: + type: string + id: + type: string + name: + type: string + type: object + domain.StackConfResponse: + properties: + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + maximum: 3 + minimum: 1 + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + maximum: 100 + minimum: 0 + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + required: + - tksInfraNode + - tksUserNode + type: object + domain.StackResponse: + properties: + cloudAccount: + $ref: '#/definitions/domain.SimpleCloudAccountResponse' + conf: + $ref: '#/definitions/domain.StackConfResponse' + createdAt: + type: string + creator: + $ref: '#/definitions/domain.SimpleUserResponse' + description: + type: string + favorited: + type: boolean + grafanaUrl: + type: string + id: + type: string + name: + type: string + organizationId: + type: string + primaryCluster: + type: boolean + resource: + $ref: '#/definitions/domain.DashboardStackResponse' + stackTemplate: + $ref: '#/definitions/domain.SimpleStackTemplateResponse' + status: + type: string + statusDesc: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/domain.SimpleUserResponse' + userClusterEndpoint: + type: string + type: object + domain.StackStepStatus: + properties: + maxStep: + type: integer + stage: + type: string + status: + type: string + step: + type: integer + type: object + domain.StackTemplate: + properties: + cloudService: + type: string + createdAt: + type: string + creator: + $ref: '#/definitions/domain.User' + creatorId: + type: string + description: + type: string + id: + type: string + kubeType: + type: string + kubeVersion: + type: string + name: + type: string + organizationId: + type: string + platform: + type: string + services: + items: + type: integer + type: array + template: + type: string + templateType: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/domain.User' + updatorId: + type: string + version: + type: string + type: object + domain.StackTemplateResponse: + properties: + cloudService: + type: string + createdAt: + type: string + creator: + $ref: '#/definitions/domain.SimpleUserResponse' + description: + type: string + id: + type: string + kubeType: + type: string + kubeVersion: + type: string + name: + type: string + platform: + type: string + services: + items: + $ref: '#/definitions/domain.StackTemplateServiceResponse' + type: array + template: + type: string + templateType: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/domain.SimpleUserResponse' + version: + type: string + type: object + domain.StackTemplateServiceApplicationResponse: + properties: + description: + type: string + name: + type: string + version: + type: string + type: object + domain.StackTemplateServiceResponse: + properties: + applications: + items: + $ref: '#/definitions/domain.StackTemplateServiceApplicationResponse' + type: array + type: + type: string + type: object + domain.StageResponse: + properties: + actions: + items: + $ref: '#/definitions/domain.ActionResponse' + type: array + name: + description: BUILD (빌드), DEPLOY (배포), PROMOTE (프로모트), ROLLBACK (롤백) + type: string + result: + type: string + status: + type: string + type: object + domain.Unit: + properties: + data: + items: + type: string + type: array + name: + type: string + type: object + domain.UpdateAlertRequest: + properties: + description: + type: string + type: object + domain.UpdateAppServeAppEndpointRequest: + properties: + endpointUrl: + type: string + helmRevision: + type: integer + previewEndpointUrl: + type: string + taskId: + type: string + required: + - taskId + type: object + domain.UpdateAppServeAppRequest: + properties: + abort: + type: boolean + appConfig: + type: string + appSecret: + type: string + artifactUrl: + type: string + executablePath: + type: string + extraEnv: + type: string + imageUrl: + type: string + port: + type: string + profile: + type: string + promote: + description: Update Strategy + type: boolean + resourceSpec: + type: string + strategy: + description: Task + type: string + type: object + domain.UpdateAppServeAppStatusRequest: + properties: + output: + type: string + status: + type: string + taskId: + type: string + required: + - status + - taskId + type: object + domain.UpdateCloudAccountRequest: + properties: + description: + type: string + type: object + domain.UpdateMyProfileRequest: + properties: + department: + maxLength: 50 + minLength: 0 + type: string + email: + type: string + name: + maxLength: 30 + minLength: 1 + type: string + password: + type: string + required: + - password + type: object + domain.UpdateMyProfileResponse: + properties: + user: + properties: + accountId: + type: string + department: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/domain.Organization' + role: + $ref: '#/definitions/domain.Role' + type: object + type: object + domain.UpdateOrganizationRequest: + properties: + description: + maxLength: 100 + minLength: 0 + type: string + name: + maxLength: 30 + minLength: 1 + type: string + phone: + type: string + primaryClusterId: + type: string + required: + - name + type: object + domain.UpdateOrganizationResponse: + properties: + description: + type: string + id: + type: string + name: + type: string + phone: + type: string + type: object + domain.UpdatePasswordRequest: + properties: + newPassword: + type: string + originPassword: + type: string + required: + - newPassword + - originPassword + type: object + domain.UpdatePrimaryClusterRequest: + properties: + primaryClusterId: + type: string + type: object + domain.UpdateStackRequest: + properties: + description: + type: string + type: object + domain.UpdateStackTemplateRequest: + properties: + description: + type: string + type: object + domain.UpdateUserRequest: + properties: + department: + maxLength: 50 + minLength: 0 + type: string + description: + maxLength: 100 + minLength: 0 + type: string + email: + type: string + name: + maxLength: 30 + minLength: 1 + type: string + role: + enum: + - admin + - user + type: string + type: object + domain.UpdateUserResponse: + properties: + user: + properties: + accountId: + type: string + createdAt: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/domain.Organization' + role: + $ref: '#/definitions/domain.Role' + updatedAt: + type: string + type: object + type: object + domain.User: + properties: + accountId: + type: string + createdAt: + type: string + creator: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/domain.Organization' + password: + type: string + passwordExpired: + type: boolean + passwordUpdatedAt: + type: string + role: + $ref: '#/definitions/domain.Role' + token: + type: string + updatedAt: + type: string + type: object + domain.VerifyIdentityForLostIdRequest: + properties: + email: + type: string + organizationId: + type: string + userName: + type: string + required: + - email + - organizationId + - userName + type: object + domain.VerifyIdentityForLostIdResponse: + properties: + validityPeriod: + type: string + type: object + domain.VerifyIdentityForLostPasswordRequest: + properties: + accountId: + type: string + email: + type: string + organizationId: + type: string + userName: + type: string + required: + - accountId + - email + - organizationId + - userName + type: object + domain.VerifyIdentityForLostPasswordResponse: + properties: + validityPeriod: + type: string + type: object + httpErrors.RestError: + properties: + code: + type: string + message: + type: string + status: + type: integer + text: + type: string + type: object +host: tks-api-ft.taco-cat.xyz +info: + contact: + email: taekyu.kang@sk.com + name: taekyu.kang@sk.com + description: This is backend api service for tks platform + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + title: tks-api service + version: "1.0" +paths: + /app-groups: + delete: + consumes: + - application/json + description: Uninstall appGroup + parameters: + - description: body + in: body + name: object + required: true + schema: + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Uninstall appGroup + tags: + - AppGroups + get: + consumes: + - application/json + description: Get appGroup list by giving params + parameters: + - description: clusterId + in: query + name: clusterId + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAppGroupsResponse' + security: + - JWT: [] + summary: Get appGroup list + tags: + - AppGroups + post: + consumes: + - application/json + description: Install appGroup + parameters: + - description: create appgroup request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.CreateAppGroupRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CreateAppGroupResponse' + security: + - JWT: [] + summary: Install appGroup + tags: + - AppGroups + /app-groups/{appGroupId}: + get: + consumes: + - application/json + description: Get appGroup detail by appGroupId + parameters: + - description: appGroupId + in: path + name: appGroupId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAppGroupResponse' + security: + - JWT: [] + summary: Get appGroup detail + tags: + - AppGroups + /app-groups/{appGroupId}/applications: + get: + consumes: + - application/json + description: Get applications + parameters: + - description: appGroupId + in: path + name: appGroupId + required: true + type: string + - description: applicationType + in: query + name: applicationType + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetApplicationsResponse' + security: + - JWT: [] + summary: Get applications + tags: + - AppGroups + post: + consumes: + - application/json + description: Create application + parameters: + - description: body + in: body + name: object + required: true + schema: + $ref: '#/definitions/domain.CreateApplicationRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Create application + tags: + - AppGroups + /auth/find-id/code: + post: + consumes: + - application/json + description: This API allows users to verify their identity for lost id by submitting + required information + parameters: + - description: Request body for verifying identity for lost id including {organization + ID, email, username} + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.VerifyIdentityForLostIdRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.VerifyIdentityForLostIdResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httpErrors.RestError' + summary: Request to verify identity for lost id + tags: + - Auth + /auth/find-id/verification: + post: + consumes: + - application/json + description: This API allows users to find their account ID by submitting required + information + parameters: + - description: Request body for finding the account ID including {organization + ID, email, username, 6 digit code} + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.FindIdRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.FindIdResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httpErrors.RestError' + summary: Request to find forgotten ID + tags: + - Auth + /auth/find-password/code: + post: + consumes: + - application/json + description: This API allows users to verify their identity for lost password + by submitting required information + parameters: + - description: Request body for verifying identity for lost password including + {organization ID, email, username, Account ID} + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.VerifyIdentityForLostPasswordRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.VerifyIdentityForLostPasswordResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/httpErrors.RestError' + summary: Request to verify identity for lost password + tags: + - Auth + /auth/find-password/verification: + post: + consumes: + - application/json + description: This API allows users to reset their forgotten password by submitting + required information + parameters: + - description: Request body for finding the password including {organization + ID, email, username, Account ID, 6 digit code} + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.FindPasswordRequest' + produces: + - application/json + responses: + "200": + description: OK + "400": + description: Bad Request + schema: + $ref: '#/definitions/httpErrors.RestError' + summary: Request to find forgotten password + tags: + - Auth + /auth/login: + post: + consumes: + - application/json + description: login + parameters: + - description: account info + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.LoginRequest' + produces: + - application/json + responses: + "200": + description: user detail + schema: + $ref: '#/definitions/domain.LoginResponse' + summary: login + tags: + - Auth + /auth/logout: + post: + consumes: + - application/json + description: logout + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.LogoutResponse' + security: + - JWT: [] + summary: logout + tags: + - Auth + /auth/ping: + post: + consumes: + - application/json + description: ping with token + parameters: + - description: token info + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.PingTokenRequest' + produces: + - application/json + responses: + "200": + description: OK + summary: ping with token + tags: + - Auth + /clusters: + get: + consumes: + - application/json + description: Get cluster list + parameters: + - description: organizationId + in: query + name: organizationId + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetClustersResponse' + security: + - JWT: [] + summary: Get clusters + tags: + - Clusters + post: + consumes: + - application/json + description: Create cluster + parameters: + - description: create cluster request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.CreateClusterRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CreateClusterResponse' + security: + - JWT: [] + summary: Create cluster + tags: + - Clusters + /clusters/{clusterId}: + delete: + consumes: + - application/json + description: Delete cluster + parameters: + - description: clusterId + in: path + name: clusterId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.Cluster' + security: + - JWT: [] + summary: Delete cluster + tags: + - Clusters + get: + consumes: + - application/json + description: Get cluster detail + parameters: + - description: clusterId + in: path + name: clusterId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.Cluster' + security: + - JWT: [] + summary: Get cluster + tags: + - Clusters + /clusters/{clusterId}/bootstrap-kubeconfig: + get: + consumes: + - application/json + description: Get bootstrap kubeconfig for BYOH + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetBootstrapKubeconfigResponse' + security: + - JWT: [] + summary: Get bootstrap kubeconfig for BYOH + tags: + - Clusters + post: + consumes: + - application/json + description: Create bootstrap kubeconfig for BYOH + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CreateBootstrapKubeconfigResponse' + security: + - JWT: [] + summary: Create bootstrap kubeconfig for BYOH + tags: + - Clusters + /clusters/{clusterId}/install: + post: + consumes: + - application/json + description: Install cluster on tks cluster + parameters: + - description: clusterId + in: path + name: clusterId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Install cluster on tks cluster + tags: + - Clusters + /clusters/{clusterId}/nodes: + get: + consumes: + - application/json + description: Get nodes information for BYOH + parameters: + - description: clusterId + in: path + name: clusterId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetClusterNodesResponse' + security: + - JWT: [] + summary: Get nodes information for BYOH + tags: + - Clusters + /clusters/{clusterId}/site-values: + get: + consumes: + - application/json + description: Get cluster site values for creating + parameters: + - description: clusterId + in: path + name: clusterId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.ClusterSiteValuesResponse' + security: + - JWT: [] + summary: Get cluster site values for creating + tags: + - Clusters + /clusters/import: + post: + consumes: + - application/json + description: Import cluster + parameters: + - description: import cluster request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.ImportClusterRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.ImportClusterResponse' + security: + - JWT: [] + summary: Import cluster + tags: + - Clusters + /organizations: + get: + consumes: + - application/json + description: Get organization list + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/domain.ListOrganizationBody' + type: array + security: + - JWT: [] + summary: Get organization list + tags: + - Organizations + post: + consumes: + - application/json + description: Create organization + parameters: + - description: create organization request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.CreateOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: object + security: + - JWT: [] + summary: Create organization + tags: + - Organizations + /organizations/{organizationId}: + delete: + consumes: + - application/json + description: Delete organization + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.Organization' + security: + - JWT: [] + summary: Delete organization + tags: + - Organizations + get: + consumes: + - application/json + description: Get organization detail + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetOrganizationResponse' + security: + - JWT: [] + summary: Get organization detail + tags: + - Organizations + put: + consumes: + - application/json + description: Update organization detail + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: update organization request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.UpdateOrganizationResponse' + security: + - JWT: [] + summary: Update organization detail + tags: + - Organizations + /organizations/{organizationId}/alerts: + get: + consumes: + - application/json + description: Get Alerts + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAlertsResponse' + security: + - JWT: [] + summary: Get Alerts + tags: + - Alerts + /organizations/{organizationId}/alerts/{alertId}: + delete: + consumes: + - application/json + description: Delete Alert + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: alertId + in: path + name: alertId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete Alert + tags: + - Alerts + get: + consumes: + - application/json + description: Get Alert + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: alertId + in: path + name: alertId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAlertResponse' + security: + - JWT: [] + summary: Get Alert + tags: + - Alerts + put: + consumes: + - application/json + description: Update Alert + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: Update cloud setting request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateAlertRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update Alert + tags: + - Alerts + /organizations/{organizationId}/alerts/{alertId}/actions: + post: + consumes: + - application/json + description: Create alert action + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Create alert action + tags: + - Alerts + /organizations/{organizationId}/app-serve-apps: + get: + consumes: + - application/json + description: Get appServeApp list by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Show all apps including deleted apps + in: query + name: showAll + type: boolean + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/domain.AppServeApp' + type: array + security: + - JWT: [] + summary: Get appServeApp list + tags: + - AppServeApps + post: + consumes: + - application/json + description: Install appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Request body to create app + in: body + name: object + required: true + schema: + $ref: '#/definitions/domain.CreateAppServeAppRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Install appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/app-serve-apps/{appId}: + delete: + consumes: + - application/json + description: Uninstall appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Uninstall appServeApp + tags: + - AppServeApps + get: + consumes: + - application/json + description: Get appServeApp by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAppServeAppResponse' + security: + - JWT: [] + summary: Get appServeApp + tags: + - AppServeApps + put: + consumes: + - application/json + description: Update appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + - description: Request body to update app + in: body + name: object + required: true + schema: + $ref: '#/definitions/domain.UpdateAppServeAppRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Update appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/app-serve-apps/{appId}/endpoint: + patch: + consumes: + - application/json + description: Update app endpoint + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: appId + in: path + name: appId + required: true + type: string + - description: Request body to update app endpoint + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateAppServeAppEndpointRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Update app endpoint + tags: + - AppServeApps + /organizations/{organizationId}/app-serve-apps/{appId}/exist: + get: + consumes: + - application/json + description: Get appServeApp by giving params + produces: + - application/json + responses: + "200": + description: OK + schema: + type: boolean + security: + - JWT: [] + summary: Get appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/app-serve-apps/{appId}/latest-task: + get: + consumes: + - application/json + description: Get latest task from appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAppServeAppTaskResponse' + security: + - JWT: [] + summary: Get latest task from appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/app-serve-apps/{appId}/rollback: + post: + consumes: + - application/json + description: Rollback appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + - description: Request body to rollback app + in: body + name: object + required: true + schema: + $ref: '#/definitions/domain.RollbackAppServeAppRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Rollback appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/app-serve-apps/{appId}/status: + patch: + consumes: + - application/json + description: Update app status + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + - description: Request body to update app status + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateAppServeAppStatusRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Update app status + tags: + - AppServeApps + /organizations/{organizationId}/app-serve-apps/count: + get: + consumes: + - application/json + description: Get number of apps on given stack + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Stack ID + in: query + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: integer + security: + - JWT: [] + summary: Get number of apps on given stack + tags: + - AppServeApps + /organizations/{organizationId}/app-serve-apps/name/{name}/existence: + get: + consumes: + - application/json + description: Check duplicate appServeAppName by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: boolean + security: + - JWT: [] + summary: Check duplicate appServeAppName + tags: + - AppServeApps + /organizations/{organizationId}/cloud-accounts: + get: + consumes: + - application/json + description: Get CloudAccounts + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetCloudAccountsResponse' + security: + - JWT: [] + summary: Get CloudAccounts + tags: + - CloudAccounts + post: + consumes: + - application/json + description: Create CloudAccount + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: create cloud setting request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.CreateCloudAccountRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CreateCloudAccountResponse' + security: + - JWT: [] + summary: Create CloudAccount + tags: + - CloudAccounts + /organizations/{organizationId}/cloud-accounts/{cloudAccountId}: + delete: + consumes: + - application/json + description: Delete CloudAccount + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: Delete cloud setting request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.DeleteCloudAccountRequest' + - description: cloudAccountId + in: path + name: cloudAccountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete CloudAccount + tags: + - CloudAccounts + get: + consumes: + - application/json + description: Get CloudAccount + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: cloudAccountId + in: path + name: cloudAccountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetCloudAccountResponse' + security: + - JWT: [] + summary: Get CloudAccount + tags: + - CloudAccounts + put: + consumes: + - application/json + description: Update CloudAccount + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: Update cloud setting request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateCloudAccountRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update CloudAccount + tags: + - CloudAccounts + /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error: + delete: + consumes: + - application/json + description: Delete Force CloudAccount + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: cloudAccountId + in: path + name: cloudAccountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete Force CloudAccount + tags: + - CloudAccounts + /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota: + get: + consumes: + - application/json + description: Get resource quota by cloudAccount + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: cloudAccountId + in: path + name: cloudAccountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetCloudAccountResourceQuotaResponse' + security: + - JWT: [] + summary: Get resource quota by cloudAccount + tags: + - CloudAccounts + /organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence: + get: + consumes: + - application/json + description: Check awsAccountId for cloudAccount + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: awsAccountId + in: path + name: awsAccountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CheckCloudAccountAwsAccountIdResponse' + security: + - JWT: [] + summary: Check awsAccountId for cloudAccount + tags: + - CloudAccounts + /organizations/{organizationId}/cloud-accounts/name/{name}/existence: + get: + consumes: + - application/json + description: Check name for cloudAccount + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CheckCloudAccountNameResponse' + security: + - JWT: [] + summary: Check name for cloudAccount + tags: + - CloudAccounts + /organizations/{organizationId}/dashboard/charts: + get: + consumes: + - application/json + description: Get charts data + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: chartType + in: query + name: chartType + type: string + - description: duration + in: query + name: duration + required: true + type: string + - description: interval + in: query + name: interval + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetDashboardChartsResponse' + security: + - JWT: [] + summary: Get charts data + tags: + - Dashboards + /organizations/{organizationId}/dashboard/charts/{chartType}: + get: + consumes: + - application/json + description: Get chart data + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: chartType + in: path + name: chartType + required: true + type: string + - description: duration + in: query + name: duration + required: true + type: string + - description: interval + in: query + name: interval + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetDashboardChartResponse' + security: + - JWT: [] + summary: Get chart data + tags: + - Dashboards + /organizations/{organizationId}/dashboard/resources: + get: + consumes: + - application/json + description: Get resources + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetDashboardResourcesResponse' + security: + - JWT: [] + summary: Get resources + tags: + - Dashboards + /organizations/{organizationId}/dashboard/stacks: + get: + consumes: + - application/json + description: Get stacks + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetDashboardStacksResponse' + security: + - JWT: [] + summary: Get stacks + tags: + - Dashboards + /organizations/{organizationId}/my-profile: + delete: + consumes: + - application/json + description: Delete myProfile + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + "400": + description: Bad Request + security: + - JWT: [] + summary: Delete myProfile + tags: + - My-profile + get: + consumes: + - application/json + description: Get my profile detail + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetMyProfileResponse' + security: + - JWT: [] + summary: Get my profile detail + tags: + - My-profile + put: + consumes: + - application/json + description: Update my profile detail + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: 'Required fields: password due to double-check' + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateMyProfileRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.UpdateMyProfileResponse' + security: + - JWT: [] + summary: Update my profile detail + tags: + - My-profile + /organizations/{organizationId}/my-profile/next-password-change: + put: + consumes: + - application/json + description: Update user's password expired date to current date + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + "400": + description: Bad Request + schema: + $ref: '#/definitions/httpErrors.RestError' + security: + - JWT: [] + summary: Update user's password expired date to current date + tags: + - My-profile + /organizations/{organizationId}/my-profile/password: + put: + consumes: + - application/json + description: Update user password detail + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: update user password request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdatePasswordRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update user password detail + tags: + - My-profile + /organizations/{organizationId}/primary-cluster: + patch: + consumes: + - application/json + description: Update primary cluster + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: update primary cluster request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdatePrimaryClusterRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update primary cluster + tags: + - Organizations + /organizations/{organizationId}/stacks: + get: + consumes: + - application/json + description: Get Stacks + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: combinedFilter + in: query + name: combinedFilter + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetStacksResponse' + security: + - JWT: [] + summary: Get Stacks + tags: + - Stacks + post: + consumes: + - application/json + description: Create Stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: create cloud setting request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.CreateStackRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CreateStackResponse' + security: + - JWT: [] + summary: Create Stack + tags: + - Stacks + /organizations/{organizationId}/stacks/{stackId}: + delete: + consumes: + - application/json + description: Delete Stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackId + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete Stack + tags: + - Stacks + get: + consumes: + - application/json + description: Get Stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackId + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetStackResponse' + security: + - JWT: [] + summary: Get Stack + tags: + - Stacks + put: + consumes: + - application/json + description: Update Stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackId + in: path + name: stackId + required: true + type: string + - description: Update cloud setting request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateStackRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update Stack + tags: + - Stacks + /organizations/{organizationId}/stacks/{stackId}/favorite: + delete: + consumes: + - application/json + description: Delete favorite stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackId + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete favorite stack + tags: + - Stacks + post: + consumes: + - application/json + description: Set favorite stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackId + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Set favorite stack + tags: + - Stacks + /organizations/{organizationId}/stacks/{stackId}/kube-config: + get: + consumes: + - application/json + description: Get KubeConfig by stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: organizationId + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetStackKubeConfigResponse' + security: + - JWT: [] + summary: Get KubeConfig by stack + tags: + - Stacks + /organizations/{organizationId}/stacks/{stackId}/status: + get: + consumes: + - application/json + description: Get Stack Status + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackId + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetStackStatusResponse' + security: + - JWT: [] + summary: Get Stack Status + tags: + - Stacks + /organizations/{organizationId}/stacks/name/{name}/existence: + get: + consumes: + - application/json + description: Check name for stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackId + in: path + name: stackId + required: true + type: string + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Check name for stack + tags: + - Stacks + /organizations/{organizationId}/users: + get: + consumes: + - application/json + description: Get user list + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/domain.ListUserBody' + type: array + security: + - JWT: [] + summary: Get user list + tags: + - Users + post: + consumes: + - application/json + description: Create user + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: create user request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.CreateUserRequest' + produces: + - application/json + responses: + "200": + description: create user response + schema: + $ref: '#/definitions/domain.CreateUserResponse' + security: + - JWT: [] + summary: Create user + tags: + - Users + /organizations/{organizationId}/users/{accountId}: + delete: + consumes: + - application/json + description: Delete user + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.User' + security: + - JWT: [] + summary: Delete user + tags: + - Users + get: + consumes: + - application/json + description: Get user detail + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetUserResponse' + security: + - JWT: [] + summary: Get user detail + tags: + - Users + put: + consumes: + - application/json + description: Update user + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + - description: input + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateUserRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.UpdateUserResponse' + security: + - JWT: [] + summary: Update user + tags: + - Users + /organizations/{organizationId}/users/{accountId}/reset-password: + put: + consumes: + - application/json + description: Reset user's password as temporary password by admin and send email + to user + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Reset user's password as temporary password by admin + tags: + - Users + /organizations/{organizationId}/users/account-id/{accountId}/existence: + get: + description: return true when accountId exists + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CheckExistedResponse' + security: + - JWT: [] + summary: Get user id existence + tags: + - Users + /organizations/{organizationId}/users/email/{email}/existence: + get: + description: return true when email exists + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: email + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CheckExistedResponse' + security: + - JWT: [] + summary: Get user email existence + tags: + - Users + /stack-templates: + get: + consumes: + - application/json + description: Get StackTemplates + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetStackTemplatesResponse' + security: + - JWT: [] + summary: Get StackTemplates + tags: + - StackTemplates + post: + consumes: + - application/json + description: Create StackTemplate + parameters: + - description: create stack template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.CreateStackTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CreateStackTemplateResponse' + security: + - JWT: [] + summary: Create StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + /stack-templates/{stackTemplateId}: + delete: + consumes: + - application/json + description: Delete StackTemplate + parameters: + - description: stackTemplateId + in: path + name: stackTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + get: + consumes: + - application/json + description: Get StackTemplate + parameters: + - description: stackTemplateId + in: path + name: stackTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetStackTemplateResponse' + security: + - JWT: [] + summary: Get StackTemplate + tags: + - StackTemplates + put: + consumes: + - application/json + description: Update StackTemplate + parameters: + - description: Update stack template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateStackTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + /system-api/organizations/{organizationId}/alerts: + post: + consumes: + - application/json + description: Create alert. ADMIN ONLY + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Create alert. ADMIN ONLY + tags: + - Alerts +securityDefinitions: + JWT: + in: header + name: Authorization + type: apiKey +swagger: "2.0" From f146f1a09e461d7bda28ef7d69a1dc52846c48f6 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 25 Jan 2024 16:22:17 +0900 Subject: [PATCH 015/502] ignore go.work file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7da128bd..3665eca7 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ web main output vendor +go.work From 47d38437149f72a1ba3a1a0527701b7e9fdda798 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 29 Jan 2024 14:41:45 +0900 Subject: [PATCH 016/502] Create Project Project Member Management --- .gitignore | 1 + api/swagger/docs.go | 445 ++++++++++++++++++ api/swagger/swagger.json | 445 ++++++++++++++++++ api/swagger/swagger.yaml | 287 ++++++++++++ cmd/server/main.go | 14 +- internal/database/database.go | 14 + internal/delivery/api/endpoint.go | 21 + internal/delivery/http/alert.go | 112 ++--- internal/delivery/http/app-group.go | 108 ++--- internal/delivery/http/app-serve-app.go | 230 ++++----- internal/delivery/http/auth.go | 116 ++--- internal/delivery/http/cloud-account.go | 172 +++---- internal/delivery/http/cluster.go | 236 +++++----- internal/delivery/http/dashboard.go | 76 +-- internal/delivery/http/organization.go | 108 ++--- internal/delivery/http/project.go | 488 +++++++++++++++++++- internal/delivery/http/stack-template.go | 88 ++-- internal/delivery/http/stack.go | 192 ++++---- internal/delivery/http/user.go | 238 +++++----- internal/middleware/auth/authorizer/rbac.go | 58 ++- internal/repository/project.go | 137 ++++++ internal/repository/repository.go | 1 + internal/route/route.go | 27 +- internal/usecase/project.go | 153 +++++- pkg/domain/project.go | 137 ++++++ scripts/erd_postgres.sql | 52 +++ scripts/init_postgres.sql | 5 +- 27 files changed, 3059 insertions(+), 902 deletions(-) create mode 100644 internal/repository/project.go create mode 100644 pkg/domain/project.go diff --git a/.gitignore b/.gitignore index 3665eca7..6c2919aa 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ main output vendor go.work +go.work.sum diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 3b595793..7ad45e4e 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -2784,6 +2784,227 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/projects": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create new project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Create new project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to create project", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateProjectRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/project-roles": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project roles by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project roles", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "project role search by query (query=all), (query=leader), (query=member), (query=viewer)", + "name": "query", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectRolesResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project role by id", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectRoleResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/members": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project members", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project members", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectMembersResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add project member to project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Add project member to project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to add project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.AddProjectMemberRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.AddProjectMemberResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -3883,6 +4104,28 @@ const docTemplate = `{ } } }, + "domain.AddProjectMemberRequest": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectMemberRequest" + } + } + } + }, + "domain.AddProjectMemberResponse": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectMember" + } + } + } + }, "domain.AlertActionResponse": { "type": "object", "properties": { @@ -4973,6 +5216,34 @@ const docTemplate = `{ } } }, + "domain.CreateProjectRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "projectLeaderId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + } + } + }, + "domain.CreateProjectResponse": { + "type": "object", + "properties": { + "project": { + "$ref": "#/definitions/domain.Project" + } + } + }, "domain.CreateStackRequest": { "type": "object", "required": [ @@ -5606,6 +5877,36 @@ const docTemplate = `{ } } }, + "domain.GetProjectMembersResponse": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectMember" + } + } + } + }, + "domain.GetProjectRoleResponse": { + "type": "object", + "properties": { + "projectRole": { + "$ref": "#/definitions/domain.ProjectRole" + } + } + }, + "domain.GetProjectRolesResponse": { + "type": "object", + "properties": { + "projectRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectRole" + } + } + } + }, "domain.GetStackKubeConfigResponse": { "type": "object", "properties": { @@ -5978,6 +6279,150 @@ const docTemplate = `{ } } }, + "domain.Project": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "projectMembers": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectMember" + } + }, + "projectNamesapces": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectNamesapce" + } + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.ProjectMember": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectRole": { + "$ref": "#/definitions/domain.ProjectRole" + }, + "projectRoleId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/domain.User" + }, + "userId": { + "type": "string" + } + } + }, + "domain.ProjectMemberRequest": { + "type": "object", + "required": [ + "projectRoleId", + "userId" + ], + "properties": { + "projectRoleId": { + "type": "string" + }, + "userId": { + "type": "string" + } + } + }, + "domain.ProjectNamesapce": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "stackId": { + "type": "string" + }, + "stackName": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.ProjectRole": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "description": "project-leader, project-member, project-viewer", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "domain.ResourceQuota": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index fa98668f..3a987667 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -2777,6 +2777,227 @@ } } }, + "/organizations/{organizationId}/projects": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create new project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Create new project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to create project", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateProjectRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/project-roles": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project roles by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project roles", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "project role search by query (query=all), (query=leader), (query=member), (query=viewer)", + "name": "query", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectRolesResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project role by id", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectRoleResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/members": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project members", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project members", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectMembersResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add project member to project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Add project member to project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to add project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.AddProjectMemberRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.AddProjectMemberResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -3876,6 +4097,28 @@ } } }, + "domain.AddProjectMemberRequest": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectMemberRequest" + } + } + } + }, + "domain.AddProjectMemberResponse": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectMember" + } + } + } + }, "domain.AlertActionResponse": { "type": "object", "properties": { @@ -4966,6 +5209,34 @@ } } }, + "domain.CreateProjectRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "projectLeaderId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + } + } + }, + "domain.CreateProjectResponse": { + "type": "object", + "properties": { + "project": { + "$ref": "#/definitions/domain.Project" + } + } + }, "domain.CreateStackRequest": { "type": "object", "required": [ @@ -5599,6 +5870,36 @@ } } }, + "domain.GetProjectMembersResponse": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectMember" + } + } + } + }, + "domain.GetProjectRoleResponse": { + "type": "object", + "properties": { + "projectRole": { + "$ref": "#/definitions/domain.ProjectRole" + } + } + }, + "domain.GetProjectRolesResponse": { + "type": "object", + "properties": { + "projectRoles": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectRole" + } + } + } + }, "domain.GetStackKubeConfigResponse": { "type": "object", "properties": { @@ -5971,6 +6272,150 @@ } } }, + "domain.Project": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "projectMembers": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectMember" + } + }, + "projectNamesapces": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectNamesapce" + } + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.ProjectMember": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectRole": { + "$ref": "#/definitions/domain.ProjectRole" + }, + "projectRoleId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/domain.User" + }, + "userId": { + "type": "string" + } + } + }, + "domain.ProjectMemberRequest": { + "type": "object", + "required": [ + "projectRoleId", + "userId" + ], + "properties": { + "projectRoleId": { + "type": "string" + }, + "userId": { + "type": "string" + } + } + }, + "domain.ProjectNamesapce": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "stackId": { + "type": "string" + }, + "stackName": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.ProjectRole": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "description": "project-leader, project-member, project-viewer", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "domain.ResourceQuota": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index dfbf2f9f..3421c4c2 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -17,6 +17,20 @@ definitions: uri: type: string type: object + domain.AddProjectMemberRequest: + properties: + projectMembers: + items: + $ref: '#/definitions/domain.ProjectMemberRequest' + type: array + type: object + domain.AddProjectMemberResponse: + properties: + projectMembers: + items: + $ref: '#/definitions/domain.ProjectMember' + type: array + type: object domain.AlertActionResponse: properties: alertId: @@ -752,6 +766,24 @@ definitions: - Email - name type: object + domain.CreateProjectRequest: + properties: + description: + type: string + name: + type: string + projectLeaderId: + type: string + projectRoleId: + type: string + required: + - name + type: object + domain.CreateProjectResponse: + properties: + project: + $ref: '#/definitions/domain.Project' + type: object domain.CreateStackRequest: properties: cloudAccountId: @@ -1172,6 +1204,25 @@ definitions: type: string type: object type: object + domain.GetProjectMembersResponse: + properties: + projectMembers: + items: + $ref: '#/definitions/domain.ProjectMember' + type: array + type: object + domain.GetProjectRoleResponse: + properties: + projectRole: + $ref: '#/definitions/domain.ProjectRole' + type: object + domain.GetProjectRolesResponse: + properties: + projectRoles: + items: + $ref: '#/definitions/domain.ProjectRole' + type: array + type: object domain.GetStackKubeConfigResponse: properties: kubeConfig: @@ -1415,6 +1466,101 @@ definitions: value: type: integer type: object + domain.Project: + properties: + createdAt: + type: string + deletedAt: + type: string + description: + type: string + id: + type: string + name: + type: string + organizationId: + type: string + projectMembers: + items: + $ref: '#/definitions/domain.ProjectMember' + type: array + projectNamesapces: + items: + $ref: '#/definitions/domain.ProjectNamesapce' + type: array + updatedAt: + type: string + type: object + domain.ProjectMember: + properties: + createdAt: + type: string + deletedAt: + type: string + id: + type: string + projectId: + type: string + projectRole: + $ref: '#/definitions/domain.ProjectRole' + projectRoleId: + type: string + updatedAt: + type: string + user: + $ref: '#/definitions/domain.User' + userId: + type: string + type: object + domain.ProjectMemberRequest: + properties: + projectRoleId: + type: string + userId: + type: string + required: + - projectRoleId + - userId + type: object + domain.ProjectNamesapce: + properties: + createdAt: + type: string + deletedAt: + type: string + description: + type: string + id: + type: string + namespace: + type: string + projectId: + type: string + stackId: + type: string + stackName: + type: string + status: + type: string + updatedAt: + type: string + type: object + domain.ProjectRole: + properties: + createdAt: + type: string + deletedAt: + type: string + description: + type: string + id: + type: string + name: + description: project-leader, project-member, project-viewer + type: string + updatedAt: + type: string + type: object domain.ResourceQuota: properties: quotas: @@ -3762,6 +3908,147 @@ paths: summary: Update primary cluster tags: - Organizations + /organizations/{organizationId}/projects: + post: + consumes: + - application/json + description: Create new project + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Request body to create project + in: body + name: request + required: true + schema: + $ref: '#/definitions/domain.CreateProjectRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CreateProjectResponse' + security: + - JWT: [] + summary: Create new project + tags: + - Projects + /organizations/{organizationId}/projects/{projectId}/members: + get: + consumes: + - application/json + description: Get project members + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectMembersResponse' + security: + - JWT: [] + summary: Get project members + tags: + - Projects + post: + consumes: + - application/json + description: Add project member to project + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Request body to add project member + in: body + name: request + required: true + schema: + $ref: '#/definitions/domain.AddProjectMemberRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.AddProjectMemberResponse' + security: + - JWT: [] + summary: Add project member to project + tags: + - Projects + /organizations/{organizationId}/projects/project-roles: + get: + consumes: + - application/json + description: Get project roles by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: project role search by query (query=all), (query=leader), (query=member), + (query=viewer) + in: query + name: query + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectRolesResponse' + security: + - JWT: [] + summary: Get project roles + tags: + - Projects + /organizations/{organizationId}/projects/project-roles/{projectRoleId}: + get: + consumes: + - application/json + description: Get project role by id + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectRoleResponse' + security: + - JWT: [] + summary: Get project role + tags: + - Projects /organizations/{organizationId}/stacks: get: consumes: diff --git a/cmd/server/main.go b/cmd/server/main.go index eea9f26d..effa4bcb 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -76,8 +76,8 @@ func init() { } -// @title tks-api service -// @version 1.0 +// @title tks-api service +// @version 1.0 // @description This is backend api service for tks platform // @contact.name taekyu.kang@sk.com @@ -85,13 +85,13 @@ func init() { // @contact.email taekyu.kang@sk.com // @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html +// @license.url http://www.apache.org/licenses/LICENSE-2.0.html -// @securitydefinitions.apikey JWT -// @in header -// @name Authorization +// @securitydefinitions.apikey JWT +// @in header +// @name Authorization -// @host tks-api-ft.taco-cat.xyz +// @host tks-api-ft.taco-cat.xyz // @BasePath /api/1.0/ func main() { log.Info("*** Arguments *** ") diff --git a/internal/database/database.go b/internal/database/database.go index 7d7ff222..2d4cd301 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -114,5 +114,19 @@ func migrateSchema(db *gorm.DB) error { return err } + // Project + if err := db.AutoMigrate(&domain.Project{}); err != nil { + return err + } + if err := db.AutoMigrate(&domain.ProjectRole{}); err != nil { + return err + } + if err := db.AutoMigrate(&domain.ProjectMember{}); err != nil { + return err + } + if err := db.AutoMigrate(&domain.ProjectNamesapce{}); err != nil { + return err + } + return nil } diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 08782aae..5a02fca9 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -127,11 +127,14 @@ const ( // Project CreateProject + GetProjectRoles + GetProjectRole GetProjects GetProject UpdateProject DeleteProject AddProjectMember + GetProjectMember GetProjectMembers RemoveProjectMember UpdateProjectMemberRole @@ -514,6 +517,14 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CreateProject", Group: "Project", }, + GetProjectRoles: { + Name: "GetProjectRoles", + Group: "Project", + }, + GetProjectRole: { + Name: "GetProjectRole", + Group: "Project", + }, GetProjects: { Name: "GetProjects", Group: "Project", @@ -534,6 +545,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "AddProjectMember", Group: "Project", }, + GetProjectMember: { + Name: "GetProjectMember", + Group: "Project", + }, GetProjectMembers: { Name: "GetProjectMembers", Group: "Project", @@ -766,6 +781,10 @@ func (e Endpoint) String() string { return "InstallStack" case CreateProject: return "CreateProject" + case GetProjectRoles: + return "GetProjectRoles" + case GetProjectRole: + return "GetProjectRole" case GetProjects: return "GetProjects" case GetProject: @@ -776,6 +795,8 @@ func (e Endpoint) String() string { return "DeleteProject" case AddProjectMember: return "AddProjectMember" + case GetProjectMember: + return "GetProjectMember" case GetProjectMembers: return "GetProjectMembers" case RemoveProjectMember: diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index 5568af51..b03d8f3b 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -28,15 +28,15 @@ func NewAlertHandler(h usecase.IAlertUsecase) *AlertHandler { } // CreateAlert godoc -// @Tags Alerts -// @Summary Create alert. ADMIN ONLY +// @Tags Alerts +// @Summary Create alert. ADMIN ONLY // @Description Create alert. ADMIN ONLY -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} nil -// @Router /system-api/organizations/{organizationId}/alerts [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} nil +// @Router /system-api/organizations/{organizationId}/alerts [post] +// @Security JWT func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { /* @@ -72,20 +72,20 @@ func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { } // GetAlert godoc -// @Tags Alerts -// @Summary Get Alerts +// @Tags Alerts +// @Summary Get Alerts // @Description Get Alerts -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetAlertsResponse -// @Router /organizations/{organizationId}/alerts [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetAlertsResponse +// @Router /organizations/{organizationId}/alerts [get] +// @Security JWT func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -160,16 +160,16 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { } // GetAlert godoc -// @Tags Alerts -// @Summary Get Alert +// @Tags Alerts +// @Summary Get Alert // @Description Get Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param alertId path string true "alertId" -// @Success 200 {object} domain.GetAlertResponse -// @Router /organizations/{organizationId}/alerts/{alertId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param alertId path string true "alertId" +// @Success 200 {object} domain.GetAlertResponse +// @Router /organizations/{organizationId}/alerts/{alertId} [get] +// @Security JWT func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["alertId"] @@ -207,31 +207,31 @@ func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { } // UpdateAlert godoc -// @Tags Alerts -// @Summary Update Alert +// @Tags Alerts +// @Summary Update Alert // @Description Update Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateAlertRequest true "Update cloud setting request" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId} [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateAlertRequest true "Update cloud setting request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/alerts/{alertId} [put] +// @Security JWT func (h *AlertHandler) UpdateAlert(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("Need implementation")) } // DeleteAlert godoc -// @Tags Alerts -// @Summary Delete Alert +// @Tags Alerts +// @Summary Delete Alert // @Description Delete Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param alertId path string true "alertId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId} [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param alertId path string true "alertId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/alerts/{alertId} [delete] +// @Security JWT func (h *AlertHandler) DeleteAlert(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("Need implementation")) } @@ -247,15 +247,15 @@ func (h *AlertHandler) AlertTest(w http.ResponseWriter, r *http.Request) { } // CreateAlertAction godoc -// @Tags Alerts -// @Summary Create alert action +// @Tags Alerts +// @Summary Create alert action // @Description Create alert action -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId}/actions [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/alerts/{alertId}/actions [post] +// @Security JWT func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["alertId"] diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 510e0d71..14aa7da6 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -25,15 +25,15 @@ func NewAppGroupHandler(h usecase.IAppGroupUsecase) *AppGroupHandler { } // CreateAppGroup godoc -// @Tags AppGroups -// @Summary Install appGroup +// @Tags AppGroups +// @Summary Install appGroup // @Description Install appGroup -// @Accept json -// @Produce json -// @Param body body domain.CreateAppGroupRequest true "create appgroup request" -// @Success 200 {object} domain.CreateAppGroupResponse -// @Router /app-groups [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param body body domain.CreateAppGroupRequest true "create appgroup request" +// @Success 200 {object} domain.CreateAppGroupResponse +// @Router /app-groups [post] +// @Security JWT func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) { input := domain.CreateAppGroupRequest{} err := UnmarshalRequestInput(r, &input) @@ -60,20 +60,20 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) } // GetAppGroups godoc -// @Tags AppGroups -// @Summary Get appGroup list +// @Tags AppGroups +// @Summary Get appGroup list // @Description Get appGroup list by giving params -// @Accept json -// @Produce json -// @Param clusterId query string false "clusterId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetAppGroupsResponse -// @Router /app-groups [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param clusterId query string false "clusterId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetAppGroupsResponse +// @Router /app-groups [get] +// @Security JWT func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -111,15 +111,15 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { } // GetAppGroup godoc -// @Tags AppGroups -// @Summary Get appGroup detail +// @Tags AppGroups +// @Summary Get appGroup detail // @Description Get appGroup detail by appGroupId -// @Accept json -// @Produce json -// @Param appGroupId path string true "appGroupId" -// @Success 200 {object} domain.GetAppGroupResponse -// @Router /app-groups/{appGroupId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param appGroupId path string true "appGroupId" +// @Success 200 {object} domain.GetAppGroupResponse +// @Router /app-groups/{appGroupId} [get] +// @Security JWT func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["appGroupId"] @@ -147,15 +147,15 @@ func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { } // DeleteAppGroup godoc -// @Tags AppGroups -// @Summary Uninstall appGroup +// @Tags AppGroups +// @Summary Uninstall appGroup // @Description Uninstall appGroup -// @Accept json -// @Produce json -// @Param object body string true "body" -// @Success 200 {object} nil -// @Router /app-groups [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param object body string true "body" +// @Success 200 {object} nil +// @Router /app-groups [delete] +// @Security JWT func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["appGroupId"] @@ -181,16 +181,16 @@ func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) } // GetApplications godoc -// @Tags AppGroups -// @Summary Get applications +// @Tags AppGroups +// @Summary Get applications // @Description Get applications -// @Accept json -// @Produce json -// @Param appGroupId path string true "appGroupId" -// @Param applicationType query string true "applicationType" -// @Success 200 {object} domain.GetApplicationsResponse -// @Router /app-groups/{appGroupId}/applications [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param appGroupId path string true "appGroupId" +// @Param applicationType query string true "applicationType" +// @Success 200 {object} domain.GetApplicationsResponse +// @Router /app-groups/{appGroupId}/applications [get] +// @Security JWT func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["appGroupId"] @@ -233,15 +233,15 @@ func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request } // CreateApplication godoc -// @Tags AppGroups -// @Summary Create application +// @Tags AppGroups +// @Summary Create application // @Description Create application -// @Accept json -// @Produce json -// @Param object body domain.CreateApplicationRequest true "body" -// @Success 200 {object} nil -// @Router /app-groups/{appGroupId}/applications [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param object body domain.CreateApplicationRequest true "body" +// @Success 200 {object} nil +// @Router /app-groups/{appGroupId}/applications [post] +// @Security JWT func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["appGroupId"] diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 7b3df3e5..2510a768 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -78,16 +78,16 @@ func NewAppServeAppHandler(h usecase.IAppServeAppUsecase) *AppServeAppHandler { } // CreateAppServeApp godoc -// @Tags AppServeApps -// @Summary Install appServeApp +// @Tags AppServeApps +// @Summary Install appServeApp // @Description Install appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param object body domain.CreateAppServeAppRequest true "Request body to create app" -// @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param object body domain.CreateAppServeAppRequest true "Request body to create app" +// @Success 200 {object} string +// @Router /organizations/{organizationId}/app-serve-apps [post] +// @Security JWT func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -206,21 +206,21 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re } // GetAppServeApps godoc -// @Tags AppServeApps -// @Summary Get appServeApp list +// @Tags AppServeApps +// @Summary Get appServeApp list // @Description Get appServeApp list by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param showAll query boolean false "Show all apps including deleted apps" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} []domain.AppServeApp -// @Router /organizations/{organizationId}/app-serve-apps [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param showAll query boolean false "Show all apps including deleted apps" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} []domain.AppServeApp +// @Router /organizations/{organizationId}/app-serve-apps [get] +// @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -267,16 +267,16 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ } // GetAppServeApp godoc -// @Tags AppServeApps -// @Summary Get appServeApp +// @Tags AppServeApps +// @Summary Get appServeApp // @Description Get appServeApp by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param appId path string true "App ID" -// @Success 200 {object} domain.GetAppServeAppResponse -// @Router /organizations/{organizationId}/app-serve-apps/{appId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param appId path string true "App ID" +// @Success 200 {object} domain.GetAppServeAppResponse +// @Router /organizations/{organizationId}/app-serve-apps/{appId} [get] +// @Security JWT func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -323,16 +323,16 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque } // GetAppServeAppLatestTask godoc -// @Tags AppServeApps -// @Summary Get latest task from appServeApp +// @Tags AppServeApps +// @Summary Get latest task from appServeApp // @Description Get latest task from appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param appId path string true "App ID" -// @Success 200 {object} domain.GetAppServeAppTaskResponse -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/latest-task [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param appId path string true "App ID" +// @Success 200 {object} domain.GetAppServeAppTaskResponse +// @Router /organizations/{organizationId}/app-serve-apps/{appId}/latest-task [get] +// @Security JWT func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -366,16 +366,16 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * } // GetNumOfAppsOnStack godoc -// @Tags AppServeApps -// @Summary Get number of apps on given stack +// @Tags AppServeApps +// @Summary Get number of apps on given stack // @Description Get number of apps on given stack -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param stackId query string true "Stack ID" -// @Success 200 {object} int64 -// @Router /organizations/{organizationId}/app-serve-apps/count [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param stackId query string true "Stack ID" +// @Success 200 {object} int64 +// @Router /organizations/{organizationId}/app-serve-apps/count [get] +// @Security JWT func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -504,14 +504,14 @@ func makeStage(app *domain.AppServeApp, pl string) domain.StageResponse { } // IsAppServeAppExist godoc -// @Tags AppServeApps -// @Summary Get appServeApp +// @Tags AppServeApps +// @Summary Get appServeApp // @Description Get appServeApp by giving params -// @Accept json -// @Produce json -// @Success 200 {object} bool -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/exist [get] -// @Security JWT +// @Accept json +// @Produce json +// @Success 200 {object} bool +// @Router /organizations/{organizationId}/app-serve-apps/{appId}/exist [get] +// @Security JWT func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -543,16 +543,16 @@ func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.R } // IsAppServeAppNameExist godoc -// @Tags AppServeApps -// @Summary Check duplicate appServeAppName +// @Tags AppServeApps +// @Summary Check duplicate appServeAppName // @Description Check duplicate appServeAppName by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param name path string true "name" -// @Success 200 {object} bool -// @Router /organizations/{organizationId}/app-serve-apps/name/{name}/existence [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param name path string true "name" +// @Success 200 {object} bool +// @Router /organizations/{organizationId}/app-serve-apps/name/{name}/existence [get] +// @Security JWT func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -582,17 +582,17 @@ func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *ht } // UpdateAppServeApp godoc -// @Tags AppServeApps -// @Summary Update appServeApp +// @Tags AppServeApps +// @Summary Update appServeApp // @Description Update appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param appId path string true "App ID" -// @Param object body domain.UpdateAppServeAppRequest true "Request body to update app" -// @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId} [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param appId path string true "App ID" +// @Param object body domain.UpdateAppServeAppRequest true "Request body to update app" +// @Success 200 {object} string +// @Router /organizations/{organizationId}/app-serve-apps/{appId} [put] +// @Security JWT func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -691,17 +691,17 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re } // UpdateAppServeAppStatus godoc -// @Tags AppServeApps -// @Summary Update app status +// @Tags AppServeApps +// @Summary Update app status // @Description Update app status -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param appId path string true "App ID" -// @Param body body domain.UpdateAppServeAppStatusRequest true "Request body to update app status" -// @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/status [patch] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param appId path string true "App ID" +// @Param body body domain.UpdateAppServeAppStatusRequest true "Request body to update app status" +// @Success 200 {object} string +// @Router /organizations/{organizationId}/app-serve-apps/{appId}/status [patch] +// @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -734,17 +734,17 @@ func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *h } // UpdateAppServeAppEndpoint godoc -// @Tags AppServeApps -// @Summary Update app endpoint +// @Tags AppServeApps +// @Summary Update app endpoint // @Description Update app endpoint -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param appId path string true "appId" -// @Param body body domain.UpdateAppServeAppEndpointRequest true "Request body to update app endpoint" -// @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/endpoint [patch] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param appId path string true "appId" +// @Param body body domain.UpdateAppServeAppEndpointRequest true "Request body to update app endpoint" +// @Success 200 {object} string +// @Router /organizations/{organizationId}/app-serve-apps/{appId}/endpoint [patch] +// @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -782,16 +782,16 @@ func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r } // DeleteAppServeApp godoc -// @Tags AppServeApps -// @Summary Uninstall appServeApp +// @Tags AppServeApps +// @Summary Uninstall appServeApp // @Description Uninstall appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param appId path string true "App ID" -// @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId} [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param appId path string true "App ID" +// @Success 200 {object} string +// @Router /organizations/{organizationId}/app-serve-apps/{appId} [delete] +// @Security JWT func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -818,17 +818,17 @@ func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Re } // RollbackAppServeApp godoc -// @Tags AppServeApps -// @Summary Rollback appServeApp +// @Tags AppServeApps +// @Summary Rollback appServeApp // @Description Rollback appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param appId path string true "App ID" -// @Param object body domain.RollbackAppServeAppRequest true "Request body to rollback app" -// @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/rollback [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param appId path string true "App ID" +// @Param object body domain.RollbackAppServeAppRequest true "Request body to rollback app" +// @Success 200 {object} string +// @Router /organizations/{organizationId}/app-serve-apps/{appId}/rollback [post] +// @Security JWT func (h *AppServeAppHandler) RollbackAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 361d33e0..8c2c2391 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -37,14 +37,14 @@ func NewAuthHandler(h usecase.IAuthUsecase) IAuthHandler { } // Login godoc -// @Tags Auth -// @Summary login +// @Tags Auth +// @Summary login // @Description login -// @Accept json -// @Produce json -// @Param body body domain.LoginRequest true "account info" -// @Success 200 {object} domain.LoginResponse "user detail" -// @Router /auth/login [post] +// @Accept json +// @Produce json +// @Param body body domain.LoginRequest true "account info" +// @Success 200 {object} domain.LoginResponse "user detail" +// @Router /auth/login [post] func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { input := domain.LoginRequest{} err := UnmarshalRequestInput(r, &input) @@ -82,14 +82,14 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { } // Logout godoc -// @Tags Auth -// @Summary logout +// @Tags Auth +// @Summary logout // @Description logout -// @Accept json -// @Produce json -// @Success 200 {object} domain.LogoutResponse -// @Router /auth/logout [post] -// @Security JWT +// @Accept json +// @Produce json +// @Success 200 {object} domain.LogoutResponse +// @Router /auth/logout [post] +// @Security JWT func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -141,15 +141,15 @@ func (h *AuthHandler) RefreshToken(w http.ResponseWriter, r *http.Request) { } // FindId godoc -// @Tags Auth -// @Summary Request to find forgotten ID +// @Tags Auth +// @Summary Request to find forgotten ID // @Description This API allows users to find their account ID by submitting required information -// @Accept json -// @Produce json -// @Param body body domain.FindIdRequest true "Request body for finding the account ID including {organization ID, email, username, 6 digit code}" -// @Success 200 {object} domain.FindIdResponse -// @Failure 400 {object} httpErrors.RestError -// @Router /auth/find-id/verification [post] +// @Accept json +// @Produce json +// @Param body body domain.FindIdRequest true "Request body for finding the account ID including {organization ID, email, username, 6 digit code}" +// @Success 200 {object} domain.FindIdResponse +// @Failure 400 {object} httpErrors.RestError +// @Router /auth/find-id/verification [post] func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { input := domain.FindIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -172,15 +172,15 @@ func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { } // FindPassword godoc -// @Tags Auth -// @Summary Request to find forgotten password +// @Tags Auth +// @Summary Request to find forgotten password // @Description This API allows users to reset their forgotten password by submitting required information -// @Accept json -// @Produce json -// @Param body body domain.FindPasswordRequest true "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}" -// @Success 200 -// @Failure 400 {object} httpErrors.RestError -// @Router /auth/find-password/verification [post] +// @Accept json +// @Produce json +// @Param body body domain.FindPasswordRequest true "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}" +// @Success 200 +// @Failure 400 {object} httpErrors.RestError +// @Router /auth/find-password/verification [post] func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { input := domain.FindPasswordRequest{} err := UnmarshalRequestInput(r, &input) @@ -200,15 +200,15 @@ func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { } // VerifyIdentityForLostId godoc -// @Tags Auth -// @Summary Request to verify identity for lost id +// @Tags Auth +// @Summary Request to verify identity for lost id // @Description This API allows users to verify their identity for lost id by submitting required information -// @Accept json -// @Produce json -// @Param body body domain.VerifyIdentityForLostIdRequest true "Request body for verifying identity for lost id including {organization ID, email, username}" -// @Success 200 {object} domain.VerifyIdentityForLostIdResponse -// @Failure 400 {object} httpErrors.RestError -// @Router /auth/find-id/code [post] +// @Accept json +// @Produce json +// @Param body body domain.VerifyIdentityForLostIdRequest true "Request body for verifying identity for lost id including {organization ID, email, username}" +// @Success 200 {object} domain.VerifyIdentityForLostIdResponse +// @Failure 400 {object} httpErrors.RestError +// @Router /auth/find-id/code [post] func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Request) { input := domain.VerifyIdentityForLostIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -230,15 +230,15 @@ func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Req } // VerifyIdentityForLostPassword godoc -// @Tags Auth -// @Summary Request to verify identity for lost password +// @Tags Auth +// @Summary Request to verify identity for lost password // @Description This API allows users to verify their identity for lost password by submitting required information -// @Accept json -// @Produce json -// @Param body body domain.VerifyIdentityForLostPasswordRequest true "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}" -// @Success 200 {object} domain.VerifyIdentityForLostPasswordResponse -// @Failure 400 {object} httpErrors.RestError -// @Router /auth/find-password/code [post] +// @Accept json +// @Produce json +// @Param body body domain.VerifyIdentityForLostPasswordRequest true "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}" +// @Success 200 {object} domain.VerifyIdentityForLostPasswordResponse +// @Failure 400 {object} httpErrors.RestError +// @Router /auth/find-password/code [post] func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *http.Request) { input := domain.VerifyIdentityForLostPasswordRequest{} err := UnmarshalRequestInput(r, &input) @@ -260,14 +260,14 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht } // Login godoc -// @Tags Auth -// @Summary ping with token +// @Tags Auth +// @Summary ping with token // @Description ping with token -// @Accept json -// @Produce json -// @Param body body domain.PingTokenRequest true "token info" -// @Success 200 {object} nil -// @Router /auth/ping [post] +// @Accept json +// @Produce json +// @Param body body domain.PingTokenRequest true "token info" +// @Success 200 {object} nil +// @Router /auth/ping [post] func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { input := domain.PingTokenRequest{} err := UnmarshalRequestInput(r, &input) @@ -287,12 +287,12 @@ func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { } // VerifyToken godoc -// @Tags Auth -// @Summary verify token +// @Tags Auth +// @Summary verify token // @Description verify token -// @Success 200 {object} nil -// @Failure 401 {object} nil -// @Router /auth/verify-token [get] +// @Success 200 {object} nil +// @Failure 401 {object} nil +// @Router /auth/verify-token [get] func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { token, ok := request.TokenFrom(r.Context()) diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 02809f30..64b6edab 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -27,16 +27,16 @@ func NewCloudAccountHandler(h usecase.ICloudAccountUsecase) *CloudAccountHandler } // CreateCloudAccount godoc -// @Tags CloudAccounts -// @Summary Create CloudAccount +// @Tags CloudAccounts +// @Summary Create CloudAccount // @Description Create CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.CreateCloudAccountRequest true "create cloud setting request" -// @Success 200 {object} domain.CreateCloudAccountResponse -// @Router /organizations/{organizationId}/cloud-accounts [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.CreateCloudAccountRequest true "create cloud setting request" +// @Success 200 {object} domain.CreateCloudAccountResponse +// @Router /organizations/{organizationId}/cloud-accounts [post] +// @Security JWT func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -71,20 +71,20 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. } // GetCloudAccount godoc -// @Tags CloudAccounts -// @Summary Get CloudAccounts +// @Tags CloudAccounts +// @Summary Get CloudAccounts // @Description Get CloudAccounts -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetCloudAccountsResponse -// @Router /organizations/{organizationId}/cloud-accounts [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetCloudAccountsResponse +// @Router /organizations/{organizationId}/cloud-accounts [get] +// @Security JWT func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -122,16 +122,16 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re } // GetCloudAccount godoc -// @Tags CloudAccounts -// @Summary Get CloudAccount +// @Tags CloudAccounts +// @Summary Get CloudAccount // @Description Get CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param cloudAccountId path string true "cloudAccountId" -// @Success 200 {object} domain.GetCloudAccountResponse -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param cloudAccountId path string true "cloudAccountId" +// @Success 200 {object} domain.GetCloudAccountResponse +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [get] +// @Security JWT func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["cloudAccountId"] @@ -161,16 +161,16 @@ func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Req } // UpdateCloudAccount godoc -// @Tags CloudAccounts -// @Summary Update CloudAccount +// @Tags CloudAccounts +// @Summary Update CloudAccount // @Description Update CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateCloudAccountRequest true "Update cloud setting request" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateCloudAccountRequest true "Update cloud setting request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [put] +// @Security JWT func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["cloudAccountId"] @@ -215,17 +215,17 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. } // DeleteCloudAccount godoc -// @Tags CloudAccounts -// @Summary Delete CloudAccount +// @Tags CloudAccounts +// @Summary Delete CloudAccount // @Description Delete CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.DeleteCloudAccountRequest true "Delete cloud setting request" -// @Param cloudAccountId path string true "cloudAccountId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.DeleteCloudAccountRequest true "Delete cloud setting request" +// @Param cloudAccountId path string true "cloudAccountId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [delete] +// @Security JWT func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) cloudAccountId, ok := vars["cloudAccountId"] @@ -263,16 +263,16 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. } // DeleteForceCloudAccount godoc -// @Tags CloudAccounts -// @Summary Delete Force CloudAccount +// @Tags CloudAccounts +// @Summary Delete Force CloudAccount // @Description Delete Force CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param cloudAccountId path string true "cloudAccountId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param cloudAccountId path string true "cloudAccountId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error [delete] +// @Security JWT func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) cloudAccountId, ok := vars["cloudAccountId"] @@ -297,16 +297,16 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * } // CheckCloudAccountName godoc -// @Tags CloudAccounts -// @Summary Check name for cloudAccount +// @Tags CloudAccounts +// @Summary Check name for cloudAccount // @Description Check name for cloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param name path string true "name" -// @Success 200 {object} domain.CheckCloudAccountNameResponse -// @Router /organizations/{organizationId}/cloud-accounts/name/{name}/existence [GET] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param name path string true "name" +// @Success 200 {object} domain.CheckCloudAccountNameResponse +// @Router /organizations/{organizationId}/cloud-accounts/name/{name}/existence [GET] +// @Security JWT func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *http.Request) { user, ok := request.UserFrom(r.Context()) if !ok { @@ -339,16 +339,16 @@ func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *ht } // CheckAwsAccountId godoc -// @Tags CloudAccounts -// @Summary Check awsAccountId for cloudAccount +// @Tags CloudAccounts +// @Summary Check awsAccountId for cloudAccount // @Description Check awsAccountId for cloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param awsAccountId path string true "awsAccountId" -// @Success 200 {object} domain.CheckCloudAccountAwsAccountIdResponse -// @Router /organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence [GET] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param awsAccountId path string true "awsAccountId" +// @Success 200 {object} domain.CheckCloudAccountAwsAccountIdResponse +// @Router /organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence [GET] +// @Security JWT func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) awsAccountId, ok := vars["awsAccountId"] @@ -375,16 +375,16 @@ func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.R } // GetResourceQuota godoc -// @Tags CloudAccounts -// @Summary Get resource quota by cloudAccount +// @Tags CloudAccounts +// @Summary Get resource quota by cloudAccount // @Description Get resource quota by cloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param cloudAccountId path string true "cloudAccountId" -// @Success 200 {object} domain.GetCloudAccountResourceQuotaResponse -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota [GET] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param cloudAccountId path string true "cloudAccountId" +// @Success 200 {object} domain.GetCloudAccountResourceQuotaResponse +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota [GET] +// @Security JWT func (h *CloudAccountHandler) GetResourceQuota(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["cloudAccountId"] diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 7565403b..e2bba0f2 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -25,20 +25,20 @@ func NewClusterHandler(h usecase.IClusterUsecase) *ClusterHandler { } // GetClusters godoc -// @Tags Clusters -// @Summary Get clusters +// @Tags Clusters +// @Summary Get clusters // @Description Get cluster list -// @Accept json -// @Produce json -// @Param organizationId query string false "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetClustersResponse -// @Router /clusters [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId query string false "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetClustersResponse +// @Router /clusters [get] +// @Security JWT func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -71,15 +71,15 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { } // GetCluster godoc -// @Tags Clusters -// @Summary Get cluster +// @Tags Clusters +// @Summary Get cluster // @Description Get cluster detail -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.Cluster -// @Router /clusters/{clusterId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} domain.Cluster +// @Router /clusters/{clusterId} [get] +// @Security JWT func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -103,15 +103,15 @@ func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { } // GetClusterSiteValues godoc -// @Tags Clusters -// @Summary Get cluster site values for creating +// @Tags Clusters +// @Summary Get cluster site values for creating // @Description Get cluster site values for creating -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.ClusterSiteValuesResponse -// @Router /clusters/{clusterId}/site-values [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} domain.ClusterSiteValuesResponse +// @Router /clusters/{clusterId}/site-values [get] +// @Security JWT func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -133,15 +133,15 @@ func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Req } // CreateCluster godoc -// @Tags Clusters -// @Summary Create cluster +// @Tags Clusters +// @Summary Create cluster // @Description Create cluster -// @Accept json -// @Produce json -// @Param body body domain.CreateClusterRequest true "create cluster request" -// @Success 200 {object} domain.CreateClusterResponse -// @Router /clusters [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param body body domain.CreateClusterRequest true "create cluster request" +// @Success 200 {object} domain.CreateClusterResponse +// @Router /clusters [post] +// @Security JWT func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { input := domain.CreateClusterRequest{} err := UnmarshalRequestInput(r, &input) @@ -192,15 +192,15 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { } // ImportCluster godoc -// @Tags Clusters -// @Summary Import cluster +// @Tags Clusters +// @Summary Import cluster // @Description Import cluster -// @Accept json -// @Produce json -// @Param body body domain.ImportClusterRequest true "import cluster request" -// @Success 200 {object} domain.ImportClusterResponse -// @Router /clusters/import [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param body body domain.ImportClusterRequest true "import cluster request" +// @Success 200 {object} domain.ImportClusterResponse +// @Router /clusters/import [post] +// @Security JWT func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { input := domain.ImportClusterRequest{} err := UnmarshalRequestInput(r, &input) @@ -234,15 +234,15 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { } // InstallCluster godoc -// @Tags Clusters -// @Summary Install cluster on tks cluster +// @Tags Clusters +// @Summary Install cluster on tks cluster // @Description Install cluster on tks cluster -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} nil -// @Router /clusters/{clusterId}/install [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} nil +// @Router /clusters/{clusterId}/install [post] +// @Security JWT func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -261,15 +261,15 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) } // DeleteCluster godoc -// @Tags Clusters -// @Summary Delete cluster +// @Tags Clusters +// @Summary Delete cluster // @Description Delete cluster -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.Cluster -// @Router /clusters/{clusterId} [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} domain.Cluster +// @Router /clusters/{clusterId} [delete] +// @Security JWT func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -288,14 +288,14 @@ func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { } // CreateBootstrapKubeconfig godoc -// @Tags Clusters -// @Summary Create bootstrap kubeconfig for BYOH +// @Tags Clusters +// @Summary Create bootstrap kubeconfig for BYOH // @Description Create bootstrap kubeconfig for BYOH -// @Accept json -// @Produce json -// @Success 200 {object} domain.CreateBootstrapKubeconfigResponse -// @Router /clusters/{clusterId}/bootstrap-kubeconfig [post] -// @Security JWT +// @Accept json +// @Produce json +// @Success 200 {object} domain.CreateBootstrapKubeconfigResponse +// @Router /clusters/{clusterId}/bootstrap-kubeconfig [post] +// @Security JWT func (h *ClusterHandler) CreateBootstrapKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -316,14 +316,14 @@ func (h *ClusterHandler) CreateBootstrapKubeconfig(w http.ResponseWriter, r *htt } // GetBootstrapKubeconfig godoc -// @Tags Clusters -// @Summary Get bootstrap kubeconfig for BYOH +// @Tags Clusters +// @Summary Get bootstrap kubeconfig for BYOH // @Description Get bootstrap kubeconfig for BYOH -// @Accept json -// @Produce json -// @Success 200 {object} domain.GetBootstrapKubeconfigResponse -// @Router /clusters/{clusterId}/bootstrap-kubeconfig [get] -// @Security JWT +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetBootstrapKubeconfigResponse +// @Router /clusters/{clusterId}/bootstrap-kubeconfig [get] +// @Security JWT func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -345,15 +345,15 @@ func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.R } // GetNodes godoc -// @Tags Clusters -// @Summary Get nodes information for BYOH +// @Tags Clusters +// @Summary Get nodes information for BYOH // @Description Get nodes information for BYOH -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.GetClusterNodesResponse -// @Router /clusters/{clusterId}/nodes [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} domain.GetClusterNodesResponse +// @Router /clusters/{clusterId}/nodes [get] +// @Security JWT func (h *ClusterHandler) GetNodes(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["clusterId"] @@ -381,14 +381,14 @@ func (h *ClusterHandler) GetNodes(w http.ResponseWriter, r *http.Request) { func (h *ClusterHandler) GetKubernetesInfo(w http.ResponseWriter, r *http.Request) { // GetKubernetesInfo godoc - // @Tags Clusters - // @Summary Get kubernetes info + // @Tags Clusters + // @Summary Get kubernetes info // @Description Get kubernetes info for cluster - // @Accept json - // @Produce json - // @Param clusterId path string true "clusterId" - // @Success 200 {object} ClusterKubeInfo - // @Router /clusters/{clusterId}/kubeInfo [get] + // @Accept json + // @Produce json + // @Param clusterId path string true "clusterId" + // @Success 200 {object} ClusterKubeInfo + // @Router /clusters/{clusterId}/kubeInfo [get] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -451,14 +451,14 @@ func (h *ClusterHandler) GetKubernetesInfo(w http.ResponseWriter, r *http.Reques func (h *ClusterHandler) GetClusterApplications(w http.ResponseWriter, r *http.Request) { // GetClusterApplications godoc - // @Tags Clusters - // @Summary Get application list + // @Tags Clusters + // @Summary Get application list // @Description Get application list by clusterId - // @Accept json - // @Produce json - // @Param clusterId path string false "clusterId" - // @Success 200 {object} []ApplicationJson - // @Router /clusters/{clusterId}/applications [get] + // @Accept json + // @Produce json + // @Param clusterId path string false "clusterId" + // @Success 200 {object} []ApplicationJson + // @Router /clusters/{clusterId}/applications [get] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -600,14 +600,14 @@ func (h *ClusterHandler) GetClusterApplicationsKubeInfo(w http.ResponseWriter, r func (h *ClusterHandler) GetClusterKubeConfig(w http.ResponseWriter, r *http.Request) { // GetClusterKubeConfig godoc - // @Tags Clusters - // @Summary Get kubernetes kubeconfig + // @Tags Clusters + // @Summary Get kubernetes kubeconfig // @Description Get kubernetes kubeconfig for cluster - // @Accept json - // @Produce json - // @Param clusterId path string true "clusterId" - // @Success 200 {object} object - // @Router /clusters/{clusterId}/kubeconfig [get] + // @Accept json + // @Produce json + // @Param clusterId path string true "clusterId" + // @Success 200 {object} object + // @Router /clusters/{clusterId}/kubeconfig [get] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -639,14 +639,14 @@ func (h *ClusterHandler) GetClusterKubeConfig(w http.ResponseWriter, r *http.Req func (h *ClusterHandler) GetClusterKubeResources(w http.ResponseWriter, r *http.Request) { // GetClusterKubeResources godoc - // @Tags Clusters - // @Summary Get kubernetes resources + // @Tags Clusters + // @Summary Get kubernetes resources // @Description Get kubernetes resources - // @Accept json - // @Produce json - // @Param clusterId path string true "clusterId" - // @Success 200 {object} ClusterJson - // @Router /clusters/{clusterId}/kube-resources [get] + // @Accept json + // @Produce json + // @Param clusterId path string true "clusterId" + // @Success 200 {object} ClusterJson + // @Router /clusters/{clusterId}/kube-resources [get] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -832,14 +832,14 @@ func (h *ClusterHandler) GetClusterKubeResources(w http.ResponseWriter, r *http. func (h *ClusterHandler) SetIstioLabel(w http.ResponseWriter, r *http.Request) { // SetIstioLabel godoc - // @Tags Clusters - // @Summary Set Istio label to namespace + // @Tags Clusters + // @Summary Set Istio label to namespace // @Description Set istio label to namespace on kubernetes - // @Accept json - // @Produce json - // @Param clusterId path string true "clusterId" - // @Success 200 {object} object - // @Router /clusters/{clusterId}/kube-resources/{namespace}/istio-label [post] + // @Accept json + // @Produce json + // @Param clusterId path string true "clusterId" + // @Success 200 {object} object + // @Router /clusters/{clusterId}/kube-resources/{namespace}/istio-label [post] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 8a5ae87b..46ae2f07 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -24,18 +24,18 @@ func NewDashboardHandler(h usecase.IDashboardUsecase) *DashboardHandler { } // GetCharts godoc -// @Tags Dashboards -// @Summary Get charts data +// @Tags Dashboards +// @Summary Get charts data // @Description Get charts data -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param chartType query string false "chartType" -// @Param duration query string true "duration" -// @Param interval query string true "interval" -// @Success 200 {object} domain.GetDashboardChartsResponse -// @Router /organizations/{organizationId}/dashboard/charts [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param chartType query string false "chartType" +// @Param duration query string true "duration" +// @Param interval query string true "interval" +// @Success 200 {object} domain.GetDashboardChartsResponse +// @Router /organizations/{organizationId}/dashboard/charts [get] +// @Security JWT func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -83,18 +83,18 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { } // GetCharts godoc -// @Tags Dashboards -// @Summary Get chart data +// @Tags Dashboards +// @Summary Get chart data // @Description Get chart data -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param chartType path string true "chartType" -// @Param duration query string true "duration" -// @Param interval query string true "interval" -// @Success 200 {object} domain.GetDashboardChartResponse -// @Router /organizations/{organizationId}/dashboard/charts/{chartType} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param chartType path string true "chartType" +// @Param duration query string true "duration" +// @Param interval query string true "interval" +// @Success 200 {object} domain.GetDashboardChartResponse +// @Router /organizations/{organizationId}/dashboard/charts/{chartType} [get] +// @Security JWT func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -159,15 +159,15 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { } // GetStacks godoc -// @Tags Dashboards -// @Summary Get stacks +// @Tags Dashboards +// @Summary Get stacks // @Description Get stacks -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.GetDashboardStacksResponse -// @Router /organizations/{organizationId}/dashboard/stacks [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetDashboardStacksResponse +// @Router /organizations/{organizationId}/dashboard/stacks [get] +// @Security JWT func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -200,15 +200,15 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } // GetResources godoc -// @Tags Dashboards -// @Summary Get resources +// @Tags Dashboards +// @Summary Get resources // @Description Get resources -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.GetDashboardResourcesResponse -// @Router /organizations/{organizationId}/dashboard/resources [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetDashboardResourcesResponse +// @Router /organizations/{organizationId}/dashboard/resources [get] +// @Security JWT func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 4489fa9c..67c7e252 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -27,15 +27,15 @@ func NewOrganizationHandler(o usecase.IOrganizationUsecase, u usecase.IUserUseca } // CreateOrganization godoc -// @Tags Organizations -// @Summary Create organization +// @Tags Organizations +// @Summary Create organization // @Description Create organization -// @Accept json -// @Produce json -// @Param body body domain.CreateOrganizationRequest true "create organization request" -// @Success 200 {object} object -// @Router /organizations [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param body body domain.CreateOrganizationRequest true "create organization request" +// @Success 200 {object} object +// @Router /organizations [post] +// @Security JWT func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http.Request) { input := domain.CreateOrganizationRequest{} @@ -76,19 +76,19 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } // GetOrganizations godoc -// @Tags Organizations -// @Summary Get organization list +// @Tags Organizations +// @Summary Get organization list // @Description Get organization list -// @Accept json -// @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} []domain.ListOrganizationBody -// @Router /organizations [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} []domain.ListOrganizationBody +// @Router /organizations [get] +// @Security JWT func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() pg, err := pagination.NewPagination(&urlParams) @@ -124,15 +124,15 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re } // GetOrganization godoc -// @Tags Organizations -// @Summary Get organization detail +// @Tags Organizations +// @Summary Get organization detail // @Description Get organization detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.GetOrganizationResponse -// @Router /organizations/{organizationId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetOrganizationResponse +// @Router /organizations/{organizationId} [get] +// @Security JWT func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -161,15 +161,15 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req } // DeleteOrganization godoc -// @Tags Organizations -// @Summary Delete organization +// @Tags Organizations +// @Summary Delete organization // @Description Delete organization -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.Organization -// @Router /organizations/{organizationId} [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.Organization +// @Router /organizations/{organizationId} [delete] +// @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -208,16 +208,16 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. } // UpdateOrganization godoc -// @Tags Organizations -// @Summary Update organization detail +// @Tags Organizations +// @Summary Update organization detail // @Description Update organization detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateOrganizationRequest true "update organization request" -// @Success 200 {object} domain.UpdateOrganizationResponse -// @Router /organizations/{organizationId} [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateOrganizationRequest true "update organization request" +// @Success 200 {object} domain.UpdateOrganizationResponse +// @Router /organizations/{organizationId} [put] +// @Security JWT func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -253,16 +253,16 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. } // UpdatePrimaryCluster godoc -// @Tags Organizations -// @Summary Update primary cluster +// @Tags Organizations +// @Summary Update primary cluster // @Description Update primary cluster -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdatePrimaryClusterRequest true "update primary cluster request" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/primary-cluster [patch] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdatePrimaryClusterRequest true "update primary cluster request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/primary-cluster [patch] +// @Security JWT func (h *OrganizationHandler) UpdatePrimaryCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 550a6313..f3666027 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1,20 +1,32 @@ package http import ( - "github.com/openinfradev/tks-api/internal/usecase" + "fmt" "net/http" + "strings" + "time" + + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" ) type IProjectHandler interface { CreateProject(w http.ResponseWriter, r *http.Request) + GetProjectRole(w http.ResponseWriter, r *http.Request) + GetProjectRoles(w http.ResponseWriter, r *http.Request) UpdateProject(w http.ResponseWriter, r *http.Request) DeleteProject(w http.ResponseWriter, r *http.Request) GetProject(w http.ResponseWriter, r *http.Request) GetProjects(w http.ResponseWriter, r *http.Request) AddProjectMember(w http.ResponseWriter, r *http.Request) - RemoveProjectMember(w http.ResponseWriter, r *http.Request) + GetProjectMember(w http.ResponseWriter, r *http.Request) GetProjectMembers(w http.ResponseWriter, r *http.Request) + RemoveProjectMember(w http.ResponseWriter, r *http.Request) + RemoveProjectMembers(w http.ResponseWriter, r *http.Request) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) @@ -32,8 +44,176 @@ type ProjectHandler struct { usecase usecase.IProjectUsecase } +func NewProjectHandler(u usecase.IProjectUsecase) IProjectHandler { + return &ProjectHandler{ + usecase: u, + } +} + +// CreateProject godoc +// @Tags Projects +// @Summary Create new project +// @Description Create new project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param request body domain.CreateProjectRequest true "Request body to create project" +// @Success 200 {object} domain.CreateProjectResponse +// @Router /organizations/{organizationId}/projects [post] +// @Security JWT func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + var projectReq domain.CreateProjectRequest + if err := UnmarshalRequestInput(r, &projectReq); err != nil { + ErrorJSON(w, r, err) + return + } + + log.Infof("projectReq: name = %s, description = %s, projectLeaderId = %s", + projectReq.Name, projectReq.Description, projectReq.ProjectLeaderId) + + now := time.Now() + project := &domain.Project{ + OrganizationId: organizationId, + Name: projectReq.Name, + Description: projectReq.Description, + CreatedAt: now, + } + log.Infof("Processing CREATE request for project '%s'...", project.Name) + + projectId, err := p.usecase.CreateProject(project) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + log.Infof("Project Id: %s", projectId) + + project.ID = projectId + pm := &domain.ProjectMember{ + ProjectId: projectId, + UserId: projectReq.ProjectLeaderId, + ProjectRoleId: projectReq.ProjectRoleId, + CreatedAt: now, + } + + projectMemberId, err := p.usecase.AddProjectMember(pm) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + pr, err := p.usecase.GetProjectRoles(usecase.ProjectLeader) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + pms := make([]domain.ProjectMember, 0) + pm.ID = projectMemberId + pm.ProjectRole = pr[0] + pms = append(pms, *pm) + + project.ProjectMembers = pms + projectRes := domain.CreateProjectResponse{ + Project: *project, + } + + ResponseJSON(w, r, http.StatusOK, projectRes) + +} + +// GetProjectRole godoc +// @Tags Projects +// @Summary Get project role +// @Description Get project role by id +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} domain.GetProjectRoleResponse +// @Router /organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] +// @Security JWT +func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectRoleId, ok := vars["projectRoleId"] + log.Debugf("projectRoleId = [%v]\n", projectRoleId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectRoleId"), + "C_INVALID_PROJECT_ROLE_ID", "")) + return + } + + pr, err := p.usecase.GetProjectRole(projectRoleId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project roles ", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectRoleResponse + out.ProjectRole = *pr + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetProjectRoles godoc +// @Tags Projects +// @Summary Get project roles +// @Description Get project roles by giving params +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" +// @Success 200 {object} domain.GetProjectRolesResponse +// @Router /organizations/{organizationId}/projects/project-roles [get] +// @Security JWT +func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) { + urlParams := r.URL.Query() + + queryParam := urlParams.Get("query") + query := usecase.ProjectAll + if queryParam == "" || strings.EqualFold(queryParam, "all") { + query = usecase.ProjectAll + } else if strings.EqualFold(queryParam, "leader") { + query = usecase.ProjectLeader + } else if strings.EqualFold(queryParam, "member") { + query = usecase.ProjectMember + } else if strings.EqualFold(queryParam, "viewer") { + query = usecase.ProjectViewer + } else { + log.ErrorWithContext(r.Context(), "Invalid query params. Err: ") + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid query params"), + "C_INVALID_QUERY_PARAM", "")) + return + } + + prs, err := p.usecase.GetProjectRoles(query) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project roles ", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectRolesResponse + out.ProjectRoles = prs + + ResponseJSON(w, r, http.StatusOK, out) } func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { @@ -52,20 +232,306 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { //TODO implement me } +// AddProjectMember godoc +// @Tags Projects +// @Summary Add project member to project +// @Description Add project member to project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param request body domain.AddProjectMemberRequest true "Request body to add project member" +// @Success 200 {object} domain.AddProjectMemberResponse +// @Router /organizations/{organizationId}/projects/{projectId}/members [post] +// @Security JWT func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + var projectMemberReq domain.AddProjectMemberRequest + if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { + ErrorJSON(w, r, err) + return + } + + log.Infof("***************** project member request: %+v", projectMemberReq) + + projectMemberResponse := domain.AddProjectMemberResponse{ + ProjectMembers: make([]domain.ProjectMember, 0), + } + now := time.Now() + for _, pmr := range projectMemberReq.ProjectMemberRequests { + pm := &domain.ProjectMember{ + ProjectId: projectId, + UserId: pmr.UserId, + ProjectRoleId: pmr.ProjectRoleId, + CreatedAt: now, + } + pmId, err := p.usecase.AddProjectMember(pm) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + pr, err := p.usecase.GetProjectRole(pm.ProjectRoleId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + pm.ID = pmId + pm.ProjectRole = *pr + projectMemberResponse.ProjectMembers = append(projectMemberResponse.ProjectMembers, *pm) + } + + ResponseJSON(w, r, http.StatusOK, projectMemberResponse) } -func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { - //TODO implement me +// GetProjectMember godoc +// @Tags Projects +// @Summary Get project member +// @Description Get project member +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectMemberId path string true "Project Member ID" +// @Success 200 {object} domain.GetProjectMemberResponse +// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] +// @Security JWT +func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + projectMemberId, ok := vars["projectMemberId"] + log.Debugf("projectMemberId = [%v]\n", projectMemberId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectMemberId"), + "C_INVALID_PROJECT_MEMBER_ID", "")) + return + } + + pm, err := p.usecase.GetProjectMemberById(projectMemberId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project member ", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectMemberResponse + out.ProjectMember = pm + + ResponseJSON(w, r, http.StatusOK, out) } +// GetProjectMembers godoc +// @Tags Projects +// @Summary Get project members +// @Description Get project members +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} domain.GetProjectMembersResponse +// @Router /organizations/{organizationId}/projects/{projectId}/members [get] +// @Security JWT func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + pms, err := p.usecase.GetProjectMembersByProjectId(projectId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project roles ", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectMembersResponse + out.ProjectMembers = pms + + ResponseJSON(w, r, http.StatusOK, out) } +// RemoveProjectMember godoc +// @Tags Projects +// @Summary Remove project members to project +// @Description Remove project members to project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectMemberId path string true "Project Member ID" +// @Success 200 {object} domain.CommonProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] +// @Security JWT +func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + projectMemberId, ok := vars["projectMemberId"] + log.Debugf("projectMemberId = [%v]\n", projectMemberId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectMemberId"), + "C_INVALID_PROJECT_MEMBER_ID", "")) + return + } + if err := p.usecase.RemoveProjectMember(projectMemberId); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + + } + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "ok"}) +} + +// RemoveProjectMembers godoc +// @Tags Projects +// @Summary Remove project members to project +// @Description Remove project members to project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param request body domain.RemoveProjectMemberRequest true "Request body to remove project member" +// @Success 200 {object} domain.CommonProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId}/members [delete] +// @Security JWT +func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + var projectMemberReq domain.RemoveProjectMemberRequest + if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { + ErrorJSON(w, r, err) + return + } + + for _, pm := range projectMemberReq.ProjectMember { + if err := p.usecase.RemoveProjectMember(pm.ProjectMemberId); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) +} + +// UpdateProjectMemberRole godoc +// @Tags Projects +// @Summary Update project member Role +// @Description Update project member Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectMemberId path string true "Project Member ID" +// @Param request body domain.UpdateProjectMemberRoleRequest true "Request body to update project member role" +// @Success 200 {object} domain.CommonProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] +// @Security JWT func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + projectMemberId, ok := vars["projectMemberId"] + log.Debugf("projectMemberId = [%v]\n", projectMemberId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectMemberId"), + "C_INVALID_PROJECT_MEMBER_ID", "")) + return + } + + var pmrReq domain.UpdateProjectMemberRoleRequest + if err := UnmarshalRequestInput(r, &pmrReq); err != nil { + ErrorJSON(w, r, err) + return + } + + if err := p.usecase.UpdateProjectMemberRole(projectMemberId, pmrReq.ProjectRoleId); err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { @@ -99,9 +565,3 @@ func (p ProjectHandler) UnSetFavoriteProject(w http.ResponseWriter, r *http.Requ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) { //TODO implement me } - -func NewProjectHandler(u usecase.IProjectUsecase) IProjectHandler { - return &ProjectHandler{ - usecase: u, - } -} diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 92c0237f..c2ad628c 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -27,33 +27,33 @@ func NewStackTemplateHandler(h usecase.IStackTemplateUsecase) *StackTemplateHand } // CreateStackTemplate godoc -// @Tags StackTemplates -// @Summary Create StackTemplate 'NOT IMPLEMENTED' +// @Tags StackTemplates +// @Summary Create StackTemplate 'NOT IMPLEMENTED' // @Description Create StackTemplate -// @Accept json -// @Produce json -// @Param body body domain.CreateStackTemplateRequest true "create stack template request" -// @Success 200 {object} domain.CreateStackTemplateResponse -// @Router /stack-templates [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param body body domain.CreateStackTemplateRequest true "create stack template request" +// @Success 200 {object} domain.CreateStackTemplateResponse +// @Router /stack-templates [post] +// @Security JWT func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) } // GetStackTemplate godoc -// @Tags StackTemplates -// @Summary Get StackTemplates +// @Tags StackTemplates +// @Summary Get StackTemplates // @Description Get StackTemplates -// @Accept json -// @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetStackTemplatesResponse -// @Router /stack-templates [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetStackTemplatesResponse +// @Router /stack-templates [get] +// @Security JWT func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() pg, err := pagination.NewPagination(&urlParams) @@ -89,15 +89,15 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. } // GetStackTemplate godoc -// @Tags StackTemplates -// @Summary Get StackTemplate +// @Tags StackTemplates +// @Summary Get StackTemplate // @Description Get StackTemplate -// @Accept json -// @Produce json -// @Param stackTemplateId path string true "stackTemplateId" -// @Success 200 {object} domain.GetStackTemplateResponse -// @Router /stack-templates/{stackTemplateId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param stackTemplateId path string true "stackTemplateId" +// @Success 200 {object} domain.GetStackTemplateResponse +// @Router /stack-templates/{stackTemplateId} [get] +// @Security JWT func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackTemplateId"] @@ -132,15 +132,15 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R } // UpdateStackTemplate godoc -// @Tags StackTemplates -// @Summary Update StackTemplate 'NOT IMPLEMENTED' +// @Tags StackTemplates +// @Summary Update StackTemplate 'NOT IMPLEMENTED' // @Description Update StackTemplate -// @Accept json -// @Produce json -// @Param body body domain.UpdateStackTemplateRequest true "Update stack template request" -// @Success 200 {object} nil -// @Router /stack-templates/{stackTemplateId} [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param body body domain.UpdateStackTemplateRequest true "Update stack template request" +// @Success 200 {object} nil +// @Router /stack-templates/{stackTemplateId} [put] +// @Security JWT func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *http.Request) { /* vars := mux.Vars(r) @@ -173,15 +173,15 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt } // DeleteStackTemplate godoc -// @Tags StackTemplates -// @Summary Delete StackTemplate 'NOT IMPLEMENTED' +// @Tags StackTemplates +// @Summary Delete StackTemplate 'NOT IMPLEMENTED' // @Description Delete StackTemplate -// @Accept json -// @Produce json -// @Param stackTemplateId path string true "stackTemplateId" -// @Success 200 {object} nil -// @Router /stack-templates/{stackTemplateId} [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param stackTemplateId path string true "stackTemplateId" +// @Success 200 {object} nil +// @Router /stack-templates/{stackTemplateId} [delete] +// @Security JWT func (h *StackTemplateHandler) DeleteStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) _, ok := vars["stackTemplateId"] diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 661e38d5..d92f6d1e 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -25,16 +25,16 @@ func NewStackHandler(h usecase.IStackUsecase) *StackHandler { } // CreateStack godoc -// @Tags Stacks -// @Summary Create Stack +// @Tags Stacks +// @Summary Create Stack // @Description Create Stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.CreateStackRequest true "create cloud setting request" -// @Success 200 {object} domain.CreateStackResponse -// @Router /organizations/{organizationId}/stacks [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.CreateStackRequest true "create cloud setting request" +// @Success 200 {object} domain.CreateStackResponse +// @Router /organizations/{organizationId}/stacks [post] +// @Security JWT func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -89,20 +89,20 @@ func (h *StackHandler) InstallStack(w http.ResponseWriter, r *http.Request) { } // GetStack godoc -// @Tags Stacks -// @Summary Get Stacks +// @Tags Stacks +// @Summary Get Stacks // @Description Get Stacks -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param combinedFilter query string false "combinedFilter" -// @Success 200 {object} domain.GetStacksResponse -// @Router /organizations/{organizationId}/stacks [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param combinedFilter query string false "combinedFilter" +// @Success 200 {object} domain.GetStacksResponse +// @Router /organizations/{organizationId}/stacks [get] +// @Security JWT func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -145,16 +145,16 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } // GetStack godoc -// @Tags Stacks -// @Summary Get Stack +// @Tags Stacks +// @Summary Get Stack // @Description Get Stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} domain.GetStackResponse -// @Router /organizations/{organizationId}/stacks/{stackId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} domain.GetStackResponse +// @Router /organizations/{organizationId}/stacks/{stackId} [get] +// @Security JWT func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackId"] @@ -183,16 +183,16 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { } // GetStackStatus godoc -// @Tags Stacks -// @Summary Get Stack Status +// @Tags Stacks +// @Summary Get Stack Status // @Description Get Stack Status -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} domain.GetStackStatusResponse -// @Router /organizations/{organizationId}/stacks/{stackId}/status [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} domain.GetStackStatusResponse +// @Router /organizations/{organizationId}/stacks/{stackId}/status [get] +// @Security JWT func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -221,17 +221,17 @@ func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { } // UpdateStack godoc -// @Tags Stacks -// @Summary Update Stack +// @Tags Stacks +// @Summary Update Stack // @Description Update Stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Param body body domain.UpdateStackRequest true "Update cloud setting request" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/{stackId} [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Param body body domain.UpdateStackRequest true "Update cloud setting request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stacks/{stackId} [put] +// @Security JWT func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackId"] @@ -276,16 +276,16 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { } // DeleteStack godoc -// @Tags Stacks -// @Summary Delete Stack +// @Tags Stacks +// @Summary Delete Stack // @Description Delete Stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/{stackId} [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stacks/{stackId} [delete] +// @Security JWT func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -314,17 +314,17 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { } // CheckStackName godoc -// @Tags Stacks -// @Summary Check name for stack +// @Tags Stacks +// @Summary Check name for stack // @Description Check name for stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Param name path string true "name" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/name/{name}/existence [GET] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Param name path string true "name" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stacks/name/{name}/existence [GET] +// @Security JWT func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -357,16 +357,16 @@ func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { } // GetStackKubeConfig godoc -// @Tags Stacks -// @Summary Get KubeConfig by stack +// @Tags Stacks +// @Summary Get KubeConfig by stack // @Description Get KubeConfig by stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "organizationId" -// @Success 200 {object} domain.GetStackKubeConfigResponse -// @Router /organizations/{organizationId}/stacks/{stackId}/kube-config [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "organizationId" +// @Success 200 {object} domain.GetStackKubeConfigResponse +// @Router /organizations/{organizationId}/stacks/{stackId}/kube-config [get] +// @Security JWT func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) _, ok := vars["organizationId"] @@ -400,16 +400,16 @@ func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request } // SetFavorite godoc -// @Tags Stacks -// @Summary Set favorite stack +// @Tags Stacks +// @Summary Set favorite stack // @Description Set favorite stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/{stackId}/favorite [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stacks/{stackId}/favorite [post] +// @Security JWT func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackId"] @@ -427,16 +427,16 @@ func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { } // DeleteFavorite godoc -// @Tags Stacks -// @Summary Delete favorite stack +// @Tags Stacks +// @Summary Delete favorite stack // @Description Delete favorite stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/{stackId}/favorite [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stacks/{stackId}/favorite [delete] +// @Security JWT func (h *StackHandler) DeleteFavorite(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackId"] diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 50a7ea11..2144ec0a 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -44,16 +44,16 @@ func NewUserHandler(h usecase.IUserUsecase) IUserHandler { } // Create godoc -// @Tags Users -// @Summary Create user +// @Tags Users +// @Summary Create user // @Description Create user -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.CreateUserRequest true "create user request" -// @Success 200 {object} domain.CreateUserResponse "create user response" -// @Router /organizations/{organizationId}/users [post] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.CreateUserRequest true "create user request" +// @Success 200 {object} domain.CreateUserResponse "create user response" +// @Router /organizations/{organizationId}/users [post] +// @Security JWT func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -108,16 +108,16 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { } // Get godoc -// @Tags Users -// @Summary Get user detail +// @Tags Users +// @Summary Get user detail // @Description Get user detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} domain.GetUserResponse -// @Router /organizations/{organizationId}/users/{accountId} [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} domain.GetUserResponse +// @Router /organizations/{organizationId}/users/{accountId} [get] +// @Security JWT func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) userId, ok := vars["accountId"] @@ -153,20 +153,20 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { } // List godoc -// @Tags Users -// @Summary Get user list +// @Tags Users +// @Summary Get user list // @Description Get user list -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} []domain.ListUserBody -// @Router /organizations/{organizationId}/users [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} []domain.ListUserBody +// @Router /organizations/{organizationId}/users [get] +// @Security JWT func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -204,16 +204,16 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { } // Delete godoc -// @Tags Users -// @Summary Delete user +// @Tags Users +// @Summary Delete user // @Description Delete user -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} domain.User -// @Router /organizations/{organizationId}/users/{accountId} [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} domain.User +// @Router /organizations/{organizationId}/users/{accountId} [delete] +// @Security JWT func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) userId, ok := vars["accountId"] @@ -243,17 +243,17 @@ func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { } // Update godoc -// @Tags Users -// @Summary Update user +// @Tags Users +// @Summary Update user // @Description Update user -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Param body body domain.UpdateUserRequest true "input" -// @Success 200 {object} domain.UpdateUserResponse -// @Router /organizations/{organizationId}/users/{accountId} [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Param body body domain.UpdateUserRequest true "input" +// @Success 200 {object} domain.UpdateUserResponse +// @Router /organizations/{organizationId}/users/{accountId} [put] +// @Security JWT func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) accountId, ok := vars["accountId"] @@ -310,16 +310,16 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } // ResetPassword godoc -// @Tags Users -// @Summary Reset user's password as temporary password by admin +// @Tags Users +// @Summary Reset user's password as temporary password by admin // @Description Reset user's password as temporary password by admin and send email to user -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 -// @Router /organizations/{organizationId}/users/{accountId}/reset-password [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 +// @Router /organizations/{organizationId}/users/{accountId}/reset-password [put] +// @Security JWT func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) accountId, ok := vars["accountId"] @@ -343,15 +343,15 @@ func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { } // GetMyProfile godoc -// @Tags My-profile -// @Summary Get my profile detail +// @Tags My-profile +// @Summary Get my profile detail // @Description Get my profile detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.GetMyProfileResponse -// @Router /organizations/{organizationId}/my-profile [get] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetMyProfileResponse +// @Router /organizations/{organizationId}/my-profile [get] +// @Security JWT func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -375,16 +375,16 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { } // UpdateMyProfile godoc -// @Tags My-profile -// @Summary Update my profile detail +// @Tags My-profile +// @Summary Update my profile detail // @Description Update my profile detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateMyProfileRequest true "Required fields: password due to double-check" -// @Success 200 {object} domain.UpdateMyProfileResponse -// @Router /organizations/{organizationId}/my-profile [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateMyProfileRequest true "Required fields: password due to double-check" +// @Success 200 {object} domain.UpdateMyProfileResponse +// @Router /organizations/{organizationId}/my-profile [put] +// @Security JWT func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -440,16 +440,16 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { } // UpdateMyPassword godoc -// @Tags My-profile -// @Summary Update user password detail +// @Tags My-profile +// @Summary Update user password detail // @Description Update user password detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdatePasswordRequest true "update user password request" -// @Success 200 -// @Router /organizations/{organizationId}/my-profile/password [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdatePasswordRequest true "update user password request" +// @Success 200 +// @Router /organizations/{organizationId}/my-profile/password [put] +// @Security JWT func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -490,16 +490,16 @@ func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { } // RenewPasswordExpiredDate godoc -// @Tags My-profile -// @Summary Update user's password expired date to current date +// @Tags My-profile +// @Summary Update user's password expired date to current date // @Description Update user's password expired date to current date -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 -// @Failure 400 {object} httpErrors.RestError -// @Router /organizations/{organizationId}/my-profile/next-password-change [put] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 +// @Failure 400 {object} httpErrors.RestError +// @Router /organizations/{organizationId}/my-profile/next-password-change [put] +// @Security JWT func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -517,16 +517,16 @@ func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Req } // DeleteMyProfile godoc -// @Tags My-profile -// @Summary Delete myProfile +// @Tags My-profile +// @Summary Delete myProfile // @Description Delete myProfile -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 -// @Failure 400 -// @Router /organizations/{organizationId}/my-profile [delete] -// @Security JWT +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 +// @Failure 400 +// @Router /organizations/{organizationId}/my-profile [delete] +// @Security JWT func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -542,15 +542,15 @@ func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { } // CheckId godoc -// @Tags Users -// @Summary Get user id existence +// @Tags Users +// @Summary Get user id existence // @Description return true when accountId exists -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} domain.CheckExistedResponse -// @Router /organizations/{organizationId}/users/account-id/{accountId}/existence [get] -// @Security JWT +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} domain.CheckExistedResponse +// @Router /organizations/{organizationId}/users/account-id/{accountId}/existence [get] +// @Security JWT func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) accountId, ok := vars["accountId"] @@ -582,15 +582,15 @@ func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { } // CheckEmail godoc -// @Tags Users -// @Summary Get user email existence +// @Tags Users +// @Summary Get user email existence // @Description return true when email exists -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "email" -// @Success 200 {object} domain.CheckExistedResponse -// @Router /organizations/{organizationId}/users/email/{email}/existence [get] -// @Security JWT +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "email" +// @Success 200 {object} domain.CheckExistedResponse +// @Router /organizations/{organizationId}/users/email/{email}/existence [get] +// @Security JWT func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) email, ok := vars["email"] diff --git a/internal/middleware/auth/authorizer/rbac.go b/internal/middleware/auth/authorizer/rbac.go index 01764465..45903fcc 100644 --- a/internal/middleware/auth/authorizer/rbac.go +++ b/internal/middleware/auth/authorizer/rbac.go @@ -7,10 +7,8 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" - internalApi "github.com/openinfradev/tks-api/internal/delivery/api" internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - internalRole "github.com/openinfradev/tks-api/internal/middleware/auth/role" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" @@ -61,34 +59,34 @@ func RBACFilter(handler http.Handler, repo repository.Repository) http.Handler { func RBACFilterWithEndpoint(handler http.Handler, repo repository.Repository) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - requestEndpointInfo, ok := request.EndpointFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) - return - } - - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) - return - } - - // if requestEndpointInfo.String() is one of ProjectEndpoints, print true - if internalApi.ApiMap[requestEndpointInfo].Group == "Project" && requestEndpointInfo != internalApi.CreateProject { - log.Infof("RBACFilterWithEndpoint: %s is ProjectEndpoint", requestEndpointInfo.String()) - vars := mux.Vars(r) - var projectRole string - if projectId, ok := vars["projectId"]; ok { - projectRole = requestUserInfo.GetRoleProjectMapping()[projectId] - } else { - log.Warn("RBACFilterWithEndpoint: projectId not found. Passing through unsafely.") - } - if !internalRole.IsRoleAllowed(requestEndpointInfo, internalRole.StrToRole(projectRole)) { - internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) - return - - } - } + //requestEndpointInfo, ok := request.EndpointFrom(r.Context()) + //if !ok { + // internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) + // return + //} + // + //requestUserInfo, ok := request.UserFrom(r.Context()) + //if !ok { + // internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + // return + //} + // + //// if requestEndpointInfo.String() is one of ProjectEndpoints, print true + //if internalApi.ApiMap[requestEndpointInfo].Group == "Project" && requestEndpointInfo != internalApi.CreateProject { + // log.Infof("RBACFilterWithEndpoint: %s is ProjectEndpoint", requestEndpointInfo.String()) + // vars := mux.Vars(r) + // var projectRole string + // if projectId, ok := vars["projectId"]; ok { + // projectRole = requestUserInfo.GetRoleProjectMapping()[projectId] + // } else { + // log.Warn("RBACFilterWithEndpoint: projectId not found. Passing through unsafely.") + // } + // if !internalRole.IsRoleAllowed(requestEndpointInfo, internalRole.StrToRole(projectRole)) { + // internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + // return + // + // } + //} handler.ServeHTTP(w, r) }) diff --git a/internal/repository/project.go b/internal/repository/project.go new file mode 100644 index 00000000..d256cf6f --- /dev/null +++ b/internal/repository/project.go @@ -0,0 +1,137 @@ +package repository + +import ( + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" + "gorm.io/gorm" +) + +type IProjectRepository interface { + CreateProject(p *domain.Project) (string, error) + GetAllProjectRoles() ([]domain.ProjectRole, error) + GetProjectRoleByName(name string) (*domain.ProjectRole, error) + GetProjectRoleById(id string) (*domain.ProjectRole, error) + AddProjectMember(pm *domain.ProjectMember) (string, error) + GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) + GetProjectMemberById(projectMemberId string) (pm domain.ProjectMember, err error) + RemoveProjectMember(projectMemberId string) error + UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error +} + +type ProjectRepository struct { + db *gorm.DB +} + +func NewProjectRepository(db *gorm.DB) IProjectRepository { + return &ProjectRepository{ + db: db, + } +} + +func (r *ProjectRepository) CreateProject(p *domain.Project) (string, error) { + res := r.db.Create(&p) + if res.Error != nil { + return "", res.Error + } + + return p.ID, nil +} + +func (r *ProjectRepository) GetProjectRoleById(id string) (*domain.ProjectRole, error) { + var pr = &domain.ProjectRole{ID: id} + result := r.db.First(pr) + if result.Error != nil { + log.Error(result.Error) + return pr, result.Error + } + if result.RowsAffected == 0 { + log.Info("There is no project_roles table data") + return pr, nil + } + + return pr, nil +} + +func (r *ProjectRepository) GetAllProjectRoles() (prs []domain.ProjectRole, err error) { + result := r.db.Find(&prs) + if result.Error != nil { + log.Error(result.Error) + return nil, result.Error + } + if result.RowsAffected == 0 { + log.Info("There is no project_roles table data") + return prs, nil + } + + return prs, nil +} + +func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *domain.ProjectRole, err error) { + log.Infof("project role name: %s", name) + result := r.db.Where("name = ?", name).First(&pr) + if result.Error != nil { + log.Error(result.Error) + return nil, result.Error + } + if result.RowsAffected == 0 { + log.Info("There is no project_roles table data") + return pr, nil + } + + return pr, nil +} + +func (r *ProjectRepository) AddProjectMember(pm *domain.ProjectMember) (string, error) { + res := r.db.Create(&pm) + if res.Error != nil { + return "", res.Error + } + + return pm.ID, nil +} + +func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string) (pms []domain.ProjectMember, err error) { + result := r.db.Joins("ProjectRole").Where("project_id = ?", projectId).Find(&pms) + if result.Error != nil { + log.Error(result.Error) + return nil, result.Error + } + if result.RowsAffected == 0 { + log.Info("Cannot find project member") + return pms, nil + } + + return pms, nil +} + +func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm domain.ProjectMember, err error) { + result := r.db.Joins("ProjectRole").Where("project_members.id = ?", projectMemberId).First(&pm) + if result.Error != nil { + log.Error(result.Error) + return pm, result.Error + } + if result.RowsAffected == 0 { + log.Info("Cannot find project member") + return pm, nil + } + + return pm, nil +} + +func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { + res := r.db.Delete(&domain.ProjectMember{ID: projectMemberId}) + if res.Error != nil { + return res.Error + } + + return nil +} + +func (r *ProjectRepository) UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error { + res := r.db.Model(&domain.ProjectMember{ID: projectMemberId}).Update("project_role_id", projectRoleId) + if res.Error != nil { + return res.Error + } + + return nil +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 0503a53d..46c56cef 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -21,6 +21,7 @@ type Repository struct { CloudAccount ICloudAccountRepository StackTemplate IStackTemplateRepository Alert IAlertRepository + Project IProjectRepository } func CombinedGormFilter(table string, filters []pagination.Filter, combinedFilter pagination.CombinedFilter) FilterFunc { diff --git a/internal/route/route.go b/internal/route/route.go index 9f5ef5e4..f69c3a10 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -62,6 +62,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa CloudAccount: repository.NewCloudAccountRepository(db), StackTemplate: repository.NewStackTemplateRepository(db), Alert: repository.NewAlertRepository(db), + Project: repository.NewProjectRepository(db), } customMiddleware := internalMiddleware.NewMiddleware( authenticator.NewAuthenticator(authKeycloak.NewKeycloakAuthenticator(kc)), @@ -195,20 +196,24 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", customMiddleware.Handle(internalApi.DeleteFavoriteStack, http.HandlerFunc(stackHandler.DeleteFavorite))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/install", customMiddleware.Handle(internalApi.InstallStack, http.HandlerFunc(stackHandler.InstallStack))).Methods(http.MethodPost) - projectHandler := delivery.NewProjectHandler(usecase.NewProjectUsecase(repoFactory)) + projectHandler := delivery.NewProjectHandler(usecase.NewProjectUsecase(repoFactory, argoClient)) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.CreateProject, http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.DeleteProject, http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles/{projectRoleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(projectHandler.GetProjectRole))).Methods(http.MethodGet) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.DeleteProject, http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.AddProjectMember, http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.GetProjectMember, http.HandlerFunc(projectHandler.GetProjectMember))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMembers))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{accountId}", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{accountId}/role", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMemberRole))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMembers))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMemberRole))).Methods(http.MethodPut) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets diff --git a/internal/usecase/project.go b/internal/usecase/project.go index d8fa9a9b..404b2ace 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -1,26 +1,177 @@ package usecase import ( + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/internal/serializer" + argowf "github.com/openinfradev/tks-api/pkg/argo-client" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" +) + +const ( + ProjectAll int = iota + ProjectLeader + ProjectMember + ProjectViewer ) type IProjectUsecase interface { + CreateProject(*domain.Project) (string, error) + GetProjectRole(id string) (*domain.ProjectRole, error) + GetProjectRoles(int) ([]domain.ProjectRole, error) + AddProjectMember(pm *domain.ProjectMember) (string, error) + GetProjectMemberById(projectMemberId string) (domain.ProjectMember, error) + GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) + RemoveProjectMember(projectMemberId string) error + UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error } type ProjectUsecase struct { + projectRepo repository.IProjectRepository userRepository repository.IUserRepository authRepository repository.IAuthRepository clusterRepository repository.IClusterRepository appgroupRepository repository.IAppGroupRepository organizationRepository repository.IOrganizationRepository + argo argowf.ArgoClient } -func NewProjectUsecase(r repository.Repository) IProjectUsecase { +func NewProjectUsecase(r repository.Repository, argoClient argowf.ArgoClient) IProjectUsecase { return &ProjectUsecase{ + projectRepo: r.Project, userRepository: r.User, authRepository: r.Auth, clusterRepository: r.Cluster, appgroupRepository: r.AppGroup, organizationRepository: r.Organization, + argo: argoClient, + } +} + +func (u *ProjectUsecase) CreateProject(p *domain.Project) (string, error) { + projectId, err := u.projectRepo.CreateProject(p) + if err != nil { + log.Error(err) + return "", errors.Wrap(err, "Failed to create project.") + } + return projectId, nil +} + +func (u *ProjectUsecase) GetProjectRole(id string) (*domain.ProjectRole, error) { + pr, err := u.projectRepo.GetProjectRoleById(id) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to get project roles.") + } + + return pr, nil +} + +func (u *ProjectUsecase) GetProjectRoles(query int) (prs []domain.ProjectRole, err error) { + var pr *domain.ProjectRole + + if query == ProjectLeader { + pr, err = u.projectRepo.GetProjectRoleByName("project-leader") + } else if query == ProjectMember { + pr, err = u.projectRepo.GetProjectRoleByName("project-member") + } else if query == ProjectViewer { + pr, err = u.projectRepo.GetProjectRoleByName("project-viewer") + } else { + prs, err = u.projectRepo.GetAllProjectRoles() + } + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to get project roles.") + } + + if pr != nil { + prs = append(prs, *pr) + } + + return prs, nil +} + +func (u *ProjectUsecase) AddProjectMember(pm *domain.ProjectMember) (string, error) { + projectMemberId, err := u.projectRepo.AddProjectMember(pm) + if err != nil { + log.Error(err) + return "", errors.Wrap(err, "Failed to add project member to project.") + } + return projectMemberId, nil +} + +func (u *ProjectUsecase) GetProjectMemberById(projectMemberId string) (pm domain.ProjectMember, err error) { + pm, err = u.projectRepo.GetProjectMemberById(projectMemberId) + if err != nil { + log.Error(err) + return pm, errors.Wrap(err, "Failed to get project member.") + } + + var uid uuid.UUID + uid, err = uuid.Parse(pm.UserId) + if err != nil { + log.Error(err) + return pm, errors.Wrap(err, "Failed to parse uuid to string") + } + user, err := u.userRepository.GetByUuid(uid) + if err != nil { + log.Error(err) + return pm, errors.Wrap(err, "Failed to retrieve user by id") + } + var pu domain.ProjectUser + if err = serializer.Map(user, &pu); err != nil { + log.Error(err) + return pm, err + } + + pm.User = pu + return pm, nil +} + +func (u *ProjectUsecase) GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) { + pms, err := u.projectRepo.GetProjectMembersByProjectId(projectId) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to get project members.") + } + + var uid uuid.UUID + for idx, pm := range pms { + uid, err = uuid.Parse(pm.UserId) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to parse uuid to string") + } + user, err := u.userRepository.GetByUuid(uid) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to retrieve user by id") + } + var pu domain.ProjectUser + if err = serializer.Map(user, &pu); err != nil { + log.Error(err) + return nil, err + } + pms[idx].User = pu + } + + return pms, nil +} + +func (u *ProjectUsecase) RemoveProjectMember(projectMemberId string) error { + if err := u.projectRepo.RemoveProjectMember(projectMemberId); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to remove project member to project.") + } + return nil +} + +func (u *ProjectUsecase) UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error { + if err := u.projectRepo.UpdateProjectMemberRole(projectMemberId, projectRoleId); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to remove project member to project.") } + return nil } diff --git a/pkg/domain/project.go b/pkg/domain/project.go new file mode 100644 index 00000000..88743906 --- /dev/null +++ b/pkg/domain/project.go @@ -0,0 +1,137 @@ +package domain + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +func (a *Project) BeforeCreate(*gorm.DB) (err error) { + a.ID = uuid.New().String() + return nil +} + +func (t *ProjectRole) BeforeCreate(*gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} + +func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} + +func (t *ProjectNamesapce) BeforeCreate(*gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} + +type Project struct { + ID string `gorm:"primarykey" json:"id"` + OrganizationId string `json:"organizationId"` + Name string `gorm:"index" json:"name"` + Description string `json:"description,omitempty"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` + ProjectMembers []ProjectMember `gorm:"foreignKey:ProjectId" json:"projectMembers,omitempty"` + ProjectNamesapces []ProjectNamesapce `gorm:"foreignKey:ProjectId" json:"projectNamesapces,omitempty"` +} + +type ProjectRole struct { + ID string `gorm:"primarykey" json:"id"` + Name string `json:"name"` // project-leader, project-member, project-viewer + Description string `json:"description,omitempty"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +type ProjectUser struct { + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} +type ProjectMember struct { + ID string `gorm:"primarykey" json:"id"` + ProjectId string `gorm:"not null" json:"projectId"` + UserId string `json:"userId"` + User ProjectUser `gorm:"-:all" json:"user"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRole ProjectRole `gorm:"foreignKey:ProjectRoleId" json:"projectRole"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +type ProjectNamesapce struct { + ID string `gorm:"primarykey" json:"id"` + ProjectId string `gorm:"not null" json:"projectId"` + StackID string `gorm:"uniqueIndex:idx_stackid_namespace" json:"stackId"` + Namespace string `gorm:"uniqueIndex:idx_stackid_namespace" json:"namespace"` + StackName string `gorm:"-:all" json:"stackName,omitempty"` + Description string `json:"description,omitempty"` + Status string `json:"status,omitempty"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +type CreateProjectRequest struct { + Name string `json:"name" validate:"required"` + Description string `json:"description"` + ProjectLeaderId string `json:"projectLeaderId"` + ProjectRoleId string `json:"projectRoleId"` +} + +type CreateProjectResponse struct { + Project Project `json:"project"` +} + +type GetProjectRoleResponse struct { + ProjectRole ProjectRole `json:"projectRole"` +} + +type GetProjectRolesResponse struct { + ProjectRoles []ProjectRole `json:"projectRoles"` +} + +type ProjectMemberRequest struct { + UserId string `json:"userId" validate:"required"` + ProjectRoleId string `json:"projectRoleId" validate:"required"` +} +type AddProjectMemberRequest struct { + ProjectMemberRequests []ProjectMemberRequest `json:"projectMembers"` +} + +type AddProjectMemberResponse struct { + ProjectMembers []ProjectMember `json:"projectMembers"` +} + +type GetProjectMemberResponse struct { + ProjectMember ProjectMember `json:"projectMember"` +} + +type GetProjectMembersResponse struct { + ProjectMembers []ProjectMember `json:"projectMembers"` +} + +type RemoveProjectMemberRequest struct { + ProjectMember []struct { + ProjectMemberId string `json:"projectMemberId"` + } `json:"projectMembers"` +} + +type CommonProjectResponse struct { + Result string `json:"result"` +} + +type UpdateProjectMemberRoleRequest struct { + ProjectRoleId string `json:"projectRoleId"` +} diff --git a/scripts/erd_postgres.sql b/scripts/erd_postgres.sql index da611fb8..acc7b24c 100644 --- a/scripts/erd_postgres.sql +++ b/scripts/erd_postgres.sql @@ -387,4 +387,56 @@ ALTER TABLE IF EXISTS public.users ON UPDATE NO ACTION ON DELETE NO ACTION; + +-- Project table Start +CREATE TABLE IF NOT EXISTS public.projects ( + id text primary key not null, + organization_id text, + name text, + description text, + created_at timestamp with time zone, + updated_at timestamp with time zone, + deleted_at timestamp with time zone +); +CREATE INDEX idx_projects_name ON projects USING btree (name); + +CREATE TABLE IF NOT EXISTS public.project_members ( + id text primary key not null, + project_id text not null, + user_id text, + project_role_id text, + created_at timestamp with time zone, + updated_at timestamp with time zone, + deleted_at timestamp with time zone, + foreign key (project_id) references public.projects (id) + match simple on update no action on delete no action, + foreign key (project_role_id) references public.project_roles (id) + match simple on update no action on delete no action +); + +CREATE TABLE IF NOT EXISTS public.project_namesapces ( + id text primary key not null, + project_id text not null, + stack_id text, + namespace text, + description text, + status text, + created_at timestamp with time zone, + updated_at timestamp with time zone, + deleted_at timestamp with time zone, + foreign key (project_id) references public.projects (id) + match simple on update no action on delete no action +); +CREATE UNIQUE INDEX idx_stackid_namespace ON project_namesapces USING btree (stack_id, namespace); + +CREATE TABLE IF NOT EXISTS public.project_roles ( + id text primary key not null, + name text, + description text, + created_at timestamp with time zone, + updated_at timestamp with time zone, + deleted_at timestamp with time zone +); +-- Project table End + END; \ No newline at end of file diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index 6797c355..98eb2b77 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -46,4 +46,7 @@ values ( 'c3396c68-03ec-4d41-991c-69e4a2ac16aa', 'master', 'psnm-backend-referen insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) values ( '23b07a65-1cb3-4609-9bba-e88c15e2e192', 'master', 'psnm-frontend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-frontend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); - +# PROJECT +insert into project_roles ( id, name, description, created_at, updated_at ) values ( 'f4358b4e-adc3-447a-8ad9-c111c4b9a974', 'project-leader', 'project-leader', now(), now() ); +insert into project_roles ( id, name, description, created_at, updated_at ) values ( '2071bd6f-26b3-4c1a-a3ab-439bc89f0011', 'project-member', 'project-member', now(), now() ); +insert into project_roles ( id, name, description, created_at, updated_at ) values ( 'f62c16e1-316c-4d7f-9cfa-dbe4ed7dfa17', 'project-viewer', 'project-viewer', now(), now() ); \ No newline at end of file From a898ee51e307dcd48d383e6bf3edfdd92dced0e3 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 5 Feb 2024 15:19:58 +0900 Subject: [PATCH 017/502] Add Project Namespace management --- internal/database/database.go | 2 +- internal/delivery/http/project.go | 275 ++++++++++++++++++++++++++++-- internal/repository/project.go | 78 ++++++++- internal/route/route.go | 9 +- internal/usecase/project.go | 57 +++++++ pkg/domain/project.go | 25 ++- scripts/erd_postgres.sql | 4 +- 7 files changed, 423 insertions(+), 27 deletions(-) diff --git a/internal/database/database.go b/internal/database/database.go index 2d4cd301..6777f915 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -124,7 +124,7 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&domain.ProjectMember{}); err != nil { return err } - if err := db.AutoMigrate(&domain.ProjectNamesapce{}); err != nil { + if err := db.AutoMigrate(&domain.ProjectNamespace{}); err != nil { return err } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index f3666027..b520c643 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -30,6 +30,7 @@ type IProjectHandler interface { UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) + IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) GetProjectNamespace(w http.ResponseWriter, r *http.Request) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) @@ -136,9 +137,9 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { // @Description Get project role by id // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Success 200 {object} domain.GetProjectRoleResponse +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} domain.GetProjectRoleResponse // @Router /organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] // @Security JWT func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { @@ -178,7 +179,7 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { // @Description Get project roles by giving params // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" +// @Param organizationId path string true "Organization ID" // @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" // @Success 200 {object} domain.GetProjectRolesResponse // @Router /organizations/{organizationId}/projects/project-roles [get] @@ -239,6 +240,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param request body domain.AddProjectMemberRequest true "Request body to add project member" // @Success 200 {object} domain.AddProjectMemberResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [post] @@ -304,8 +306,8 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // @Description Get project member // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" // @Success 200 {object} domain.GetProjectMemberResponse // @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] @@ -371,7 +373,6 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), "C_INVALID_PROJECT_ID", "")) @@ -433,7 +434,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque return } - ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "ok"}) + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } // RemoveProjectMembers godoc @@ -513,7 +514,6 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } projectMemberId, ok := vars["projectMemberId"] - log.Debugf("projectMemberId = [%v]\n", projectMemberId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectMemberId"), "C_INVALID_PROJECT_MEMBER_ID", "")) @@ -534,20 +534,269 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } +// CreateProjectNamespace godoc +// @Tags Projects +// @Summary Create project namespace +// @Description Create project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Stack ID" +// @Param request body domain.CreateProjectNamespaceRequest true "Request body to create project namespace" +// @Success 200 {object} domain.CreateProjectNamespaceResponse +// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces [post] +// @Security JWT func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), + "C_INVALID_STACK_ID", "")) + return + } + + var projectNamespaceReq domain.CreateProjectNamespaceRequest + if err := UnmarshalRequestInput(r, &projectNamespaceReq); err != nil { + ErrorJSON(w, r, err) + return + } + + now := time.Now() + pn := &domain.ProjectNamespace{ + ProjectId: projectId, + StackId: stackId, + Namespace: projectNamespaceReq.Namespace, + Description: projectNamespaceReq.Description, + Status: "CREATING", + CreatedAt: now, + } + + pnId, err := p.usecase.CreateProjectNamespace(pn) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + out := domain.CreateProjectNamespaceResponse{ProjectNamesapceId: pnId} + ResponseJSON(w, r, http.StatusOK, out) +} + +// IsProjectNamespaceExist godoc +// @Tags Projects +// @Summary Check project namespace exist +// @Description Check project namespace exist +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Project Stack ID" +// @Param projectNamespace path string true "Project Namespace" +// @Success 200 {object} domain.CheckExistedResponse +// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespace}/existence [get] +// @Security JWT +func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), + "C_INVALID_STACK_ID", "")) + return + } + projectNamespace, ok := vars["projectNamespace"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectNamespace not found in path"), + "C_INVALID_PROJECT_NAMESPACE", "")) + return + } + + exist, err := p.usecase.IsProjectNamespaceExist(organizationId, projectId, stackId, projectNamespace) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CheckExistedResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) } +// GetProjectNamespaces godoc +// @Tags Projects +// @Summary Get project namespaces +// @Description Get project namespaces +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Project Stack ID" +// @Success 200 {object} domain.GetProjectNamespacesResponse +// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces [get] +// @Security JWT func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + stackId, ok := vars["stackId"] + log.Debugf("stackId = [%v]\n", stackId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), + "C_INVALID_STACK_ID", "")) + return + } + + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, stackId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project namespaces.", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectNamespacesResponse + out.ProjectNamespaces = pns + + ResponseJSON(w, r, http.StatusOK, out) + } +// GetProjectNamespace godoc +// @Tags Projects +// @Summary Get project namespace +// @Description Get project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Project Stack ID" +// @Param projectNamespaceId path string true "Project Namespace ID" +// @Success 200 {object} domain.GetProjectNamespaceResponse +// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespaceId} [get] +// @Security JWT func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), + "C_INVALID_STACK_ID", "")) + return + } + projectNamespaceId, ok := vars["projectNamespaceId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespaceId"), + "C_INVALID_PROJECT_NAMESPACE_ID", "")) + return + } + + pn, err := p.usecase.GetProjectNamespace(organizationId, projectId, stackId, projectNamespaceId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project namespace.", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectNamespaceResponse + out.ProjectNamespace = pn + if pn == nil { + log.Info("*************************************************s") + ResponseJSON(w, r, http.StatusNotFound, out) + } else { + ResponseJSON(w, r, http.StatusOK, out) + } } +// DeleteProjectNamespace godoc +// @Tags Projects +// @Summary Delete project namespace +// @Description Delete project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Stack ID" +// @Param projectNamespaceId path string true "Project Namespace ID" +// @Success 200 {object} domain.CommonProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespaceId} [delete] +// @Security JWT func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), + "C_INVALID_STACK_ID", "")) + return + } + projectNamespaceId, ok := vars["projectNamespaceId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespaceId"), + "C_INVALID_PROJECT_NAMESPACE_ID", "")) + return + } + + if err := p.usecase.DeleteProjectNamespace(organizationId, projectId, stackId, projectNamespaceId); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + + } + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } func (p ProjectHandler) SetFavoriteProject(w http.ResponseWriter, r *http.Request) { diff --git a/internal/repository/project.go b/internal/repository/project.go index d256cf6f..996eb35b 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -3,6 +3,7 @@ package repository import ( "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" "gorm.io/gorm" ) @@ -11,11 +12,16 @@ type IProjectRepository interface { GetAllProjectRoles() ([]domain.ProjectRole, error) GetProjectRoleByName(name string) (*domain.ProjectRole, error) GetProjectRoleById(id string) (*domain.ProjectRole, error) - AddProjectMember(pm *domain.ProjectMember) (string, error) + AddProjectMember(*domain.ProjectMember) (string, error) GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) - GetProjectMemberById(projectMemberId string) (pm domain.ProjectMember, err error) + GetProjectMemberById(projectMemberId string) (domain.ProjectMember, error) RemoveProjectMember(projectMemberId string) error UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error + CreateProjectNamespace(*domain.ProjectNamespace) (string, error) + GetProjectNamespaceByName(organizationId string, projectId string, stackId string, projectNamespace string) (*domain.ProjectNamespace, error) + GetProjectNamespaces(organizationId string, projectId string, stackId string) ([]domain.ProjectNamespace, error) + GetProjectNamespaceById(organizationId string, projectId string, stackId string, projectNamespaceId string) (*domain.ProjectNamespace, error) + DeleteProjectNamespace(organizationId string, projectId string, stackId string, projectNamespaceId string) error } type ProjectRepository struct { @@ -67,7 +73,6 @@ func (r *ProjectRepository) GetAllProjectRoles() (prs []domain.ProjectRole, err } func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *domain.ProjectRole, err error) { - log.Infof("project role name: %s", name) result := r.db.Where("name = ?", name).First(&pr) if result.Error != nil { log.Error(result.Error) @@ -135,3 +140,70 @@ func (r *ProjectRepository) UpdateProjectMemberRole(projectMemberId string, proj return nil } + +func (r *ProjectRepository) CreateProjectNamespace(pn *domain.ProjectNamespace) (string, error) { + res := r.db.Create(&pn) + if res.Error != nil { + return "", res.Error + } + + return pn.ID, nil +} + +func (r *ProjectRepository) GetProjectNamespaceByName(organizationId string, projectId string, stackId string, + projectNamespace string) (pn *domain.ProjectNamespace, err error) { + res := r.db.Limit(1).Where("project_id = ? and stack_id = ? and namespace = ?", projectId, stackId, projectNamespace).First(&pn) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found project namespace") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pn, nil +} + +func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectId string, + stackId string) (pns []domain.ProjectNamespace, err error) { + result := r.db.Where("project_id = ? and stack_id = ?", projectId, stackId).Find(&pns) + if result.Error != nil { + log.Error(result.Error) + return nil, result.Error + } + if result.RowsAffected == 0 { + log.Info("Cannot find project namespace") + return pns, nil + } + + return pns, nil +} + +func (r *ProjectRepository) GetProjectNamespaceById(organizationId string, projectId string, stackId string, + projectNamespaceId string) (pn *domain.ProjectNamespace, err error) { + res := r.db.Limit(1).Where("id = ? and project_id = ? and stack_id = ?", projectNamespaceId, projectId, stackId).First(&pn) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found project namespace") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pn, nil +} + +func (r *ProjectRepository) DeleteProjectNamespace(organizationId string, projectId string, + stackId string, projectNamespaceId string) error { + res := r.db.Where("project_id = ? and stack_id = ?", projectId, stackId). + Delete(&domain.ProjectNamespace{ID: projectNamespaceId}) + if res.Error != nil { + return res.Error + } + + return nil +} diff --git a/internal/route/route.go b/internal/route/route.go index f69c3a10..c3dd5aa2 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -210,10 +210,11 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMembers))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMemberRole))).Methods(http.MethodPut) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{namespaceId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespace}/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNamespaceExist))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespaceId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespaceId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 404b2ace..81f62194 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -26,6 +26,11 @@ type IProjectUsecase interface { GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) RemoveProjectMember(projectMemberId string) error UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error + CreateProjectNamespace(pn *domain.ProjectNamespace) (string, error) + IsProjectNamespaceExist(organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) + GetProjectNamespaces(organizationId string, projectId string, stackId string) ([]domain.ProjectNamespace, error) + GetProjectNamespace(organizationId string, projectId string, stackId string, projectNamespaceId string) (*domain.ProjectNamespace, error) + DeleteProjectNamespace(organizationId string, projectId string, stackId string, projectNamespaceId string) error } type ProjectUsecase struct { @@ -175,3 +180,55 @@ func (u *ProjectUsecase) UpdateProjectMemberRole(projectMemberId string, project } return nil } + +func (u *ProjectUsecase) CreateProjectNamespace(pn *domain.ProjectNamespace) (string, error) { + projectNamespaceId, err := u.projectRepo.CreateProjectNamespace(pn) + if err != nil { + log.Error(err) + return "", errors.Wrap(err, "Failed to create project namespace.") + } + return projectNamespaceId, nil +} + +func (u *ProjectUsecase) IsProjectNamespaceExist(organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) { + exist := true + pn, err := u.projectRepo.GetProjectNamespaceByName(organizationId, projectId, stackId, projectNamespace) + if err != nil { + log.Error(err) + exist = false + return exist, errors.Wrap(err, "Failed to retrieve project namespace.") + } + if pn == nil { + exist = false + } + return exist, nil +} + +func (u *ProjectUsecase) GetProjectNamespaces(organizationId string, projectId string, stackId string) ([]domain.ProjectNamespace, error) { + pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, stackId) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") + } + + return pns, nil +} + +func (u *ProjectUsecase) GetProjectNamespace(organizationId string, projectId string, stackId string, projectNamespaceId string) (*domain.ProjectNamespace, error) { + pn, err := u.projectRepo.GetProjectNamespaceById(organizationId, projectId, stackId, projectNamespaceId) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") + } + + return pn, nil +} + +func (u *ProjectUsecase) DeleteProjectNamespace(organizationId string, projectId string, stackId string, + projectNamespaceId string) error { + if err := u.projectRepo.DeleteProjectNamespace(organizationId, projectId, stackId, projectNamespaceId); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to delete project namespace.") + } + return nil +} diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 88743906..32d8639b 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -22,7 +22,7 @@ func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { return nil } -func (t *ProjectNamesapce) BeforeCreate(*gorm.DB) (err error) { +func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { t.ID = uuid.New().String() return nil } @@ -36,7 +36,7 @@ type Project struct { UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` ProjectMembers []ProjectMember `gorm:"foreignKey:ProjectId" json:"projectMembers,omitempty"` - ProjectNamesapces []ProjectNamesapce `gorm:"foreignKey:ProjectId" json:"projectNamesapces,omitempty"` + ProjectNamesapces []ProjectNamespace `gorm:"foreignKey:ProjectId" json:"projectNamespaces,omitempty"` } type ProjectRole struct { @@ -70,10 +70,10 @@ type ProjectMember struct { DeletedAt *time.Time `json:"deletedAt"` } -type ProjectNamesapce struct { +type ProjectNamespace struct { ID string `gorm:"primarykey" json:"id"` ProjectId string `gorm:"not null" json:"projectId"` - StackID string `gorm:"uniqueIndex:idx_stackid_namespace" json:"stackId"` + StackId string `gorm:"uniqueIndex:idx_stackid_namespace" json:"stackId"` Namespace string `gorm:"uniqueIndex:idx_stackid_namespace" json:"namespace"` StackName string `gorm:"-:all" json:"stackName,omitempty"` Description string `json:"description,omitempty"` @@ -135,3 +135,20 @@ type CommonProjectResponse struct { type UpdateProjectMemberRoleRequest struct { ProjectRoleId string `json:"projectRoleId"` } + +type CreateProjectNamespaceRequest struct { + Namespace string `json:"namespace"` + Description string `json:"description"` +} + +type CreateProjectNamespaceResponse struct { + ProjectNamesapceId string `json:"projectNamespaceId"` +} + +type GetProjectNamespacesResponse struct { + ProjectNamespaces []ProjectNamespace `json:"projectNamespaces"` +} + +type GetProjectNamespaceResponse struct { + ProjectNamespace *ProjectNamespace `json:"projectNamespace"` +} diff --git a/scripts/erd_postgres.sql b/scripts/erd_postgres.sql index acc7b24c..95b5b5b5 100644 --- a/scripts/erd_postgres.sql +++ b/scripts/erd_postgres.sql @@ -414,7 +414,7 @@ CREATE TABLE IF NOT EXISTS public.project_members ( match simple on update no action on delete no action ); -CREATE TABLE IF NOT EXISTS public.project_namesapces ( +CREATE TABLE IF NOT EXISTS public.project_namespaces ( id text primary key not null, project_id text not null, stack_id text, @@ -427,7 +427,7 @@ CREATE TABLE IF NOT EXISTS public.project_namesapces ( foreign key (project_id) references public.projects (id) match simple on update no action on delete no action ); -CREATE UNIQUE INDEX idx_stackid_namespace ON project_namesapces USING btree (stack_id, namespace); +CREATE UNIQUE INDEX idx_stackid_namespace ON project_namespaces USING btree (stack_id, namespace); CREATE TABLE IF NOT EXISTS public.project_roles ( id text primary key not null, From ac2f7fa5dfdc5139d09e5f6b4ec517a2328d6206 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 5 Feb 2024 18:10:39 +0900 Subject: [PATCH 018/502] minor fix: fix error code of verify token API --- internal/delivery/http/auth.go | 2 +- pkg/httpErrors/errorCode.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 361d33e0..3b929bd5 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -310,7 +310,7 @@ func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { } if !isActive { - ErrorJSON(w, r, httpErrors.NewUnauthorizedError(fmt.Errorf("token is not active"), "C_UNAUTHORIZED", "")) + ErrorJSON(w, r, httpErrors.NewUnauthorizedError(fmt.Errorf("token is not active"), "A_UNUSABLE_TOKEN", "")) return } diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 70558e34..d4d2b65f 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -28,6 +28,7 @@ var errorMap = map[ErrorCode]string{ "A_INVALID_CODE": "인증번호가 일치하지 않습니다.", "A_NO_SESSION": "세션 정보를 찾을 수 없습니다.", "A_EXPIRED_CODE": "인증번호가 만료되었습니다.", + "A_UNUSABLE_TOKEN": "사용할 수 없는 토큰입니다.", // User "U_NO_USER": "해당 사용자 정보를 찾을 수 없습니다.", From 0c9da6b47a9e7def50d3a4c859df1f5262a62a49 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 5 Feb 2024 19:27:38 +0900 Subject: [PATCH 019/502] Get Projects list --- internal/delivery/http/project.go | 96 ++++++++++++++++++++++--------- internal/repository/project.go | 60 +++++++++++++------ internal/route/route.go | 6 +- internal/usecase/project.go | 74 +++++++++++------------- pkg/domain/project.go | 51 ++++++++++++++-- 5 files changed, 193 insertions(+), 94 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index b520c643..8350a88f 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -2,6 +2,7 @@ package http import ( "fmt" + "github.com/google/uuid" "net/http" "strings" "time" @@ -98,9 +99,15 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { log.Infof("Project Id: %s", projectId) project.ID = projectId + ProjectLeaderId, err := uuid.Parse(projectReq.ProjectLeaderId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to parse uuid to string")) + return + } pm := &domain.ProjectMember{ ProjectId: projectId, - UserId: projectReq.ProjectLeaderId, + ProjectUserId: ProjectLeaderId, ProjectRoleId: projectReq.ProjectRoleId, CreatedAt: now, } @@ -131,6 +138,54 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { } +// GetProjects godoc +// @Tags Projects +// @Summary Get projects +// @Description Get projects +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetProjectsResponse +// @Router /organizations/{organizationId}/projects [get] +// @Security JWT +func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + ps, err := p.usecase.GetProjects(organizationId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to retrieve projects ", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectsResponse + out.Projects = ps + + if ps == nil { + ResponseJSON(w, r, http.StatusNotFound, out) + } else { + ResponseJSON(w, r, http.StatusOK, out) + } +} + +func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me +} + +func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me +} + +func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { + //TODO implement me +} + // GetProjectRole godoc // @Tags Projects // @Summary Get project role @@ -217,22 +272,6 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) ResponseJSON(w, r, http.StatusOK, out) } -func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { - //TODO implement me -} - -func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { - //TODO implement me -} - -func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { - //TODO implement me -} - -func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { - //TODO implement me -} - // AddProjectMember godoc // @Tags Projects // @Summary Add project member to project @@ -268,16 +307,21 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } - log.Infof("***************** project member request: %+v", projectMemberReq) - projectMemberResponse := domain.AddProjectMemberResponse{ ProjectMembers: make([]domain.ProjectMember, 0), } now := time.Now() for _, pmr := range projectMemberReq.ProjectMemberRequests { + ProjectUserId, err := uuid.Parse(pmr.ProjectUserId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to parse uuid to string")) + return + } + pm := &domain.ProjectMember{ ProjectId: projectId, - UserId: pmr.UserId, + ProjectUserId: ProjectUserId, ProjectRoleId: pmr.ProjectRoleId, CreatedAt: now, } @@ -345,9 +389,11 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) return } - var out domain.GetProjectMemberResponse - out.ProjectMember = pm - + out := domain.GetProjectMemberResponse{ProjectMember: pm} + if pm == nil { + ResponseJSON(w, r, http.StatusNotFound, out) + return + } ResponseJSON(w, r, http.StatusOK, out) } @@ -386,8 +432,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request return } - var out domain.GetProjectMembersResponse - out.ProjectMembers = pms + out := domain.GetProjectMembersResponse{ProjectMembers: pms} ResponseJSON(w, r, http.StatusOK, out) } @@ -744,7 +789,6 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque var out domain.GetProjectNamespaceResponse out.ProjectNamespace = pn if pn == nil { - log.Info("*************************************************s") ResponseJSON(w, r, http.StatusNotFound, out) } else { ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/repository/project.go b/internal/repository/project.go index 996eb35b..96cbd117 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -9,12 +9,13 @@ import ( type IProjectRepository interface { CreateProject(p *domain.Project) (string, error) + GetProjects(organizationId string) ([]domain.Project, error) GetAllProjectRoles() ([]domain.ProjectRole, error) GetProjectRoleByName(name string) (*domain.ProjectRole, error) GetProjectRoleById(id string) (*domain.ProjectRole, error) AddProjectMember(*domain.ProjectMember) (string, error) GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) - GetProjectMemberById(projectMemberId string) (domain.ProjectMember, error) + GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) RemoveProjectMember(projectMemberId string) error UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error CreateProjectNamespace(*domain.ProjectNamespace) (string, error) @@ -43,6 +44,25 @@ func (r *ProjectRepository) CreateProject(p *domain.Project) (string, error) { return p.ID, nil } +func (r *ProjectRepository) GetProjects(organizationId string) (ps []domain.Project, err error) { + res := r.db.Where("organization_id = ?", organizationId). + Preload("ProjectMembers"). + Preload("ProjectMembers.ProjectRole"). + Preload("ProjectMembers.ProjectUser"). + Preload("ProjectNamespaces").Find(&ps) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return ps, nil +} + func (r *ProjectRepository) GetProjectRoleById(id string) (*domain.ProjectRole, error) { var pr = &domain.ProjectRole{ID: id} result := r.db.First(pr) @@ -96,28 +116,32 @@ func (r *ProjectRepository) AddProjectMember(pm *domain.ProjectMember) (string, } func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string) (pms []domain.ProjectMember, err error) { - result := r.db.Joins("ProjectRole").Where("project_id = ?", projectId).Find(&pms) - if result.Error != nil { - log.Error(result.Error) - return nil, result.Error - } - if result.RowsAffected == 0 { - log.Info("Cannot find project member") - return pms, nil + res := r.db.Preload("ProjectUser"). + Joins("ProjectRole").Where("project_id = ?", projectId).Find(&pms) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project member") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } } return pms, nil } -func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm domain.ProjectMember, err error) { - result := r.db.Joins("ProjectRole").Where("project_members.id = ?", projectMemberId).First(&pm) - if result.Error != nil { - log.Error(result.Error) - return pm, result.Error - } - if result.RowsAffected == 0 { - log.Info("Cannot find project member") - return pm, nil +func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm *domain.ProjectMember, err error) { + res := r.db.Preload("ProjectUser"). + Joins("ProjectRole").Where("project_members.id = ?", projectMemberId).First(&pm) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project member") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } } return pm, nil diff --git a/internal/route/route.go b/internal/route/route.go index c3dd5aa2..4161ad37 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -198,12 +198,12 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa projectHandler := delivery.NewProjectHandler(usecase.NewProjectUsecase(repoFactory, argoClient)) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.CreateProject, http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles/{projectRoleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(projectHandler.GetProjectRole))).Methods(http.MethodGet) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.DeleteProject, http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles/{projectRoleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(projectHandler.GetProjectRole))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.AddProjectMember, http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.GetProjectMember, http.HandlerFunc(projectHandler.GetProjectMember))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMembers))).Methods(http.MethodGet) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 81f62194..159f9bf2 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -1,9 +1,7 @@ package usecase import ( - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/internal/serializer" argowf "github.com/openinfradev/tks-api/pkg/argo-client" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" @@ -19,10 +17,11 @@ const ( type IProjectUsecase interface { CreateProject(*domain.Project) (string, error) + GetProjects(organizationId string) ([]domain.Project, error) GetProjectRole(id string) (*domain.ProjectRole, error) GetProjectRoles(int) ([]domain.ProjectRole, error) AddProjectMember(pm *domain.ProjectMember) (string, error) - GetProjectMemberById(projectMemberId string) (domain.ProjectMember, error) + GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) RemoveProjectMember(projectMemberId string) error UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error @@ -64,6 +63,15 @@ func (u *ProjectUsecase) CreateProject(p *domain.Project) (string, error) { return projectId, nil } +func (u *ProjectUsecase) GetProjects(organizationId string) (ps []domain.Project, err error) { + ps, err = u.projectRepo.GetProjects(organizationId) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to get projects.") + } + return ps, err +} + func (u *ProjectUsecase) GetProjectRole(id string) (*domain.ProjectRole, error) { pr, err := u.projectRepo.GetProjectRoleById(id) if err != nil { @@ -107,31 +115,32 @@ func (u *ProjectUsecase) AddProjectMember(pm *domain.ProjectMember) (string, err return projectMemberId, nil } -func (u *ProjectUsecase) GetProjectMemberById(projectMemberId string) (pm domain.ProjectMember, err error) { +func (u *ProjectUsecase) GetProjectMemberById(projectMemberId string) (pm *domain.ProjectMember, err error) { pm, err = u.projectRepo.GetProjectMemberById(projectMemberId) if err != nil { log.Error(err) return pm, errors.Wrap(err, "Failed to get project member.") } - var uid uuid.UUID - uid, err = uuid.Parse(pm.UserId) - if err != nil { - log.Error(err) - return pm, errors.Wrap(err, "Failed to parse uuid to string") - } - user, err := u.userRepository.GetByUuid(uid) - if err != nil { - log.Error(err) - return pm, errors.Wrap(err, "Failed to retrieve user by id") - } - var pu domain.ProjectUser - if err = serializer.Map(user, &pu); err != nil { - log.Error(err) - return pm, err - } - - pm.User = pu + //var uid uuid.UUID + //uid, err = uuid.Parse(pm.ProjectUserId) + //if err != nil { + // log.Error(err) + // return pm, errors.Wrap(err, "Failed to parse uuid to string") + //} + + //user, err := u.userRepository.GetByUuid(pm.ProjectUserId) + //if err != nil { + // log.Error(err) + // return pm, errors.Wrap(err, "Failed to retrieve user by id") + //} + //var pu domain.ProjectUser + //if err = serializer.Map(user, &pu); err != nil { + // log.Error(err) + // return pm, err + //} + // + //pm.ProjectUser = pu return pm, nil } @@ -142,25 +151,8 @@ func (u *ProjectUsecase) GetProjectMembersByProjectId(projectId string) ([]domai return nil, errors.Wrap(err, "Failed to get project members.") } - var uid uuid.UUID - for idx, pm := range pms { - uid, err = uuid.Parse(pm.UserId) - if err != nil { - log.Error(err) - return nil, errors.Wrap(err, "Failed to parse uuid to string") - } - user, err := u.userRepository.GetByUuid(uid) - if err != nil { - log.Error(err) - return nil, errors.Wrap(err, "Failed to retrieve user by id") - } - var pu domain.ProjectUser - if err = serializer.Map(user, &pu); err != nil { - log.Error(err) - return nil, err - } - pms[idx].User = pu - } + //var uid uuid.UUID + //s return pms, nil } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 32d8639b..6eb5148b 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -36,7 +36,41 @@ type Project struct { UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` ProjectMembers []ProjectMember `gorm:"foreignKey:ProjectId" json:"projectMembers,omitempty"` - ProjectNamesapces []ProjectNamespace `gorm:"foreignKey:ProjectId" json:"projectNamespaces,omitempty"` + ProjectNamespaces []ProjectNamespace `gorm:"foreignKey:ProjectId" json:"projectNamespaces,omitempty"` +} + +//type ProjectList struct { +// ID string `json:"id"` +// OrganizationId string `json:"organizationId"` +// Name string `json:"name"` +// Description string `json:"description"` +// ProjectMembers []struct { +// ID string `json:"id"` +// UserId string `json:"userId"` +// AccountId string `json:"accountId"` +// Name string `json:"name"` +// Email string `json:"email"` +// ProjectRoleId string `json:"projectId"` +// ProjectRoleName string `json:"projectRoleName"` +// CreatedAt time.Time `json:"createdAt"` +// UpdatedAt *time.Time `json:"updatedAt"` +// } `json:"projectMembers"` +// ProjectNamespaces []struct { +// ID string `json:"id"` +// StackId string `json:"stackId"` +// StackName string `json:"stackName"` +// Namespace string `json:"namespace"` +// Description string `json:"description"` +// Status string `json:"status"` +// CreatedAt time.Time `json:"createdAt"` +// UpdatedAt *time.Time `json:"updatedAt"` +// } `json:"projectNamespaces"` +// CreatedAt time.Time `json:"createdAt"` +// UpdatedAt *time.Time `json:"updatedAt"` +//} + +type GetProjectsResponse struct { + Projects []Project `json:"projects"` } type ProjectRole struct { @@ -49,7 +83,7 @@ type ProjectRole struct { } type ProjectUser struct { - ID string `json:"id"` + ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` Email string `json:"email"` @@ -58,11 +92,16 @@ type ProjectUser struct { CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } + +func (ProjectUser) TableName() string { + return "users" +} + type ProjectMember struct { ID string `gorm:"primarykey" json:"id"` ProjectId string `gorm:"not null" json:"projectId"` - UserId string `json:"userId"` - User ProjectUser `gorm:"-:all" json:"user"` + ProjectUserId uuid.UUID `json:"projectUserId"` + ProjectUser ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID" json:"projectUser"` ProjectRoleId string `json:"projectRoleId"` ProjectRole ProjectRole `gorm:"foreignKey:ProjectRoleId" json:"projectRole"` CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` @@ -103,7 +142,7 @@ type GetProjectRolesResponse struct { } type ProjectMemberRequest struct { - UserId string `json:"userId" validate:"required"` + ProjectUserId string `json:"projectUserId" validate:"required"` ProjectRoleId string `json:"projectRoleId" validate:"required"` } type AddProjectMemberRequest struct { @@ -115,7 +154,7 @@ type AddProjectMemberResponse struct { } type GetProjectMemberResponse struct { - ProjectMember ProjectMember `json:"projectMember"` + ProjectMember *ProjectMember `json:"projectMember"` } type GetProjectMembersResponse struct { From f075d5a1ea936c02212fc98b687f56b8ec86d3a1 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 6 Feb 2024 19:15:48 +0900 Subject: [PATCH 020/502] Add Namespace management --- api/swagger/docs.go | 987 ++++++++++++++++++++++++++++-- api/swagger/swagger.json | 987 ++++++++++++++++++++++++++++-- api/swagger/swagger.yaml | 630 +++++++++++++++++-- internal/delivery/http/project.go | 501 +++++++++++---- internal/repository/project.go | 155 +++-- internal/route/route.go | 19 +- internal/usecase/project.go | 109 ++-- pkg/domain/project.go | 153 +++-- 8 files changed, 3089 insertions(+), 452 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 7ad45e4e..2a1391be 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -2785,6 +2785,41 @@ const docTemplate = `{ } }, "/organizations/{organizationId}/projects": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get projects", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get projects", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectsResponse" + } + } + } + }, "post": { "security": [ { @@ -2830,7 +2865,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/project-roles": { + "/organizations/{organizationId}/projects/pass/project-roles": { "get": { "security": [ { @@ -2873,7 +2908,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "/organizations/{organizationId}/projects/pass/project-roles/{projectRoleId}": { "get": { "security": [ { @@ -2891,6 +2926,238 @@ const docTemplate = `{ "Projects" ], "summary": "Get project role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Role ID", + "name": "projectRoleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectRoleResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get projects", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get projects", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateProjectRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/members": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project members", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project members", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectMembersResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project member Role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project member Role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project member role", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateProjectMembersRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add project member to project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Add project member to project", "parameters": [ { "type": "string", @@ -2905,26 +3172,411 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true + }, + { + "description": "Request body to add project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.AddProjectMemberRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove project members to project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Remove project members to project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Request body to remove project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.RemoveProjectMemberRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project member", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project member", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectMemberResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove project members to project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Remove project members to project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project member Role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project member Role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project member role", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateProjectMemberRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/namespaces": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project namespaces", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project namespaces", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectNamespacesResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Create project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Request body to create project namespace", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateProjectNamespaceRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectRoleResponse" + "$ref": "#/definitions/domain.GetProjectNamespaceResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/members": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get project members", + "description": "Delete project namespace", "consumes": [ "application/json" ], @@ -2934,7 +3586,7 @@ const docTemplate = `{ "tags": [ "Projects" ], - "summary": "Get project members", + "summary": "Delete project namespace", "parameters": [ { "type": "string", @@ -2949,24 +3601,40 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectMembersResponse" + "$ref": "#/definitions/domain.CommonProjectResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { + "get": { "security": [ { "JWT": [] } ], - "description": "Add project member to project", + "description": "Check project namespace exist", "consumes": [ "application/json" ], @@ -2976,7 +3644,7 @@ const docTemplate = `{ "tags": [ "Projects" ], - "summary": "Add project member to project", + "summary": "Check project namespace exist", "parameters": [ { "type": "string", @@ -2986,20 +3654,32 @@ const docTemplate = `{ "required": true }, { - "description": "Request body to add project member", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.AddProjectMemberRequest" - } + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.AddProjectMemberResponse" + "$ref": "#/definitions/domain.CheckExistedResponse" } } } @@ -4115,17 +4795,6 @@ const docTemplate = `{ } } }, - "domain.AddProjectMemberResponse": { - "type": "object", - "properties": { - "projectMembers": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ProjectMember" - } - } - } - }, "domain.AlertActionResponse": { "type": "object", "properties": { @@ -4928,6 +5597,14 @@ const docTemplate = `{ } } }, + "domain.CommonProjectResponse": { + "type": "object", + "properties": { + "result": { + "type": "string" + } + } + }, "domain.CreateAppGroupRequest": { "type": "object", "required": [ @@ -5216,6 +5893,20 @@ const docTemplate = `{ } } }, + "domain.CreateProjectNamespaceRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "stackId": { + "type": "string" + } + } + }, "domain.CreateProjectRequest": { "type": "object", "required": [ @@ -5239,8 +5930,8 @@ const docTemplate = `{ "domain.CreateProjectResponse": { "type": "object", "properties": { - "project": { - "$ref": "#/definitions/domain.Project" + "projectId": { + "type": "string" } } }, @@ -5877,6 +6568,14 @@ const docTemplate = `{ } } }, + "domain.GetProjectMemberResponse": { + "type": "object", + "properties": { + "projectMember": { + "$ref": "#/definitions/domain.ProjectMember" + } + } + }, "domain.GetProjectMembersResponse": { "type": "object", "properties": { @@ -5888,6 +6587,33 @@ const docTemplate = `{ } } }, + "domain.GetProjectNamespaceResponse": { + "type": "object", + "properties": { + "projectNamespace": { + "$ref": "#/definitions/domain.ProjectNamespaceResponse" + } + } + }, + "domain.GetProjectNamespacesResponse": { + "type": "object", + "properties": { + "projectNamespaces": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectNamespaceResponse" + } + } + } + }, + "domain.GetProjectResponse": { + "type": "object", + "properties": { + "project": { + "$ref": "#/definitions/domain.ProjectDetailResponse" + } + } + }, "domain.GetProjectRoleResponse": { "type": "object", "properties": { @@ -5907,6 +6633,17 @@ const docTemplate = `{ } } }, + "domain.GetProjectsResponse": { + "type": "object", + "properties": { + "projects": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectResponse" + } + } + } + }, "domain.GetStackKubeConfigResponse": { "type": "object", "properties": { @@ -6279,13 +7016,13 @@ const docTemplate = `{ } } }, - "domain.Project": { + "domain.ProjectDetailResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" + "appCount": { + "type": "integer" }, - "deletedAt": { + "createdAt": { "type": "string" }, "description": { @@ -6294,23 +7031,29 @@ const docTemplate = `{ "id": { "type": "string" }, + "memberCount": { + "type": "integer" + }, "name": { "type": "string" }, + "namespaceCount": { + "type": "integer" + }, "organizationId": { "type": "string" }, - "projectMembers": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ProjectMember" - } + "projectLeaderAccountId": { + "type": "string" }, - "projectNamesapces": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ProjectNamesapce" - } + "projectLeaderDepartment": { + "type": "string" + }, + "projectLeaderId": { + "type": "string" + }, + "projectLeaderName": { + "type": "string" }, "updatedAt": { "type": "string" @@ -6338,13 +7081,13 @@ const docTemplate = `{ "projectRoleId": { "type": "string" }, - "updatedAt": { - "type": "string" + "projectUser": { + "$ref": "#/definitions/domain.ProjectUser" }, - "user": { - "$ref": "#/definitions/domain.User" + "projectUserId": { + "type": "string" }, - "userId": { + "updatedAt": { "type": "string" } } @@ -6353,32 +7096,29 @@ const docTemplate = `{ "type": "object", "required": [ "projectRoleId", - "userId" + "projectUserId" ], "properties": { "projectRoleId": { "type": "string" }, - "userId": { + "projectUserId": { "type": "string" } } }, - "domain.ProjectNamesapce": { + "domain.ProjectNamespaceResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" + "appCount": { + "type": "integer" }, - "deletedAt": { + "createdAt": { "type": "string" }, "description": { "type": "string" }, - "id": { - "type": "string" - }, "namespace": { "type": "string" }, @@ -6399,6 +7139,41 @@ const docTemplate = `{ } } }, + "domain.ProjectResponse": { + "type": "object", + "properties": { + "appCount": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "memberCount": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "namespaceCount": { + "type": "integer" + }, + "organizationId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + }, + "projectRoleName": { + "type": "string" + } + } + }, "domain.ProjectRole": { "type": "object", "properties": { @@ -6423,6 +7198,51 @@ const docTemplate = `{ } } }, + "domain.ProjectUser": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.RemoveProjectMemberRequest": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectMemberId": { + "type": "string" + } + } + } + } + } + }, "domain.ResourceQuota": { "type": "object", "properties": { @@ -7081,6 +7901,47 @@ const docTemplate = `{ } } }, + "domain.UpdateProjectMemberRoleRequest": { + "type": "object", + "properties": { + "projectRoleId": { + "type": "string" + } + } + }, + "domain.UpdateProjectMembersRoleRequest": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectMemberId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + } + } + } + } + } + }, + "domain.UpdateProjectRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "domain.UpdateStackRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 3a987667..1a1789a2 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -2778,6 +2778,41 @@ } }, "/organizations/{organizationId}/projects": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get projects", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get projects", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectsResponse" + } + } + } + }, "post": { "security": [ { @@ -2823,7 +2858,7 @@ } } }, - "/organizations/{organizationId}/projects/project-roles": { + "/organizations/{organizationId}/projects/pass/project-roles": { "get": { "security": [ { @@ -2866,7 +2901,7 @@ } } }, - "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "/organizations/{organizationId}/projects/pass/project-roles/{projectRoleId}": { "get": { "security": [ { @@ -2884,6 +2919,238 @@ "Projects" ], "summary": "Get project role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Role ID", + "name": "projectRoleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectRoleResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get projects", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get projects", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateProjectRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/members": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project members", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project members", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectMembersResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project member Role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project member Role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project member role", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateProjectMembersRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add project member to project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Add project member to project", "parameters": [ { "type": "string", @@ -2898,26 +3165,411 @@ "name": "projectId", "in": "path", "required": true + }, + { + "description": "Request body to add project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.AddProjectMemberRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove project members to project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Remove project members to project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Request body to remove project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.RemoveProjectMemberRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project member", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project member", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectMemberResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove project members to project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Remove project members to project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project member Role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project member Role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project member role", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateProjectMemberRoleRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/namespaces": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project namespaces", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project namespaces", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectNamespacesResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Create project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Request body to create project namespace", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateProjectNamespaceRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectRoleResponse" + "$ref": "#/definitions/domain.GetProjectNamespaceResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/members": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get project members", + "description": "Delete project namespace", "consumes": [ "application/json" ], @@ -2927,7 +3579,7 @@ "tags": [ "Projects" ], - "summary": "Get project members", + "summary": "Delete project namespace", "parameters": [ { "type": "string", @@ -2942,24 +3594,40 @@ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectMembersResponse" + "$ref": "#/definitions/domain.CommonProjectResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { + "get": { "security": [ { "JWT": [] } ], - "description": "Add project member to project", + "description": "Check project namespace exist", "consumes": [ "application/json" ], @@ -2969,7 +3637,7 @@ "tags": [ "Projects" ], - "summary": "Add project member to project", + "summary": "Check project namespace exist", "parameters": [ { "type": "string", @@ -2979,20 +3647,32 @@ "required": true }, { - "description": "Request body to add project member", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.AddProjectMemberRequest" - } + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.AddProjectMemberResponse" + "$ref": "#/definitions/domain.CheckExistedResponse" } } } @@ -4108,17 +4788,6 @@ } } }, - "domain.AddProjectMemberResponse": { - "type": "object", - "properties": { - "projectMembers": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ProjectMember" - } - } - } - }, "domain.AlertActionResponse": { "type": "object", "properties": { @@ -4921,6 +5590,14 @@ } } }, + "domain.CommonProjectResponse": { + "type": "object", + "properties": { + "result": { + "type": "string" + } + } + }, "domain.CreateAppGroupRequest": { "type": "object", "required": [ @@ -5209,6 +5886,20 @@ } } }, + "domain.CreateProjectNamespaceRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "stackId": { + "type": "string" + } + } + }, "domain.CreateProjectRequest": { "type": "object", "required": [ @@ -5232,8 +5923,8 @@ "domain.CreateProjectResponse": { "type": "object", "properties": { - "project": { - "$ref": "#/definitions/domain.Project" + "projectId": { + "type": "string" } } }, @@ -5870,6 +6561,14 @@ } } }, + "domain.GetProjectMemberResponse": { + "type": "object", + "properties": { + "projectMember": { + "$ref": "#/definitions/domain.ProjectMember" + } + } + }, "domain.GetProjectMembersResponse": { "type": "object", "properties": { @@ -5881,6 +6580,33 @@ } } }, + "domain.GetProjectNamespaceResponse": { + "type": "object", + "properties": { + "projectNamespace": { + "$ref": "#/definitions/domain.ProjectNamespaceResponse" + } + } + }, + "domain.GetProjectNamespacesResponse": { + "type": "object", + "properties": { + "projectNamespaces": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectNamespaceResponse" + } + } + } + }, + "domain.GetProjectResponse": { + "type": "object", + "properties": { + "project": { + "$ref": "#/definitions/domain.ProjectDetailResponse" + } + } + }, "domain.GetProjectRoleResponse": { "type": "object", "properties": { @@ -5900,6 +6626,17 @@ } } }, + "domain.GetProjectsResponse": { + "type": "object", + "properties": { + "projects": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.ProjectResponse" + } + } + } + }, "domain.GetStackKubeConfigResponse": { "type": "object", "properties": { @@ -6272,13 +7009,13 @@ } } }, - "domain.Project": { + "domain.ProjectDetailResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" + "appCount": { + "type": "integer" }, - "deletedAt": { + "createdAt": { "type": "string" }, "description": { @@ -6287,23 +7024,29 @@ "id": { "type": "string" }, + "memberCount": { + "type": "integer" + }, "name": { "type": "string" }, + "namespaceCount": { + "type": "integer" + }, "organizationId": { "type": "string" }, - "projectMembers": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ProjectMember" - } + "projectLeaderAccountId": { + "type": "string" }, - "projectNamesapces": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.ProjectNamesapce" - } + "projectLeaderDepartment": { + "type": "string" + }, + "projectLeaderId": { + "type": "string" + }, + "projectLeaderName": { + "type": "string" }, "updatedAt": { "type": "string" @@ -6331,13 +7074,13 @@ "projectRoleId": { "type": "string" }, - "updatedAt": { - "type": "string" + "projectUser": { + "$ref": "#/definitions/domain.ProjectUser" }, - "user": { - "$ref": "#/definitions/domain.User" + "projectUserId": { + "type": "string" }, - "userId": { + "updatedAt": { "type": "string" } } @@ -6346,32 +7089,29 @@ "type": "object", "required": [ "projectRoleId", - "userId" + "projectUserId" ], "properties": { "projectRoleId": { "type": "string" }, - "userId": { + "projectUserId": { "type": "string" } } }, - "domain.ProjectNamesapce": { + "domain.ProjectNamespaceResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" + "appCount": { + "type": "integer" }, - "deletedAt": { + "createdAt": { "type": "string" }, "description": { "type": "string" }, - "id": { - "type": "string" - }, "namespace": { "type": "string" }, @@ -6392,6 +7132,41 @@ } } }, + "domain.ProjectResponse": { + "type": "object", + "properties": { + "appCount": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "memberCount": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "namespaceCount": { + "type": "integer" + }, + "organizationId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + }, + "projectRoleName": { + "type": "string" + } + } + }, "domain.ProjectRole": { "type": "object", "properties": { @@ -6416,6 +7191,51 @@ } } }, + "domain.ProjectUser": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "domain.RemoveProjectMemberRequest": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectMemberId": { + "type": "string" + } + } + } + } + } + }, "domain.ResourceQuota": { "type": "object", "properties": { @@ -7074,6 +7894,47 @@ } } }, + "domain.UpdateProjectMemberRoleRequest": { + "type": "object", + "properties": { + "projectRoleId": { + "type": "string" + } + } + }, + "domain.UpdateProjectMembersRoleRequest": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectMemberId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + } + } + } + } + } + }, + "domain.UpdateProjectRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "domain.UpdateStackRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 3421c4c2..9a27aad1 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -24,13 +24,6 @@ definitions: $ref: '#/definitions/domain.ProjectMemberRequest' type: array type: object - domain.AddProjectMemberResponse: - properties: - projectMembers: - items: - $ref: '#/definitions/domain.ProjectMember' - type: array - type: object domain.AlertActionResponse: properties: alertId: @@ -568,6 +561,11 @@ definitions: tksUserNodeType: type: string type: object + domain.CommonProjectResponse: + properties: + result: + type: string + type: object domain.CreateAppGroupRequest: properties: appGroupType: @@ -766,6 +764,15 @@ definitions: - Email - name type: object + domain.CreateProjectNamespaceRequest: + properties: + description: + type: string + namespace: + type: string + stackId: + type: string + type: object domain.CreateProjectRequest: properties: description: @@ -781,8 +788,8 @@ definitions: type: object domain.CreateProjectResponse: properties: - project: - $ref: '#/definitions/domain.Project' + projectId: + type: string type: object domain.CreateStackRequest: properties: @@ -1204,6 +1211,11 @@ definitions: type: string type: object type: object + domain.GetProjectMemberResponse: + properties: + projectMember: + $ref: '#/definitions/domain.ProjectMember' + type: object domain.GetProjectMembersResponse: properties: projectMembers: @@ -1211,6 +1223,23 @@ definitions: $ref: '#/definitions/domain.ProjectMember' type: array type: object + domain.GetProjectNamespaceResponse: + properties: + projectNamespace: + $ref: '#/definitions/domain.ProjectNamespaceResponse' + type: object + domain.GetProjectNamespacesResponse: + properties: + projectNamespaces: + items: + $ref: '#/definitions/domain.ProjectNamespaceResponse' + type: array + type: object + domain.GetProjectResponse: + properties: + project: + $ref: '#/definitions/domain.ProjectDetailResponse' + type: object domain.GetProjectRoleResponse: properties: projectRole: @@ -1223,6 +1252,13 @@ definitions: $ref: '#/definitions/domain.ProjectRole' type: array type: object + domain.GetProjectsResponse: + properties: + projects: + items: + $ref: '#/definitions/domain.ProjectResponse' + type: array + type: object domain.GetStackKubeConfigResponse: properties: kubeConfig: @@ -1466,28 +1502,32 @@ definitions: value: type: integer type: object - domain.Project: + domain.ProjectDetailResponse: properties: + appCount: + type: integer createdAt: type: string - deletedAt: - type: string description: type: string id: type: string + memberCount: + type: integer name: type: string + namespaceCount: + type: integer organizationId: type: string - projectMembers: - items: - $ref: '#/definitions/domain.ProjectMember' - type: array - projectNamesapces: - items: - $ref: '#/definitions/domain.ProjectNamesapce' - type: array + projectLeaderAccountId: + type: string + projectLeaderDepartment: + type: string + projectLeaderId: + type: string + projectLeaderName: + type: string updatedAt: type: string type: object @@ -1505,33 +1545,31 @@ definitions: $ref: '#/definitions/domain.ProjectRole' projectRoleId: type: string - updatedAt: + projectUser: + $ref: '#/definitions/domain.ProjectUser' + projectUserId: type: string - user: - $ref: '#/definitions/domain.User' - userId: + updatedAt: type: string type: object domain.ProjectMemberRequest: properties: projectRoleId: type: string - userId: + projectUserId: type: string required: - projectRoleId - - userId + - projectUserId type: object - domain.ProjectNamesapce: + domain.ProjectNamespaceResponse: properties: + appCount: + type: integer createdAt: type: string - deletedAt: - type: string description: type: string - id: - type: string namespace: type: string projectId: @@ -1545,6 +1583,29 @@ definitions: updatedAt: type: string type: object + domain.ProjectResponse: + properties: + appCount: + type: integer + createdAt: + type: string + description: + type: string + id: + type: string + memberCount: + type: integer + name: + type: string + namespaceCount: + type: integer + organizationId: + type: string + projectRoleId: + type: string + projectRoleName: + type: string + type: object domain.ProjectRole: properties: createdAt: @@ -1561,6 +1622,35 @@ definitions: updatedAt: type: string type: object + domain.ProjectUser: + properties: + accountId: + type: string + createdAt: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + updatedAt: + type: string + type: object + domain.RemoveProjectMemberRequest: + properties: + projectMembers: + items: + properties: + projectMemberId: + type: string + type: object + type: array + type: object domain.ResourceQuota: properties: quotas: @@ -1996,6 +2086,32 @@ definitions: primaryClusterId: type: string type: object + domain.UpdateProjectMemberRoleRequest: + properties: + projectRoleId: + type: string + type: object + domain.UpdateProjectMembersRoleRequest: + properties: + projectMembers: + items: + properties: + projectMemberId: + type: string + projectRoleId: + type: string + type: object + type: array + type: object + domain.UpdateProjectRequest: + properties: + description: + type: string + name: + type: string + required: + - name + type: object domain.UpdateStackRequest: properties: description: @@ -3909,6 +4025,28 @@ paths: tags: - Organizations /organizations/{organizationId}/projects: + get: + consumes: + - application/json + description: Get projects + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectsResponse' + security: + - JWT: [] + summary: Get projects + tags: + - Projects post: consumes: - application/json @@ -3937,7 +4075,101 @@ paths: summary: Create new project tags: - Projects + /organizations/{organizationId}/projects/{projectId}: + get: + consumes: + - application/json + description: Get projects + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectResponse' + security: + - JWT: [] + summary: Get projects + tags: + - Projects + put: + consumes: + - application/json + description: Update project + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Request body to update project + in: body + name: request + required: true + schema: + $ref: '#/definitions/domain.UpdateProjectRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CommonProjectResponse' + security: + - JWT: [] + summary: Update project + tags: + - Projects /organizations/{organizationId}/projects/{projectId}/members: + delete: + consumes: + - application/json + description: Remove project members to project + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Request body to remove project member + in: body + name: request + required: true + schema: + $ref: '#/definitions/domain.RemoveProjectMemberRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CommonProjectResponse' + security: + - JWT: [] + summary: Remove project members to project + tags: + - Projects get: consumes: - application/json @@ -3975,6 +4207,11 @@ paths: name: organizationId required: true type: string + - description: Project ID + in: path + name: projectId + required: true + type: string - description: Request body to add project member in: body name: request @@ -3987,13 +4224,334 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.AddProjectMemberResponse' + $ref: '#/definitions/domain.CommonProjectResponse' security: - JWT: [] summary: Add project member to project tags: - Projects - /organizations/{organizationId}/projects/project-roles: + put: + consumes: + - application/json + description: Update project member Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Request body to update project member role + in: body + name: request + required: true + schema: + $ref: '#/definitions/domain.UpdateProjectMembersRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CommonProjectResponse' + security: + - JWT: [] + summary: Update project member Role + tags: + - Projects + /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}: + delete: + consumes: + - application/json + description: Remove project members to project + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Project Member ID + in: path + name: projectMemberId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CommonProjectResponse' + security: + - JWT: [] + summary: Remove project members to project + tags: + - Projects + get: + consumes: + - application/json + description: Get project member + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Project Member ID + in: path + name: projectMemberId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectMemberResponse' + security: + - JWT: [] + summary: Get project member + tags: + - Projects + /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role: + put: + consumes: + - application/json + description: Update project member Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Project Member ID + in: path + name: projectMemberId + required: true + type: string + - description: Request body to update project member role + in: body + name: request + required: true + schema: + $ref: '#/definitions/domain.UpdateProjectMemberRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CommonProjectResponse' + security: + - JWT: [] + summary: Update project member Role + tags: + - Projects + /organizations/{organizationId}/projects/{projectId}/namespaces: + get: + consumes: + - application/json + description: Get project namespaces + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Project Stack ID + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectNamespacesResponse' + security: + - JWT: [] + summary: Get project namespaces + tags: + - Projects + post: + consumes: + - application/json + description: Create project namespace + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Stack ID + in: path + name: stackId + required: true + type: string + - description: Request body to create project namespace + in: body + name: request + required: true + schema: + $ref: '#/definitions/domain.CreateProjectNamespaceRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CommonProjectResponse' + security: + - JWT: [] + summary: Create project namespace + tags: + - Projects + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}: + delete: + consumes: + - application/json + description: Delete project namespace + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Stack ID + in: path + name: stackId + required: true + type: string + - description: Project Namespace + in: path + name: projectNamespace + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CommonProjectResponse' + security: + - JWT: [] + summary: Delete project namespace + tags: + - Projects + get: + consumes: + - application/json + description: Get project namespace + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Project Namespace + in: path + name: projectNamespace + required: true + type: string + - description: Project Stack ID + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectNamespaceResponse' + security: + - JWT: [] + summary: Get project namespace + tags: + - Projects + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence: + get: + consumes: + - application/json + description: Check project namespace exist + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Project Stack ID + in: path + name: stackId + required: true + type: string + - description: Project Namespace + in: path + name: projectNamespace + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CheckExistedResponse' + security: + - JWT: [] + summary: Check project namespace exist + tags: + - Projects + /organizations/{organizationId}/projects/pass/project-roles: get: consumes: - application/json @@ -4021,7 +4579,7 @@ paths: summary: Get project roles tags: - Projects - /organizations/{organizationId}/projects/project-roles/{projectRoleId}: + /organizations/{organizationId}/projects/pass/project-roles/{projectRoleId}: get: consumes: - application/json @@ -4032,9 +4590,9 @@ paths: name: organizationId required: true type: string - - description: Project ID + - description: Project Role ID in: path - name: projectId + name: projectRoleId required: true type: string produces: diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 8350a88f..23fa384c 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -3,6 +3,7 @@ package http import ( "fmt" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/serializer" "net/http" "strings" "time" @@ -29,6 +30,7 @@ type IProjectHandler interface { RemoveProjectMember(w http.ResponseWriter, r *http.Request) RemoveProjectMembers(w http.ResponseWriter, r *http.Request) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) + UpdateProjectMembersRole(w http.ResponseWriter, r *http.Request) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) @@ -78,9 +80,6 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } - log.Infof("projectReq: name = %s, description = %s, projectLeaderId = %s", - projectReq.Name, projectReq.Description, projectReq.ProjectLeaderId) - now := time.Now() project := &domain.Project{ OrganizationId: organizationId, @@ -96,8 +95,6 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } - log.Infof("Project Id: %s", projectId) - project.ID = projectId ProjectLeaderId, err := uuid.Parse(projectReq.ProjectLeaderId) if err != nil { @@ -105,8 +102,11 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to parse uuid to string")) return } + //Don't add ProjectUser Object because of Cascading pm := &domain.ProjectMember{ - ProjectId: projectId, + ProjectId: projectId, + //ProjectUser: &domain.ProjectUser{ID: ProjectLeaderId}, + //ProjectRole: &domain.ProjectRole{ID: projectReq.ProjectRoleId}, ProjectUserId: ProjectLeaderId, ProjectRoleId: projectReq.ProjectRoleId, CreatedAt: now, @@ -114,27 +114,29 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { projectMemberId, err := p.usecase.AddProjectMember(pm) if err != nil { + log.Errorf("projectMemberId: %v", projectMemberId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - pr, err := p.usecase.GetProjectRoles(usecase.ProjectLeader) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - - pms := make([]domain.ProjectMember, 0) - pm.ID = projectMemberId - pm.ProjectRole = pr[0] - pms = append(pms, *pm) - - project.ProjectMembers = pms - projectRes := domain.CreateProjectResponse{ - Project: *project, - } - - ResponseJSON(w, r, http.StatusOK, projectRes) + //pr, err := p.usecase.GetProjectRoles(usecase.ProjectLeader) + //if err != nil { + // ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + // return + //} + // + //pms := make([]domain.ProjectMember, 0) + //pm.ID = projectMemberId + //pm.ProjectRole = pr[0] + //pms = append(pms, *pm) + // + //project.ProjectMembers = pms + //projectRes := domain.CreateProjectResponse{ + // Project: *project, + //} + + out := domain.CreateProjectResponse{ProjectId: projectId} + ResponseJSON(w, r, http.StatusOK, out) } @@ -144,8 +146,8 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { // @Description Get projects // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Success 200 {object} domain.GetProjectsResponse +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetProjectsResponse // @Router /organizations/{organizationId}/projects [get] // @Security JWT func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { @@ -164,8 +166,35 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { return } + // TODO: get myUserId from login component + myUserId := "58568003-9812-42d6-b10e-61a60e52cb06" + prs := make([]domain.ProjectResponse, 0) + for _, project := range ps { + var projectRoleId, projectRoleName string + for _, pm := range project.ProjectMembers { + if myUserId == pm.ProjectUserId.String() { + projectRoleId = pm.ProjectRoleId + projectRoleName = pm.ProjectRole.Name + } + } + // TODO: implement AppCount + pr := domain.ProjectResponse{ + ID: project.ID, + OrganizationId: project.OrganizationId, + Name: project.Name, + Description: project.Description, + ProjectRoleId: projectRoleId, + ProjectRoleName: projectRoleName, + NamespaceCount: len(project.ProjectNamespaces), + AppCount: 0, + MemberCount: len(project.ProjectMembers), + CreatedAt: project.CreatedAt, + } + prs = append(prs, pr) + } + var out domain.GetProjectsResponse - out.Projects = ps + out.Projects = prs if ps == nil { ResponseJSON(w, r, http.StatusNotFound, out) @@ -174,12 +203,127 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { } } +// GetProject godoc +// @Tags Projects +// @Summary Get projects +// @Description Get projects +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} domain.GetProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId} [get] +// @Security JWT func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + project, err := p.usecase.GetProject(organizationId, projectId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to retrieve project", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectResponse + if project == nil { + ResponseJSON(w, r, http.StatusNotFound, out) + return + } + + var projectLeaderId, projectLeaderName, projectLeaderAccountId, projectLeaderDepartment string + for _, pu := range project.ProjectMembers { + if pu.ProjectRole.Name == "project-leader" { + projectLeaderId = pu.ProjectUser.ID.String() + projectLeaderName = pu.ProjectUser.Name + projectLeaderAccountId = pu.ProjectUser.AccountId + projectLeaderDepartment = pu.ProjectUser.Department + } + } + + var pdr domain.ProjectDetailResponse + if err = serializer.Map(*project, &pdr); err != nil { + log.Error(err) + ErrorJSON(w, r, err) + return + } + pdr.ProjectLeaderId = projectLeaderId + pdr.ProjectLeaderName = projectLeaderName + pdr.ProjectLeaderAccountId = projectLeaderAccountId + pdr.ProjectLeaderDepartment = projectLeaderDepartment + pdr.NamespaceCount = len(project.ProjectNamespaces) + pdr.MemberCount = len(project.ProjectMembers) + //TODO implement AppCount + pdr.AppCount = 0 + + out.Project = &pdr + ResponseJSON(w, r, http.StatusOK, out) } +// UpdateProject godoc +// @Tags Projects +// @Summary Update project +// @Description Update project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param request body domain.UpdateProjectRequest true "Request body to update project" +// @Success 200 {object} domain.CommonProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId} [put] +// @Security JWT func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { - //TODO implement me + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + var projectReq domain.UpdateProjectRequest + if err := UnmarshalRequestInput(r, &projectReq); err != nil { + ErrorJSON(w, r, err) + return + } + + now := time.Now() + project, err := p.usecase.GetProject(organizationId, projectId) + if err != nil { + + } + + project.Name = projectReq.Name + project.Description = projectReq.Description + project.UpdatedAt = &now + project.ProjectNamespaces = nil + project.ProjectMembers = nil + + if err := p.usecase.UpdateProject(project); err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { @@ -192,10 +336,10 @@ func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { // @Description Get project role by id // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" +// @Param organizationId path string true "Organization ID" +// @Param projectRoleId path string true "Project Role ID" // @Success 200 {object} domain.GetProjectRoleResponse -// @Router /organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] +// @Router /organizations/{organizationId}/projects/pass/project-roles/{projectRoleId} [get] // @Security JWT func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -234,10 +378,10 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { // @Description Get project roles by giving params // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" +// @Param organizationId path string true "Organization ID" // @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" // @Success 200 {object} domain.GetProjectRolesResponse -// @Router /organizations/{organizationId}/projects/project-roles [get] +// @Router /organizations/{organizationId}/projects/pass/project-roles [get] // @Security JWT func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -281,7 +425,7 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Param request body domain.AddProjectMemberRequest true "Request body to add project member" -// @Success 200 {object} domain.AddProjectMemberResponse +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [post] // @Security JWT func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { @@ -294,7 +438,6 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), "C_INVALID_PROJECT_ID", "")) @@ -307,41 +450,46 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } - projectMemberResponse := domain.AddProjectMemberResponse{ - ProjectMembers: make([]domain.ProjectMember, 0), - } now := time.Now() for _, pmr := range projectMemberReq.ProjectMemberRequests { - ProjectUserId, err := uuid.Parse(pmr.ProjectUserId) + pu, err := p.usecase.GetProjectUser(pmr.ProjectUserId) if err != nil { log.Error(err) - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to parse uuid to string")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectUserId"), + "C_INVALID_PROJECT_USER_ID", "")) return } - pm := &domain.ProjectMember{ - ProjectId: projectId, - ProjectUserId: ProjectUserId, - ProjectRoleId: pmr.ProjectRoleId, - CreatedAt: now, - } - pmId, err := p.usecase.AddProjectMember(pm) + pr, err := p.usecase.GetProjectRole(pmr.ProjectRoleId) if err != nil { + log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } + if pr == nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectRoleId"), + "C_INVALID_PROJECT_ROLE_ID", "")) + return + } - pr, err := p.usecase.GetProjectRole(pm.ProjectRoleId) + pm := &domain.ProjectMember{ + ProjectId: projectId, + ProjectUserId: pu.ID, + ProjectUser: nil, + ProjectRoleId: pr.ID, + ProjectRole: nil, + CreatedAt: now, + } + pmId, err := p.usecase.AddProjectMember(pm) if err != nil { + log.Errorf("projectMemberId: %s", pmId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - pm.ID = pmId - pm.ProjectRole = *pr - projectMemberResponse.ProjectMembers = append(projectMemberResponse.ProjectMembers, *pm) } - ResponseJSON(w, r, http.StatusOK, projectMemberResponse) + out := domain.CommonProjectResponse{Result: "OK"} + ResponseJSON(w, r, http.StatusOK, out) } // GetProjectMember godoc @@ -351,7 +499,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" +// @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" // @Success 200 {object} domain.GetProjectMemberResponse // @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] @@ -382,7 +530,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) return } - pm, err := p.usecase.GetProjectMemberById(projectMemberId) + pm, err := p.usecase.GetProjectMember(projectMemberId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project member ", err) ErrorJSON(w, r, err) @@ -446,7 +594,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" -// @Success 200 {object} domain.CommonProjectResponse +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] // @Security JWT func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { @@ -518,6 +666,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ return } + // TODO: change multi row delete for _, pm := range projectMemberReq.ProjectMember { if err := p.usecase.RemoveProjectMember(pm.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -571,11 +720,93 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R return } - if err := p.usecase.UpdateProjectMemberRole(projectMemberId, pmrReq.ProjectRoleId); err != nil { + now := time.Now() + pm, err := p.usecase.GetProjectMember(projectMemberId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if pm == nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectMemberId"), + "C_INVALID_PROJECT_MEMBER_ID", "")) + return + } + + pm.ProjectRoleId = pmrReq.ProjectRoleId + pm.ProjectUser = nil + pm.ProjectRole = nil + pm.UpdatedAt = &now + + if err := p.usecase.UpdateProjectMemberRole(pm); err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) +} + +// UpdateProjectMembersRole godoc +// @Tags Projects +// @Summary Update project member Role +// @Description Update project member Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param request body domain.UpdateProjectMembersRoleRequest true "Request body to update project member role" +// @Success 200 {object} domain.CommonProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId}/members [put] +// @Security JWT +func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + now := time.Now() + var projectMemberReq domain.UpdateProjectMembersRoleRequest + if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { ErrorJSON(w, r, err) return } + for _, pmr := range projectMemberReq.ProjectMemberRoleRequests { + pm, err := p.usecase.GetProjectMember(pmr.ProjectMemberId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if pm == nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectMemberId"), + "C_INVALID_PROJECT_MEMBER_ID", "")) + return + } + + pm.ProjectRoleId = pmr.ProjectRoleId + pm.ProjectUser = nil + pm.ProjectRole = nil + pm.UpdatedAt = &now + + if err := p.usecase.UpdateProjectMemberRole(pm); err != nil { + ErrorJSON(w, r, err) + return + } + } + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } @@ -589,13 +820,12 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R // @Param projectId path string true "Project ID" // @Param stackId path string true "Stack ID" // @Param request body domain.CreateProjectNamespaceRequest true "Request body to create project namespace" -// @Success 200 {object} domain.CreateProjectNamespaceResponse -// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces [post] +// @Success 200 {object} domain.CommonProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces [post] // @Security JWT func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -607,12 +837,6 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re "C_INVALID_PROJECT_ID", "")) return } - stackId, ok := vars["stackId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), - "C_INVALID_STACK_ID", "")) - return - } var projectNamespaceReq domain.CreateProjectNamespaceRequest if err := UnmarshalRequestInput(r, &projectNamespaceReq); err != nil { @@ -622,20 +846,20 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re now := time.Now() pn := &domain.ProjectNamespace{ - ProjectId: projectId, - StackId: stackId, + StackId: projectNamespaceReq.StackId, Namespace: projectNamespaceReq.Namespace, + ProjectId: projectId, + Stack: nil, Description: projectNamespaceReq.Description, Status: "CREATING", CreatedAt: now, } - pnId, err := p.usecase.CreateProjectNamespace(pn) - if err != nil { + if err := p.usecase.CreateProjectNamespace(organizationId, pn); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - out := domain.CreateProjectNamespaceResponse{ProjectNamesapceId: pnId} + out := domain.CommonProjectResponse{Result: "OK"} ResponseJSON(w, r, http.StatusOK, out) } @@ -650,7 +874,7 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re // @Param stackId path string true "Project Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} domain.CheckExistedResponse -// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespace}/existence [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence [get] // @Security JWT func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -701,7 +925,7 @@ func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.R // @Param projectId path string true "Project ID" // @Param stackId path string true "Project Stack ID" // @Success 200 {object} domain.GetProjectNamespacesResponse -// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -717,15 +941,8 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ "C_INVALID_PROJECT_ID", "")) return } - stackId, ok := vars["stackId"] - log.Debugf("stackId = [%v]\n", stackId) - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), - "C_INVALID_STACK_ID", "")) - return - } - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, stackId) + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project namespaces.", err) ErrorJSON(w, r, err) @@ -733,8 +950,26 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ } var out domain.GetProjectNamespacesResponse - out.ProjectNamespaces = pns + if pns == nil { + ResponseJSON(w, r, http.StatusNotFound, out) + return + } + pnrs := make([]domain.ProjectNamespaceResponse, 0) + for _, pn := range pns { + var pnr domain.ProjectNamespaceResponse + if err = serializer.Map(pn, &pnr); err != nil { + log.Error(err) + ErrorJSON(w, r, err) + return + } + pnr.StackName = pn.Stack.Name + //TODO: implement AppCount + pnr.AppCount = 0 + + pnrs = append(pnrs, pnr) + } + out.ProjectNamespaces = pnrs ResponseJSON(w, r, http.StatusOK, out) } @@ -747,10 +982,10 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" +// @Param projectNamespace path string true "Project Namespace" // @Param stackId path string true "Project Stack ID" -// @Param projectNamespaceId path string true "Project Namespace ID" // @Success 200 {object} domain.GetProjectNamespaceResponse -// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespaceId} [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [get] // @Security JWT func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -766,20 +1001,20 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque "C_INVALID_PROJECT_ID", "")) return } - stackId, ok := vars["stackId"] + projectNamespace, ok := vars["projectNamespace"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), - "C_INVALID_STACK_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespace"), + "C_INVALID_PROJECT_NAMESPACE", "")) return } - projectNamespaceId, ok := vars["projectNamespaceId"] + stackId, ok := vars["stackId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespaceId"), - "C_INVALID_PROJECT_NAMESPACE_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), + "C_INVALID_STACK_ID", "")) return } - pn, err := p.usecase.GetProjectNamespace(organizationId, projectId, stackId, projectNamespaceId) + pn, err := p.usecase.GetProjectNamespace(organizationId, projectId, projectNamespace, stackId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project namespace.", err) ErrorJSON(w, r, err) @@ -787,12 +1022,24 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque } var out domain.GetProjectNamespaceResponse - out.ProjectNamespace = pn if pn == nil { ResponseJSON(w, r, http.StatusNotFound, out) - } else { - ResponseJSON(w, r, http.StatusOK, out) + return + } + + var pnr domain.ProjectNamespaceResponse + if err = serializer.Map(*pn, &pnr); err != nil { + log.Error(err) + ErrorJSON(w, r, err) + return } + pnr.StackName = pn.Stack.Name + //TODO: implement AppCount + pnr.AppCount = 0 + + out.ProjectNamespace = &pnr + ResponseJSON(w, r, http.StatusOK, out) + } // DeleteProjectNamespace godoc @@ -804,43 +1051,45 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Param stackId path string true "Stack ID" -// @Param projectNamespaceId path string true "Project Namespace ID" +// @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespaceId} [delete] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] // @Security JWT func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), - "C_INVALID_ORGANIZATION_ID", "")) - return - } - projectId, ok := vars["projectId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), - "C_INVALID_PROJECT_ID", "")) - return - } - stackId, ok := vars["stackId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), - "C_INVALID_STACK_ID", "")) - return - } - projectNamespaceId, ok := vars["projectNamespaceId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespaceId"), - "C_INVALID_PROJECT_NAMESPACE_ID", "")) - return - } - - if err := p.usecase.DeleteProjectNamespace(organizationId, projectId, stackId, projectNamespaceId); err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return + //TODO implement me - } - ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) + //vars := mux.Vars(r) + //organizationId, ok := vars["organizationId"] + //if !ok { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + // "C_INVALID_ORGANIZATION_ID", "")) + // return + //} + //projectId, ok := vars["projectId"] + //if !ok { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + // "C_INVALID_PROJECT_ID", "")) + // return + //} + //projectNamespace, ok := vars["projectNamespace"] + //if !ok { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespace"), + // "C_INVALID_PROJECT_NAMESPACE", "")) + // return + //} + //stackId, ok := vars["stackId"] + //if !ok { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), + // "C_INVALID_STACK_ID", "")) + // return + //} + // + //if err := p.usecase.DeleteProjectNamespace(organizationId, projectId, projectNamespace, stackId); err != nil { + // ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + // return + // + //} + //ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } func (p ProjectHandler) SetFavoriteProject(w http.ResponseWriter, r *http.Request) { diff --git a/internal/repository/project.go b/internal/repository/project.go index 96cbd117..dfa6293f 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -10,6 +10,8 @@ import ( type IProjectRepository interface { CreateProject(p *domain.Project) (string, error) GetProjects(organizationId string) ([]domain.Project, error) + GetProjectById(organizationId string, projectId string) (*domain.Project, error) + UpdateProject(p *domain.Project) error GetAllProjectRoles() ([]domain.ProjectRole, error) GetProjectRoleByName(name string) (*domain.ProjectRole, error) GetProjectRoleById(id string) (*domain.ProjectRole, error) @@ -17,12 +19,13 @@ type IProjectRepository interface { GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) RemoveProjectMember(projectMemberId string) error - UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error - CreateProjectNamespace(*domain.ProjectNamespace) (string, error) + //UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error + UpdateProjectMemberRole(pm *domain.ProjectMember) error + CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error GetProjectNamespaceByName(organizationId string, projectId string, stackId string, projectNamespace string) (*domain.ProjectNamespace, error) - GetProjectNamespaces(organizationId string, projectId string, stackId string) ([]domain.ProjectNamespace, error) - GetProjectNamespaceById(organizationId string, projectId string, stackId string, projectNamespaceId string) (*domain.ProjectNamespace, error) - DeleteProjectNamespace(organizationId string, projectId string, stackId string, projectNamespaceId string) error + GetProjectNamespaces(organizationId string, projectId string) ([]domain.ProjectNamespace, error) + GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) + DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error } type ProjectRepository struct { @@ -63,44 +66,75 @@ func (r *ProjectRepository) GetProjects(organizationId string) (ps []domain.Proj return ps, nil } +func (r *ProjectRepository) GetProjectById(organizationId string, projectId string) (p *domain.Project, err error) { + res := r.db.Limit(1).Where("organization_id = ? and id = ?", organizationId, projectId). + Preload("ProjectMembers"). + Preload("ProjectMembers.ProjectRole"). + Preload("ProjectMembers.ProjectUser"). + First(&p) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return p, nil +} + +func (r *ProjectRepository) UpdateProject(p *domain.Project) error { + res := r.db.Model(&p).Updates(domain.Project{Name: p.Name, Description: p.Description, UpdatedAt: p.UpdatedAt}) + if res.Error != nil { + return res.Error + } + + return nil +} + func (r *ProjectRepository) GetProjectRoleById(id string) (*domain.ProjectRole, error) { var pr = &domain.ProjectRole{ID: id} - result := r.db.First(pr) - if result.Error != nil { - log.Error(result.Error) - return pr, result.Error - } - if result.RowsAffected == 0 { - log.Info("There is no project_roles table data") - return pr, nil + res := r.db.First(pr) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project role") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } } return pr, nil } func (r *ProjectRepository) GetAllProjectRoles() (prs []domain.ProjectRole, err error) { - result := r.db.Find(&prs) - if result.Error != nil { - log.Error(result.Error) - return nil, result.Error - } - if result.RowsAffected == 0 { - log.Info("There is no project_roles table data") - return prs, nil + res := r.db.Find(&prs) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project roles") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } } return prs, nil } func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *domain.ProjectRole, err error) { - result := r.db.Where("name = ?", name).First(&pr) - if result.Error != nil { - log.Error(result.Error) - return nil, result.Error - } - if result.RowsAffected == 0 { - log.Info("There is no project_roles table data") - return pr, nil + res := r.db.Where("name = ?", name).First(&pr) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project roles") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } } return pr, nil @@ -156,8 +190,17 @@ func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { return nil } -func (r *ProjectRepository) UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error { - res := r.db.Model(&domain.ProjectMember{ID: projectMemberId}).Update("project_role_id", projectRoleId) +//func (r *ProjectRepository) UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error { +// res := r.db.Model(&domain.ProjectMember{ID: projectMemberId}).Update("project_role_id", projectRoleId) +// if res.Error != nil { +// return res.Error +// } +// +// return nil +//} + +func (r *ProjectRepository) UpdateProjectMemberRole(pm *domain.ProjectMember) error { + res := r.db.Model(&pm).Updates(domain.ProjectMember{ProjectRoleId: pm.ProjectRoleId, UpdatedAt: pm.UpdatedAt}) if res.Error != nil { return res.Error } @@ -165,18 +208,21 @@ func (r *ProjectRepository) UpdateProjectMemberRole(projectMemberId string, proj return nil } -func (r *ProjectRepository) CreateProjectNamespace(pn *domain.ProjectNamespace) (string, error) { +func (r *ProjectRepository) CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error { res := r.db.Create(&pn) if res.Error != nil { - return "", res.Error + return res.Error } - return pn.ID, nil + //return pn.ID, nil + return nil } func (r *ProjectRepository) GetProjectNamespaceByName(organizationId string, projectId string, stackId string, projectNamespace string) (pn *domain.ProjectNamespace, err error) { - res := r.db.Limit(1).Where("project_id = ? and stack_id = ? and namespace = ?", projectId, stackId, projectNamespace).First(&pn) + res := r.db.Limit(1). + Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). + First(&pn) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Not found project namespace") @@ -190,24 +236,29 @@ func (r *ProjectRepository) GetProjectNamespaceByName(organizationId string, pro return pn, nil } -func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectId string, - stackId string) (pns []domain.ProjectNamespace, err error) { - result := r.db.Where("project_id = ? and stack_id = ?", projectId, stackId).Find(&pns) - if result.Error != nil { - log.Error(result.Error) - return nil, result.Error - } - if result.RowsAffected == 0 { - log.Info("Cannot find project namespace") - return pns, nil +func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectId string) (pns []domain.ProjectNamespace, err error) { + res := r.db.Where("project_id = ?", projectId). + Preload("Stack"). + Find(&pns) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found project namespaces") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } } return pns, nil } -func (r *ProjectRepository) GetProjectNamespaceById(organizationId string, projectId string, stackId string, - projectNamespaceId string) (pn *domain.ProjectNamespace, err error) { - res := r.db.Limit(1).Where("id = ? and project_id = ? and stack_id = ?", projectNamespaceId, projectId, stackId).First(&pn) +func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, + projectNamespace string, stackId string) (pn *domain.ProjectNamespace, err error) { + res := r.db.Limit(1). + Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). + Preload("Stack"). + First(&pn) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Not found project namespace") @@ -221,10 +272,10 @@ func (r *ProjectRepository) GetProjectNamespaceById(organizationId string, proje return pn, nil } -func (r *ProjectRepository) DeleteProjectNamespace(organizationId string, projectId string, - stackId string, projectNamespaceId string) error { - res := r.db.Where("project_id = ? and stack_id = ?", projectId, stackId). - Delete(&domain.ProjectNamespace{ID: projectNamespaceId}) +func (r *ProjectRepository) DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, + stackId string) error { + res := r.db.Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). + Delete(&domain.ProjectNamespace{StackId: stackId, Namespace: projectNamespace}) if res.Error != nil { return res.Error } diff --git a/internal/route/route.go b/internal/route/route.go index 4161ad37..fa536594 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -199,22 +199,23 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa projectHandler := delivery.NewProjectHandler(usecase.NewProjectUsecase(repoFactory, argoClient)) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.CreateProject, http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.DeleteProject, http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles/{projectRoleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(projectHandler.GetProjectRole))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/pass/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/pass/project-roles/{projectRoleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(projectHandler.GetProjectRole))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.AddProjectMember, http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.GetProjectMember, http.HandlerFunc(projectHandler.GetProjectMember))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMembers))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMembers))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMembersRole))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMemberRole))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespace}/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNamespaceExist))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespaceId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/stacks/{stackId}/namespaces/{projectNamespaceId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNamespaceExist))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 159f9bf2..39fd33b5 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -1,7 +1,9 @@ package usecase import ( + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/internal/serializer" argowf "github.com/openinfradev/tks-api/pkg/argo-client" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" @@ -18,18 +20,21 @@ const ( type IProjectUsecase interface { CreateProject(*domain.Project) (string, error) GetProjects(organizationId string) ([]domain.Project, error) + GetProject(organizationId string, projectId string) (*domain.Project, error) + UpdateProject(p *domain.Project) error GetProjectRole(id string) (*domain.ProjectRole, error) GetProjectRoles(int) ([]domain.ProjectRole, error) AddProjectMember(pm *domain.ProjectMember) (string, error) - GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) + GetProjectUser(projectUserId string) (*domain.ProjectUser, error) + GetProjectMember(projectMemberId string) (*domain.ProjectMember, error) GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) RemoveProjectMember(projectMemberId string) error - UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error - CreateProjectNamespace(pn *domain.ProjectNamespace) (string, error) + UpdateProjectMemberRole(pm *domain.ProjectMember) error + CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error IsProjectNamespaceExist(organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) - GetProjectNamespaces(organizationId string, projectId string, stackId string) ([]domain.ProjectNamespace, error) - GetProjectNamespace(organizationId string, projectId string, stackId string, projectNamespaceId string) (*domain.ProjectNamespace, error) - DeleteProjectNamespace(organizationId string, projectId string, stackId string, projectNamespaceId string) error + GetProjectNamespaces(organizationId string, projectId string) ([]domain.ProjectNamespace, error) + GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) + DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error } type ProjectUsecase struct { @@ -72,6 +77,23 @@ func (u *ProjectUsecase) GetProjects(organizationId string) (ps []domain.Project return ps, err } +func (u *ProjectUsecase) GetProject(organizationId string, projectId string) (*domain.Project, error) { + p, err := u.projectRepo.GetProjectById(organizationId, projectId) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to get projects.") + } + return p, err +} + +func (u *ProjectUsecase) UpdateProject(p *domain.Project) error { + if err := u.projectRepo.UpdateProject(p); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to update project.") + } + return nil +} + func (u *ProjectUsecase) GetProjectRole(id string) (*domain.ProjectRole, error) { pr, err := u.projectRepo.GetProjectRoleById(id) if err != nil { @@ -115,32 +137,34 @@ func (u *ProjectUsecase) AddProjectMember(pm *domain.ProjectMember) (string, err return projectMemberId, nil } -func (u *ProjectUsecase) GetProjectMemberById(projectMemberId string) (pm *domain.ProjectMember, err error) { +func (u *ProjectUsecase) GetProjectUser(projectUserId string) (*domain.ProjectUser, error) { + var uid uuid.UUID + uid, err := uuid.Parse(projectUserId) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to parse uuid to string") + } + + user, err := u.userRepository.GetByUuid(uid) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to retrieve user by id") + } + var pu domain.ProjectUser + if err = serializer.Map(user, &pu); err != nil { + log.Error(err) + return nil, err + } + return &pu, nil +} + +func (u *ProjectUsecase) GetProjectMember(projectMemberId string) (pm *domain.ProjectMember, err error) { pm, err = u.projectRepo.GetProjectMemberById(projectMemberId) if err != nil { log.Error(err) return pm, errors.Wrap(err, "Failed to get project member.") } - //var uid uuid.UUID - //uid, err = uuid.Parse(pm.ProjectUserId) - //if err != nil { - // log.Error(err) - // return pm, errors.Wrap(err, "Failed to parse uuid to string") - //} - - //user, err := u.userRepository.GetByUuid(pm.ProjectUserId) - //if err != nil { - // log.Error(err) - // return pm, errors.Wrap(err, "Failed to retrieve user by id") - //} - //var pu domain.ProjectUser - //if err = serializer.Map(user, &pu); err != nil { - // log.Error(err) - // return pm, err - //} - // - //pm.ProjectUser = pu return pm, nil } @@ -151,9 +175,6 @@ func (u *ProjectUsecase) GetProjectMembersByProjectId(projectId string) ([]domai return nil, errors.Wrap(err, "Failed to get project members.") } - //var uid uuid.UUID - //s - return pms, nil } @@ -165,21 +186,21 @@ func (u *ProjectUsecase) RemoveProjectMember(projectMemberId string) error { return nil } -func (u *ProjectUsecase) UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error { - if err := u.projectRepo.UpdateProjectMemberRole(projectMemberId, projectRoleId); err != nil { +func (u *ProjectUsecase) UpdateProjectMemberRole(pm *domain.ProjectMember) error { + + if err := u.projectRepo.UpdateProjectMemberRole(pm); err != nil { log.Error(err) return errors.Wrap(err, "Failed to remove project member to project.") } return nil } -func (u *ProjectUsecase) CreateProjectNamespace(pn *domain.ProjectNamespace) (string, error) { - projectNamespaceId, err := u.projectRepo.CreateProjectNamespace(pn) - if err != nil { +func (u *ProjectUsecase) CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error { + if err := u.projectRepo.CreateProjectNamespace(organizationId, pn); err != nil { log.Error(err) - return "", errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to create project namespace.") } - return projectNamespaceId, nil + return nil } func (u *ProjectUsecase) IsProjectNamespaceExist(organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) { @@ -196,8 +217,8 @@ func (u *ProjectUsecase) IsProjectNamespaceExist(organizationId string, projectI return exist, nil } -func (u *ProjectUsecase) GetProjectNamespaces(organizationId string, projectId string, stackId string) ([]domain.ProjectNamespace, error) { - pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, stackId) +func (u *ProjectUsecase) GetProjectNamespaces(organizationId string, projectId string) ([]domain.ProjectNamespace, error) { + pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) if err != nil { log.Error(err) return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") @@ -206,19 +227,19 @@ func (u *ProjectUsecase) GetProjectNamespaces(organizationId string, projectId s return pns, nil } -func (u *ProjectUsecase) GetProjectNamespace(organizationId string, projectId string, stackId string, projectNamespaceId string) (*domain.ProjectNamespace, error) { - pn, err := u.projectRepo.GetProjectNamespaceById(organizationId, projectId, stackId, projectNamespaceId) +func (u *ProjectUsecase) GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) { + pn, err := u.projectRepo.GetProjectNamespaceByPrimaryKey(organizationId, projectId, projectNamespace, stackId) if err != nil { log.Error(err) - return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") + return nil, errors.Wrap(err, "Failed to retrieve project namespace.") } return pn, nil } -func (u *ProjectUsecase) DeleteProjectNamespace(organizationId string, projectId string, stackId string, - projectNamespaceId string) error { - if err := u.projectRepo.DeleteProjectNamespace(organizationId, projectId, stackId, projectNamespaceId); err != nil { +func (u *ProjectUsecase) DeleteProjectNamespace(organizationId string, projectId string, + stackId string, projectNamespace string) error { + if err := u.projectRepo.DeleteProjectNamespace(organizationId, projectId, projectNamespace, stackId); err != nil { log.Error(err) return errors.Wrap(err, "Failed to delete project namespace.") } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 6eb5148b..0ce775e2 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -22,8 +22,12 @@ func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { return nil } +//func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { +// t.ID = uuid.New().String() +// return nil +//} + func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { - t.ID = uuid.New().String() return nil } @@ -39,38 +43,41 @@ type Project struct { ProjectNamespaces []ProjectNamespace `gorm:"foreignKey:ProjectId" json:"projectNamespaces,omitempty"` } -//type ProjectList struct { -// ID string `json:"id"` -// OrganizationId string `json:"organizationId"` -// Name string `json:"name"` -// Description string `json:"description"` -// ProjectMembers []struct { -// ID string `json:"id"` -// UserId string `json:"userId"` -// AccountId string `json:"accountId"` -// Name string `json:"name"` -// Email string `json:"email"` -// ProjectRoleId string `json:"projectId"` -// ProjectRoleName string `json:"projectRoleName"` -// CreatedAt time.Time `json:"createdAt"` -// UpdatedAt *time.Time `json:"updatedAt"` -// } `json:"projectMembers"` -// ProjectNamespaces []struct { -// ID string `json:"id"` -// StackId string `json:"stackId"` -// StackName string `json:"stackName"` -// Namespace string `json:"namespace"` -// Description string `json:"description"` -// Status string `json:"status"` -// CreatedAt time.Time `json:"createdAt"` -// UpdatedAt *time.Time `json:"updatedAt"` -// } `json:"projectNamespaces"` -// CreatedAt time.Time `json:"createdAt"` -// UpdatedAt *time.Time `json:"updatedAt"` -//} +type ProjectResponse struct { + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` + NamespaceCount int `json:"namespaceCount"` + AppCount int `json:"appCount"` + MemberCount int `json:"memberCount"` + CreatedAt time.Time `json:"createdAt"` +} type GetProjectsResponse struct { - Projects []Project `json:"projects"` + Projects []ProjectResponse `json:"projects"` +} + +type ProjectDetailResponse struct { + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + ProjectLeaderId string `json:"projectLeaderId"` + ProjectLeaderName string `json:"projectLeaderName"` + ProjectLeaderAccountId string `json:"projectLeaderAccountId"` + ProjectLeaderDepartment string `json:"projectLeaderDepartment"` + NamespaceCount int `json:"namespaceCount"` + AppCount int `json:"appCount"` + MemberCount int `json:"memberCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt *time.Time `json:"updatedAt"` +} + +type GetProjectResponse struct { + Project *ProjectDetailResponse `json:"project"` } type ProjectRole struct { @@ -98,28 +105,37 @@ func (ProjectUser) TableName() string { } type ProjectMember struct { - ID string `gorm:"primarykey" json:"id"` - ProjectId string `gorm:"not null" json:"projectId"` - ProjectUserId uuid.UUID `json:"projectUserId"` - ProjectUser ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID" json:"projectUser"` - ProjectRoleId string `json:"projectRoleId"` - ProjectRole ProjectRole `gorm:"foreignKey:ProjectRoleId" json:"projectRole"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` + ID string `gorm:"primarykey" json:"id"` + ProjectId string `gorm:"not null" json:"projectId"` + ProjectUserId uuid.UUID `json:"projectUserId"` + ProjectUser *ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectUser"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +type ProjectStack struct { + ID string `gorm:"primarykey" json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` +} + +func (ProjectStack) TableName() string { + return "clusters" } type ProjectNamespace struct { - ID string `gorm:"primarykey" json:"id"` - ProjectId string `gorm:"not null" json:"projectId"` - StackId string `gorm:"uniqueIndex:idx_stackid_namespace" json:"stackId"` - Namespace string `gorm:"uniqueIndex:idx_stackid_namespace" json:"namespace"` - StackName string `gorm:"-:all" json:"stackName,omitempty"` - Description string `json:"description,omitempty"` - Status string `json:"status,omitempty"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` + StackId string `gorm:"primarykey" json:"stackId"` + Namespace string `gorm:"primarykey" json:"namespace"` + Stack *ProjectStack `gorm:"foreignKey:StackId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"stack"` + ProjectId string `gorm:"not null" json:"projectId"` + Description string `json:"description,omitempty"` + Status string `json:"status,omitempty"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` } type CreateProjectRequest struct { @@ -130,7 +146,14 @@ type CreateProjectRequest struct { } type CreateProjectResponse struct { - Project Project `json:"project"` + ProjectId string `json:"projectId"` +} + +type UpdateProjectRequest struct { + Name string `json:"name" validate:"required"` + Description string `json:"description"` + //ProjectLeaderId string `json:"projectLeaderId"` + //ProjectRoleId string `json:"projectRoleId"` } type GetProjectRoleResponse struct { @@ -149,10 +172,6 @@ type AddProjectMemberRequest struct { ProjectMemberRequests []ProjectMemberRequest `json:"projectMembers"` } -type AddProjectMemberResponse struct { - ProjectMembers []ProjectMember `json:"projectMembers"` -} - type GetProjectMemberResponse struct { ProjectMember *ProjectMember `json:"projectMember"` } @@ -175,19 +194,35 @@ type UpdateProjectMemberRoleRequest struct { ProjectRoleId string `json:"projectRoleId"` } +type UpdateProjectMembersRoleRequest struct { + ProjectMemberRoleRequests []struct { + ProjectMemberId string `json:"projectMemberId"` + ProjectRoleId string `json:"projectRoleId"` + } `json:"projectMembers"` +} + type CreateProjectNamespaceRequest struct { + StackId string `json:"stackId"` Namespace string `json:"namespace"` Description string `json:"description"` } -type CreateProjectNamespaceResponse struct { - ProjectNamesapceId string `json:"projectNamespaceId"` +type ProjectNamespaceResponse struct { + StackId string `json:"stackId"` + Namespace string `json:"namespace"` + StackName string `json:"stackName"` + ProjectId string `json:"projectId"` + Description string `json:"description"` + Status string `json:"status"` + AppCount int `json:"appCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt *time.Time `json:"updatedAt"` } type GetProjectNamespacesResponse struct { - ProjectNamespaces []ProjectNamespace `json:"projectNamespaces"` + ProjectNamespaces []ProjectNamespaceResponse `json:"projectNamespaces"` } type GetProjectNamespaceResponse struct { - ProjectNamespace *ProjectNamespace `json:"projectNamespace"` + ProjectNamespace *ProjectNamespaceResponse `json:"projectNamespace"` } From b956bb63cc37853b67509369d42cc19204ba1151 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 7 Feb 2024 11:20:47 +0900 Subject: [PATCH 021/502] change swagger url to dev --- api/swagger/docs.go | 2 +- api/swagger/swagger.json | 2 +- api/swagger/swagger.yaml | 2 +- cmd/server/main.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 2a1391be..36557fe7 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -8166,7 +8166,7 @@ const docTemplate = `{ // SwaggerInfo holds exported Swagger Info so clients can modify it var SwaggerInfo = &swag.Spec{ Version: "1.0", - Host: "tks-api-ft.taco-cat.xyz", + Host: "tks-api-dev.taco-cat.xyz", BasePath: "/api/1.0/", Schemes: []string{}, Title: "tks-api service", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 1a1789a2..ae62399c 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -13,7 +13,7 @@ }, "version": "1.0" }, - "host": "tks-api-ft.taco-cat.xyz", + "host": "tks-api-dev.taco-cat.xyz", "basePath": "/api/1.0/", "paths": { "/app-groups": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 9a27aad1..48d62682 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2253,7 +2253,7 @@ definitions: text: type: string type: object -host: tks-api-ft.taco-cat.xyz +host: tks-api-dev.taco-cat.xyz info: contact: email: taekyu.kang@sk.com diff --git a/cmd/server/main.go b/cmd/server/main.go index effa4bcb..d1aae690 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -91,7 +91,7 @@ func init() { // @in header // @name Authorization -// @host tks-api-ft.taco-cat.xyz +// @host tks-api-dev.taco-cat.xyz // @BasePath /api/1.0/ func main() { log.Info("*** Arguments *** ") From 88eb85f39fa15c1f57626e8bb92f96e7a5632b17 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 7 Feb 2024 13:47:59 +0900 Subject: [PATCH 022/502] trivial. support dynamic swagger url --- cmd/server/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index d1aae690..e07e43d1 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/pflag" "github.com/spf13/viper" - _ "github.com/openinfradev/tks-api/api/swagger" + "github.com/openinfradev/tks-api/api/swagger" "github.com/openinfradev/tks-api/internal/database" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/mail" @@ -74,6 +74,7 @@ func init() { log.Error(err) } + swagger.SwaggerInfo.Host = viper.GetString("external-address") } // @title tks-api service From c5cdeec121e421ddfe42841ac74d58b91ef6f408 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 8 Feb 2024 10:56:28 +0900 Subject: [PATCH 023/502] trivial. minor fix --- cmd/server/main.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index e07e43d1..13d060cf 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "strconv" + "strings" "github.com/spf13/pflag" "github.com/spf13/viper" @@ -74,7 +75,13 @@ func init() { log.Error(err) } - swagger.SwaggerInfo.Host = viper.GetString("external-address") + address := viper.GetString("external-address") + arr := strings.Split(address, "//") + if len(arr) >= 2 { + address = arr[1] + } + + swagger.SwaggerInfo.Host = address } // @title tks-api service From 5b90ba9cbd90156a51625485d16e223f78c84eb2 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 15 Feb 2024 15:53:47 +0900 Subject: [PATCH 024/502] Modify the logic that manages the project --- api/swagger/docs.go | 100 +++++++++++------------------- api/swagger/swagger.json | 100 +++++++++++------------------- api/swagger/swagger.yaml | 75 +++++++++------------- internal/delivery/http/project.go | 96 ++++++++++++++++++---------- internal/repository/project.go | 18 +++++- internal/usecase/project.go | 10 +++ pkg/domain/project.go | 70 +++++++++++++-------- 7 files changed, 234 insertions(+), 235 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 36557fe7..56d16d79 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -5921,9 +5921,6 @@ const docTemplate = `{ }, "projectLeaderId": { "type": "string" - }, - "projectRoleId": { - "type": "string" } } }, @@ -6572,7 +6569,7 @@ const docTemplate = `{ "type": "object", "properties": { "projectMember": { - "$ref": "#/definitions/domain.ProjectMember" + "$ref": "#/definitions/domain.ProjectMemberResponse" } } }, @@ -6582,7 +6579,7 @@ const docTemplate = `{ "projectMembers": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectMember" + "$ref": "#/definitions/domain.ProjectMemberResponse" } } } @@ -7019,10 +7016,8 @@ const docTemplate = `{ "domain.ProjectDetailResponse": { "type": "object", "properties": { - "appCount": { - "type": "integer" - }, "createdAt": { + "description": "NamespaceCount int ` + "`" + `json:\"namespaceCount\"` + "`" + `\nAppCount int ` + "`" + `json:\"appCount\"` + "`" + `\nMemberCount int ` + "`" + `json:\"memberCount\"` + "`" + `", "type": "string" }, "description": { @@ -7031,15 +7026,9 @@ const docTemplate = `{ "id": { "type": "string" }, - "memberCount": { - "type": "integer" - }, "name": { "type": "string" }, - "namespaceCount": { - "type": "integer" - }, "organizationId": { "type": "string" }, @@ -7055,18 +7044,36 @@ const docTemplate = `{ "projectLeaderName": { "type": "string" }, + "projectRoleId": { + "type": "string" + }, + "projectRoleName": { + "type": "string" + }, "updatedAt": { "type": "string" } } }, - "domain.ProjectMember": { + "domain.ProjectMemberRequest": { "type": "object", + "required": [ + "projectRoleId", + "projectUserId" + ], "properties": { - "createdAt": { + "projectRoleId": { "type": "string" }, - "deletedAt": { + "projectUserId": { + "type": "string" + } + } + }, + "domain.ProjectMemberResponse": { + "type": "object", + "properties": { + "createdAt": { "type": "string" }, "id": { @@ -7075,35 +7082,29 @@ const docTemplate = `{ "projectId": { "type": "string" }, - "projectRole": { - "$ref": "#/definitions/domain.ProjectRole" - }, "projectRoleId": { "type": "string" }, - "projectUser": { - "$ref": "#/definitions/domain.ProjectUser" + "projectRoleName": { + "type": "string" }, - "projectUserId": { + "projectUserAccountId": { "type": "string" }, - "updatedAt": { + "projectUserDepartment": { "type": "string" - } - } - }, - "domain.ProjectMemberRequest": { - "type": "object", - "required": [ - "projectRoleId", - "projectUserId" - ], - "properties": { - "projectRoleId": { + }, + "projectUserEmail": { "type": "string" }, "projectUserId": { "type": "string" + }, + "projectUserName": { + "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -7198,35 +7199,6 @@ const docTemplate = `{ } } }, - "domain.ProjectUser": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "domain.RemoveProjectMemberRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index ae62399c..4f72dcfc 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -5914,9 +5914,6 @@ }, "projectLeaderId": { "type": "string" - }, - "projectRoleId": { - "type": "string" } } }, @@ -6565,7 +6562,7 @@ "type": "object", "properties": { "projectMember": { - "$ref": "#/definitions/domain.ProjectMember" + "$ref": "#/definitions/domain.ProjectMemberResponse" } } }, @@ -6575,7 +6572,7 @@ "projectMembers": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectMember" + "$ref": "#/definitions/domain.ProjectMemberResponse" } } } @@ -7012,10 +7009,8 @@ "domain.ProjectDetailResponse": { "type": "object", "properties": { - "appCount": { - "type": "integer" - }, "createdAt": { + "description": "NamespaceCount int `json:\"namespaceCount\"`\nAppCount int `json:\"appCount\"`\nMemberCount int `json:\"memberCount\"`", "type": "string" }, "description": { @@ -7024,15 +7019,9 @@ "id": { "type": "string" }, - "memberCount": { - "type": "integer" - }, "name": { "type": "string" }, - "namespaceCount": { - "type": "integer" - }, "organizationId": { "type": "string" }, @@ -7048,18 +7037,36 @@ "projectLeaderName": { "type": "string" }, + "projectRoleId": { + "type": "string" + }, + "projectRoleName": { + "type": "string" + }, "updatedAt": { "type": "string" } } }, - "domain.ProjectMember": { + "domain.ProjectMemberRequest": { "type": "object", + "required": [ + "projectRoleId", + "projectUserId" + ], "properties": { - "createdAt": { + "projectRoleId": { "type": "string" }, - "deletedAt": { + "projectUserId": { + "type": "string" + } + } + }, + "domain.ProjectMemberResponse": { + "type": "object", + "properties": { + "createdAt": { "type": "string" }, "id": { @@ -7068,35 +7075,29 @@ "projectId": { "type": "string" }, - "projectRole": { - "$ref": "#/definitions/domain.ProjectRole" - }, "projectRoleId": { "type": "string" }, - "projectUser": { - "$ref": "#/definitions/domain.ProjectUser" + "projectRoleName": { + "type": "string" }, - "projectUserId": { + "projectUserAccountId": { "type": "string" }, - "updatedAt": { + "projectUserDepartment": { "type": "string" - } - } - }, - "domain.ProjectMemberRequest": { - "type": "object", - "required": [ - "projectRoleId", - "projectUserId" - ], - "properties": { - "projectRoleId": { + }, + "projectUserEmail": { "type": "string" }, "projectUserId": { "type": "string" + }, + "projectUserName": { + "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -7191,35 +7192,6 @@ } } }, - "domain.ProjectUser": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "domain.RemoveProjectMemberRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 48d62682..7c59d3c0 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -781,8 +781,6 @@ definitions: type: string projectLeaderId: type: string - projectRoleId: - type: string required: - name type: object @@ -1214,13 +1212,13 @@ definitions: domain.GetProjectMemberResponse: properties: projectMember: - $ref: '#/definitions/domain.ProjectMember' + $ref: '#/definitions/domain.ProjectMemberResponse' type: object domain.GetProjectMembersResponse: properties: projectMembers: items: - $ref: '#/definitions/domain.ProjectMember' + $ref: '#/definitions/domain.ProjectMemberResponse' type: array type: object domain.GetProjectNamespaceResponse: @@ -1504,20 +1502,18 @@ definitions: type: object domain.ProjectDetailResponse: properties: - appCount: - type: integer createdAt: + description: |- + NamespaceCount int `json:"namespaceCount"` + AppCount int `json:"appCount"` + MemberCount int `json:"memberCount"` type: string description: type: string id: type: string - memberCount: - type: integer name: type: string - namespaceCount: - type: integer organizationId: type: string projectLeaderAccountId: @@ -1528,39 +1524,47 @@ definitions: type: string projectLeaderName: type: string + projectRoleId: + type: string + projectRoleName: + type: string updatedAt: type: string type: object - domain.ProjectMember: + domain.ProjectMemberRequest: properties: - createdAt: + projectRoleId: type: string - deletedAt: + projectUserId: + type: string + required: + - projectRoleId + - projectUserId + type: object + domain.ProjectMemberResponse: + properties: + createdAt: type: string id: type: string projectId: type: string - projectRole: - $ref: '#/definitions/domain.ProjectRole' projectRoleId: type: string - projectUser: - $ref: '#/definitions/domain.ProjectUser' - projectUserId: + projectRoleName: type: string - updatedAt: + projectUserAccountId: type: string - type: object - domain.ProjectMemberRequest: - properties: - projectRoleId: + projectUserDepartment: + type: string + projectUserEmail: type: string projectUserId: type: string - required: - - projectRoleId - - projectUserId + projectUserName: + type: string + updatedAt: + type: string type: object domain.ProjectNamespaceResponse: properties: @@ -1622,25 +1626,6 @@ definitions: updatedAt: type: string type: object - domain.ProjectUser: - properties: - accountId: - type: string - createdAt: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - updatedAt: - type: string - type: object domain.RemoveProjectMemberRequest: properties: projectMembers: diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 23fa384c..d0a72ea5 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -102,14 +102,23 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to parse uuid to string")) return } + + prs, err := p.usecase.GetProjectRoles(usecase.ProjectLeader) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to retrieve project-leader id")) + return + } + //Don't add ProjectUser Object because of Cascading pm := &domain.ProjectMember{ ProjectId: projectId, //ProjectUser: &domain.ProjectUser{ID: ProjectLeaderId}, //ProjectRole: &domain.ProjectRole{ID: projectReq.ProjectRoleId}, - ProjectUserId: ProjectLeaderId, - ProjectRoleId: projectReq.ProjectRoleId, - CreatedAt: now, + ProjectUserId: ProjectLeaderId, + ProjectRoleId: prs[0].ID, + IsProjectLeader: true, + CreatedAt: now, } projectMemberId, err := p.usecase.AddProjectMember(pm) @@ -119,22 +128,6 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } - //pr, err := p.usecase.GetProjectRoles(usecase.ProjectLeader) - //if err != nil { - // ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - // return - //} - // - //pms := make([]domain.ProjectMember, 0) - //pm.ID = projectMemberId - //pm.ProjectRole = pr[0] - //pms = append(pms, *pm) - // - //project.ProjectMembers = pms - //projectRes := domain.CreateProjectResponse{ - // Project: *project, - //} - out := domain.CreateProjectResponse{ProjectId: projectId} ResponseJSON(w, r, http.StatusOK, out) @@ -229,7 +222,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { return } - project, err := p.usecase.GetProject(organizationId, projectId) + project, err := p.usecase.GetProjectWithLeader(organizationId, projectId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to retrieve project", err) ErrorJSON(w, r, err) @@ -243,13 +236,14 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { } var projectLeaderId, projectLeaderName, projectLeaderAccountId, projectLeaderDepartment string + var projectRoleId, projectRoleName string for _, pu := range project.ProjectMembers { - if pu.ProjectRole.Name == "project-leader" { - projectLeaderId = pu.ProjectUser.ID.String() - projectLeaderName = pu.ProjectUser.Name - projectLeaderAccountId = pu.ProjectUser.AccountId - projectLeaderDepartment = pu.ProjectUser.Department - } + projectLeaderId = pu.ProjectUser.ID.String() + projectLeaderName = pu.ProjectUser.Name + projectLeaderAccountId = pu.ProjectUser.AccountId + projectLeaderDepartment = pu.ProjectUser.Department + projectRoleId = pu.ProjectRole.ID + projectRoleName = pu.ProjectRole.Name } var pdr domain.ProjectDetailResponse @@ -262,10 +256,12 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { pdr.ProjectLeaderName = projectLeaderName pdr.ProjectLeaderAccountId = projectLeaderAccountId pdr.ProjectLeaderDepartment = projectLeaderDepartment - pdr.NamespaceCount = len(project.ProjectNamespaces) - pdr.MemberCount = len(project.ProjectMembers) - //TODO implement AppCount - pdr.AppCount = 0 + pdr.ProjectRoleId = projectRoleId + pdr.ProjectRoleName = projectRoleName + //pdr.NamespaceCount = len(project.ProjectNamespaces) + //pdr.MemberCount = len(project.ProjectMembers) + ////TODO implement AppCount + //pdr.AppCount = 0 out.Project = &pdr ResponseJSON(w, r, http.StatusOK, out) @@ -315,8 +311,8 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { project.Name = projectReq.Name project.Description = projectReq.Description project.UpdatedAt = &now - project.ProjectNamespaces = nil - project.ProjectMembers = nil + //project.ProjectNamespaces = nil + //project.ProjectMembers = nil if err := p.usecase.UpdateProject(project); err != nil { ErrorJSON(w, r, err) @@ -537,7 +533,21 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) return } - out := domain.GetProjectMemberResponse{ProjectMember: pm} + pmr := &domain.ProjectMemberResponse{ + ID: pm.ID, + ProjectId: pm.ProjectId, + ProjectUserId: pm.ProjectUser.ID.String(), + ProjectUserName: pm.ProjectUser.Name, + ProjectUserAccountId: pm.ProjectUser.AccountId, + ProjectUserEmail: pm.ProjectUser.Email, + ProjectUserDepartment: pm.ProjectUser.Department, + ProjectRoleId: pm.ProjectRole.ID, + ProjectRoleName: pm.ProjectRole.Name, + CreatedAt: pm.CreatedAt, + UpdatedAt: pm.UpdatedAt, + } + + out := domain.GetProjectMemberResponse{ProjectMember: pmr} if pm == nil { ResponseJSON(w, r, http.StatusNotFound, out) return @@ -580,7 +590,25 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request return } - out := domain.GetProjectMembersResponse{ProjectMembers: pms} + pmrs := make([]domain.ProjectMemberResponse, 0) + for _, pm := range pms { + pmr := domain.ProjectMemberResponse{ + ID: pm.ID, + ProjectId: pm.ProjectId, + ProjectUserId: pm.ProjectUser.ID.String(), + ProjectUserName: pm.ProjectUser.Name, + ProjectUserAccountId: pm.ProjectUser.AccountId, + ProjectUserEmail: pm.ProjectUser.Email, + ProjectUserDepartment: pm.ProjectUser.Department, + ProjectRoleId: pm.ProjectRole.ID, + ProjectRoleName: pm.ProjectRole.Name, + CreatedAt: pm.CreatedAt, + UpdatedAt: pm.UpdatedAt, + } + pmrs = append(pmrs, pmr) + } + + out := domain.GetProjectMembersResponse{ProjectMembers: pmrs} ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/repository/project.go b/internal/repository/project.go index dfa6293f..ef999779 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -11,6 +11,7 @@ type IProjectRepository interface { CreateProject(p *domain.Project) (string, error) GetProjects(organizationId string) ([]domain.Project, error) GetProjectById(organizationId string, projectId string) (*domain.Project, error) + GetProjectByIdAndLeader(organizationId string, projectId string) (*domain.Project, error) UpdateProject(p *domain.Project) error GetAllProjectRoles() ([]domain.ProjectRole, error) GetProjectRoleByName(name string) (*domain.ProjectRole, error) @@ -67,8 +68,23 @@ func (r *ProjectRepository) GetProjects(organizationId string) (ps []domain.Proj } func (r *ProjectRepository) GetProjectById(organizationId string, projectId string) (p *domain.Project, err error) { + res := r.db.Limit(1).Where("organization_id = ? and id = ?", organizationId, projectId).First(&p) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return p, nil +} + +func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, projectId string) (p *domain.Project, err error) { res := r.db.Limit(1).Where("organization_id = ? and id = ?", organizationId, projectId). - Preload("ProjectMembers"). + Limit(1).Preload("ProjectMembers", "is_project_leader = ?", true). Preload("ProjectMembers.ProjectRole"). Preload("ProjectMembers.ProjectUser"). First(&p) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 39fd33b5..6c9e8a36 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -21,6 +21,7 @@ type IProjectUsecase interface { CreateProject(*domain.Project) (string, error) GetProjects(organizationId string) ([]domain.Project, error) GetProject(organizationId string, projectId string) (*domain.Project, error) + GetProjectWithLeader(organizationId string, projectId string) (*domain.Project, error) UpdateProject(p *domain.Project) error GetProjectRole(id string) (*domain.ProjectRole, error) GetProjectRoles(int) ([]domain.ProjectRole, error) @@ -86,6 +87,15 @@ func (u *ProjectUsecase) GetProject(organizationId string, projectId string) (*d return p, err } +func (u *ProjectUsecase) GetProjectWithLeader(organizationId string, projectId string) (*domain.Project, error) { + p, err := u.projectRepo.GetProjectByIdAndLeader(organizationId, projectId) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to get projects.") + } + return p, err +} + func (u *ProjectUsecase) UpdateProject(p *domain.Project) error { if err := u.projectRepo.UpdateProject(p); err != nil { log.Error(err) diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 0ce775e2..1faf726f 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -39,8 +39,8 @@ type Project struct { CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` - ProjectMembers []ProjectMember `gorm:"foreignKey:ProjectId" json:"projectMembers,omitempty"` - ProjectNamespaces []ProjectNamespace `gorm:"foreignKey:ProjectId" json:"projectNamespaces,omitempty"` + ProjectMembers []ProjectMember `gorm:"foreignKey:ProjectId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectMembers,omitempty"` + ProjectNamespaces []ProjectNamespace `gorm:"foreignKey:ProjectId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectNamespaces,omitempty"` } type ProjectResponse struct { @@ -61,19 +61,21 @@ type GetProjectsResponse struct { } type ProjectDetailResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - ProjectLeaderId string `json:"projectLeaderId"` - ProjectLeaderName string `json:"projectLeaderName"` - ProjectLeaderAccountId string `json:"projectLeaderAccountId"` - ProjectLeaderDepartment string `json:"projectLeaderDepartment"` - NamespaceCount int `json:"namespaceCount"` - AppCount int `json:"appCount"` - MemberCount int `json:"memberCount"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt *time.Time `json:"updatedAt"` + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + ProjectLeaderId string `json:"projectLeaderId"` + ProjectLeaderName string `json:"projectLeaderName"` + ProjectLeaderAccountId string `json:"projectLeaderAccountId"` + ProjectLeaderDepartment string `json:"projectLeaderDepartment"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` + //NamespaceCount int `json:"namespaceCount"` + //AppCount int `json:"appCount"` + //MemberCount int `json:"memberCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt *time.Time `json:"updatedAt"` } type GetProjectResponse struct { @@ -105,15 +107,16 @@ func (ProjectUser) TableName() string { } type ProjectMember struct { - ID string `gorm:"primarykey" json:"id"` - ProjectId string `gorm:"not null" json:"projectId"` - ProjectUserId uuid.UUID `json:"projectUserId"` - ProjectUser *ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectUser"` - ProjectRoleId string `json:"projectRoleId"` - ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` + ID string `gorm:"primarykey" json:"id"` + ProjectId string `gorm:"not null" json:"projectId"` + ProjectUserId uuid.UUID `json:"projectUserId"` + ProjectUser *ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectUser"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` + IsProjectLeader bool `gorm:"default:false" json:"projectLeader"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` } type ProjectStack struct { @@ -142,7 +145,6 @@ type CreateProjectRequest struct { Name string `json:"name" validate:"required"` Description string `json:"description"` ProjectLeaderId string `json:"projectLeaderId"` - ProjectRoleId string `json:"projectRoleId"` } type CreateProjectResponse struct { @@ -172,12 +174,26 @@ type AddProjectMemberRequest struct { ProjectMemberRequests []ProjectMemberRequest `json:"projectMembers"` } +type ProjectMemberResponse struct { + ID string `json:"id"` + ProjectId string `json:"projectId"` + ProjectUserId string `json:"projectUserId"` + ProjectUserName string `json:"projectUserName"` + ProjectUserAccountId string `json:"projectUserAccountId"` + ProjectUserEmail string `json:"projectUserEmail"` + ProjectUserDepartment string `json:"projectUserDepartment"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt *time.Time `json:"updatedAt"` +} + type GetProjectMemberResponse struct { - ProjectMember *ProjectMember `json:"projectMember"` + ProjectMember *ProjectMemberResponse `json:"projectMember"` } type GetProjectMembersResponse struct { - ProjectMembers []ProjectMember `json:"projectMembers"` + ProjectMembers []ProjectMemberResponse `json:"projectMembers"` } type RemoveProjectMemberRequest struct { From 4b06b584555f9fa6e172761d08820993728f02ba Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 16 Feb 2024 13:14:52 +0900 Subject: [PATCH 025/502] trivial. swaggo update to v1.16.3 --- Dockerfile | 2 +- api/swagger/docs.go | 159 +++++++++++++++++++++++++++++++++++++-- api/swagger/swagger.json | 154 +++++++++++++++++++++++++++++++++++-- api/swagger/swagger.yaml | 152 +++++++++++++++++++++++++++++++++---- go.mod | 16 ++-- go.sum | 34 ++++----- 6 files changed, 463 insertions(+), 54 deletions(-) diff --git a/Dockerfile b/Dockerfile index 68d504c1..b1971e88 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Build - backend FROM --platform=linux/amd64 docker.io/library/golang:1.18-buster AS backend-build RUN DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata -RUN wget https://github.com/swaggo/swag/releases/download/v1.8.5/swag_1.8.5_Linux_x86_64.tar.gz -O - | tar -xz -C /tmp && cp /tmp/swag /usr/local/bin +RUN wget https://github.com/swaggo/swag/releases/download/v1.16.3/swag_1.16.3_Linux_amd64.tar.gz -O - | tar -xz -C /tmp && cp /tmp/swag /usr/local/bin WORKDIR /app/backend COPY ./ . diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 56d16d79..748e8ecb 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1,5 +1,4 @@ -// Package swagger GENERATED BY SWAG; DO NOT EDIT -// This file was generated by swaggo/swag +// Package swagger Code generated by swaggo/swag. DO NOT EDIT package swagger import "github.com/swaggo/swag" @@ -77,6 +76,7 @@ const docTemplate = `{ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -582,6 +582,7 @@ const docTemplate = `{ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -955,6 +956,7 @@ const docTemplate = `{ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -1181,6 +1183,7 @@ const docTemplate = `{ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -1415,6 +1418,7 @@ const docTemplate = `{ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -1988,6 +1992,7 @@ const docTemplate = `{ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -4198,6 +4203,7 @@ const docTemplate = `{ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -4568,6 +4574,7 @@ const docTemplate = `{ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -4896,7 +4903,7 @@ const docTemplate = `{ "type": "object", "properties": { "appGroupType": { - "type": "integer" + "$ref": "#/definitions/domain.AppGroupType" }, "clusterId": { "type": "string" @@ -4917,7 +4924,7 @@ const docTemplate = `{ "type": "string" }, "status": { - "type": "integer" + "$ref": "#/definitions/domain.AppGroupStatus" }, "statusDesc": { "type": "string" @@ -4933,6 +4940,40 @@ const docTemplate = `{ } } }, + "domain.AppGroupStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "x-enum-varnames": [ + "AppGroupStatus_PENDING", + "AppGroupStatus_INSTALLING", + "AppGroupStatus_RUNNING", + "AppGroupStatus_DELETING", + "AppGroupStatus_DELETED", + "AppGroupStatus_INSTALL_ERROR", + "AppGroupStatus_DELETE_ERROR" + ] + }, + "domain.AppGroupType": { + "type": "integer", + "enum": [ + 0, + 1, + 2 + ], + "x-enum-varnames": [ + "AppGroupType_UNSPECIFIED", + "AppGroupType_LMA", + "AppGroupType_SERVICE_MESH" + ] + }, "domain.AppServeApp": { "type": "object", "properties": { @@ -5107,7 +5148,7 @@ const docTemplate = `{ "type": "string" }, "applicationType": { - "type": "integer" + "$ref": "#/definitions/domain.ApplicationType" }, "createdAt": { "type": "string" @@ -5126,6 +5167,35 @@ const docTemplate = `{ } } }, + "domain.ApplicationType": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "x-enum-varnames": [ + "ApplicationType_UNSPECIFIED", + "ApplicationType_THANOS", + "ApplicationType_PROMETHEUS", + "ApplicationType_GRAFANA", + "ApplicationType_KIALI", + "ApplicationType_KIBANA", + "ApplicationType_ELASTICSERCH", + "ApplicationType_CLOUD_CONSOLE", + "ApplicationType_HORIZON", + "ApplicationType_JAEGER", + "ApplicationType_KUBERNETES_DASHBOARD" + ] + }, "domain.Axis": { "type": "object", "properties": { @@ -5241,7 +5311,7 @@ const docTemplate = `{ "type": "string" }, "status": { - "type": "integer" + "$ref": "#/definitions/domain.CloudAccountStatus" }, "statusDesc": { "type": "string" @@ -5304,6 +5374,27 @@ const docTemplate = `{ } } }, + "domain.CloudAccountStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "x-enum-varnames": [ + "CloudAccountStatus_PENDING", + "CloudAccountStatus_CREATING", + "CloudAccountStatus_CREATED", + "CloudAccountStatus_DELETING", + "CloudAccountStatus_DELETED", + "CloudAccountStatus_CREATE_ERROR", + "CloudAccountStatus_DELETE_ERROR" + ] + }, "domain.Cluster": { "type": "object", "properties": { @@ -5368,7 +5459,7 @@ const docTemplate = `{ "type": "string" }, "status": { - "type": "integer" + "$ref": "#/definitions/domain.ClusterStatus" }, "statusDesc": { "type": "string" @@ -5597,6 +5688,33 @@ const docTemplate = `{ } } }, + "domain.ClusterStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "x-enum-varnames": [ + "ClusterStatus_PENDING", + "ClusterStatus_INSTALLING", + "ClusterStatus_RUNNING", + "ClusterStatus_DELETING", + "ClusterStatus_DELETED", + "ClusterStatus_INSTALL_ERROR", + "ClusterStatus_DELETE_ERROR", + "ClusterStatus_BOOTSTRAPPING", + "ClusterStatus_BOOTSTRAPPED", + "ClusterStatus_BOOTSTRAP_ERROR" + ] + }, "domain.CommonProjectResponse": { "type": "object", "properties": { @@ -6948,7 +7066,7 @@ const docTemplate = `{ "type": "string" }, "status": { - "type": "integer" + "$ref": "#/definitions/domain.OrganizationStatus" }, "statusDesc": { "type": "string" @@ -6958,6 +7076,29 @@ const docTemplate = `{ } } }, + "domain.OrganizationStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "x-enum-varnames": [ + "OrganizationStatus_PENDING", + "OrganizationStatus_CREATE", + "OrganizationStatus_CREATING", + "OrganizationStatus_CREATED", + "OrganizationStatus_DELETE", + "OrganizationStatus_DELETING", + "OrganizationStatus_DELETED", + "OrganizationStatus_ERROR" + ] + }, "domain.PaginationResponse": { "type": "object", "properties": { @@ -8145,6 +8286,8 @@ var SwaggerInfo = &swag.Spec{ Description: "This is backend api service for tks platform", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", } func init() { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 4f72dcfc..d273cdb0 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -70,6 +70,7 @@ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -575,6 +576,7 @@ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -948,6 +950,7 @@ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -1174,6 +1177,7 @@ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -1408,6 +1412,7 @@ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -1981,6 +1986,7 @@ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -4191,6 +4197,7 @@ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -4561,6 +4568,7 @@ "items": { "type": "string" }, + "collectionFormat": "csv", "description": "filters", "name": "filters", "in": "query" @@ -4889,7 +4897,7 @@ "type": "object", "properties": { "appGroupType": { - "type": "integer" + "$ref": "#/definitions/domain.AppGroupType" }, "clusterId": { "type": "string" @@ -4910,7 +4918,7 @@ "type": "string" }, "status": { - "type": "integer" + "$ref": "#/definitions/domain.AppGroupStatus" }, "statusDesc": { "type": "string" @@ -4926,6 +4934,40 @@ } } }, + "domain.AppGroupStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "x-enum-varnames": [ + "AppGroupStatus_PENDING", + "AppGroupStatus_INSTALLING", + "AppGroupStatus_RUNNING", + "AppGroupStatus_DELETING", + "AppGroupStatus_DELETED", + "AppGroupStatus_INSTALL_ERROR", + "AppGroupStatus_DELETE_ERROR" + ] + }, + "domain.AppGroupType": { + "type": "integer", + "enum": [ + 0, + 1, + 2 + ], + "x-enum-varnames": [ + "AppGroupType_UNSPECIFIED", + "AppGroupType_LMA", + "AppGroupType_SERVICE_MESH" + ] + }, "domain.AppServeApp": { "type": "object", "properties": { @@ -5100,7 +5142,7 @@ "type": "string" }, "applicationType": { - "type": "integer" + "$ref": "#/definitions/domain.ApplicationType" }, "createdAt": { "type": "string" @@ -5119,6 +5161,35 @@ } } }, + "domain.ApplicationType": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "x-enum-varnames": [ + "ApplicationType_UNSPECIFIED", + "ApplicationType_THANOS", + "ApplicationType_PROMETHEUS", + "ApplicationType_GRAFANA", + "ApplicationType_KIALI", + "ApplicationType_KIBANA", + "ApplicationType_ELASTICSERCH", + "ApplicationType_CLOUD_CONSOLE", + "ApplicationType_HORIZON", + "ApplicationType_JAEGER", + "ApplicationType_KUBERNETES_DASHBOARD" + ] + }, "domain.Axis": { "type": "object", "properties": { @@ -5234,7 +5305,7 @@ "type": "string" }, "status": { - "type": "integer" + "$ref": "#/definitions/domain.CloudAccountStatus" }, "statusDesc": { "type": "string" @@ -5297,6 +5368,27 @@ } } }, + "domain.CloudAccountStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "x-enum-varnames": [ + "CloudAccountStatus_PENDING", + "CloudAccountStatus_CREATING", + "CloudAccountStatus_CREATED", + "CloudAccountStatus_DELETING", + "CloudAccountStatus_DELETED", + "CloudAccountStatus_CREATE_ERROR", + "CloudAccountStatus_DELETE_ERROR" + ] + }, "domain.Cluster": { "type": "object", "properties": { @@ -5361,7 +5453,7 @@ "type": "string" }, "status": { - "type": "integer" + "$ref": "#/definitions/domain.ClusterStatus" }, "statusDesc": { "type": "string" @@ -5590,6 +5682,33 @@ } } }, + "domain.ClusterStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "x-enum-varnames": [ + "ClusterStatus_PENDING", + "ClusterStatus_INSTALLING", + "ClusterStatus_RUNNING", + "ClusterStatus_DELETING", + "ClusterStatus_DELETED", + "ClusterStatus_INSTALL_ERROR", + "ClusterStatus_DELETE_ERROR", + "ClusterStatus_BOOTSTRAPPING", + "ClusterStatus_BOOTSTRAPPED", + "ClusterStatus_BOOTSTRAP_ERROR" + ] + }, "domain.CommonProjectResponse": { "type": "object", "properties": { @@ -6941,7 +7060,7 @@ "type": "string" }, "status": { - "type": "integer" + "$ref": "#/definitions/domain.OrganizationStatus" }, "statusDesc": { "type": "string" @@ -6951,6 +7070,29 @@ } } }, + "domain.OrganizationStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "x-enum-varnames": [ + "OrganizationStatus_PENDING", + "OrganizationStatus_CREATE", + "OrganizationStatus_CREATING", + "OrganizationStatus_CREATED", + "OrganizationStatus_DELETE", + "OrganizationStatus_DELETING", + "OrganizationStatus_DELETED", + "OrganizationStatus_ERROR" + ] + }, "domain.PaginationResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 7c59d3c0..2c54f7f7 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -91,7 +91,7 @@ definitions: domain.AppGroupResponse: properties: appGroupType: - type: integer + $ref: '#/definitions/domain.AppGroupType' clusterId: type: string createdAt: @@ -105,7 +105,7 @@ definitions: name: type: string status: - type: integer + $ref: '#/definitions/domain.AppGroupStatus' statusDesc: type: string updatedAt: @@ -115,6 +115,34 @@ definitions: workflowId: type: string type: object + domain.AppGroupStatus: + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + type: integer + x-enum-varnames: + - AppGroupStatus_PENDING + - AppGroupStatus_INSTALLING + - AppGroupStatus_RUNNING + - AppGroupStatus_DELETING + - AppGroupStatus_DELETED + - AppGroupStatus_INSTALL_ERROR + - AppGroupStatus_DELETE_ERROR + domain.AppGroupType: + enum: + - 0 + - 1 + - 2 + type: integer + x-enum-varnames: + - AppGroupType_UNSPECIFIED + - AppGroupType_LMA + - AppGroupType_SERVICE_MESH domain.AppServeApp: properties: appServeAppTasks: @@ -240,7 +268,7 @@ definitions: appGroupId: type: string applicationType: - type: integer + $ref: '#/definitions/domain.ApplicationType' createdAt: type: string endpoint: @@ -252,6 +280,32 @@ definitions: updatedAt: type: string type: object + domain.ApplicationType: + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + type: integer + x-enum-varnames: + - ApplicationType_UNSPECIFIED + - ApplicationType_THANOS + - ApplicationType_PROMETHEUS + - ApplicationType_GRAFANA + - ApplicationType_KIALI + - ApplicationType_KIBANA + - ApplicationType_ELASTICSERCH + - ApplicationType_CLOUD_CONSOLE + - ApplicationType_HORIZON + - ApplicationType_JAEGER + - ApplicationType_KUBERNETES_DASHBOARD domain.Axis: properties: data: @@ -327,7 +381,7 @@ definitions: sessionToken: type: string status: - type: integer + $ref: '#/definitions/domain.CloudAccountStatus' statusDesc: type: string updatedAt: @@ -368,6 +422,24 @@ definitions: updator: $ref: '#/definitions/domain.SimpleUserResponse' type: object + domain.CloudAccountStatus: + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + type: integer + x-enum-varnames: + - CloudAccountStatus_PENDING + - CloudAccountStatus_CREATING + - CloudAccountStatus_CREATED + - CloudAccountStatus_DELETING + - CloudAccountStatus_DELETED + - CloudAccountStatus_CREATE_ERROR + - CloudAccountStatus_DELETE_ERROR domain.Cluster: properties: byoClusterEndpointHost: @@ -411,7 +483,7 @@ definitions: stackTemplateId: type: string status: - type: integer + $ref: '#/definitions/domain.ClusterStatus' statusDesc: type: string updatedAt: @@ -561,6 +633,30 @@ definitions: tksUserNodeType: type: string type: object + domain.ClusterStatus: + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + type: integer + x-enum-varnames: + - ClusterStatus_PENDING + - ClusterStatus_INSTALLING + - ClusterStatus_RUNNING + - ClusterStatus_DELETING + - ClusterStatus_DELETED + - ClusterStatus_INSTALL_ERROR + - ClusterStatus_DELETE_ERROR + - ClusterStatus_BOOTSTRAPPING + - ClusterStatus_BOOTSTRAPPED + - ClusterStatus_BOOTSTRAP_ERROR domain.CommonProjectResponse: properties: result: @@ -1458,12 +1554,32 @@ definitions: primaryClusterId: type: string status: - type: integer + $ref: '#/definitions/domain.OrganizationStatus' statusDesc: type: string updatedAt: type: string type: object + domain.OrganizationStatus: + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + type: integer + x-enum-varnames: + - OrganizationStatus_PENDING + - OrganizationStatus_CREATE + - OrganizationStatus_CREATING + - OrganizationStatus_CREATED + - OrganizationStatus_DELETE + - OrganizationStatus_DELETING + - OrganizationStatus_DELETED + - OrganizationStatus_ERROR domain.PaginationResponse: properties: filters: @@ -2297,7 +2413,8 @@ paths: in: query name: sortOrder type: string - - description: filters + - collectionFormat: csv + description: filters in: query items: type: string @@ -2605,7 +2722,8 @@ paths: in: query name: sortOrder type: string - - description: filters + - collectionFormat: csv + description: filters in: query items: type: string @@ -2837,7 +2955,8 @@ paths: in: query name: sortOrder type: string - - description: filters + - collectionFormat: csv + description: filters in: query items: type: string @@ -2980,7 +3099,8 @@ paths: in: query name: sortOrder type: string - - description: filters + - collectionFormat: csv + description: filters in: query items: type: string @@ -3129,7 +3249,8 @@ paths: in: query name: sortOrder type: string - - description: filters + - collectionFormat: csv + description: filters in: query items: type: string @@ -3495,7 +3616,8 @@ paths: in: query name: sortOrder type: string - - description: filters + - collectionFormat: csv + description: filters in: query items: type: string @@ -4912,7 +5034,8 @@ paths: in: query name: sortOrder type: string - - description: filters + - collectionFormat: csv + description: filters in: query items: type: string @@ -5149,7 +5272,8 @@ paths: in: query name: sortOrder type: string - - description: filters + - collectionFormat: csv + description: filters in: query items: type: string diff --git a/go.mod b/go.mod index d9b1afe1..f7864ad4 100644 --- a/go.mod +++ b/go.mod @@ -30,12 +30,12 @@ require ( github.com/sirupsen/logrus v1.9.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.12.0 - github.com/swaggo/http-swagger v1.3.3 - github.com/swaggo/swag v1.8.5 + github.com/swaggo/http-swagger v1.3.4 + github.com/swaggo/swag v1.16.3 github.com/thoas/go-funk v0.9.3 github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.4.0 - golang.org/x/crypto v0.9.0 - golang.org/x/net v0.10.0 + golang.org/x/crypto v0.14.0 + golang.org/x/net v0.17.0 golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 @@ -113,11 +113,11 @@ require ( github.com/stretchr/testify v1.8.2 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/tools v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index f9e03911..5c2b7b8e 100644 --- a/go.sum +++ b/go.sum @@ -599,10 +599,10 @@ github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe h1:K8pHPVoTgxFJt1lXuIzzOX7zZhZFldJQK/CgKx9BFIc= github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= -github.com/swaggo/http-swagger v1.3.3 h1:Hu5Z0L9ssyBLofaama21iYaF2VbWyA8jdohaaCGpHsc= -github.com/swaggo/http-swagger v1.3.3/go.mod h1:sE+4PjD89IxMPm77FnkDz0sdO+p5lbXzrVWT6OTVVGo= -github.com/swaggo/swag v1.8.5 h1:7NgtfXsXE+jrcOwRyiftGKW7Ppydj7tZiVenuRf1fE4= -github.com/swaggo/swag v1.8.5/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg= +github.com/swaggo/http-swagger v1.3.4 h1:q7t/XLx0n15H1Q9/tk3Y9L4n210XzJF5WtnDX64a5ww= +github.com/swaggo/http-swagger v1.3.4/go.mod h1:9dAh0unqMBAlbp1uE2Uc2mQTxNMU/ha4UbucIg1MFkQ= +github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= +github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw= github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -671,8 +671,8 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -709,7 +709,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -762,8 +762,8 @@ golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -864,14 +864,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -882,8 +882,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -952,8 +952,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From b95f78a123eedcd6105ddcb2c70069087fc7e46f Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Wed, 14 Feb 2024 13:24:39 +0900 Subject: [PATCH 026/502] implement tks-issues-1038 - make appserving belongs to project - add new APIs to return task list and detail --- internal/delivery/http/app-serve-app.go | 235 +++++++++++++++++++----- internal/repository/app-serve-app.go | 73 ++++++-- internal/usecase/app-serve-app.go | 20 ++ pkg/domain/app-serve-app.go | 9 + pkg/httpErrors/errorCode.go | 1 + 5 files changed, 280 insertions(+), 58 deletions(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 2510a768..bfc92b0e 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -84,16 +84,24 @@ func NewAppServeAppHandler(h usecase.IAppServeAppUsecase) *AppServeAppHandler { // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param object body domain.CreateAppServeAppRequest true "Request body to create app" // @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps [post] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [post] // @Security JWT func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] log.Debugf("organizationId = [%v]\n", organizationId) if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid projectId"), "C_INVALID_PROJECT_ID", "")) return } @@ -116,6 +124,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re now := time.Now() app.OrganizationId = organizationId + app.ProjectId = projectId app.EndpointUrl = "N/A" app.PreviewEndpointUrl = "N/A" app.Status = "PREPARING" @@ -151,29 +160,29 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re return } - // Create namespace if it's not given by user - if len(strings.TrimSpace(app.Namespace)) == 0 { - // Check if the new namespace is already used in the target cluster - ns := "" - nsExist := true - for nsExist { - // Generate unique namespace based on name and random number - src := rand.NewSource(time.Now().UnixNano()) - r1 := rand.New(src) - ns = fmt.Sprintf("%s-%s", app.Name, strconv.Itoa(r1.Intn(10000))) + // Create namespace if it's not given by user + if len(strings.TrimSpace(app.Namespace)) == 0 { + // Check if the new namespace is already used in the target cluster + ns := "" + nsExist := true + for nsExist { + // Generate unique namespace based on name and random number + src := rand.NewSource(time.Now().UnixNano()) + r1 := rand.New(src) + ns = fmt.Sprintf("%s-%s", app.Name, strconv.Itoa(r1.Intn(10000))) - nsExist, err = h.usecase.IsAppServeAppNamespaceExist(app.TargetClusterId, ns) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - } + nsExist, err = h.usecase.IsAppServeAppNamespaceExist(app.TargetClusterId, ns) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } - log.Infof("Created new namespace: %s", ns) - app.Namespace = ns - } else { - log.Infof("Using existing namespace: %s", app.Namespace) - } + log.Infof("Created new namespace: %s", ns) + app.Namespace = ns + } else { + log.Infof("Using existing namespace: %s", app.Namespace) + } // Validate port param for springboot app if app.AppType == "springboot" { @@ -212,6 +221,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param showAll query boolean false "Show all apps including deleted apps" // @Param limit query string false "pageSize" // @Param page query string false "pageNumber" @@ -219,7 +229,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.AppServeApp -// @Router /organizations/{organizationId}/app-serve-apps [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -273,9 +283,10 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} domain.GetAppServeAppResponse -// @Router /organizations/{organizationId}/app-serve-apps/{appId} [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -317,7 +328,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque var out domain.GetAppServeAppResponse out.AppServeApp = *app - out.Stages = makeStages(app) + //out.Stages = makeStages(app) ResponseJSON(w, r, http.StatusOK, out) } @@ -329,9 +340,10 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} domain.GetAppServeAppTaskResponse -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/latest-task [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -372,9 +384,10 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param stackId query string true "Stack ID" // @Success 200 {object} int64 -// @Router /organizations/{organizationId}/app-serve-apps/count [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/count [get] // @Security JWT func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -402,13 +415,135 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. ResponseJSON(w, r, http.StatusOK, numApps) } -func makeStages(app *domain.AppServeApp) []domain.StageResponse { +// New func +// GetAppServeAppTasksByAppId godoc +// @Tags AppServeApps +// @Summary Get appServeAppTask list +// @Description Get appServeAppTask list by giving params +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param sortColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} []domain.AppServeApp +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] +// @Security JWT +func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId: %s", organizationId), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + appId, ok := vars["appId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid appId: %s", appId), "C_INVALID_ASA_ID", "")) + return + } + + urlParams := r.URL.Query() + pg, err := pagination.NewPagination(&urlParams) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + tasks, err := h.usecase.GetAppServeAppTasks(appId, pg) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get app-serve-app-tasks ", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetAppServeAppTasksResponse + out.AppServeAppTasks = tasks + + if err := serializer.Map(*pg, &out.Pagination); err != nil { + log.InfoWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetAppServeAppTaskDetail godoc +// @Tags AppServeApps +// @Summary Get task detail from appServeApp +// @Description Get task detail from appServeApp +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Param taskId path string true "Task ID" +// @Success 200 {object} domain.GetAppServeAppTaskResponse +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId} [get] +// @Security JWT +func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId: [%s]", organizationId), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf("projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid projectId: [%s]", projectId), "C_INVALID_PROJECT_ID", "")) + return + } + + appId, ok := vars["appId"] + log.Debugf("appId = [%s]\n", appId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid appId: [%s]", appId), "C_INVALID_ASA_ID", "")) + return + } + + taskId, ok := vars["taskId"] + log.Debugf("taskId = [%s]\n", taskId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid taskId: [%s]", taskId), "C_INVALID_ASA_TASK_ID", "")) + return + } + + task, app, err := h.usecase.GetAppServeAppTaskById(taskId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if task == nil { + ErrorJSON(w, r, httpErrors.NewNoContentError(fmt.Errorf("No task exists"), "", "")) + return + } + + if strings.Contains(task.Status, "SUCCESS") && task.Status != "ABORT_SUCCESS" && + task.Status != "ROLLBACK_SUCCESS" { + task.AvailableRollback = true + } + + var out domain.GetAppServeAppTaskResponse + out.AppServeApp = *app + out.AppServeAppTask = *task + out.Stages = makeStages(task, app) + + ResponseJSON(w, r, http.StatusOK, out) +} + +func makeStages(task *domain.AppServeAppTask, app *domain.AppServeApp) []domain.StageResponse { stages := make([]domain.StageResponse, 0) var stage domain.StageResponse var pipelines []string - taskStatus := app.AppServeAppTasks[0].Status - strategy := app.AppServeAppTasks[0].Strategy + taskStatus := task.Status + strategy := task.Strategy if taskStatus == "ROLLBACKING" || taskStatus == "ROLLBACK_SUCCESS" || @@ -437,21 +572,21 @@ func makeStages(app *domain.AppServeApp) []domain.StageResponse { fmt.Printf("Pipeline stages: %v\n", pipelines) for _, pl := range pipelines { - stage = makeStage(app, pl) + stage = makeStage(task, app, pl) stages = append(stages, stage) } return stages } -func makeStage(app *domain.AppServeApp, pl string) domain.StageResponse { - taskStatus := app.AppServeAppTasks[0].Status - strategy := app.AppServeAppTasks[0].Strategy +func makeStage(task *domain.AppServeAppTask, app *domain.AppServeApp, pl string) domain.StageResponse { + taskStatus := task.Status + strategy := task.Strategy stage := domain.StageResponse{ Name: pl, - Status: StatusStages[app.Status][pl], - Result: StatusResult[StatusStages[app.Status][pl]], + Status: StatusStages[taskStatus][pl], + Result: StatusResult[StatusStages[taskStatus][pl]], } var actions []domain.ActionResponse @@ -480,7 +615,7 @@ func makeStage(app *domain.AppServeApp, pl string) domain.StageResponse { action := domain.ActionResponse{ Name: "ABORT", Uri: fmt.Sprintf(internal.API_PREFIX+internal.API_VERSION+ - "/organizations/%v/app-serve-apps/%v", app.OrganizationId, app.ID), + "/organizations/%v/projects/%v/app-serve-apps/%v", app.OrganizationId, app.ProjectId, app.ID), Type: "API", Method: "PUT", Body: map[string]string{"strategy": "blue-green", "abort": "true"}, @@ -490,7 +625,7 @@ func makeStage(app *domain.AppServeApp, pl string) domain.StageResponse { action = domain.ActionResponse{ Name: "PROMOTE", Uri: fmt.Sprintf(internal.API_PREFIX+internal.API_VERSION+ - "/organizations/%v/app-serve-apps/%v", app.OrganizationId, app.ID), + "/organizations/%v/projects/%v/app-serve-apps/%v", app.OrganizationId, app.ProjectId, app.ID), Type: "API", Method: "PUT", Body: map[string]string{"strategy": "blue-green", "promote": "true"}, @@ -509,8 +644,10 @@ func makeStage(app *domain.AppServeApp, pl string) domain.StageResponse { // @Description Get appServeApp by giving params // @Accept json // @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Success 200 {object} bool -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/exist [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist [get] // @Security JWT func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -549,9 +686,10 @@ func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.R // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param name path string true "name" // @Success 200 {object} bool -// @Router /organizations/{organizationId}/app-serve-apps/name/{name}/existence [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence [get] // @Security JWT func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -588,10 +726,11 @@ func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *ht // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Param object body domain.UpdateAppServeAppRequest true "Request body to update app" // @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId} [put] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [put] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -697,10 +836,11 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Param body body domain.UpdateAppServeAppStatusRequest true "Request body to update app status" // @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/status [patch] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status [patch] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -740,10 +880,11 @@ func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *h // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param appId path string true "appId" // @Param body body domain.UpdateAppServeAppEndpointRequest true "Request body to update app endpoint" // @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/endpoint [patch] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint [patch] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -788,9 +929,10 @@ func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId} [delete] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [delete] // @Security JWT func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -824,10 +966,11 @@ func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Re // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Param object body domain.RollbackAppServeAppRequest true "Request body to rollback app" // @Success 200 {object} string -// @Router /organizations/{organizationId}/app-serve-apps/{appId}/rollback [post] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback [post] // @Security JWT func (h *AppServeAppHandler) RollbackAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index d27adfb6..a24a43fa 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -15,14 +15,18 @@ type IAppServeAppRepository interface { CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) GetAppServeAppById(appId string) (*domain.AppServeApp, error) + + GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) + GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) + GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) + IsAppServeAppExist(appId string) (int64, error) IsAppServeAppNameExist(orgId string, appName string) (int64, error) CreateTask(task *domain.AppServeAppTask) (taskId string, err error) UpdateStatus(appId string, taskId string, status string, output string) error UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error - GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, error) GetTaskCountById(appId string) (int64, error) } @@ -109,9 +113,10 @@ func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppSer return nil, res.Error } if res.RowsAffected == 0 { - return nil, nil + return nil, nil, fmt.Errorf("No app with ID %s", appId) } + // Populate tasks into app object if err := r.db.Model(&app).Order("created_at desc").Association("AppServeAppTasks").Find(&app.AppServeAppTasks); err != nil { log.Debug(err) return nil, err @@ -124,9 +129,63 @@ func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppSer return &app, nil } +func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []domain.AppServeAppTask, err error) { + if pg == nil { + pg = pagination.NewDefaultPagination() + } + + filterFunc := CombinedGormFilter("app_serve_app_tasks", pg.GetFilters(), pg.CombinedFilter) + db := filterFunc(r.db.Model(&domain.AppServeAppTask{}). + Where("app_serve_app_tasks.app_serve_app_id = ?", appId)) + db.Count(&pg.TotalRows) + + pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) + orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) + res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&tasks) + if res.Error != nil { + return nil, fmt.Errorf("Error while finding tasks with appId: %s", appId) + } + + // If no record is found, just return empty array. + if res.RowsAffected == 0 { + return tasks, nil + } + + return +} + +// Return single task info along with its parent app info +func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) { + var task domain.AppServeAppTask + var app domain.AppServeApp + + // Retrieve task info + res := r.db.Where("id = ?", taskId).First(&task) + if res.Error != nil { + log.Debug(res.Error) + return nil, nil, res.Error + } + if res.RowsAffected == 0 { + return nil, nil, fmt.Errorf("No task with ID %s", taskId) + } + + // Retrieve app info + res = r.db.Where("id = ?", task.AppServeAppId).First(&app) + if res.Error != nil { + log.Debug(res.Error) + return nil, nil, res.Error + } + if res.RowsAffected == 0 { + return nil, nil, fmt.Errorf("Couldn't find app with ID %s associated with task %s", appId, taskId) + } + + return &task, &app, nil +} + func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) { var task domain.AppServeAppTask + // TODO: Does this work?? where's app ID here? res := r.db.Order("created_at desc").First(&task) if res.Error != nil { log.Debug(res.Error) @@ -267,16 +326,6 @@ func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endp return nil } -func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, error) { - var task domain.AppServeAppTask - - if err := r.db.Where("id = ?", taskId).First(&task).Error; err != nil { - return nil, fmt.Errorf("could not find AppServeAppTask with ID: %s", taskId) - } - - return &task, nil -} - func (r *AppServeAppRepository) GetTaskCountById(appId string) (int64, error) { var count int64 if err := r.db.Model(&domain.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 38e0b702..b16163f1 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -26,6 +26,8 @@ type IAppServeAppUsecase interface { CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) GetAppServeAppById(appId string) (*domain.AppServeApp, error) + GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) + GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) IsAppServeAppExist(appId string) (bool, error) @@ -220,6 +222,24 @@ func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*domain.AppServeA return asa, nil } +func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) { + tasks, err := u.repo.GetAppServeAppTasksByAppId(appId, pg) + if err != nil { + log.Debugf("Tasks: %v", tasks) + } + + return tasks, nil +} + +func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) { + task, app, err := u.repo.GetAppServeAppTaskById(taskId) + if err != nil { + return nil, nil, err + } + + return task, app, nil +} + func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) { task, err := u.repo.GetAppServeAppLatestTask(appId) if err != nil { diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index 5cb82ff1..45239154 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -12,6 +12,7 @@ type AppServeApp struct { Name string `gorm:"index" json:"name,omitempty"` // application name Namespace string `json:"namespace,omitempty"` // application namespace OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to Type string `json:"type,omitempty"` // type (build/deploy/all) AppType string `json:"appType,omitempty"` // appType (spring/springboot) EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app @@ -161,13 +162,21 @@ type GetAppServeAppsResponse struct { Pagination PaginationResponse `json:"pagination"` } +// TODO: This will be deprecated later type GetAppServeAppResponse struct { AppServeApp AppServeApp `json:"appServeApp"` Stages []StageResponse `json:"stages"` } +type GetAppServeAppTasksResponse struct { + AppServeAppTasks []AppServeAppTask `json:"appServeAppTasks"` + Pagination PaginationResponse `json:"pagination"` +} + type GetAppServeAppTaskResponse struct { + AppServeApp AppServeApp `json:"appServeApp"` AppServeAppTask AppServeAppTask `json:"appServeAppTask"` + Stages []StageResponse `json:"stages"` } type StageResponse struct { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index d4d2b65f..b6c91281 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -10,6 +10,7 @@ var errorMap = map[ErrorCode]string{ "C_INVALID_CLUSTER_ID": "유효하지 않은 클러스터 아이디입니다. 클러스터 아이디를 확인하세요.", "C_INVALID_APPGROUP_ID": "유효하지 않은 앱그룹 아이디입니다. 앱그룹 아이디를 확인하세요.", "C_INVALID_ORGANIZATION_ID": "유효하지 않은 조직 아이디입니다. 조직 아이디를 확인하세요.", + "C_INVALID_PROJECT_ID": "유효하지 않은 프로젝트 아이디입니다. 아이디를 확인하세요.", "C_INVALID_CLOUD_ACCOUNT_ID": "유효하지 않은 클라우드어카운트 아이디입니다. 클라우드어카운트 아이디를 확인하세요.", "C_INVALID_STACK_TEMPLATE_ID": "유효하지 않은 스택템플릿 아이디입니다. 스택템플릿 아이디를 확인하세요.", "C_INVALID_ASA_ID": "유효하지 않은 앱서빙앱 아이디입니다. 앱서빙앱 아이디를 확인하세요.", From 92a267f1f21f3b2d902d770224afb7c80f1877c3 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Thu, 15 Feb 2024 16:18:02 +0900 Subject: [PATCH 027/502] fix wrong return values --- internal/repository/app-serve-app.go | 4 ++-- internal/route/route.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index a24a43fa..6d2e72e4 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -113,7 +113,7 @@ func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppSer return nil, res.Error } if res.RowsAffected == 0 { - return nil, nil, fmt.Errorf("No app with ID %s", appId) + return nil, fmt.Errorf("No app with ID %s", appId) } // Populate tasks into app object @@ -176,7 +176,7 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*domain.A return nil, nil, res.Error } if res.RowsAffected == 0 { - return nil, nil, fmt.Errorf("Couldn't find app with ID %s associated with task %s", appId, taskId) + return nil, nil, fmt.Errorf("Couldn't find app with ID %s associated with task %s", app.ID, taskId) } return &task, &app, nil diff --git a/internal/route/route.go b/internal/route/route.go index fa536594..bbd35194 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -136,9 +136,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa appServeAppHandler := delivery.NewAppServeAppHandler(usecase.NewAppServeAppUsecase(repoFactory, argoClient)) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps", customMiddleware.Handle(internalApi.CreateAppServeApp, http.HandlerFunc(appServeAppHandler.CreateAppServeApp))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApps))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApps))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/count", customMiddleware.Handle(internalApi.GetNumOfAppsOnStack, http.HandlerFunc(appServeAppHandler.GetNumOfAppsOnStack))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApp))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApp))).Methods(http.MethodGet) // TODO: To be implemented // r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/tasks/{taskId}", customMiddleware.Handle(http.HandlerFunc(appServeAppHandler.GetAppServeAppTask))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/latest-task", customMiddleware.Handle(internalApi.GetAppServeAppLatestTask, http.HandlerFunc(appServeAppHandler.GetAppServeAppLatestTask))).Methods(http.MethodGet) From 19914fdd8c050b30403facbdd2e55f9defa5f522 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Thu, 15 Feb 2024 16:35:16 +0900 Subject: [PATCH 028/502] update swagger docs --- api/swagger/docs.go | 825 ++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.json | 827 ++++++++++++++++++++++++++++++++++++++- api/swagger/swagger.yaml | 537 +++++++++++++++++++++++++ 3 files changed, 2188 insertions(+), 1 deletion(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 748e8ecb..14e94b5c 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3052,6 +3052,818 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp list by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp list", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "boolean", + "description": "Show all apps including deleted apps", + "name": "showAll", + "in": "query" + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppServeApp" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Install appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Request body to create app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get number of apps on given stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get number of apps on given stack", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check duplicate appServeAppName by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Check duplicate appServeAppName", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Uninstall appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Uninstall appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update app endpoint", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update app endpoint", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "appId", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app endpoint", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get latest task from appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get latest task from appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Rollback appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Rollback appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to rollback app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.RollbackAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update app status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update app status", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app status", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeAppTask list by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeAppTask list", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppServeApp" + } + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get task detail from appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get task detail from appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Task ID", + "name": "taskId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/members": { "get": { "security": [ @@ -5020,6 +5832,10 @@ const docTemplate = `{ "description": "preview svc endpoint URL in B/G deployment", "type": "string" }, + "projectId": { + "description": "project ID which this app belongs to", + "type": "string" + }, "status": { "description": "status is status of deployed app", "type": "string" @@ -6492,8 +7308,17 @@ const docTemplate = `{ "domain.GetAppServeAppTaskResponse": { "type": "object", "properties": { + "appServeApp": { + "$ref": "#/definitions/domain.AppServeApp" + }, "appServeAppTask": { "$ref": "#/definitions/domain.AppServeAppTask" + }, + "stages": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StageResponse" + } } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index d273cdb0..eb162ade 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3046,6 +3046,818 @@ } } }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp list by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp list", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "boolean", + "description": "Show all apps including deleted apps", + "name": "showAll", + "in": "query" + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppServeApp" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Install appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "description": "Request body to create app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get number of apps on given stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get number of apps on given stack", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "integer" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check duplicate appServeAppName by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Check duplicate appServeAppName", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Uninstall appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Uninstall appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update app endpoint", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update app endpoint", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "appId", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app endpoint", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeApp by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "boolean" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get latest task from appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get latest task from appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Rollback appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Rollback appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to rollback app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.RollbackAppServeAppRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update app status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Update app status", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app status", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get appServeAppTask list by giving params", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get appServeAppTask list", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AppServeApp" + } + } + } + } + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get task detail from appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get task detail from appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Task ID", + "name": "taskId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/members": { "get": { "security": [ @@ -5014,6 +5826,10 @@ "description": "preview svc endpoint URL in B/G deployment", "type": "string" }, + "projectId": { + "description": "project ID which this app belongs to", + "type": "string" + }, "status": { "description": "status is status of deployed app", "type": "string" @@ -6486,8 +7302,17 @@ "domain.GetAppServeAppTaskResponse": { "type": "object", "properties": { + "appServeApp": { + "$ref": "#/definitions/domain.AppServeApp" + }, "appServeAppTask": { "$ref": "#/definitions/domain.AppServeAppTask" + }, + "stages": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.StageResponse" + } } } }, @@ -8268,4 +9093,4 @@ "in": "header" } } -} \ No newline at end of file +} diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 2c54f7f7..520e3eeb 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -176,6 +176,9 @@ definitions: previewEndpointUrl: description: preview svc endpoint URL in B/G deployment type: string + projectId: + description: project ID which this app belongs to + type: string status: description: status is status of deployed app type: string @@ -1183,8 +1186,14 @@ definitions: type: object domain.GetAppServeAppTaskResponse: properties: + appServeApp: + $ref: '#/definitions/domain.AppServeApp' appServeAppTask: $ref: '#/definitions/domain.AppServeAppTask' + stages: + items: + $ref: '#/definitions/domain.StageResponse' + type: array type: object domain.GetApplicationsResponse: properties: @@ -4243,6 +4252,534 @@ paths: summary: Update project tags: - Projects + /organizations/{organizationId}/projects/{projectId}/app-serve-apps: + get: + consumes: + - application/json + description: Get appServeApp list by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Show all apps including deleted apps + in: query + name: showAll + type: boolean + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/domain.AppServeApp' + type: array + security: + - JWT: [] + summary: Get appServeApp list + tags: + - AppServeApps + post: + consumes: + - application/json + description: Install appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Request body to create app + in: body + name: object + required: true + schema: + $ref: '#/definitions/domain.CreateAppServeAppRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Install appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}: + delete: + consumes: + - application/json + description: Uninstall appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Uninstall appServeApp + tags: + - AppServeApps + get: + consumes: + - application/json + description: Get appServeApp by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAppServeAppResponse' + security: + - JWT: [] + summary: Get appServeApp + tags: + - AppServeApps + put: + consumes: + - application/json + description: Update appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + - description: Request body to update app + in: body + name: object + required: true + schema: + $ref: '#/definitions/domain.UpdateAppServeAppRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Update appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint: + patch: + consumes: + - application/json + description: Update app endpoint + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: appId + in: path + name: appId + required: true + type: string + - description: Request body to update app endpoint + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateAppServeAppEndpointRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Update app endpoint + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist: + get: + consumes: + - application/json + description: Get appServeApp by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: boolean + security: + - JWT: [] + summary: Get appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task: + get: + consumes: + - application/json + description: Get latest task from appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAppServeAppTaskResponse' + security: + - JWT: [] + summary: Get latest task from appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback: + post: + consumes: + - application/json + description: Rollback appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + - description: Request body to rollback app + in: body + name: object + required: true + schema: + $ref: '#/definitions/domain.RollbackAppServeAppRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Rollback appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status: + patch: + consumes: + - application/json + description: Update app status + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + - description: Request body to update app status + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.UpdateAppServeAppStatusRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + security: + - JWT: [] + summary: Update app status + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks: + get: + consumes: + - application/json + description: Get appServeAppTask list by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: sortColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/domain.AppServeApp' + type: array + security: + - JWT: [] + summary: Get appServeAppTask list + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}: + get: + consumes: + - application/json + description: Get task detail from appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + - description: Task ID + in: path + name: taskId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAppServeAppTaskResponse' + security: + - JWT: [] + summary: Get task detail from appServeApp + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/count: + get: + consumes: + - application/json + description: Get number of apps on given stack + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Stack ID + in: query + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: integer + security: + - JWT: [] + summary: Get number of apps on given stack + tags: + - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence: + get: + consumes: + - application/json + description: Check duplicate appServeAppName by giving params + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: boolean + security: + - JWT: [] + summary: Check duplicate appServeAppName + tags: + - AppServeApps /organizations/{organizationId}/projects/{projectId}/members: delete: consumes: From 01f9a7cc845a5071599ba1bd2a72cfcf3a5ef833 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Thu, 15 Feb 2024 16:37:46 +0900 Subject: [PATCH 029/502] update go.mod --- go.mod | 71 +++++++++++++++---------- go.sum | 165 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 124 insertions(+), 112 deletions(-) diff --git a/go.mod b/go.mod index f7864ad4..5ee6e741 100644 --- a/go.mod +++ b/go.mod @@ -20,8 +20,8 @@ require ( github.com/go-playground/validator/v10 v10.13.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/mock v1.6.0 - github.com/google/uuid v1.3.0 - github.com/gorilla/handlers v1.5.1 + github.com/google/uuid v1.6.0 + github.com/gorilla/handlers v1.5.2 github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.5.0 github.com/opentracing/opentracing-go v1.2.0 @@ -29,14 +29,14 @@ require ( github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.0 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.12.0 + github.com/spf13/viper v1.18.2 github.com/swaggo/http-swagger v1.3.4 github.com/swaggo/swag v1.16.3 github.com/thoas/go-funk v0.9.3 github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.4.0 - golang.org/x/crypto v0.14.0 - golang.org/x/net v0.17.0 - golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 + golang.org/x/crypto v0.19.0 + golang.org/x/net v0.21.0 + golang.org/x/oauth2 v0.15.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 gorm.io/datatypes v1.1.1 @@ -62,27 +62,27 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.8.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/go-logr/logr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect - github.com/go-openapi/spec v0.20.6 // indirect - github.com/go-openapi/swag v0.19.15 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.20.2 // indirect + github.com/go-openapi/jsonreference v0.20.4 // indirect + github.com/go-openapi/spec v0.20.14 // indirect + github.com/go-openapi/swag v0.22.9 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.15 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.3.1 // indirect @@ -92,38 +92,51 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.3 // indirect - github.com/magiconair/properties v1.8.6 // indirect - github.com/mailru/easyjson v0.7.6 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/segmentio/ksuid v1.0.4 // indirect - github.com/spf13/afero v1.8.2 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/stretchr/testify v1.8.2 // indirect - github.com/subosito/gotenv v1.3.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect +<<<<<<< HEAD golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/tools v0.7.0 // indirect +======= + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/term v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.18.0 // indirect +>>>>>>> 878ab9c (update go.mod) gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.66.4 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.5.0 // indirect k8s.io/api v0.25.4 // indirect diff --git a/go.sum b/go.sum index 5c2b7b8e..88873e3f 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -38,7 +36,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= @@ -158,8 +155,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -182,15 +180,16 @@ github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMi github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -206,23 +205,24 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= +github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= +github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= +github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= +github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= @@ -283,8 +283,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= @@ -303,8 +304,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -321,21 +323,19 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -372,8 +372,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= @@ -418,8 +418,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -428,12 +428,13 @@ github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA= github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= @@ -491,19 +492,17 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= -github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -537,10 +536,15 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= @@ -556,28 +560,29 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -592,11 +597,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= -github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe h1:K8pHPVoTgxFJt1lXuIzzOX7zZhZFldJQK/CgKx9BFIc= github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= github.com/swaggo/http-swagger v1.3.4 h1:q7t/XLx0n15H1Q9/tk3Y9L4n210XzJF5WtnDX64a5ww= @@ -646,17 +652,19 @@ go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4 go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -666,13 +674,11 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -683,6 +689,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -709,7 +717,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -749,7 +757,6 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= @@ -759,11 +766,10 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -778,8 +784,8 @@ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -843,35 +849,31 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -882,15 +884,15 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -945,15 +947,14 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1028,9 +1029,7 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1072,8 +1071,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= @@ -1091,8 +1090,8 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= -gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= From 00c9e929b63e626e935990c824dd9a3501526884 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Thu, 15 Feb 2024 19:26:19 +0900 Subject: [PATCH 030/502] update API routes --- internal/delivery/api/endpoint.go | 2 ++ internal/route/route.go | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 5a02fca9..934dbed9 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -71,6 +71,8 @@ const ( GetAppServeApps GetNumOfAppsOnStack GetAppServeApp + GetAppServeAppTasksByAppId + GetAppServeAppTaskDetail GetAppServeAppLatestTask IsAppServeAppExist IsAppServeAppNameExist diff --git a/internal/route/route.go b/internal/route/route.go index bbd35194..e4a6a7c2 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -135,20 +135,20 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}/applications", customMiddleware.Handle(internalApi.CreateApplication, http.HandlerFunc(appGroupHandler.CreateApplication))).Methods(http.MethodPost) appServeAppHandler := delivery.NewAppServeAppHandler(usecase.NewAppServeAppUsecase(repoFactory, argoClient)) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps", customMiddleware.Handle(internalApi.CreateAppServeApp, http.HandlerFunc(appServeAppHandler.CreateAppServeApp))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps", customMiddleware.Handle(internalApi.CreateAppServeApp, http.HandlerFunc(appServeAppHandler.CreateAppServeApp))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApps))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/count", customMiddleware.Handle(internalApi.GetNumOfAppsOnStack, http.HandlerFunc(appServeAppHandler.GetNumOfAppsOnStack))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApp))).Methods(http.MethodGet) - // TODO: To be implemented - // r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/tasks/{taskId}", customMiddleware.Handle(http.HandlerFunc(appServeAppHandler.GetAppServeAppTask))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/latest-task", customMiddleware.Handle(internalApi.GetAppServeAppLatestTask, http.HandlerFunc(appServeAppHandler.GetAppServeAppLatestTask))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/exist", customMiddleware.Handle(internalApi.IsAppServeAppExist, http.HandlerFunc(appServeAppHandler.IsAppServeAppExist))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/name/{name}/existence", customMiddleware.Handle(internalApi.IsAppServeAppNameExist, http.HandlerFunc(appServeAppHandler.IsAppServeAppNameExist))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.DeleteAppServeApp, http.HandlerFunc(appServeAppHandler.DeleteAppServeApp))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.UpdateAppServeApp, http.HandlerFunc(appServeAppHandler.UpdateAppServeApp))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/status", customMiddleware.Handle(internalApi.UpdateAppServeAppStatus, http.HandlerFunc(appServeAppHandler.UpdateAppServeAppStatus))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/endpoint", customMiddleware.Handle(internalApi.UpdateAppServeAppEndpoint, http.HandlerFunc(appServeAppHandler.UpdateAppServeAppEndpoint))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/app-serve-apps/{appId}/rollback", customMiddleware.Handle(internalApi.RollbackAppServeApp, http.HandlerFunc(appServeAppHandler.RollbackAppServeApp))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count", customMiddleware.Handle(internalApi.GetNumOfAppsOnStack, http.HandlerFunc(appServeAppHandler.GetNumOfAppsOnStack))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.GetAppServeApp, http.HandlerFunc(appServeAppHandler.GetAppServeApp))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks", customMiddleware.Handle(internalApi.GetAppServeAppTasksByAppId, http.HandlerFunc(appServeAppHandler.GetAppServeAppTasksByAppId))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}", customMiddleware.Handle(internalApi.GetAppServeAppTaskDetail, http.HandlerFunc(appServeAppHandler.GetAppServeAppTaskDetail))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task", customMiddleware.Handle(internalApi.GetAppServeAppLatestTask, http.HandlerFunc(appServeAppHandler.GetAppServeAppLatestTask))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist", customMiddleware.Handle(internalApi.IsAppServeAppExist, http.HandlerFunc(appServeAppHandler.IsAppServeAppExist))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence", customMiddleware.Handle(internalApi.IsAppServeAppNameExist, http.HandlerFunc(appServeAppHandler.IsAppServeAppNameExist))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.DeleteAppServeApp, http.HandlerFunc(appServeAppHandler.DeleteAppServeApp))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.UpdateAppServeApp, http.HandlerFunc(appServeAppHandler.UpdateAppServeApp))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status", customMiddleware.Handle(internalApi.UpdateAppServeAppStatus, http.HandlerFunc(appServeAppHandler.UpdateAppServeAppStatus))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint", customMiddleware.Handle(internalApi.UpdateAppServeAppEndpoint, http.HandlerFunc(appServeAppHandler.UpdateAppServeAppEndpoint))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback", customMiddleware.Handle(internalApi.RollbackAppServeApp, http.HandlerFunc(appServeAppHandler.RollbackAppServeApp))).Methods(http.MethodPost) cloudAccountHandler := delivery.NewCloudAccountHandler(usecase.NewCloudAccountUsecase(repoFactory, argoClient)) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts", customMiddleware.Handle(internalApi.GetCloudAccounts, http.HandlerFunc(cloudAccountHandler.GetCloudAccounts))).Methods(http.MethodGet) From 3cf05e5c82f79e04805dca5fe2118fd42ddf609d Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 16 Feb 2024 14:07:21 +0900 Subject: [PATCH 031/502] Add project member count group by project role --- api/swagger/docs.go | 67 +++++++++++++++++++++++++++ api/swagger/swagger.json | 67 +++++++++++++++++++++++++++ api/swagger/swagger.yaml | 44 ++++++++++++++++++ internal/delivery/http/project.go | 76 +++++++++++++++++++++++++++++-- internal/repository/project.go | 71 +++++++++++++++++++++++++++-- internal/route/route.go | 1 + internal/usecase/project.go | 25 ++++++++-- pkg/domain/project.go | 7 +++ 8 files changed, 348 insertions(+), 10 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 56d16d79..b057dcde 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3079,6 +3079,12 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "project member search by query (query=all), (query=leader), (query=member), (query=viewer)", + "name": "query", + "in": "query" } ], "responses": { @@ -3244,6 +3250,50 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/projects/{projectId}/members/project-roles/count": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project member count group by project role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project member count group by project role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectMemberCountResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { "get": { "security": [ @@ -6565,6 +6615,23 @@ const docTemplate = `{ } } }, + "domain.GetProjectMemberCountResponse": { + "type": "object", + "properties": { + "projectLeaderCount": { + "type": "integer" + }, + "projectMemberAllCount": { + "type": "integer" + }, + "projectMemberCount": { + "type": "integer" + }, + "projectViewerCount": { + "type": "integer" + } + } + }, "domain.GetProjectMemberResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 4f72dcfc..46113e34 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3072,6 +3072,12 @@ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "project member search by query (query=all), (query=leader), (query=member), (query=viewer)", + "name": "query", + "in": "query" } ], "responses": { @@ -3237,6 +3243,50 @@ } } }, + "/organizations/{organizationId}/projects/{projectId}/members/project-roles/count": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project member count group by project role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project member count group by project role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectMemberCountResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { "get": { "security": [ @@ -6558,6 +6608,23 @@ } } }, + "domain.GetProjectMemberCountResponse": { + "type": "object", + "properties": { + "projectLeaderCount": { + "type": "integer" + }, + "projectMemberAllCount": { + "type": "integer" + }, + "projectMemberCount": { + "type": "integer" + }, + "projectViewerCount": { + "type": "integer" + } + } + }, "domain.GetProjectMemberResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 7c59d3c0..fc5a9644 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1209,6 +1209,17 @@ definitions: type: string type: object type: object + domain.GetProjectMemberCountResponse: + properties: + projectLeaderCount: + type: integer + projectMemberAllCount: + type: integer + projectMemberCount: + type: integer + projectViewerCount: + type: integer + type: object domain.GetProjectMemberResponse: properties: projectMember: @@ -4170,6 +4181,11 @@ paths: name: projectId required: true type: string + - description: project member search by query (query=all), (query=leader), (query=member), + (query=viewer) + in: query + name: query + type: string produces: - application/json responses: @@ -4352,6 +4368,34 @@ paths: summary: Update project member Role tags: - Projects + /organizations/{organizationId}/projects/{projectId}/members/project-roles/count: + get: + consumes: + - application/json + description: Get project member count group by project role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectMemberCountResponse' + security: + - JWT: [] + summary: Get project member count group by project role + tags: + - Projects /organizations/{organizationId}/projects/{projectId}/namespaces: get: consumes: diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index d0a72ea5..5ef3ca2e 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -27,6 +27,7 @@ type IProjectHandler interface { AddProjectMember(w http.ResponseWriter, r *http.Request) GetProjectMember(w http.ResponseWriter, r *http.Request) GetProjectMembers(w http.ResponseWriter, r *http.Request) + GetProjectMemberCount(w http.ResponseWriter, r *http.Request) RemoveProjectMember(w http.ResponseWriter, r *http.Request) RemoveProjectMembers(w http.ResponseWriter, r *http.Request) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) @@ -563,6 +564,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" +// @Param query query string false "project member search by query (query=all), (query=leader), (query=member), (query=viewer)" // @Success 200 {object} domain.GetProjectMembersResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [get] // @Security JWT @@ -583,13 +585,38 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request return } - pms, err := p.usecase.GetProjectMembersByProjectId(projectId) + urlParams := r.URL.Query() + + queryParam := urlParams.Get("query") + query := usecase.ProjectAll + if queryParam == "" || strings.EqualFold(queryParam, "all") { + query = usecase.ProjectAll + } else if strings.EqualFold(queryParam, "leader") { + query = usecase.ProjectLeader + } else if strings.EqualFold(queryParam, "member") { + query = usecase.ProjectMember + } else if strings.EqualFold(queryParam, "viewer") { + query = usecase.ProjectViewer + } else { + log.ErrorWithContext(r.Context(), "Invalid query params. Err: ") + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid query params"), + "C_INVALID_QUERY_PARAM", "")) + return + } + + pms, err := p.usecase.GetProjectMembers(projectId, query) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project roles ", err) + log.ErrorWithContext(r.Context(), "Failed to get project members ", err) ErrorJSON(w, r, err) return } + var out domain.GetProjectMembersResponse + if pms == nil { + ResponseJSON(w, r, http.StatusNotFound, out) + return + } + pmrs := make([]domain.ProjectMemberResponse, 0) for _, pm := range pms { pmr := domain.ProjectMemberResponse{ @@ -608,11 +635,52 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request pmrs = append(pmrs, pmr) } - out := domain.GetProjectMembersResponse{ProjectMembers: pmrs} - + out = domain.GetProjectMembersResponse{ProjectMembers: pmrs} ResponseJSON(w, r, http.StatusOK, out) } +// GetProjectMemberCount godoc +// @Tags Projects +// @Summary Get project member count group by project role +// @Description Get project member count group by project role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} domain.GetProjectMemberCountResponse +// @Router /organizations/{organizationId}/projects/{projectId}/members/project-roles/count [get] +// @Security JWT +func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + + pmcr, err := p.usecase.GetProjectMemberCount(projectId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project member count", err) + ErrorJSON(w, r, err) + return + } + + if pmcr == nil { + ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectMembersResponse{}) + return + } + ResponseJSON(w, r, http.StatusOK, pmcr) +} + // RemoveProjectMember godoc // @Tags Projects // @Summary Remove project members to project diff --git a/internal/repository/project.go b/internal/repository/project.go index ef999779..e671246d 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -18,6 +18,8 @@ type IProjectRepository interface { GetProjectRoleById(id string) (*domain.ProjectRole, error) AddProjectMember(*domain.ProjectMember) (string, error) GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) + GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string) ([]domain.ProjectMember, error) + GetProjectMemberCountByProjectId(projectId string) (*domain.GetProjectMemberCountResponse, error) GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) RemoveProjectMember(projectMemberId string) error //UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error @@ -83,10 +85,13 @@ func (r *ProjectRepository) GetProjectById(organizationId string, projectId stri } func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, projectId string) (p *domain.Project, err error) { - res := r.db.Limit(1).Where("organization_id = ? and id = ?", organizationId, projectId). + res := r.db.Limit(1).Where("projects.organization_id = ? and projects.id = ?", organizationId, projectId). Limit(1).Preload("ProjectMembers", "is_project_leader = ?", true). Preload("ProjectMembers.ProjectRole"). Preload("ProjectMembers.ProjectUser"). + //InnerJoins("ProjectMembers", r.db.Where(&domain.ProjectMember{IsProjectLeader: true})). + //InnerJoins("ProjectMembers.ProjectRole"). + //InnerJoins("ProjectMembers.ProjectUser"). First(&p) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -166,8 +171,13 @@ func (r *ProjectRepository) AddProjectMember(pm *domain.ProjectMember) (string, } func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string) (pms []domain.ProjectMember, err error) { - res := r.db.Preload("ProjectUser"). - Joins("ProjectRole").Where("project_id = ?", projectId).Find(&pms) + //res := r.db.Preload("ProjectUser"). + // Joins("ProjectRole").Where("project_id = ?", projectId).Find(&pms) + res := r.db.Joins("ProjectUser"). + Joins("ProjectRole"). + Where("project_members.project_id = ?", projectId). + Order("project_members.created_at ASC"). + Find(&pms) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project member") @@ -181,6 +191,61 @@ func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string) (pms return pms, nil } +func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string) (pms []domain.ProjectMember, err error) { + res := r.db.Joins("ProjectUser"). + //Joins("ProjectRole"). + //Find(&pms, "project_members.project_id = ? and \"ProjectRole\".name = ?", projectId, memberRole) + InnerJoins("ProjectRole", r.db.Where(&domain.ProjectRole{Name: memberRole})). + Order("project_members.created_at ASC"). + Find(&pms, "project_members.project_id = ?", projectId) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project member") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pms, nil +} + +func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { + res := r.db.Raw(""+ + "select (plc.count + pmc.count + pvc.count) as project_member_all_count,"+ + " plc.count as project_leader_count,"+ + " pmc.count as project_member_count,"+ + " pvc.count as project_viewer_count"+ + " from (select count(project_members.id) as count"+ + " from project_members"+ + " left join project_roles on project_roles.id = project_members.project_role_id"+ + " where project_members.project_id = ?"+ + " and project_roles.name = 'project-leader') as plc,"+ + " (select count(project_members.id) as count"+ + " from project_members"+ + " left join project_roles on project_roles.id = project_members.project_role_id"+ + " where project_members.project_id = ?"+ + " and project_roles.name = 'project-member') as pmc,"+ + " (select count(project_members.id) as count"+ + " from project_members"+ + " left join project_roles on project_roles.id = project_members.project_role_id"+ + " where project_members.project_id = ?"+ + " and project_roles.name = 'project-viewer') as pvc", projectId, projectId, projectId). + Scan(&pmcr) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project member count") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pmcr, nil +} + func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm *domain.ProjectMember, err error) { res := r.db.Preload("ProjectUser"). Joins("ProjectRole").Where("project_members.id = ?", projectMemberId).First(&pm) diff --git a/internal/route/route.go b/internal/route/route.go index fa536594..7814b9f7 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -207,6 +207,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.AddProjectMember, http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.GetProjectMember, http.HandlerFunc(projectHandler.GetProjectMember))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMembers))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/project-roles/count", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMemberCount))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMembers))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMembersRole))).Methods(http.MethodPut) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 6c9e8a36..70d9cbb3 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -28,7 +28,8 @@ type IProjectUsecase interface { AddProjectMember(pm *domain.ProjectMember) (string, error) GetProjectUser(projectUserId string) (*domain.ProjectUser, error) GetProjectMember(projectMemberId string) (*domain.ProjectMember, error) - GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) + GetProjectMembers(projectId string, query int) ([]domain.ProjectMember, error) + GetProjectMemberCount(projectMemberId string) (*domain.GetProjectMemberCountResponse, error) RemoveProjectMember(projectMemberId string) error UpdateProjectMemberRole(pm *domain.ProjectMember) error CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error @@ -178,8 +179,16 @@ func (u *ProjectUsecase) GetProjectMember(projectMemberId string) (pm *domain.Pr return pm, nil } -func (u *ProjectUsecase) GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) { - pms, err := u.projectRepo.GetProjectMembersByProjectId(projectId) +func (u *ProjectUsecase) GetProjectMembers(projectId string, query int) (pms []domain.ProjectMember, err error) { + if query == ProjectLeader { + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-leader") + } else if query == ProjectMember { + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-member") + } else if query == ProjectViewer { + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-viewer") + } else { + pms, err = u.projectRepo.GetProjectMembersByProjectId(projectId) + } if err != nil { log.Error(err) return nil, errors.Wrap(err, "Failed to get project members.") @@ -188,6 +197,16 @@ func (u *ProjectUsecase) GetProjectMembersByProjectId(projectId string) ([]domai return pms, nil } +func (u *ProjectUsecase) GetProjectMemberCount(projectMemberId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { + pmcr, err = u.projectRepo.GetProjectMemberCountByProjectId(projectMemberId) + if err != nil { + log.Error(err) + return pmcr, errors.Wrap(err, "Failed to get project member count.") + } + + return pmcr, nil +} + func (u *ProjectUsecase) RemoveProjectMember(projectMemberId string) error { if err := u.projectRepo.RemoveProjectMember(projectMemberId); err != nil { log.Error(err) diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 1faf726f..a60059eb 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -196,6 +196,13 @@ type GetProjectMembersResponse struct { ProjectMembers []ProjectMemberResponse `json:"projectMembers"` } +type GetProjectMemberCountResponse struct { + ProjectMemberAllCount int `json:"projectMemberAllCount"` + ProjectLeaderCount int `json:"projectLeaderCount"` + ProjectMemberCount int `json:"projectMemberCount"` + ProjectViewerCount int `json:"projectViewerCount"` +} + type RemoveProjectMemberRequest struct { ProjectMember []struct { ProjectMemberId string `json:"projectMemberId"` From cee8cf93762fdc38769ccc67ce7b8c4dea32acd5 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Fri, 16 Feb 2024 13:42:15 +0900 Subject: [PATCH 032/502] regenerate swagger docs --- api/swagger/docs.go | 580 ----------------------- api/swagger/swagger.json | 582 +----------------------- api/swagger/swagger.yaml | 371 --------------- go.mod | 8 - internal/delivery/http/app-serve-app.go | 1 - internal/repository/app-serve-app.go | 1 + 6 files changed, 2 insertions(+), 1541 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 14e94b5c..e031a834 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1357,586 +1357,6 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/app-serve-apps": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp list by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp list", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "boolean", - "description": "Show all apps including deleted apps", - "name": "showAll", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AppServeApp" - } - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Install appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Install appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Request body to create app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/count": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get number of apps on given stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get number of apps on given stack", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "integer" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check duplicate appServeAppName by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Check duplicate appServeAppName", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppServeAppResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Uninstall appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Uninstall appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/endpoint": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update app endpoint", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update app endpoint", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "appId", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app endpoint", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/exist": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/latest-task": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get latest task from appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get latest task from appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/rollback": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Rollback appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Rollback appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to rollback app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.RollbackAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/status": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update app status", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update app status", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app status", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index eb162ade..2a7a032d 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1351,586 +1351,6 @@ } } }, - "/organizations/{organizationId}/app-serve-apps": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp list by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp list", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "boolean", - "description": "Show all apps including deleted apps", - "name": "showAll", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/domain.AppServeApp" - } - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Install appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Install appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Request body to create app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.CreateAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/count": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get number of apps on given stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get number of apps on given stack", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "integer" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check duplicate appServeAppName by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Check duplicate appServeAppName", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppServeAppResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Uninstall appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Uninstall appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/endpoint": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update app endpoint", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update app endpoint", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "appId", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app endpoint", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/exist": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/latest-task": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get latest task from appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get latest task from appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/rollback": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Rollback appServeApp", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Rollback appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to rollback app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.RollbackAppServeAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, - "/organizations/{organizationId}/app-serve-apps/{appId}/status": { - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update app status", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Update app status", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app status", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ @@ -9093,4 +8513,4 @@ "in": "header" } } -} +} \ No newline at end of file diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 520e3eeb..6b15ef84 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -3227,377 +3227,6 @@ paths: summary: Create alert action tags: - Alerts - /organizations/{organizationId}/app-serve-apps: - get: - consumes: - - application/json - description: Get appServeApp list by giving params - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: Show all apps including deleted apps - in: query - name: showAll - type: boolean - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/domain.AppServeApp' - type: array - security: - - JWT: [] - summary: Get appServeApp list - tags: - - AppServeApps - post: - consumes: - - application/json - description: Install appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: Request body to create app - in: body - name: object - required: true - schema: - $ref: '#/definitions/domain.CreateAppServeAppRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Install appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}: - delete: - consumes: - - application/json - description: Uninstall appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Uninstall appServeApp - tags: - - AppServeApps - get: - consumes: - - application/json - description: Get appServeApp by giving params - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetAppServeAppResponse' - security: - - JWT: [] - summary: Get appServeApp - tags: - - AppServeApps - put: - consumes: - - application/json - description: Update appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - - description: Request body to update app - in: body - name: object - required: true - schema: - $ref: '#/definitions/domain.UpdateAppServeAppRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Update appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/endpoint: - patch: - consumes: - - application/json - description: Update app endpoint - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: appId - in: path - name: appId - required: true - type: string - - description: Request body to update app endpoint - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateAppServeAppEndpointRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Update app endpoint - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/exist: - get: - consumes: - - application/json - description: Get appServeApp by giving params - produces: - - application/json - responses: - "200": - description: OK - schema: - type: boolean - security: - - JWT: [] - summary: Get appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/latest-task: - get: - consumes: - - application/json - description: Get latest task from appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/domain.GetAppServeAppTaskResponse' - security: - - JWT: [] - summary: Get latest task from appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/rollback: - post: - consumes: - - application/json - description: Rollback appServeApp - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - - description: Request body to rollback app - in: body - name: object - required: true - schema: - $ref: '#/definitions/domain.RollbackAppServeAppRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Rollback appServeApp - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/{appId}/status: - patch: - consumes: - - application/json - description: Update app status - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - - description: Request body to update app status - in: body - name: body - required: true - schema: - $ref: '#/definitions/domain.UpdateAppServeAppStatusRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - security: - - JWT: [] - summary: Update app status - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/count: - get: - consumes: - - application/json - description: Get number of apps on given stack - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: Stack ID - in: query - name: stackId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - type: integer - security: - - JWT: [] - summary: Get number of apps on given stack - tags: - - AppServeApps - /organizations/{organizationId}/app-serve-apps/name/{name}/existence: - get: - consumes: - - application/json - description: Check duplicate appServeAppName by giving params - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: name - in: path - name: name - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - type: boolean - security: - - JWT: [] - summary: Check duplicate appServeAppName - tags: - - AppServeApps /organizations/{organizationId}/cloud-accounts: get: consumes: diff --git a/go.mod b/go.mod index 5ee6e741..18d6f8dc 100644 --- a/go.mod +++ b/go.mod @@ -115,13 +115,6 @@ require ( github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect -<<<<<<< HEAD - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect - golang.org/x/tools v0.7.0 // indirect -======= go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect @@ -130,7 +123,6 @@ require ( golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.18.0 // indirect ->>>>>>> 878ab9c (update go.mod) gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index bfc92b0e..0aa9e663 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -415,7 +415,6 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. ResponseJSON(w, r, http.StatusOK, numApps) } -// New func // GetAppServeAppTasksByAppId godoc // @Tags AppServeApps // @Summary Get appServeAppTask list diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 6d2e72e4..f761b6a7 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -67,6 +67,7 @@ func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll b pg = pagination.NewDefaultPagination() } + // TODO: should return different records based on showAll param filterFunc := CombinedGormFilter("app_serve_apps", pg.GetFilters(), pg.CombinedFilter) db := filterFunc(r.db.Model(&domain.AppServeApp{}). Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId)) From 38d8bb169beab6bd677f86b639204e7861017b6e Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Fri, 16 Feb 2024 16:30:44 +0900 Subject: [PATCH 033/502] add note for future API deprecation --- internal/delivery/http/app-serve-app.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 0aa9e663..578e69fc 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -289,6 +289,11 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ // @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Request) { + ////////////////////////////////////////////////////////////////////////////////////////// + // TODO: this API will'be deprecated soon once the new task-related API's are verified. + // Until then, this is available (except for stage info) just for backward compatibility. + ////////////////////////////////////////////////////////////////////////////////////////// + vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -328,6 +333,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque var out domain.GetAppServeAppResponse out.AppServeApp = *app + // NOTE: makeStages function's been changed to use task instead of app //out.Stages = makeStages(app) ResponseJSON(w, r, http.StatusOK, out) From eb9d6c7a66ad0f6e1e994520e0f7cd144efcd35c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 20 Feb 2024 14:27:11 +0900 Subject: [PATCH 034/502] trivial. golang version up to v1.22 --- .github/workflows/build.yml | 4 +- Dockerfile | 2 +- go.mod | 129 +++---- go.sum | 701 +++++++++--------------------------- 4 files changed, 235 insertions(+), 601 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e8644715..e016dd67 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,14 +11,14 @@ env: TAG: ${{github.sha}} jobs: - build-and-push-image: + build-image: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Login to DockerHub uses: docker/login-action@v1 diff --git a/Dockerfile b/Dockerfile index b1971e88..9c401c07 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build - backend -FROM --platform=linux/amd64 docker.io/library/golang:1.18-buster AS backend-build +FROM --platform=linux/amd64 docker.io/library/golang:1.21 AS backend-build RUN DEBIAN_FRONTEND="noninteractive" apt-get -y install tzdata RUN wget https://github.com/swaggo/swag/releases/download/v1.16.3/swag_1.16.3_Linux_amd64.tar.gz -O - | tar -xz -C /tmp && cp /tmp/swag /usr/local/bin diff --git a/go.mod b/go.mod index 18d6f8dc..7803d30a 100644 --- a/go.mod +++ b/go.mod @@ -1,97 +1,99 @@ module github.com/openinfradev/tks-api -go 1.18 +go 1.21 require ( - github.com/Nerzal/gocloak/v13 v13.1.0 - github.com/aws/aws-sdk-go-v2 v1.20.1 - github.com/aws/aws-sdk-go-v2/config v1.18.32 - github.com/aws/aws-sdk-go-v2/credentials v1.13.31 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.110.1 - github.com/aws/aws-sdk-go-v2/service/eks v1.29.2 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.16.2 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.20.2 - github.com/aws/aws-sdk-go-v2/service/servicequotas v1.15.1 - github.com/aws/aws-sdk-go-v2/service/ses v1.15.7 - github.com/aws/aws-sdk-go-v2/service/sts v1.21.1 + github.com/Nerzal/gocloak/v13 v13.9.0 + github.com/aws/aws-sdk-go-v2 v1.25.0 + github.com/aws/aws-sdk-go-v2/config v1.27.0 + github.com/aws/aws-sdk-go-v2/credentials v1.17.0 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.148.0 + github.com/aws/aws-sdk-go-v2/service/eks v1.39.0 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.23.0 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.29.0 + github.com/aws/aws-sdk-go-v2/service/servicequotas v1.20.1 + github.com/aws/aws-sdk-go-v2/service/ses v1.21.0 + github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 - github.com/go-playground/validator/v10 v10.13.0 + github.com/go-playground/validator/v10 v10.18.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/mock v1.6.0 github.com/google/uuid v1.6.0 github.com/gorilla/handlers v1.5.2 - github.com/gorilla/mux v1.8.0 - github.com/gorilla/websocket v1.5.0 + github.com/gorilla/mux v1.8.1 + github.com/gorilla/websocket v1.5.1 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.9.0 + github.com/sirupsen/logrus v1.9.3 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.18.2 github.com/swaggo/http-swagger v1.3.4 github.com/swaggo/swag v1.16.3 github.com/thoas/go-funk v0.9.3 - github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.4.0 + github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0 golang.org/x/crypto v0.19.0 golang.org/x/net v0.21.0 - golang.org/x/oauth2 v0.15.0 + golang.org/x/oauth2 v0.17.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 - gorm.io/datatypes v1.1.1 - gorm.io/driver/postgres v1.5.0 - gorm.io/gorm v1.25.1 + gorm.io/datatypes v1.2.0 + gorm.io/driver/postgres v1.5.6 + gorm.io/gorm v1.25.7 goyave.dev/goyave/v4 v4.4.11 - k8s.io/apimachinery v0.25.4 - k8s.io/client-go v0.25.2 - k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed + k8s.io/apimachinery v0.29.2 + k8s.io/client-go v0.29.2 + k8s.io/utils v0.0.0-20240102154912-e7106e64919e ) require ( github.com/Code-Hex/uniseg v0.2.0 // indirect github.com/KyleBanks/depth v1.2.1 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1 // indirect - github.com/aws/smithy-go v1.14.1 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.19.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.0 // indirect + github.com/aws/smithy-go v1.20.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/logr v1.3.0 // indirect - github.com/go-openapi/jsonpointer v0.20.2 // indirect - github.com/go-openapi/jsonreference v0.20.4 // indirect - github.com/go-openapi/spec v0.20.14 // indirect - github.com/go-openapi/swag v0.22.9 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/spec v0.20.6 // indirect + github.com/go-openapi/swag v0.22.3 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v5 v5.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect + github.com/imdario/mergo v0.3.15 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.3.1 // indirect + github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/leodido/go-urn v1.2.3 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -99,13 +101,12 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pelletier/go-toml/v2 v2.1.1 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/segmentio/ksuid v1.0.4 // indirect @@ -115,14 +116,14 @@ require ( github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect - go.uber.org/atomic v1.11.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/sys v0.17.0 // indirect golang.org/x/term v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.18.0 // indirect + golang.org/x/tools v0.16.1 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect @@ -131,15 +132,15 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.5.0 // indirect - k8s.io/api v0.25.4 // indirect - k8s.io/apiextensions-apiserver v0.23.5 // indirect - k8s.io/component-base v0.25.2 // indirect - k8s.io/klog/v2 v2.80.1 // indirect - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect - sigs.k8s.io/cluster-api v1.1.3 // indirect - sigs.k8s.io/controller-runtime v0.11.2 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + k8s.io/api v0.29.2 // indirect + k8s.io/apiextensions-apiserver v0.26.1 // indirect + k8s.io/component-base v0.26.1 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + sigs.k8s.io/cluster-api v1.4.4 // indirect + sigs.k8s.io/controller-runtime v0.14.5 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 88873e3f..d2cc6fdc 100644 --- a/go.sum +++ b/go.sum @@ -13,11 +13,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -26,7 +21,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -37,99 +31,64 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Code-Hex/uniseg v0.2.0 h1:QB/2UJFvEuRLSZqe+Sb1XQBTWjqGVbZoC6oSWzQRKws= github.com/Code-Hex/uniseg v0.2.0/go.mod h1:/ndS2tP+X1lk2HUOcXWGtVTxVq0lWilwgMa4CbzdRsg= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/Nerzal/gocloak/v13 v13.1.0 h1:ret4pZTIsSQGZHURDMJ4jXnUmHyEoRykBqDTsAKoj8c= -github.com/Nerzal/gocloak/v13 v13.1.0/go.mod h1:rRBtEdh5N0+JlZZEsrfZcB2sRMZWbgSxI2EIv9jpJp4= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= +github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go-v2 v1.17.8/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2 v1.20.0/go.mod h1:uWOr0m0jDsiWw8nnXiqZ+YG6LdvAlGYDLLf2NmHZoy4= -github.com/aws/aws-sdk-go-v2 v1.20.1 h1:rZBf5DWr7YGrnlTK4kgDQGn1ltqOg5orCYb/UhOFZkg= -github.com/aws/aws-sdk-go-v2 v1.20.1/go.mod h1:NU06lETsFm8fUC6ZjhgDpVBcGZTFQ6XM+LZWZxMI4ac= -github.com/aws/aws-sdk-go-v2/config v1.18.32 h1:tqEOvkbTxwEV7hToRcJ1xZRjcATqwDVsWbAscgRKyNI= -github.com/aws/aws-sdk-go-v2/config v1.18.32/go.mod h1:U3ZF0fQRRA4gnbn9GGvOWLoT2EzzZfAWeKwnVrm1rDc= -github.com/aws/aws-sdk-go-v2/credentials v1.13.31 h1:vJyON3lG7R8VOErpJJBclBADiWTwzcwdkQpTKx8D2sk= -github.com/aws/aws-sdk-go-v2/credentials v1.13.31/go.mod h1:T4sESjBtY2lNxLgkIASmeP57b5j7hTQqCbqG0tWnxC4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 h1:X3H6+SU21x+76LRglk21dFRgMTJMa5QcpW+SqUf5BBg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7/go.mod h1:3we0V09SwcJBzNlnyovrR2wWJhWmVdqAsmVs4uronv8= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.32/go.mod h1:RudqOgadTWdcS3t/erPQo24pcVEoYyqj/kKW5Vya21I= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37/go.mod h1:Pdn4j43v49Kk6+82spO3Tu5gSeQXRsxo56ePPQAvFiA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 h1:c8ed/T9T2K5I+h/JzmF5tpI46+OODQ74dzmdo+QnaMg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38/go.mod h1:qggunOChCMu9ZF/UkAfhTz25+U2rLVb3ya0Ua6TTfCA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.26/go.mod h1:vq86l7956VgFr0/FWQ2BWnK07QC3WYsepKzy33qqY5U= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31/go.mod h1:fTJDMe8LOFYtqiFFFeHA+SVMAwqLhoq0kcInYoLa9Js= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32 h1:hNeAAymUY5gu11WrrmFb3CVIp9Dar9hbo44yzzcQpzA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32/go.mod h1:0ZXSqrty4FtQ7p8TEuRde/SZm9X05KT18LAUlR40Ln0= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38 h1:+i1DOFrW3YZ3apE45tCal9+aDKK6kNEbW6Ib7e1nFxE= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38/go.mod h1:1/jLp0OgOaWIetycOmycW+vYTYgTZFPttJQRgsI1PoU= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.110.1 h1:OaDeV+sdve2NV+kUheZX5bToHFmfIkflgOlZTKij0Bo= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.110.1/go.mod h1:Ie0Kp61cLk223argiS+t8vO29SpbFIphzlPflIvYcv0= -github.com/aws/aws-sdk-go-v2/service/eks v1.29.2 h1:ZwK94/wSfjVrsp9UucUZOb3QCn6zL9Wru5KauaYQCBg= -github.com/aws/aws-sdk-go-v2/service/eks v1.29.2/go.mod h1:B7NksWEFv8tWu1ob60c1bU1oa1iCIhoQ7AtnT3dE3+8= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.16.2 h1:AnXbttLaoY2bgyTotlmKJxozPUQdDQ3WGIQ7MwnznPE= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.16.2/go.mod h1:DYqqNwjoFTL0URDn5odwM4Pq455DHNlBmQXSAI2DbWs= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.20.2 h1:8TXQKxY0UjNAt/9nkDtfGechuri15a+yw9QtsEuOLtE= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.20.2/go.mod h1:AZv/T0/2rhNBLiY2k109TT6HJ7Z0P8Z+SYvs0jqVkXE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31/go.mod h1:3+lloe3sZuBQw1aBc5MyndvodzQlyqCZ7x1QPDHaWP4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32 h1:dGAseBFEYxth10V23b5e2mAS+tX7oVbfYHD6dnDdAsg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32/go.mod h1:4jwAWKEkCR0anWk5+1RbfSg1R5Gzld7NLiuaq5bTR/Y= -github.com/aws/aws-sdk-go-v2/service/servicequotas v1.15.1 h1:ZL1ul+QW+JGT7my64SG8cPTudyLXRZXifPgJrpIA8qI= -github.com/aws/aws-sdk-go-v2/service/servicequotas v1.15.1/go.mod h1:2rmOo0RfixF8lcXxkquMIb1SY9oPY0iY/Mau8w8nFNs= -github.com/aws/aws-sdk-go-v2/service/ses v1.15.7 h1:eS3hpWtxVYnrysF+NEcjZo5zVvmgNTk22zRwJbtmCZY= -github.com/aws/aws-sdk-go-v2/service/ses v1.15.7/go.mod h1:sDSPw06IV4uB+RByvHkqDZKfP7SgIataOehYkchSups= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.1 h1:DSNpSbfEgFXRV+IfEcKE5kTbqxm+MeF5WgyeRlsLnHY= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.1/go.mod h1:TC9BubuFMVScIU+TLKamO6VZiYTkYoEHqlSQwAe2omw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1 h1:hd0SKLMdOL/Sl6Z0np1PX9LeH2gqNtBe0MhTedA8MGI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1/go.mod h1:XO/VcyoQ8nKyKfFW/3DMsRQXsfh/052tHTWmg3xBXRg= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.1 h1:pAOJj+80tC8sPVgSDHzMYD6KLWsaLQ1kZw31PTeORbs= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.1/go.mod h1:G8SbvL0rFk4WOJroU8tKBczhsbhj2p/YY7qeJezJ3CI= -github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/aws/smithy-go v1.14.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/aws/smithy-go v1.14.1 h1:EFKMUmH/iHMqLiwoEDx2rRjRQpI1YCn5jTysoaDujFs= -github.com/aws/smithy-go v1.14.1/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/aws/aws-sdk-go-v2 v1.25.0 h1:sv7+1JVJxOu/dD/sz/csHX7jFqmP001TIY7aytBWDSQ= +github.com/aws/aws-sdk-go-v2 v1.25.0/go.mod h1:G104G1Aho5WqF+SR3mDIobTABQzpYV0WxMsKxlMggOA= +github.com/aws/aws-sdk-go-v2/config v1.27.0 h1:J5sdGCAHuWKIXLeXiqr8II/adSvetkx0qdZwdbXXpb0= +github.com/aws/aws-sdk-go-v2/config v1.27.0/go.mod h1:cfh8v69nuSUohNFMbIISP2fhmblGmYEOKs5V53HiHnk= +github.com/aws/aws-sdk-go-v2/credentials v1.17.0 h1:lMW2x6sKBsiAJrpi1doOXqWFyEPoE886DTb1X0wb7So= +github.com/aws/aws-sdk-go-v2/credentials v1.17.0/go.mod h1:uT41FIH8cCIxOdUYIL0PYyHlL1NoneDuDSCwg5VE/5o= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0 h1:xWCwjjvVz2ojYTP4kBKUuUh9ZrXfcAXpflhOUUeXg1k= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0/go.mod h1:j3fACuqXg4oMTQOR2yY7m0NmJY0yBK4L4sLsRXq1Ins= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 h1:NPs/EqVO+ajwOoq56EfcGKa3L3ruWuazkIw1BqxwOPw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0/go.mod h1:D+duLy2ylgatV+yTlQ8JTuLfDD0BnFvnQRc+o6tbZ4M= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 h1:ks7KGMVUMoDzcxNWUlEdI+/lokMFD136EL6DWmUOV80= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0/go.mod h1:hL6BWM/d/qz113fVitZjbXR0E+RCTU1+x+1Idyn5NgE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.148.0 h1:7imiXQvuqyUEu6wdcn6xRjR3zIJjDuAnS2e1S3ND+C0= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.148.0/go.mod h1:ntWksNNQcXImRQMdxab74tp+H94neF/TwQJ9Ndxb04k= +github.com/aws/aws-sdk-go-v2/service/eks v1.39.0 h1:0kuYeUF+PtxQbuIj74KQY9eUVYp06HRWWZGSExmPXqI= +github.com/aws/aws-sdk-go-v2/service/eks v1.39.0/go.mod h1:5OIWnEO/Vlng8uQmOSCxkTCuz5uh4091V3iOASiDZPQ= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.23.0 h1:DNOrYgqzRj9728Dh7Sf0cKLa3yG+z5w8ILz/X+BUnSc= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.23.0/go.mod h1:3AUoqMlKZDo28l0bjM706TIvYoJpq8siDNYYGVhqHEU= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.29.0 h1:6NKKRfzXW5KYHHuZp/QVfoj3sWFk5wZGuSnmY7EhPR8= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.29.0/go.mod h1:wBfYhqVwYqHxYkU3l5WZCdAyorLCFZf8T5ZnY6CPyw4= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0 h1:a33HuFlO0KsveiP90IUJh8Xr/cx9US2PqkSroaLc+o8= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0/go.mod h1:SxIkWpByiGbhbHYTo9CMTUnx2G4p4ZQMrDPcRRy//1c= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0 h1:SHN/umDLTmFTmYfI+gkanz6da3vK8Kvj/5wkqnTHbuA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0/go.mod h1:l8gPU5RYGOFHJqWEpPMoRTP0VoaWQSkJdKo+hwWnnDA= +github.com/aws/aws-sdk-go-v2/service/servicequotas v1.20.1 h1:RP62bFan0ocUpERLjEIgFzpcZkIccs2P3yxvNdPzETc= +github.com/aws/aws-sdk-go-v2/service/servicequotas v1.20.1/go.mod h1:qyFFLkY1mrTC8HV/GMtO5InUd6xGLtGoZulZVRl3o+o= +github.com/aws/aws-sdk-go-v2/service/ses v1.21.0 h1:0LOo7FveHh6sm7Oi08dPR4SurWRAONcf2/1Ld+z9VX8= +github.com/aws/aws-sdk-go-v2/service/ses v1.21.0/go.mod h1:uk3in5nX2gMAdKQf/Bpn9dHdPuJxnxDsAkTlgehuhLg= +github.com/aws/aws-sdk-go-v2/service/sso v1.19.0 h1:u6OkVDxtBPnxPkZ9/63ynEe+8kHbtS5IfaC4PzVxzWM= +github.com/aws/aws-sdk-go-v2/service/sso v1.19.0/go.mod h1:YqbU3RS/pkDVu+v+Nwxvn0i1WB0HkNWEePWbmODEbbs= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.0 h1:6DL0qu5+315wbsAEEmzK+P9leRwNbkp+lGjPC+CEvb8= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.0/go.mod h1:olUAyg+FaoFaL/zFaeQQONjOZ9HXoxgvI/c7mQTYz7M= +github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 h1:cjTRjh700H36MQ8M0LnDn33W3JmwC77mdxIIyPWCdpM= +github.com/aws/aws-sdk-go-v2/service/sts v1.27.0/go.mod h1:nXfOBMWPokIbOY+Gi7a1psWMSvskUCemZzI+SMB7Akc= +github.com/aws/smithy-go v1.20.0 h1:6+kZsCXZwKxZS9RfISnPc4EXlHoyAkm2hPuM8X2BrrQ= +github.com/aws/smithy-go v1.20.0/go.mod h1:uo5RKksAl4PzhqaAbjd4rLgFoq5koTsQKYuGe7dklGc= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -138,120 +97,90 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= +github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= -github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= -github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= -github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ= +github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= -github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.13.0 h1:cFRQdfaSMCOSfGCCLB20MHvuoHb/s5G8L5pu2ppK5AQ= -github.com/go-playground/validator/v10 v10.13.0/go.mod h1:dwu7+CG8/CtBiJFZDz4e+5Upb6OLw04gtBYw0mcG/z4= +github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U= +github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/flect v0.2.4 h1:BSYA8+T60cdyq+vynaSUjqSVI9mDEg9ZfQUXKmfjo4I= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= +github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -264,7 +193,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -282,17 +210,13 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.9.0/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= -github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -300,20 +224,16 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -321,68 +241,32 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= -github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= -github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= -github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= @@ -392,8 +276,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -404,30 +286,23 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA= -github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -435,28 +310,15 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microsoft/go-mssqldb v0.21.0 h1:p2rpHIL7TlSv1QrbXJUAcbyRKnIT0C9rRkH2E4OjLn8= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/microsoft/go-mssqldb v0.21.0/go.mod h1:+4wZTUnz/SV6nffv+RRRB/ss8jPng5Sho2SmM1l2ts4= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -464,126 +326,78 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -591,16 +405,13 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe h1:K8pHPVoTgxFJt1lXuIzzOX7zZhZFldJQK/CgKx9BFIc= @@ -611,72 +422,32 @@ github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw= github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.4.0 h1:sP0eIUypeNWLgUXhkko79xEnfuhBjURyPxef7+4SjjE= -github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.4.0/go.mod h1:qpFFjYuV3ATwNkHuUIWXePY/DcNUXFGlNXy0lDqoVlo= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0 h1:BBu+4LBAa6kMzOwhA5hchMa8NVW2JlyUMldoRrcd67g= +github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0/go.mod h1:4N15SpYBrqBFtblYzwp3RkRXVYlT69UZIZKbpU96FTQ= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -689,8 +460,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -703,8 +474,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -713,18 +482,12 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -736,7 +499,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -747,27 +509,17 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -775,17 +527,10 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -797,14 +542,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -815,11 +554,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -834,44 +569,25 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -879,41 +595,30 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -933,7 +638,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -941,20 +645,10 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -977,12 +671,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1012,30 +700,14 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1048,16 +720,6 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1070,7 +732,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1083,24 +744,14 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1109,22 +760,21 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/datatypes v1.1.1 h1:XAjO7NNfUKVUvnS3+BkqMrPXxCAcxDlpOYbjnizxNCw= -gorm.io/datatypes v1.1.1/go.mod h1:u8GEgFjJ+GpsGfgHmBUcQqHm/937t3sj/SO9dvbndTg= +gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco= +gorm.io/datatypes v1.2.0/go.mod h1:o1dh0ZvjIjhH/bngTpypG6lVRJ5chTBxE09FH/71k04= gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM= gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo= -gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= -gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= +gorm.io/driver/postgres v1.5.6 h1:ydr9xEd5YAM0vxVDY0X139dyzNz10spDiDlC7+ibLeU= +gorm.io/driver/postgres v1.5.6/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= +gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= gorm.io/driver/sqlserver v1.4.3 h1:ji91Zb/zS7NWrMRJBfoM9C0gyxCSh9anQoJApqEkiV8= +gorm.io/driver/sqlserver v1.4.3/go.mod h1:6ytXpaVImPf267JVRZ74Hn+gZaBRUX/HkvYx+3aS+78= gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64= -gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= goyave.dev/goyave/v4 v4.4.11 h1:HdJJ82ZWrkB7sBsituVRgQhcDvmAavfVbd6xynaUN8Y= goyave.dev/goyave/v4 v4.4.11/go.mod h1:kMbB3bf7ZhUD4Cq1Zy6nM4fHBHYO5mPSkTF6WStf4ik= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1134,51 +784,34 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8= -k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs= -k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= -k8s.io/apiextensions-apiserver v0.23.5 h1:5SKzdXyvIJKu+zbfPc3kCbWpbxi+O+zdmAJBm26UJqI= -k8s.io/apiextensions-apiserver v0.23.5/go.mod h1:ntcPWNXS8ZPKN+zTXuzYMeg731CP0heCTl6gYBxLcuQ= -k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= -k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc= -k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= -k8s.io/apiserver v0.23.5/go.mod h1:7wvMtGJ42VRxzgVI7jkbKvMbuCbVbgsWFT7RyXiRNTw= -k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4= -k8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo= -k8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4= -k8s.io/code-generator v0.23.5/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk= -k8s.io/component-base v0.23.5/go.mod h1:c5Nq44KZyt1aLl0IpHX82fhsn84Sb0jjzwjpcA42bY0= -k8s.io/component-base v0.25.2 h1:Nve/ZyHLUBHz1rqwkjXm/Re6IniNa5k7KgzxZpTfSQY= -k8s.io/component-base v0.25.2/go.mod h1:90W21YMr+Yjg7MX+DohmZLzjsBtaxQDDwaX4YxDkl60= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= +k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= +k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= +k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= +k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= +k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= +k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= +k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= +k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= +k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/kubectl v0.25.2 h1:2993lTeVimxKSWx/7z2PiJxUILygRa3tmC4QhFaeioA= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg= +k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= +k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= -sigs.k8s.io/cluster-api v1.1.3 h1:t682KcIPFeKGwe2SlxGvZa/HVmLA80XJ45KHBhzUETM= -sigs.k8s.io/cluster-api v1.1.3/go.mod h1:XqFZ0s9+KKjI/K39/EzHyAb4Sljprqvnm/XKWPgPp3Y= -sigs.k8s.io/controller-runtime v0.11.2 h1:H5GTxQl0Mc9UjRJhORusqfJCIjBO8UtUxGggCwL1rLA= -sigs.k8s.io/controller-runtime v0.11.2/go.mod h1:P6QCzrEjLaZGqHsfd+os7JQ+WFZhvB8MRFsn4dWF7O4= -sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/cluster-api v1.4.4 h1:+V+mzDe+gsWYclosvWlH0wadC8vIUsBvZLcWOYnVWRA= +sigs.k8s.io/cluster-api v1.4.4/go.mod h1:/SeFds4NXJ+Gp2etqHyoNuO6yoxTfVq6Zmd2OGxd/qM= +sigs.k8s.io/controller-runtime v0.14.5 h1:6xaWFqzT5KuAQ9ufgUaj1G/+C4Y1GRkhrxl+BJ9i+5s= +sigs.k8s.io/controller-runtime v0.14.5/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= From ef0f4e4c588ea7ed4dccd9be6dea8d8fa1b600a1 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 20 Feb 2024 06:51:05 +0000 Subject: [PATCH 035/502] trivial. resolve build error --- go.mod | 30 ++++++++-------- go.sum | 110 +++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 83 insertions(+), 57 deletions(-) diff --git a/go.mod b/go.mod index 7803d30a..d92bc9f9 100644 --- a/go.mod +++ b/go.mod @@ -43,9 +43,9 @@ require ( gorm.io/driver/postgres v1.5.6 gorm.io/gorm v1.25.7 goyave.dev/goyave/v4 v4.4.11 - k8s.io/apimachinery v0.29.2 - k8s.io/client-go v0.29.2 - k8s.io/utils v0.0.0-20240102154912-e7106e64919e + k8s.io/apimachinery v0.26.4 + k8s.io/client-go v0.26.1 + k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 ) require ( @@ -64,14 +64,14 @@ require ( github.com/blang/semver v3.5.1+incompatible // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/go-logr/logr v1.3.0 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/spec v0.20.6 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect @@ -80,8 +80,8 @@ require ( github.com/golang-jwt/jwt/v5 v5.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.15 // indirect @@ -123,7 +123,7 @@ require ( golang.org/x/term v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.16.1 // indirect + golang.org/x/tools v0.13.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect @@ -132,15 +132,15 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.5.0 // indirect - k8s.io/api v0.29.2 // indirect + k8s.io/api v0.26.1 // indirect k8s.io/apiextensions-apiserver v0.26.1 // indirect k8s.io/component-base v0.26.1 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect sigs.k8s.io/cluster-api v1.4.4 // indirect sigs.k8s.io/controller-runtime v0.14.5 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index d2cc6fdc..fc216539 100644 --- a/go.sum +++ b/go.sum @@ -39,11 +39,13 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aws/aws-sdk-go-v2 v1.25.0 h1:sv7+1JVJxOu/dD/sz/csHX7jFqmP001TIY7aytBWDSQ= github.com/aws/aws-sdk-go-v2 v1.25.0/go.mod h1:G104G1Aho5WqF+SR3mDIobTABQzpYV0WxMsKxlMggOA= github.com/aws/aws-sdk-go-v2/config v1.27.0 h1:J5sdGCAHuWKIXLeXiqr8II/adSvetkx0qdZwdbXXpb0= @@ -88,7 +90,9 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -97,6 +101,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -104,11 +110,14 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= @@ -117,12 +126,14 @@ github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -134,17 +145,16 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ= github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= @@ -215,8 +225,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -226,9 +236,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -241,9 +250,10 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -254,6 +264,7 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -294,7 +305,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -331,10 +342,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= +github.com/onsi/gomega v1.27.5 h1:T/X6I0RNFw/kTqgfkZPcQ5KU6vCnWNBGdtrIx2dpGeQ= +github.com/onsi/gomega v1.27.5/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= @@ -374,9 +385,10 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -390,6 +402,7 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= @@ -398,6 +411,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -405,11 +419,11 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -424,6 +438,9 @@ github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw= github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q= github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0 h1:BBu+4LBAa6kMzOwhA5hchMa8NVW2JlyUMldoRrcd67g= github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0/go.mod h1:4N15SpYBrqBFtblYzwp3RkRXVYlT69UZIZKbpU96FTQ= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -434,6 +451,7 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= @@ -483,8 +501,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -595,6 +613,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= @@ -647,8 +666,8 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -702,12 +721,14 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -720,6 +741,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -732,6 +756,7 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -752,6 +777,7 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -784,24 +810,24 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= -k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= +k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= +k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= -k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= -k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= -k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= +k8s.io/apimachinery v0.26.4 h1:rZccKdBLg9vP6J09JD+z8Yr99Ce8gk3Lbi9TCx05Jzs= +k8s.io/apimachinery v0.26.4/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= +k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/kubectl v0.25.2 h1:2993lTeVimxKSWx/7z2PiJxUILygRa3tmC4QhFaeioA= k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= +k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= @@ -809,9 +835,9 @@ sigs.k8s.io/cluster-api v1.4.4 h1:+V+mzDe+gsWYclosvWlH0wadC8vIUsBvZLcWOYnVWRA= sigs.k8s.io/cluster-api v1.4.4/go.mod h1:/SeFds4NXJ+Gp2etqHyoNuO6yoxTfVq6Zmd2OGxd/qM= sigs.k8s.io/controller-runtime v0.14.5 h1:6xaWFqzT5KuAQ9ufgUaj1G/+C4Y1GRkhrxl+BJ9i+5s= sigs.k8s.io/controller-runtime v0.14.5/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= From 357b27b3648263f6338c233037f9032ff93970e9 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 19 Feb 2024 10:37:44 +0900 Subject: [PATCH 036/502] feature. support for ilter --- internal/filter/util.go | 4 ---- internal/pagination/pagination.go | 14 ++++++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/internal/filter/util.go b/internal/filter/util.go index 68b9bcc4..44f350f7 100644 --- a/internal/filter/util.go +++ b/internal/filter/util.go @@ -5,7 +5,6 @@ import ( "strings" "time" - "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm/schema" "goyave.dev/goyave/v4/util/sliceutil" ) @@ -156,9 +155,6 @@ func getDataType(field *schema.Field) DataType { } func ConvertToSafeType(arg string, dataType DataType) (interface{}, bool) { - log.Info(arg) - log.Info(dataType) - switch dataType { case DataTypeText, DataTypeTextArray, DataTypeEnum, DataTypeEnumArray: return arg, true diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 73b58c9f..d7547d70 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -10,7 +10,6 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" "goyave.dev/goyave/v4" @@ -22,6 +21,7 @@ const SORT_ORDER = "sortOrder" const PAGE_NUMBER = "pageNumber" const PAGE_SIZE = "pageSize" const FILTER = "filter" +const OR = "or" const COMBINED_FILTER = "combinedFilter" var DEFAULT_LIMIT = 10 @@ -41,6 +41,7 @@ type Pagination struct { } type Filter struct { + Or bool Relation string Column string Operator string @@ -100,7 +101,7 @@ func (p *Pagination) MakePaginationRequest() { Field: field, Operator: convertOperator(f.Operator), Args: f.Values, - Or: false, + Or: f.Or, } pgFilters = append(pgFilters, &pgFilter) @@ -187,9 +188,8 @@ func NewPagination(urlParams *url.Values) (*Pagination, error) { return nil, fmt.Errorf("Invalid query string : combinedFilter ") } } - case FILTER: + case FILTER, OR: for _, filterValue := range value { - log.Debug("filterValue : ", filterValue) arr := strings.Split(filterValue, "|") column := arr[0] @@ -208,11 +208,17 @@ func NewPagination(urlParams *url.Values) (*Pagination, error) { op = arr[2] } + or := false + if key == OR { + or = true + } + pg.Filters = append(pg.Filters, Filter{ Column: helper.ToSnakeCase(strings.Replace(column, "[]", "", -1)), Relation: releation, Operator: op, Values: values, + Or: or, }) } } From 84cc40f5f19bee9d18d459eacc4ae7016c724704 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 19 Feb 2024 14:20:06 +0900 Subject: [PATCH 037/502] Add logic to check if the project namespace exists --- api/swagger/docs.go | 123 ++++++++++++++++++++++++++++++ api/swagger/swagger.json | 123 ++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 80 +++++++++++++++++++ internal/delivery/api/endpoint.go | 9 +++ internal/delivery/http/project.go | 114 ++++++++++++++++++++++++++- internal/repository/project.go | 51 ++++++++++--- internal/route/route.go | 2 + internal/usecase/project.go | 24 ++++++ pkg/domain/project.go | 4 + 9 files changed, 515 insertions(+), 15 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index fdd76771..45cd7d55 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -2290,6 +2290,56 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/projects/check/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check project name exist", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Check project name exist", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "type (name)", + "name": "type", + "in": "query" + }, + { + "type": "string", + "description": "value (project name)", + "name": "value", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckExistedResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/pass/project-roles": { "get": { "security": [ @@ -3857,6 +3907,71 @@ const docTemplate = `{ } } }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project namespace", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateProjectNamespaceRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + }, "delete": { "security": [ { @@ -8353,6 +8468,14 @@ const docTemplate = `{ } } }, + "domain.UpdateProjectNamespaceRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, "domain.UpdateProjectRequest": { "type": "object", "required": [ diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 3a7ebfa6..4cacc82f 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -2284,6 +2284,56 @@ } } }, + "/organizations/{organizationId}/projects/check/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check project name exist", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Check project name exist", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "type (name)", + "name": "type", + "in": "query" + }, + { + "type": "string", + "description": "value (project name)", + "name": "value", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CheckExistedResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/pass/project-roles": { "get": { "security": [ @@ -3851,6 +3901,71 @@ } } }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project namespace", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.UpdateProjectNamespaceRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CommonProjectResponse" + } + } + } + }, "delete": { "security": [ { @@ -8347,6 +8462,14 @@ } } }, + "domain.UpdateProjectNamespaceRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, "domain.UpdateProjectRequest": { "type": "object", "required": [ diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 2ef9e90c..04aa35d6 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2224,6 +2224,11 @@ definitions: type: object type: array type: object + domain.UpdateProjectNamespaceRequest: + properties: + description: + type: string + type: object domain.UpdateProjectRequest: properties: description: @@ -4830,6 +4835,49 @@ paths: summary: Get project namespace tags: - Projects + put: + consumes: + - application/json + description: Update project namespace + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Project Namespace + in: path + name: projectNamespace + required: true + type: string + - description: Project Stack ID + in: path + name: stackId + required: true + type: string + - description: Request body to update project namespace + in: body + name: request + required: true + schema: + $ref: '#/definitions/domain.UpdateProjectNamespaceRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CommonProjectResponse' + security: + - JWT: [] + summary: Update project namespace + tags: + - Projects /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence: get: consumes: @@ -4868,6 +4916,38 @@ paths: summary: Check project namespace exist tags: - Projects + /organizations/{organizationId}/projects/check/existence: + get: + consumes: + - application/json + description: Check project name exist + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: type (name) + in: query + name: type + type: string + - description: value (project name) + in: query + name: value + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CheckExistedResponse' + security: + - JWT: [] + summary: Check project name exist + tags: + - Projects /organizations/{organizationId}/projects/pass/project-roles: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 934dbed9..a2bd6e14 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -143,6 +143,7 @@ const ( CreateProjectNamespace GetProjectNamespaces GetProjectNamespace + UpdateProjectNamespace DeleteProjectNamespace SetFavoriteProject SetFavoriteProjectNamespace @@ -575,6 +576,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetProjectNamespace", Group: "Project", }, + UpdateProjectNamespace: { + Name: "UpdateProjectNamespace", + Group: "Project", + }, DeleteProjectNamespace: { Name: "DeleteProjectNamespace", Group: "Project", @@ -811,6 +816,8 @@ func (e Endpoint) String() string { return "GetProjectNamespaces" case GetProjectNamespace: return "GetProjectNamespace" + case UpdateProjectNamespace: + return "UpdateProjectNamespace" case DeleteProjectNamespace: return "DeleteProjectNamespace" case SetFavoriteProject: @@ -1033,6 +1040,8 @@ func GetEndpoint(name string) Endpoint { return GetProjectNamespaces case "GetProjectNamespace": return GetProjectNamespace + case "UpdateProjectNamespace": + return UpdateProjectNamespace case "DeleteProjectNamespace": return DeleteProjectNamespace case "SetFavoriteProject": diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 5ef3ca2e..d9c0fb4e 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -3,6 +3,7 @@ package http import ( "fmt" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/serializer" "net/http" "strings" @@ -22,6 +23,7 @@ type IProjectHandler interface { UpdateProject(w http.ResponseWriter, r *http.Request) DeleteProject(w http.ResponseWriter, r *http.Request) GetProject(w http.ResponseWriter, r *http.Request) + IsProjectNameExist(w http.ResponseWriter, r *http.Request) GetProjects(w http.ResponseWriter, r *http.Request) AddProjectMember(w http.ResponseWriter, r *http.Request) @@ -37,6 +39,7 @@ type IProjectHandler interface { IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) GetProjectNamespace(w http.ResponseWriter, r *http.Request) + UpdateProjectNamespace(w http.ResponseWriter, r *http.Request) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) SetFavoriteProject(w http.ResponseWriter, r *http.Request) @@ -160,8 +163,9 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { return } - // TODO: get myUserId from login component - myUserId := "58568003-9812-42d6-b10e-61a60e52cb06" + // get myUserId from login component + requestUserInfo, ok := request.UserFrom(r.Context()) + myUserId := requestUserInfo.GetUserId().String() prs := make([]domain.ProjectResponse, 0) for _, project := range ps { var projectRoleId, projectRoleName string @@ -169,6 +173,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { if myUserId == pm.ProjectUserId.String() { projectRoleId = pm.ProjectRoleId projectRoleName = pm.ProjectRole.Name + continue } } // TODO: implement AppCount @@ -268,6 +273,42 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } +// IsProjectNameExist godoc +// @Tags Projects +// @Summary Check project name exist +// @Description Check project name exist +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param type query string false "type (name)" +// @Param value query string true "value (project name)" +// @Success 200 {object} domain.CheckExistedResponse +// @Router /organizations/{organizationId}/projects/check/existence [get] +// @Security JWT +func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + urlParams := r.URL.Query() + projectName := urlParams.Get("value") + + exist, err := p.usecase.IsProjectNameExist(organizationId, projectName) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CheckExistedResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} + // UpdateProject godoc // @Tags Projects // @Summary Update project @@ -947,7 +988,7 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re ProjectId: projectId, Stack: nil, Description: projectNamespaceReq.Description, - Status: "CREATING", + Status: "RUNNING", CreatedAt: now, } @@ -1138,6 +1179,73 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque } +// UpdateProjectNamespace godoc +// @Tags Projects +// @Summary Update project namespace +// @Description Update project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectNamespace path string true "Project Namespace" +// @Param stackId path string true "Project Stack ID" +// @Param request body domain.UpdateProjectNamespaceRequest true "Request body to update project namespace" +// @Success 200 {object} domain.CommonProjectResponse +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] +// @Security JWT +func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + log.Debugf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), + "C_INVALID_PROJECT_ID", "")) + return + } + projectNamespace, ok := vars["projectNamespace"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespace"), + "C_INVALID_PROJECT_NAMESPACE", "")) + return + } + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), + "C_INVALID_STACK_ID", "")) + return + } + + var projectNamespaceReq domain.UpdateProjectNamespaceRequest + if err := UnmarshalRequestInput(r, &projectNamespaceReq); err != nil { + ErrorJSON(w, r, err) + return + } + + now := time.Now() + pn, err := p.usecase.GetProjectNamespace(organizationId, projectId, projectNamespace, stackId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project namespace.", err) + ErrorJSON(w, r, err) + return + } + + pn.Description = projectNamespaceReq.Description + pn.UpdatedAt = &now + + if err := p.usecase.UpdateProjectNamespace(pn); err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) +} + // DeleteProjectNamespace godoc // @Tags Projects // @Summary Delete project namespace diff --git a/internal/repository/project.go b/internal/repository/project.go index e671246d..606157eb 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -1,6 +1,7 @@ package repository import ( + "database/sql" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" @@ -12,6 +13,7 @@ type IProjectRepository interface { GetProjects(organizationId string) ([]domain.Project, error) GetProjectById(organizationId string, projectId string) (*domain.Project, error) GetProjectByIdAndLeader(organizationId string, projectId string) (*domain.Project, error) + GetProjectByName(organizationId string, projectName string) (*domain.Project, error) UpdateProject(p *domain.Project) error GetAllProjectRoles() ([]domain.ProjectRole, error) GetProjectRoleByName(name string) (*domain.ProjectRole, error) @@ -22,12 +24,12 @@ type IProjectRepository interface { GetProjectMemberCountByProjectId(projectId string) (*domain.GetProjectMemberCountResponse, error) GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) RemoveProjectMember(projectMemberId string) error - //UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error UpdateProjectMemberRole(pm *domain.ProjectMember) error CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error GetProjectNamespaceByName(organizationId string, projectId string, stackId string, projectNamespace string) (*domain.ProjectNamespace, error) GetProjectNamespaces(organizationId string, projectId string) ([]domain.ProjectNamespace, error) GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) + UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error } @@ -55,7 +57,8 @@ func (r *ProjectRepository) GetProjects(organizationId string) (ps []domain.Proj Preload("ProjectMembers"). Preload("ProjectMembers.ProjectRole"). Preload("ProjectMembers.ProjectUser"). - Preload("ProjectNamespaces").Find(&ps) + Preload("ProjectNamespaces"). + Find(&ps) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project") @@ -85,14 +88,12 @@ func (r *ProjectRepository) GetProjectById(organizationId string, projectId stri } func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, projectId string) (p *domain.Project, err error) { - res := r.db.Limit(1).Where("projects.organization_id = ? and projects.id = ?", organizationId, projectId). - Limit(1).Preload("ProjectMembers", "is_project_leader = ?", true). + res := r.db.Limit(1). + Preload("ProjectMembers", "is_project_leader = ?", true). Preload("ProjectMembers.ProjectRole"). Preload("ProjectMembers.ProjectUser"). - //InnerJoins("ProjectMembers", r.db.Where(&domain.ProjectMember{IsProjectLeader: true})). - //InnerJoins("ProjectMembers.ProjectRole"). - //InnerJoins("ProjectMembers.ProjectUser"). - First(&p) + First(&p, "organization_id = ? and id = ?", organizationId, projectId) + if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project") @@ -106,6 +107,23 @@ func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, proje return p, nil } +func (r *ProjectRepository) GetProjectByName(organizationId string, projectName string) (p *domain.Project, err error) { + res := r.db.Limit(1). + Where("organization_id = ? and name = ?", organizationId, projectName). + First(&p) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found project name") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return p, nil +} + func (r *ProjectRepository) UpdateProject(p *domain.Project) error { res := r.db.Model(&p).Updates(domain.Project{Name: p.Name, Description: p.Description, UpdatedAt: p.UpdatedAt}) if res.Error != nil { @@ -220,18 +238,18 @@ func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) ( " from (select count(project_members.id) as count"+ " from project_members"+ " left join project_roles on project_roles.id = project_members.project_role_id"+ - " where project_members.project_id = ?"+ + " where project_members.project_id = @projectId"+ " and project_roles.name = 'project-leader') as plc,"+ " (select count(project_members.id) as count"+ " from project_members"+ " left join project_roles on project_roles.id = project_members.project_role_id"+ - " where project_members.project_id = ?"+ + " where project_members.project_id = @projectId"+ " and project_roles.name = 'project-member') as pmc,"+ " (select count(project_members.id) as count"+ " from project_members"+ " left join project_roles on project_roles.id = project_members.project_role_id"+ - " where project_members.project_id = ?"+ - " and project_roles.name = 'project-viewer') as pvc", projectId, projectId, projectId). + " where project_members.project_id = @projectId"+ + " and project_roles.name = 'project-viewer') as pvc", sql.Named("projectId", projectId)). Scan(&pmcr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -353,6 +371,15 @@ func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(organizationId strin return pn, nil } +func (r *ProjectRepository) UpdateProjectNamespace(pn *domain.ProjectNamespace) error { + res := r.db.Model(&pn).Updates(domain.ProjectNamespace{Description: pn.Description, UpdatedAt: pn.UpdatedAt}) + if res.Error != nil { + return res.Error + } + + return nil +} + func (r *ProjectRepository) DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error { res := r.db.Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). diff --git a/internal/route/route.go b/internal/route/route.go index 20723a55..248968c9 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -200,6 +200,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.CreateProject, http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/check/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNameExist))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.DeleteProject, http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/pass/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) @@ -216,6 +217,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNamespaceExist))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateProjectNamespace, http.HandlerFunc(projectHandler.UpdateProjectNamespace))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 70d9cbb3..46cf0751 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -22,6 +22,7 @@ type IProjectUsecase interface { GetProjects(organizationId string) ([]domain.Project, error) GetProject(organizationId string, projectId string) (*domain.Project, error) GetProjectWithLeader(organizationId string, projectId string) (*domain.Project, error) + IsProjectNameExist(organizationId string, projectName string) (bool, error) UpdateProject(p *domain.Project) error GetProjectRole(id string) (*domain.ProjectRole, error) GetProjectRoles(int) ([]domain.ProjectRole, error) @@ -36,6 +37,7 @@ type IProjectUsecase interface { IsProjectNamespaceExist(organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) GetProjectNamespaces(organizationId string, projectId string) ([]domain.ProjectNamespace, error) GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) + UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error } @@ -97,6 +99,20 @@ func (u *ProjectUsecase) GetProjectWithLeader(organizationId string, projectId s return p, err } +func (u *ProjectUsecase) IsProjectNameExist(organizationId string, projectName string) (bool, error) { + exist := true + p, err := u.projectRepo.GetProjectByName(organizationId, projectName) + if err != nil { + log.Error(err) + exist = false + return exist, errors.Wrap(err, "Failed to retrieve project name.") + } + if p == nil { + exist = false + } + return exist, nil +} + func (u *ProjectUsecase) UpdateProject(p *domain.Project) error { if err := u.projectRepo.UpdateProject(p); err != nil { log.Error(err) @@ -266,6 +282,14 @@ func (u *ProjectUsecase) GetProjectNamespace(organizationId string, projectId st return pn, nil } +func (u *ProjectUsecase) UpdateProjectNamespace(pn *domain.ProjectNamespace) error { + if err := u.projectRepo.UpdateProjectNamespace(pn); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to update project namespace") + } + return nil +} + func (u *ProjectUsecase) DeleteProjectNamespace(organizationId string, projectId string, stackId string, projectNamespace string) error { if err := u.projectRepo.DeleteProjectNamespace(organizationId, projectId, projectNamespace, stackId); err != nil { diff --git a/pkg/domain/project.go b/pkg/domain/project.go index a60059eb..b75e9334 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -249,3 +249,7 @@ type GetProjectNamespacesResponse struct { type GetProjectNamespaceResponse struct { ProjectNamespace *ProjectNamespaceResponse `json:"projectNamespace"` } + +type UpdateProjectNamespaceRequest struct { + Description string `json:"description"` +} From 18911e2012c224b450e62cce13d15ed6a0d713b3 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 20 Feb 2024 14:53:31 +0900 Subject: [PATCH 038/502] merge commit --- internal/delivery/api/endpoint.go | 31 +++++++++++ internal/delivery/http/project.go | 32 +++++++++++ internal/kubernetes/kubernetes.go | 41 ++++++++++++++ internal/kubernetes/kubernetes_test.go | 74 ++++++++++++++++++++++++++ internal/route/route.go | 1 + internal/usecase/project.go | 22 ++++++++ pkg/domain/project.go | 4 ++ 7 files changed, 205 insertions(+) create mode 100644 internal/kubernetes/kubernetes_test.go diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index a2bd6e14..21ee33c4 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -149,6 +149,7 @@ const ( SetFavoriteProjectNamespace UnSetFavoriteProject UnSetFavoriteProjectNamespace + GetProjectKubeconfig ) var ApiMap = map[Endpoint]EndpointInfo{ @@ -344,6 +345,14 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetAppServeApp", Group: "AppServeApp", }, + GetAppServeAppTasksByAppId: { + Name: "GetAppServeAppTasksByAppId", + Group: "AppServeApp", + }, + GetAppServeAppTaskDetail: { + Name: "GetAppServeAppTaskDetail", + Group: "AppServeApp", + }, GetAppServeAppLatestTask: { Name: "GetAppServeAppLatestTask", Group: "AppServeApp", @@ -600,6 +609,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UnSetFavoriteProjectNamespace", Group: "Project", }, + GetProjectKubeconfig: { + Name: "GetProjectKubeconfig", + Group: "Project", + }, } func (e Endpoint) String() string { @@ -700,6 +713,10 @@ func (e Endpoint) String() string { return "GetNumOfAppsOnStack" case GetAppServeApp: return "GetAppServeApp" + case GetAppServeAppTasksByAppId: + return "GetAppServeAppTasksByAppId" + case GetAppServeAppTaskDetail: + return "GetAppServeAppTaskDetail" case GetAppServeAppLatestTask: return "GetAppServeAppLatestTask" case IsAppServeAppExist: @@ -828,6 +845,8 @@ func (e Endpoint) String() string { return "UnSetFavoriteProject" case UnSetFavoriteProjectNamespace: return "UnSetFavoriteProjectNamespace" + case GetProjectKubeconfig: + return "GetProjectKubeconfig" default: return "" } @@ -930,6 +949,10 @@ func GetEndpoint(name string) Endpoint { return GetNumOfAppsOnStack case "GetAppServeApp": return GetAppServeApp + case "GetAppServeAppTasksByAppId": + return GetAppServeAppTasksByAppId + case "GetAppServeAppTaskDetail": + return GetAppServeAppTaskDetail case "GetAppServeAppLatestTask": return GetAppServeAppLatestTask case "IsAppServeAppExist": @@ -1018,6 +1041,10 @@ func GetEndpoint(name string) Endpoint { return InstallStack case "CreateProject": return CreateProject + case "GetProjectRoles": + return GetProjectRoles + case "GetProjectRole": + return GetProjectRole case "GetProjects": return GetProjects case "GetProject": @@ -1028,6 +1055,8 @@ func GetEndpoint(name string) Endpoint { return DeleteProject case "AddProjectMember": return AddProjectMember + case "GetProjectMember": + return GetProjectMember case "GetProjectMembers": return GetProjectMembers case "RemoveProjectMember": @@ -1052,6 +1081,8 @@ func GetEndpoint(name string) Endpoint { return UnSetFavoriteProject case "UnSetFavoriteProjectNamespace": return UnSetFavoriteProjectNamespace + case "GetProjectKubeconfig": + return GetProjectKubeconfig default: return -1 } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index d9c0fb4e..185fba18 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -46,6 +46,8 @@ type IProjectHandler interface { SetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) UnSetFavoriteProject(w http.ResponseWriter, r *http.Request) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) + + GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) } type ProjectHandler struct { @@ -1311,3 +1313,33 @@ func (p ProjectHandler) UnSetFavoriteProject(w http.ResponseWriter, r *http.Requ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) { //TODO implement me } + +func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found in path"), + "C_INVALID_PROJECT_ID", "")) + return + } + + kubeconfig, err := p.usecase.GetProjectKubeconfig(organizationId, projectId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project kubeconfig.", err) + ErrorJSON(w, r, err) + return + } + + out := domain.GetProjectKubeconfigResponse{ + Kubeconfig: kubeconfig, + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index d202a55d..6b5f577b 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -3,6 +3,7 @@ package kubernetes import ( "context" "fmt" + "gopkg.in/yaml.v3" "strings" "github.com/spf13/viper" @@ -185,3 +186,43 @@ func GetKubernetesVserion() (string, error) { return information.GitVersion, nil } + +func MergeKubeconfigsWithSingleUser(kubeconfigs []string) (string, error) { + type kubeConfigType struct { + APIVersion string `yaml:"apiVersion"` + Kind string `yaml:"kind"` + Clusters []struct { + Name string `yaml:"name"` + Cluster struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + } `yaml:"cluster"` + } `yaml:"clusters"` + Contexts []struct { + Name string `yaml:"name"` + Context struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + } `yaml:"context"` + } `yaml:"contexts"` + Users []interface{} `yaml:"users,omitempty"` + } + + var config kubeConfigType + var combindConfig kubeConfigType + for _, kc := range kubeconfigs { + err := yaml.Unmarshal([]byte(kc), &config) + if err != nil { + return "", err + } + combindConfig.APIVersion = config.APIVersion + combindConfig.Kind = config.Kind + combindConfig.Clusters = append(combindConfig.Clusters, config.Clusters...) + combindConfig.Contexts = append(combindConfig.Contexts, config.Contexts...) + combindConfig.Users = config.Users + } + + modContents, err := yaml.Marshal(combindConfig) + + return string(modContents), err +} diff --git a/internal/kubernetes/kubernetes_test.go b/internal/kubernetes/kubernetes_test.go new file mode 100644 index 00000000..c4203ea7 --- /dev/null +++ b/internal/kubernetes/kubernetes_test.go @@ -0,0 +1,74 @@ +package kubernetes_test + +import ( + "github.com/openinfradev/tks-api/internal/kubernetes" + "testing" +) + +func TestMergeKubeconfigsWithSingleUser(t *testing.T) { + kubeconfigs := []string{ + `apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: test + server: https://10.10.202.33:6443 + name: test-cluster +contexts: +- context: + cluster: test-cluster + user: oidc-user + name: oidc-user@test-cluster +kind: Config +preferences: {} +users: +- name: oidc-user + user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + args: + - oidc-login + - get-token + - --oidc-issuer-url=https://tks-console-stg.skbroadband.com/auth/realms/o25pwnjp0 + - --oidc-client-id=c03fk0ox4-k8s-api + - --grant-type=password + command: kubectl + env: null + interactiveMode: IfAvailable + provideClusterInfo: false`, + + `apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: test + server: https://10.10.202.33:6443 + name: test-cluster2 +contexts: +- context: + cluster: test-cluster2 + user: oidc-user + name: oidc-user@test-cluster2 +kind: Config +preferences: {} +users: +- name: oidc-user + user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + args: + - oidc-login + - get-token + - --oidc-issuer-url=https://tks-console-stg.skbroadband.com/auth/realms/o25pwnjp0 + - --oidc-client-id=c03fk0ox4-k8s-api + - --grant-type=password + command: kubectl + env: null + interactiveMode: IfAvailable + provideClusterInfo: false `, + } + + out, err := kubernetes.MergeKubeconfigsWithSingleUser(kubeconfigs) + if err != nil { + t.Error(err) + } + t.Log(out) +} diff --git a/internal/route/route.go b/internal/route/route.go index 248968c9..951cb554 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -219,6 +219,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateProjectNamespace, http.HandlerFunc(projectHandler.UpdateProjectNamespace))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 46cf0751..4662f64f 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -2,6 +2,7 @@ package usecase import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -39,6 +40,7 @@ type IProjectUsecase interface { GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error + GetProjectKubeconfig(organizationId string, projectId string) (string, error) } type ProjectUsecase struct { @@ -298,3 +300,23 @@ func (u *ProjectUsecase) DeleteProjectNamespace(organizationId string, projectId } return nil } + +func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId string) (string, error) { + projectNamespaces, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) + if err != nil { + log.Error(err) + return "", errors.Wrap(err, "Failed to retrieve project namespaces.") + } + + kubeconfigs := make([]string, 0) + for _, pn := range projectNamespaces { + kubeconfig, err := kubernetes.GetKubeConfig(pn.StackId) + if err != nil { + log.Error(err) + return "", errors.Wrap(err, "Failed to retrieve kubeconfig.") + } + kubeconfigs = append(kubeconfigs, string(kubeconfig[:])) + } + + return kubernetes.MergeKubeconfigsWithSingleUser(kubeconfigs) +} diff --git a/pkg/domain/project.go b/pkg/domain/project.go index b75e9334..6f0639e2 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -253,3 +253,7 @@ type GetProjectNamespaceResponse struct { type UpdateProjectNamespaceRequest struct { Description string `json:"description"` } + +type GetProjectKubeconfigResponse struct { + Kubeconfig string `json:"kubeconfig"` +} From 81d76f3b852adbfa2bcbf154fb21d0b9812bfae0 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 20 Feb 2024 17:09:13 +0900 Subject: [PATCH 039/502] add project kubeconfig with namespace --- internal/kubernetes/kubernetes.go | 22 +- internal/kubernetes/kubernetes_test.go | 351 ++++++++++++++++++++----- internal/usecase/project.go | 38 +++ 3 files changed, 348 insertions(+), 63 deletions(-) diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index 6b5f577b..8addc0b1 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -1,9 +1,11 @@ package kubernetes import ( + "bytes" "context" "fmt" "gopkg.in/yaml.v3" + "os" "strings" "github.com/spf13/viper" @@ -201,13 +203,21 @@ func MergeKubeconfigsWithSingleUser(kubeconfigs []string) (string, error) { Contexts []struct { Name string `yaml:"name"` Context struct { - Cluster string `yaml:"cluster"` - User string `yaml:"user"` + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` } `yaml:"context"` } `yaml:"contexts"` + Users []interface{} `yaml:"users,omitempty"` } + var buf bytes.Buffer + encoder := yaml.NewEncoder(&buf) + defer encoder.Close() + + encoder.SetIndent(2) + var config kubeConfigType var combindConfig kubeConfigType for _, kc := range kubeconfigs { @@ -222,7 +232,11 @@ func MergeKubeconfigsWithSingleUser(kubeconfigs []string) (string, error) { combindConfig.Users = config.Users } - modContents, err := yaml.Marshal(combindConfig) + err := encoder.Encode(combindConfig) + //modContents, err := yaml.Marshal(combindConfig) + + // write the kubeconfig to a file + err = os.WriteFile("combind-kubeconfig", buf.Bytes(), 0644) - return string(modContents), err + return buf.String(), err } diff --git a/internal/kubernetes/kubernetes_test.go b/internal/kubernetes/kubernetes_test.go index c4203ea7..3f8a578a 100644 --- a/internal/kubernetes/kubernetes_test.go +++ b/internal/kubernetes/kubernetes_test.go @@ -2,73 +2,306 @@ package kubernetes_test import ( "github.com/openinfradev/tks-api/internal/kubernetes" + "gopkg.in/yaml.v3" + "reflect" "testing" ) func TestMergeKubeconfigsWithSingleUser(t *testing.T) { - kubeconfigs := []string{ - `apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: test - server: https://10.10.202.33:6443 - name: test-cluster -contexts: -- context: - cluster: test-cluster - user: oidc-user - name: oidc-user@test-cluster -kind: Config -preferences: {} -users: -- name: oidc-user - user: - exec: - apiVersion: client.authentication.k8s.io/v1beta1 - args: - - oidc-login - - get-token - - --oidc-issuer-url=https://tks-console-stg.skbroadband.com/auth/realms/o25pwnjp0 - - --oidc-client-id=c03fk0ox4-k8s-api - - --grant-type=password - command: kubectl - env: null - interactiveMode: IfAvailable - provideClusterInfo: false`, + type kubeConfigType struct { + APIVersion string `yaml:"apiVersion"` + Kind string `yaml:"kind"` + Clusters []struct { + Name string `yaml:"name"` + Cluster struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + } `yaml:"cluster"` + } `yaml:"clusters"` + Contexts []struct { + Name string `yaml:"name"` + Context struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + } `yaml:"context"` + } `yaml:"contexts"` - `apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: test - server: https://10.10.202.33:6443 - name: test-cluster2 -contexts: -- context: - cluster: test-cluster2 - user: oidc-user - name: oidc-user@test-cluster2 -kind: Config -preferences: {} -users: -- name: oidc-user - user: - exec: - apiVersion: client.authentication.k8s.io/v1beta1 - args: - - oidc-login - - get-token - - --oidc-issuer-url=https://tks-console-stg.skbroadband.com/auth/realms/o25pwnjp0 - - --oidc-client-id=c03fk0ox4-k8s-api - - --grant-type=password - command: kubectl - env: null - interactiveMode: IfAvailable - provideClusterInfo: false `, + Users []interface{} `yaml:"users,omitempty"` } - out, err := kubernetes.MergeKubeconfigsWithSingleUser(kubeconfigs) + inputObjs := []kubeConfigType{ + { + APIVersion: "v1", + Kind: "Config", + Clusters: []struct { + Name string `yaml:"name"` + Cluster struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + } `yaml:"cluster"` + }{ + { + Name: "test-cluster1", + Cluster: struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + }{ + Server: "https://10.0.0.1:6443", + CertificateAuthorityData: "test==", + }, + }, + }, + Contexts: []struct { + Name string `yaml:"name"` + Context struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + } `yaml:"context"` + }{ + { + Name: "oidc-user@test-cluster1", + Context: struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + }{ + Cluster: "test-cluster1", + User: "oidc-user", + Namespace: "test-namespaces", + }, + }, + }, + Users: []interface{}{ + map[string]interface{}{ + "name": "oidc-user", + "user": map[string]interface{}{ + "exec": map[string]interface{}{ + "apiVersion": "client.authentication.k8s.io/v1beta1", + "args": []string{ + "oidc-login", + "get-token", + "--oidc-issuer-url=https://idp-domain/auth", + "--oidc-client-id=k8s-api", + "--grant-type=password", + }, + "command": "kubectl", + "env": nil, + "interactiveMode": "IfAvailable", + "provideClusterInfo": false, + }, + }, + }, + }, + }, + { + APIVersion: "v1", + Kind: "Config", + Clusters: []struct { + Name string `yaml:"name"` + Cluster struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + } `yaml:"cluster"` + }{ + { + Name: "test-cluster2", + Cluster: struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + }{ + Server: "https://10.0.0.2:6443", + CertificateAuthorityData: "test2==", + }, + }, + }, + Contexts: []struct { + Name string `yaml:"name"` + Context struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + } `yaml:"context"` + }{ + { + Name: "oidc-user@test-cluster2", + Context: struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + }{ + Cluster: "test-cluster2", + User: "oidc-user", + }, + }, + }, + Users: []interface{}{ + map[string]interface{}{ + "name": "oidc-user", + "user": map[string]interface{}{ + "exec": map[string]interface{}{ + "apiVersion": "client.authentication.k8s.io/v1beta1", + "args": []string{ + "oidc-login", + "get-token", + "--oidc-issuer-url=https://idp-domain/auth", + "--oidc-client-id=k8s-api", + "--grant-type=password", + }, + "command": "kubectl", + "env": nil, + "interactiveMode": "IfAvailable", + "provideClusterInfo": false, + }, + }, + }, + }, + }, + } + + expected := kubeConfigType{ + APIVersion: "v1", + Kind: "Config", + Clusters: []struct { + Name string `yaml:"name"` + Cluster struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + } `yaml:"cluster"` + }{ + { + Name: "test-cluster1", + Cluster: struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + }{ + Server: "https://10.0.0.1:6443", + CertificateAuthorityData: "test==", + }, + }, + { + Name: "test-cluster2", + Cluster: struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + }{ + Server: "https://10.0.0.2:6443", + CertificateAuthorityData: "test2==", + }, + }, + }, + Contexts: []struct { + Name string `yaml:"name"` + Context struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + } `yaml:"context"` + }{ + { + Name: "oidc-user@test-cluster1", + Context: struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + }{ + Cluster: "test-cluster1", + User: "oidc-user", + Namespace: "test-namespaces", + }, + }, + { + Name: "oidc-user@test-cluster2", + Context: struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + }{ + Cluster: "test-cluster2", + User: "oidc-user", + }, + }, + }, + + Users: []interface{}{ + map[string]interface{}{ + "name": "oidc-user2", + "user": map[string]interface{}{ + "exec": map[string]interface{}{ + "apiVersion": "client.authentication.k8s.io/v1beta1", + "args": []string{ + "oidc-login", + "get-token", + "--oidc-issuer-url=https://idp-domain/auth", + "--oidc-client-id=k8s-api", + "--grant-type=password", + }, + "command": "kubectl", + "env": nil, + "interactiveMode": "IfAvailable", + "provideClusterInfo": false, + }, + }, + }, + }, + } + + in := make([]string, len(inputObjs)) + for _, v := range inputObjs { + o, err := yaml.Marshal(&v) + if err != nil { + t.Error(err) + } + in = append(in, string(o)) + } + r, err := kubernetes.MergeKubeconfigsWithSingleUser(in) + t.Log(r) if err != nil { t.Error(err) } - t.Log(out) + + var result kubeConfigType + if err := yaml.Unmarshal([]byte(r), &result); err != nil { + t.Error(err) + } + + { + if result.APIVersion != expected.APIVersion { + t.Errorf("expected: %s, got: %s", expected.APIVersion, result.APIVersion) + } + if result.Kind != expected.Kind { + t.Errorf("expected: %s, got: %s", expected.Kind, result.Kind) + } + for i, v := range result.Clusters { + if v.Name != expected.Clusters[i].Name { + t.Errorf("expected: %s, got: %s", expected.Clusters[i].Name, v.Name) + } + if v.Cluster.Server != expected.Clusters[i].Cluster.Server { + t.Errorf("expected: %s, got: %s", expected.Clusters[i].Cluster.Server, v.Cluster.Server) + } + if v.Cluster.CertificateAuthorityData != expected.Clusters[i].Cluster.CertificateAuthorityData { + t.Errorf("expected: %s, got: %s", expected.Clusters[i].Cluster.CertificateAuthorityData, v.Cluster.CertificateAuthorityData) + } + } + for i, v := range result.Contexts { + if v.Name != expected.Contexts[i].Name { + t.Errorf("expected: %s, got: %s", expected.Contexts[i].Name, v.Name) + } + if v.Context.Cluster != expected.Contexts[i].Context.Cluster { + t.Errorf("expected: %s, got: %s", expected.Contexts[i].Context.Cluster, v.Context.Cluster) + } + if v.Context.User != expected.Contexts[i].Context.User { + t.Errorf("expected: %s, got: %s", expected.Contexts[i].Context.User, v.Context.User) + } + if v.Context.Namespace != expected.Contexts[i].Context.Namespace { + t.Errorf("expected: %s, got: %s", expected.Contexts[i].Context.Namespace, v.Context.Namespace) + } + } + + //ToDo: This test case down below results in true negative. Need to fix the test case. + if reflect.DeepEqual(result.Users, expected.Users) { + t.Errorf("expected: %v, got: %v", expected.Users, result.Users) + } + } } diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 4662f64f..6c70077f 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -9,6 +9,7 @@ import ( "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" + "gopkg.in/yaml.v3" ) const ( @@ -308,6 +309,28 @@ func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId s return "", errors.Wrap(err, "Failed to retrieve project namespaces.") } + type kubeConfigType struct { + APIVersion string `yaml:"apiVersion"` + Kind string `yaml:"kind"` + Clusters []struct { + Name string `yaml:"name"` + Cluster struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + } `yaml:"cluster"` + } `yaml:"clusters"` + Contexts []struct { + Name string `yaml:"name"` + Context struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + } `yaml:"context"` + } `yaml:"contexts"` + + Users []interface{} `yaml:"users,omitempty"` + } + kubeconfigs := make([]string, 0) for _, pn := range projectNamespaces { kubeconfig, err := kubernetes.GetKubeConfig(pn.StackId) @@ -315,6 +338,21 @@ func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId s log.Error(err) return "", errors.Wrap(err, "Failed to retrieve kubeconfig.") } + + var config kubeConfigType + err = yaml.Unmarshal(kubeconfig, &config) + if err != nil { + log.Error(err) + return "", errors.Wrap(err, "Failed to unmarshal kubeconfig.") + } + config.Contexts[0].Context.Namespace = pn.Namespace + + kubeconfig, err = yaml.Marshal(config) + if err != nil { + log.Error(err) + return "", errors.Wrap(err, "Failed to marshal kubeconfig.") + } + kubeconfigs = append(kubeconfigs, string(kubeconfig[:])) } From 6460365c9a179a67f4e27734b16597484ecae81a Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 20 Feb 2024 17:16:18 +0900 Subject: [PATCH 040/502] add swag docs --- internal/delivery/http/project.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 185fba18..fffd35ab 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1314,6 +1314,17 @@ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r * //TODO implement me } +// GetProjectKubeconfig godoc +// @Tags Projects +// @Summary Get project kubeconfig +// @Description Get project kubeconfig +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} domain.GetProjectKubeconfigResponse +// @Router /organizations/{organizationId}/projects/{projectId}/kubeconfig [get] +// @Security JWT func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] From d4ee7d6bd555d4013e03188fb4f5fcc1c80b357f Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 21 Feb 2024 15:20:48 +0900 Subject: [PATCH 041/502] feature. refactoring usecase --- api/swagger/docs.go | 52 ++++++++++++++++++++++++ api/swagger/swagger.json | 52 ++++++++++++++++++++++++ api/swagger/swagger.yaml | 33 +++++++++++++++ internal/delivery/http/alert.go | 4 +- internal/delivery/http/app-group.go | 4 +- internal/delivery/http/app-serve-app.go | 14 +++---- internal/delivery/http/auth.go | 4 +- internal/delivery/http/cloud-account.go | 4 +- internal/delivery/http/cluster.go | 4 +- internal/delivery/http/dashboard.go | 4 +- internal/delivery/http/organization.go | 6 +-- internal/delivery/http/project.go | 11 ++--- internal/delivery/http/stack-template.go | 4 +- internal/delivery/http/stack.go | 4 +- internal/delivery/http/user.go | 4 +- internal/route/route.go | 51 +++++++++++++++-------- internal/usecase/usecase.go | 32 ++++++--------- 17 files changed, 218 insertions(+), 69 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 45cd7d55..0520123d 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3334,6 +3334,50 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project kubeconfig", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project kubeconfig", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectKubeconfigResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/members": { "get": { "security": [ @@ -7093,6 +7137,14 @@ const docTemplate = `{ } } }, + "domain.GetProjectKubeconfigResponse": { + "type": "object", + "properties": { + "kubeconfig": { + "type": "string" + } + } + }, "domain.GetProjectMemberCountResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 4cacc82f..a9f7dbc0 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3328,6 +3328,50 @@ } } }, + "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project kubeconfig", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project kubeconfig", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectKubeconfigResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/members": { "get": { "security": [ @@ -7087,6 +7131,14 @@ } } }, + "domain.GetProjectKubeconfigResponse": { + "type": "object", + "properties": { + "kubeconfig": { + "type": "string" + } + } + }, "domain.GetProjectMemberCountResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 04aa35d6..8f0537c5 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1314,6 +1314,11 @@ definitions: type: string type: object type: object + domain.GetProjectKubeconfigResponse: + properties: + kubeconfig: + type: string + type: object domain.GetProjectMemberCountResponse: properties: projectLeaderCount: @@ -4425,6 +4430,34 @@ paths: summary: Check duplicate appServeAppName tags: - AppServeApps + /organizations/{organizationId}/projects/{projectId}/kubeconfig: + get: + consumes: + - application/json + description: Get project kubeconfig + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectKubeconfigResponse' + security: + - JWT: [] + summary: Get project kubeconfig + tags: + - Projects /organizations/{organizationId}/projects/{projectId}/members: delete: consumes: diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index b03d8f3b..3591c4dd 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -21,9 +21,9 @@ type AlertHandler struct { usecase usecase.IAlertUsecase } -func NewAlertHandler(h usecase.IAlertUsecase) *AlertHandler { +func NewAlertHandler(h usecase.Usecase) *AlertHandler { return &AlertHandler{ - usecase: h, + usecase: h.Alert, } } diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 14aa7da6..1efd767a 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -18,9 +18,9 @@ type AppGroupHandler struct { usecase usecase.IAppGroupUsecase } -func NewAppGroupHandler(h usecase.IAppGroupUsecase) *AppGroupHandler { +func NewAppGroupHandler(h usecase.Usecase) *AppGroupHandler { return &AppGroupHandler{ - usecase: h, + usecase: h.AppGroup, } } diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 578e69fc..b2bd74d0 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -71,9 +71,9 @@ type AppServeAppHandler struct { usecase usecase.IAppServeAppUsecase } -func NewAppServeAppHandler(h usecase.IAppServeAppUsecase) *AppServeAppHandler { +func NewAppServeAppHandler(h usecase.Usecase) *AppServeAppHandler { return &AppServeAppHandler{ - usecase: h, + usecase: h.AppServeApp, } } @@ -289,10 +289,10 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ // @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Request) { - ////////////////////////////////////////////////////////////////////////////////////////// - // TODO: this API will'be deprecated soon once the new task-related API's are verified. - // Until then, this is available (except for stage info) just for backward compatibility. - ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + // TODO: this API will'be deprecated soon once the new task-related API's are verified. + // Until then, this is available (except for stage info) just for backward compatibility. + ////////////////////////////////////////////////////////////////////////////////////////// vars := mux.Vars(r) @@ -333,7 +333,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque var out domain.GetAppServeAppResponse out.AppServeApp = *app - // NOTE: makeStages function's been changed to use task instead of app + // NOTE: makeStages function's been changed to use task instead of app //out.Stages = makeStages(app) ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index c04dd331..1b84dbde 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -30,9 +30,9 @@ type AuthHandler struct { usecase usecase.IAuthUsecase } -func NewAuthHandler(h usecase.IAuthUsecase) IAuthHandler { +func NewAuthHandler(h usecase.Usecase) IAuthHandler { return &AuthHandler{ - usecase: h, + usecase: h.Auth, } } diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 64b6edab..dfce7a78 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -20,9 +20,9 @@ type CloudAccountHandler struct { usecase usecase.ICloudAccountUsecase } -func NewCloudAccountHandler(h usecase.ICloudAccountUsecase) *CloudAccountHandler { +func NewCloudAccountHandler(h usecase.Usecase) *CloudAccountHandler { return &CloudAccountHandler{ - usecase: h, + usecase: h.CloudAccount, } } diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index e2bba0f2..5cd1848a 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -18,9 +18,9 @@ type ClusterHandler struct { usecase usecase.IClusterUsecase } -func NewClusterHandler(h usecase.IClusterUsecase) *ClusterHandler { +func NewClusterHandler(h usecase.Usecase) *ClusterHandler { return &ClusterHandler{ - usecase: h, + usecase: h.Cluster, } } diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 46ae2f07..babc03ae 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -17,9 +17,9 @@ type DashboardHandler struct { usecase usecase.IDashboardUsecase } -func NewDashboardHandler(h usecase.IDashboardUsecase) *DashboardHandler { +func NewDashboardHandler(h usecase.Usecase) *DashboardHandler { return &DashboardHandler{ - usecase: h, + usecase: h.Dashboard, } } diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 67c7e252..1d90f6a0 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -19,10 +19,10 @@ type OrganizationHandler struct { userUsecase usecase.IUserUsecase } -func NewOrganizationHandler(o usecase.IOrganizationUsecase, u usecase.IUserUsecase) *OrganizationHandler { +func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { return &OrganizationHandler{ - usecase: o, - userUsecase: u, + usecase: u.Organization, + userUsecase: u.User, } } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index fffd35ab..557ebc91 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -2,13 +2,14 @@ package http import ( "fmt" - "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/serializer" "net/http" "strings" "time" + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" @@ -54,9 +55,9 @@ type ProjectHandler struct { usecase usecase.IProjectUsecase } -func NewProjectHandler(u usecase.IProjectUsecase) IProjectHandler { +func NewProjectHandler(u usecase.Usecase) IProjectHandler { return &ProjectHandler{ - usecase: u, + usecase: u.Project, } } diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index c2ad628c..4e699d35 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -20,9 +20,9 @@ type StackTemplateHandler struct { usecase usecase.IStackTemplateUsecase } -func NewStackTemplateHandler(h usecase.IStackTemplateUsecase) *StackTemplateHandler { +func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { return &StackTemplateHandler{ - usecase: h, + usecase: h.StackTemplate, } } diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index d92f6d1e..1ec8987d 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -18,9 +18,9 @@ type StackHandler struct { usecase usecase.IStackUsecase } -func NewStackHandler(h usecase.IStackUsecase) *StackHandler { +func NewStackHandler(h usecase.Usecase) *StackHandler { return &StackHandler{ - usecase: h, + usecase: h.Stack, } } diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 2144ec0a..85ad3ce4 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -37,9 +37,9 @@ type UserHandler struct { usecase usecase.IUserUsecase } -func NewUserHandler(h usecase.IUserUsecase) IUserHandler { +func NewUserHandler(h usecase.Usecase) IUserHandler { return &UserHandler{ - usecase: h, + usecase: h.User, } } diff --git a/internal/route/route.go b/internal/route/route.go index 951cb554..448e9361 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -4,13 +4,14 @@ import ( "bytes" "context" "fmt" - internalApi "github.com/openinfradev/tks-api/internal/delivery/api" - "github.com/openinfradev/tks-api/internal/middleware/audit" - "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" "io" "net/http" "time" + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/middleware/audit" + "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" + "github.com/google/uuid" "github.com/gorilla/handlers" "github.com/gorilla/mux" @@ -52,6 +53,8 @@ func (r *StatusRecorder) WriteHeader(status int) { func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloak, asset http.Handler) http.Handler { r := mux.NewRouter() + cache := gcache.New(5*time.Minute, 10*time.Minute) + repoFactory := repository.Repository{ Auth: repository.NewAuthRepository(db), User: repository.NewUserRepository(db), @@ -64,20 +67,34 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Alert: repository.NewAlertRepository(db), Project: repository.NewProjectRepository(db), } + + usecaseFactory := usecase.Usecase{ + Auth: usecase.NewAuthUsecase(repoFactory, kc), + User: usecase.NewUserUsecase(repoFactory, kc), + Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache), + Organization: usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), + AppGroup: usecase.NewAppGroupUsecase(repoFactory, argoClient), + AppServeApp: usecase.NewAppServeAppUsecase(repoFactory, argoClient), + CloudAccount: usecase.NewCloudAccountUsecase(repoFactory, argoClient), + StackTemplate: usecase.NewStackTemplateUsecase(repoFactory), + Dashboard: usecase.NewDashboardUsecase(repoFactory, cache), + Alert: usecase.NewAlertUsecase(repoFactory), + Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), + Project: usecase.NewProjectUsecase(repoFactory, argoClient), + } + customMiddleware := internalMiddleware.NewMiddleware( authenticator.NewAuthenticator(authKeycloak.NewKeycloakAuthenticator(kc)), authorizer.NewDefaultAuthorization(repoFactory), requestRecoder.NewDefaultRequestRecoder(), audit.NewDefaultAudit(repoFactory)) - cache := gcache.New(5*time.Minute, 10*time.Minute) - r.Use(loggingMiddleware) // [TODO] Transaction //r.Use(transactionMiddleware(db)) - authHandler := delivery.NewAuthHandler(usecase.NewAuthUsecase(repoFactory, kc)) + authHandler := delivery.NewAuthHandler(usecaseFactory) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/login", authHandler.Login).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/ping", authHandler.PingToken).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/auth/logout", customMiddleware.Handle(internalApi.Logout, http.HandlerFunc(authHandler.Logout))).Methods(http.MethodPost) @@ -90,7 +107,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa //r.HandleFunc(API_PREFIX+API_VERSION+"/cookie-test", authHandler.CookieTest).Methods(http.MethodPost) //r.HandleFunc(API_PREFIX+API_VERSION+"/auth/callback", authHandler.CookieTestCallback).Methods(http.MethodGet) - userHandler := delivery.NewUserHandler(usecase.NewUserUsecase(repoFactory, kc)) + userHandler := delivery.NewUserHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.CreateUser, http.HandlerFunc(userHandler.Create))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.ListUser, http.HandlerFunc(userHandler.List))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.GetUser, http.HandlerFunc(userHandler.Get))).Methods(http.MethodGet) @@ -106,7 +123,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/next-password-change", customMiddleware.Handle(internalApi.RenewPasswordExpiredDate, http.HandlerFunc(userHandler.RenewPasswordExpiredDate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.DeleteMyProfile, http.HandlerFunc(userHandler.DeleteMyProfile))).Methods(http.MethodDelete) - organizationHandler := delivery.NewOrganizationHandler(usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), usecase.NewUserUsecase(repoFactory, kc)) + organizationHandler := delivery.NewOrganizationHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.CreateOrganization, http.HandlerFunc(organizationHandler.CreateOrganization))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.GetOrganizations, http.HandlerFunc(organizationHandler.GetOrganizations))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.GetOrganization, http.HandlerFunc(organizationHandler.GetOrganization))).Methods(http.MethodGet) @@ -114,7 +131,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.UpdateOrganization, http.HandlerFunc(organizationHandler.UpdateOrganization))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/primary-cluster", customMiddleware.Handle(internalApi.UpdatePrimaryCluster, http.HandlerFunc(organizationHandler.UpdatePrimaryCluster))).Methods(http.MethodPatch) - clusterHandler := delivery.NewClusterHandler(usecase.NewClusterUsecase(repoFactory, argoClient, cache)) + clusterHandler := delivery.NewClusterHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/clusters", customMiddleware.Handle(internalApi.CreateCluster, http.HandlerFunc(clusterHandler.CreateCluster))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/clusters", customMiddleware.Handle(internalApi.GetClusters, http.HandlerFunc(clusterHandler.GetClusters))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/clusters/import", customMiddleware.Handle(internalApi.ImportCluster, http.HandlerFunc(clusterHandler.ImportCluster))).Methods(http.MethodPost) @@ -126,7 +143,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/bootstrap-kubeconfig", customMiddleware.Handle(internalApi.GetBootstrapKubeconfig, http.HandlerFunc(clusterHandler.GetBootstrapKubeconfig))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/nodes", customMiddleware.Handle(internalApi.GetNodes, http.HandlerFunc(clusterHandler.GetNodes))).Methods(http.MethodGet) - appGroupHandler := delivery.NewAppGroupHandler(usecase.NewAppGroupUsecase(repoFactory, argoClient)) + appGroupHandler := delivery.NewAppGroupHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/app-groups", customMiddleware.Handle(internalApi.CreateAppgroup, http.HandlerFunc(appGroupHandler.CreateAppGroup))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/app-groups", customMiddleware.Handle(internalApi.GetAppgroups, http.HandlerFunc(appGroupHandler.GetAppGroups))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}", customMiddleware.Handle(internalApi.GetAppgroup, http.HandlerFunc(appGroupHandler.GetAppGroup))).Methods(http.MethodGet) @@ -134,7 +151,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}/applications", customMiddleware.Handle(internalApi.GetApplications, http.HandlerFunc(appGroupHandler.GetApplications))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/app-groups/{appGroupId}/applications", customMiddleware.Handle(internalApi.CreateApplication, http.HandlerFunc(appGroupHandler.CreateApplication))).Methods(http.MethodPost) - appServeAppHandler := delivery.NewAppServeAppHandler(usecase.NewAppServeAppUsecase(repoFactory, argoClient)) + appServeAppHandler := delivery.NewAppServeAppHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps", customMiddleware.Handle(internalApi.CreateAppServeApp, http.HandlerFunc(appServeAppHandler.CreateAppServeApp))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApps))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count", customMiddleware.Handle(internalApi.GetNumOfAppsOnStack, http.HandlerFunc(appServeAppHandler.GetNumOfAppsOnStack))).Methods(http.MethodGet) @@ -150,7 +167,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint", customMiddleware.Handle(internalApi.UpdateAppServeAppEndpoint, http.HandlerFunc(appServeAppHandler.UpdateAppServeAppEndpoint))).Methods(http.MethodPatch) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback", customMiddleware.Handle(internalApi.RollbackAppServeApp, http.HandlerFunc(appServeAppHandler.RollbackAppServeApp))).Methods(http.MethodPost) - cloudAccountHandler := delivery.NewCloudAccountHandler(usecase.NewCloudAccountUsecase(repoFactory, argoClient)) + cloudAccountHandler := delivery.NewCloudAccountHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts", customMiddleware.Handle(internalApi.GetCloudAccounts, http.HandlerFunc(cloudAccountHandler.GetCloudAccounts))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts", customMiddleware.Handle(internalApi.CreateCloudAccount, http.HandlerFunc(cloudAccountHandler.CreateCloudAccount))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/name/{name}/existence", customMiddleware.Handle(internalApi.CheckCloudAccountName, http.HandlerFunc(cloudAccountHandler.CheckCloudAccountName))).Methods(http.MethodGet) @@ -161,20 +178,20 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error", customMiddleware.Handle(internalApi.DeleteForceCloudAccount, http.HandlerFunc(cloudAccountHandler.DeleteForceCloudAccount))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quotas", customMiddleware.Handle(internalApi.GetResourceQuota, http.HandlerFunc(cloudAccountHandler.GetResourceQuota))).Methods(http.MethodGet) - stackTemplateHandler := delivery.NewStackTemplateHandler(usecase.NewStackTemplateUsecase(repoFactory)) + stackTemplateHandler := delivery.NewStackTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/stack-templates", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/stack-templates", customMiddleware.Handle(internalApi.CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetStackTemplate, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) - dashboardHandler := delivery.NewDashboardHandler(usecase.NewDashboardUsecase(repoFactory, cache)) + dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts/{chartType}", customMiddleware.Handle(internalApi.GetChartDashboard, http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) - alertHandler := delivery.NewAlertHandler(usecase.NewAlertUsecase(repoFactory)) + alertHandler := delivery.NewAlertHandler(usecaseFactory) r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/alerts", alertHandler.CreateAlert).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts", customMiddleware.Handle(internalApi.GetAlerts, http.HandlerFunc(alertHandler.GetAlerts))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", customMiddleware.Handle(internalApi.GetAlert, http.HandlerFunc(alertHandler.GetAlert))).Methods(http.MethodGet) @@ -183,7 +200,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}/actions", customMiddleware.Handle(internalApi.CreateAlertAction, http.HandlerFunc(alertHandler.CreateAlertAction))).Methods(http.MethodPost) //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}/actions/status", customMiddleware.Handle(http.HandlerFunc(alertHandler.UpdateAlertActionStatus))).Methods(http.MethodPatch) - stackHandler := delivery.NewStackHandler(usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache))) + stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.CreateStack, http.HandlerFunc(stackHandler.CreateStack))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/name/{name}/existence", customMiddleware.Handle(internalApi.CheckStackName, http.HandlerFunc(stackHandler.CheckStackName))).Methods(http.MethodGet) @@ -196,7 +213,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", customMiddleware.Handle(internalApi.DeleteFavoriteStack, http.HandlerFunc(stackHandler.DeleteFavorite))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/install", customMiddleware.Handle(internalApi.InstallStack, http.HandlerFunc(stackHandler.InstallStack))).Methods(http.MethodPost) - projectHandler := delivery.NewProjectHandler(usecase.NewProjectUsecase(repoFactory, argoClient)) + projectHandler := delivery.NewProjectHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.CreateProject, http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index d9a67132..b8838933 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -1,22 +1,16 @@ package usecase -import ( - kube "github.com/openinfradev/tks-api/internal/kubernetes" - gcache "github.com/patrickmn/go-cache" - "k8s.io/client-go/kubernetes" -) - -func GetKubeClient(cache *gcache.Cache, clusterId string) (*kubernetes.Clientset, error) { - const prefix = "CACHE_KEY_KUBE_CLIENT_" - value, found := cache.Get(prefix + clusterId) - if found { - return value.(*kubernetes.Clientset), nil - } - client, err := kube.GetClientFromClusterId(clusterId) - if err != nil { - return nil, err - } - - cache.Set(prefix+clusterId, client, gcache.DefaultExpiration) - return client, nil +type Usecase struct { + Auth IAuthUsecase + User IUserUsecase + Cluster IClusterUsecase + Organization IOrganizationUsecase + AppGroup IAppGroupUsecase + AppServeApp IAppServeAppUsecase + CloudAccount ICloudAccountUsecase + StackTemplate IStackTemplateUsecase + Dashboard IDashboardUsecase + Alert IAlertUsecase + Stack IStackUsecase + Project IProjectUsecase } From 4d94376beb7830ef35dfb5af77adede2f1b8322d Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 22 Feb 2024 10:30:15 +0900 Subject: [PATCH 042/502] Change project role uri --- internal/delivery/http/project.go | 8 +++----- internal/route/route.go | 6 +++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 557ebc91..1c3dfc8c 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -380,7 +380,7 @@ func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param projectRoleId path string true "Project Role ID" // @Success 200 {object} domain.GetProjectRoleResponse -// @Router /organizations/{organizationId}/projects/pass/project-roles/{projectRoleId} [get] +// @Router /organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] // @Security JWT func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -422,7 +422,7 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" // @Success 200 {object} domain.GetProjectRolesResponse -// @Router /organizations/{organizationId}/projects/pass/project-roles [get] +// @Router /organizations/{organizationId}/projects/project-roles [get] // @Security JWT func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -692,7 +692,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} domain.GetProjectMemberCountResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members/project-roles/count [get] +// @Router /organizations/{organizationId}/projects/{projectId}/members/count [get] // @Security JWT func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -958,7 +958,6 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Param stackId path string true "Stack ID" // @Param request body domain.CreateProjectNamespaceRequest true "Request body to create project namespace" // @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces [post] @@ -1063,7 +1062,6 @@ func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.R // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Param stackId path string true "Project Stack ID" // @Success 200 {object} domain.GetProjectNamespacesResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces [get] // @Security JWT diff --git a/internal/route/route.go b/internal/route/route.go index 448e9361..793457a0 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -216,16 +216,16 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa projectHandler := delivery.NewProjectHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.CreateProject, http.HandlerFunc(projectHandler.CreateProject))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles/{projectRoleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(projectHandler.GetProjectRole))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/check/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNameExist))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.DeleteProject, http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/pass/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/pass/project-roles/{projectRoleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(projectHandler.GetProjectRole))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.AddProjectMember, http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/count", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMemberCount))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.GetProjectMember, http.HandlerFunc(projectHandler.GetProjectMember))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMembers))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/project-roles/count", customMiddleware.Handle(internalApi.GetProjectMembers, http.HandlerFunc(projectHandler.GetProjectMemberCount))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMember))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.RemoveProjectMember, http.HandlerFunc(projectHandler.RemoveProjectMembers))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMembersRole))).Methods(http.MethodPut) From fbc46e588b94665673dcde9d64f56fd91b3837aa Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 22 Feb 2024 14:25:04 +0900 Subject: [PATCH 043/502] fix swagger ui and project uri path --- api/swagger/docs.go | 25 ++++--------- api/swagger/swagger.json | 25 ++++--------- api/swagger/swagger.yaml | 20 +++------- internal/delivery/http/project.go | 18 ++++++--- internal/repository/project.go | 24 +++++++++++- internal/route/route.go | 2 +- internal/usecase/project.go | 62 ++++++++++++++++++++++++++++++- pkg/domain/project.go | 5 +-- 8 files changed, 117 insertions(+), 64 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0520123d..25c5a8d6 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -2290,7 +2290,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/check/existence": { + "/organizations/{organizationId}/projects/existence": { "get": { "security": [ { @@ -2340,7 +2340,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/pass/project-roles": { + "/organizations/{organizationId}/projects/project-roles": { "get": { "security": [ { @@ -2383,7 +2383,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/pass/project-roles/{projectRoleId}": { + "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { "get": { "security": [ { @@ -3581,7 +3581,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/members/project-roles/count": { + "/organizations/{organizationId}/projects/{projectId}/members/count": { "get": { "security": [ { @@ -3817,13 +3817,6 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true - }, - { - "type": "string", - "description": "Project Stack ID", - "name": "stackId", - "in": "path", - "required": true } ], "responses": { @@ -3867,13 +3860,6 @@ const docTemplate = `{ "in": "path", "required": true }, - { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, { "description": "Request body to create project namespace", "name": "request", @@ -8539,6 +8525,9 @@ const docTemplate = `{ }, "name": { "type": "string" + }, + "projectLeaderId": { + "type": "string" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index a9f7dbc0..54a4cacd 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -2284,7 +2284,7 @@ } } }, - "/organizations/{organizationId}/projects/check/existence": { + "/organizations/{organizationId}/projects/existence": { "get": { "security": [ { @@ -2334,7 +2334,7 @@ } } }, - "/organizations/{organizationId}/projects/pass/project-roles": { + "/organizations/{organizationId}/projects/project-roles": { "get": { "security": [ { @@ -2377,7 +2377,7 @@ } } }, - "/organizations/{organizationId}/projects/pass/project-roles/{projectRoleId}": { + "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { "get": { "security": [ { @@ -3575,7 +3575,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/members/project-roles/count": { + "/organizations/{organizationId}/projects/{projectId}/members/count": { "get": { "security": [ { @@ -3811,13 +3811,6 @@ "name": "projectId", "in": "path", "required": true - }, - { - "type": "string", - "description": "Project Stack ID", - "name": "stackId", - "in": "path", - "required": true } ], "responses": { @@ -3861,13 +3854,6 @@ "in": "path", "required": true }, - { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, { "description": "Request body to create project namespace", "name": "request", @@ -8533,6 +8519,9 @@ }, "name": { "type": "string" + }, + "projectLeaderId": { + "type": "string" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 8f0537c5..aa05361a 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2240,6 +2240,8 @@ definitions: type: string name: type: string + projectLeaderId: + type: string required: - name type: object @@ -4694,7 +4696,7 @@ paths: summary: Update project member Role tags: - Projects - /organizations/{organizationId}/projects/{projectId}/members/project-roles/count: + /organizations/{organizationId}/projects/{projectId}/members/count: get: consumes: - application/json @@ -4738,11 +4740,6 @@ paths: name: projectId required: true type: string - - description: Project Stack ID - in: path - name: stackId - required: true - type: string produces: - application/json responses: @@ -4770,11 +4767,6 @@ paths: name: projectId required: true type: string - - description: Stack ID - in: path - name: stackId - required: true - type: string - description: Request body to create project namespace in: body name: request @@ -4949,7 +4941,7 @@ paths: summary: Check project namespace exist tags: - Projects - /organizations/{organizationId}/projects/check/existence: + /organizations/{organizationId}/projects/existence: get: consumes: - application/json @@ -4981,7 +4973,7 @@ paths: summary: Check project name exist tags: - Projects - /organizations/{organizationId}/projects/pass/project-roles: + /organizations/{organizationId}/projects/project-roles: get: consumes: - application/json @@ -5009,7 +5001,7 @@ paths: summary: Get project roles tags: - Projects - /organizations/{organizationId}/projects/pass/project-roles/{projectRoleId}: + /organizations/{organizationId}/projects/project-roles/{projectRoleId}: get: consumes: - application/json diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 1c3dfc8c..cc864945 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -286,7 +286,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { // @Param type query string false "type (name)" // @Param value query string true "value (project name)" // @Success 200 {object} domain.CheckExistedResponse -// @Router /organizations/{organizationId}/projects/check/existence [get] +// @Router /organizations/{organizationId}/projects/existence [get] // @Security JWT func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -348,18 +348,24 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { } now := time.Now() - project, err := p.usecase.GetProject(organizationId, projectId) + project, err := p.usecase.GetProjectWithLeader(organizationId, projectId) if err != nil { - + ErrorJSON(w, r, err) + return + } + if project == nil { + project, err = p.usecase.GetProject(organizationId, projectId) + if err != nil { + ErrorJSON(w, r, err) + return + } } project.Name = projectReq.Name project.Description = projectReq.Description project.UpdatedAt = &now - //project.ProjectNamespaces = nil - //project.ProjectMembers = nil - if err := p.usecase.UpdateProject(project); err != nil { + if err := p.usecase.UpdateProject(project, projectReq.ProjectLeaderId); err != nil { ErrorJSON(w, r, err) return } diff --git a/internal/repository/project.go b/internal/repository/project.go index 606157eb..d28d5310 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -23,6 +23,7 @@ type IProjectRepository interface { GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string) ([]domain.ProjectMember, error) GetProjectMemberCountByProjectId(projectId string) (*domain.GetProjectMemberCountResponse, error) GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) + GetProjectMemberByUserId(projectId string, projectUserId string) (pm *domain.ProjectMember, err error) RemoveProjectMember(projectMemberId string) error UpdateProjectMemberRole(pm *domain.ProjectMember) error CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error @@ -280,6 +281,22 @@ func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm *do return pm, nil } +func (r *ProjectRepository) GetProjectMemberByUserId(projectId string, projectUserId string) (pm *domain.ProjectMember, err error) { + res := r.db.Preload("ProjectUser"). + Joins("ProjectRole").Where("project_id = ? and project_user_id = ?", projectId, projectUserId).First(&pm) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project member") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pm, nil +} + func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { res := r.db.Delete(&domain.ProjectMember{ID: projectMemberId}) if res.Error != nil { @@ -299,7 +316,12 @@ func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { //} func (r *ProjectRepository) UpdateProjectMemberRole(pm *domain.ProjectMember) error { - res := r.db.Model(&pm).Updates(domain.ProjectMember{ProjectRoleId: pm.ProjectRoleId, UpdatedAt: pm.UpdatedAt}) + res := r.db.Model(&pm).Updates( + domain.ProjectMember{ + ProjectRoleId: pm.ProjectRoleId, + IsProjectLeader: pm.IsProjectLeader, + UpdatedAt: pm.UpdatedAt, + }) if res.Error != nil { return res.Error } diff --git a/internal/route/route.go b/internal/route/route.go index 793457a0..e97a514a 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -218,8 +218,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.GetProjects, http.HandlerFunc(projectHandler.GetProjects))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles", customMiddleware.Handle(internalApi.GetProjectRoles, http.HandlerFunc(projectHandler.GetProjectRoles))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/project-roles/{projectRoleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(projectHandler.GetProjectRole))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNameExist))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.GetProject, http.HandlerFunc(projectHandler.GetProject))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/check/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNameExist))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.UpdateProject, http.HandlerFunc(projectHandler.UpdateProject))).Methods(http.MethodPut) //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}", customMiddleware.Handle(internalApi.DeleteProject, http.HandlerFunc(projectHandler.DeleteProject))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members", customMiddleware.Handle(internalApi.AddProjectMember, http.HandlerFunc(projectHandler.AddProjectMember))).Methods(http.MethodPost) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 6c70077f..4817bff8 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -25,7 +25,7 @@ type IProjectUsecase interface { GetProject(organizationId string, projectId string) (*domain.Project, error) GetProjectWithLeader(organizationId string, projectId string) (*domain.Project, error) IsProjectNameExist(organizationId string, projectName string) (bool, error) - UpdateProject(p *domain.Project) error + UpdateProject(p *domain.Project, newLeaderId string) error GetProjectRole(id string) (*domain.ProjectRole, error) GetProjectRoles(int) ([]domain.ProjectRole, error) AddProjectMember(pm *domain.ProjectMember) (string, error) @@ -116,11 +116,69 @@ func (u *ProjectUsecase) IsProjectNameExist(organizationId string, projectName s return exist, nil } -func (u *ProjectUsecase) UpdateProject(p *domain.Project) error { +func (u *ProjectUsecase) UpdateProject(p *domain.Project, newLeaderId string) error { + + var currentMemberId, currentLeaderId, projectRoleId string + for _, pm := range p.ProjectMembers { + currentMemberId = pm.ID + currentLeaderId = pm.ProjectUser.ID.String() + projectRoleId = pm.ProjectRole.ID + } + p.ProjectNamespaces = nil + p.ProjectMembers = nil + if err := u.projectRepo.UpdateProject(p); err != nil { log.Error(err) return errors.Wrap(err, "Failed to update project.") } + + if newLeaderId != "" && currentLeaderId != newLeaderId { + if err := u.RemoveProjectMember(currentMemberId); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to remove project member.") + } + + pu, err := u.GetProjectUser(newLeaderId) + if err != nil { + return err + } + if pu == nil { + return errors.Wrap(err, "No userid") + } + + pm, err := u.projectRepo.GetProjectMemberByUserId(p.ID, newLeaderId) + if err != nil { + return err + } + if pm == nil { + newPm := &domain.ProjectMember{ + ProjectId: p.ID, + ProjectUserId: pu.ID, + ProjectUser: nil, + ProjectRoleId: projectRoleId, + ProjectRole: nil, + IsProjectLeader: true, + CreatedAt: *p.UpdatedAt, + } + res, err := u.AddProjectMember(newPm) + if err != nil { + return err + } + log.Infof("Added project member: %s", res) + } else { + pm.ProjectUserId = pu.ID + pm.ProjectRoleId = projectRoleId + pm.IsProjectLeader = true + pm.UpdatedAt = p.UpdatedAt + pm.ProjectUser = nil + pm.ProjectRole = nil + err := u.UpdateProjectMemberRole(pm) + if err != nil { + return err + } + } + } + return nil } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 6f0639e2..10e5d9a4 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -152,10 +152,7 @@ type CreateProjectResponse struct { } type UpdateProjectRequest struct { - Name string `json:"name" validate:"required"` - Description string `json:"description"` - //ProjectLeaderId string `json:"projectLeaderId"` - //ProjectRoleId string `json:"projectRoleId"` + CreateProjectRequest } type GetProjectRoleResponse struct { From b9d15dd5d3d6402ddfe23d3f03b969a11b26f7ea Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 26 Feb 2024 10:29:43 +0900 Subject: [PATCH 044/502] feature. implemtation audit --- api/swagger/docs.go | 277 ++++++++++++++++++ api/swagger/swagger.json | 277 ++++++++++++++++++ api/swagger/swagger.yaml | 177 +++++++++++ internal/database/database.go | 5 + internal/delivery/api/endpoint.go | 29 ++ internal/delivery/http/audit.go | 145 +++++++++ internal/delivery/http/auth.go | 27 +- internal/delivery/http/handler.go | 9 - internal/middleware/audit/audit-map.go | 67 +++++ internal/middleware/audit/audit.go | 78 ++++- internal/middleware/auth/request/context.go | 1 + internal/middleware/logging/logging.go | 35 +++ internal/middleware/logging/respose-writer.go | 35 +++ internal/middleware/middleware.go | 14 +- internal/pagination/pagination.go | 6 +- internal/repository/audit.go | 112 +++++++ internal/repository/repository.go | 1 + internal/repository/stack-template.go | 6 +- internal/route/route.go | 45 +-- internal/usecase/audit.go | 68 +++++ internal/usecase/usecase.go | 1 + pkg/domain/audit.go | 49 ++++ pkg/domain/organization.go | 6 + pkg/domain/user.go | 13 +- pkg/httpErrors/errorCode.go | 1 + 25 files changed, 1412 insertions(+), 72 deletions(-) create mode 100644 internal/delivery/http/audit.go create mode 100644 internal/middleware/audit/audit-map.go create mode 100644 internal/middleware/logging/logging.go create mode 100644 internal/middleware/logging/respose-writer.go create mode 100644 internal/repository/audit.go create mode 100644 internal/usecase/audit.go create mode 100644 pkg/domain/audit.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 25c5a8d6..47925f5a 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1357,6 +1357,186 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/audits": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audits", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audits", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filter", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "or", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAuditsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Create Audit", + "parameters": [ + { + "description": "create audit request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateAuditRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateAuditResponse" + } + } + } + } + }, + "/organizations/{organizationId}/audits/{auditId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audit", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAuditResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Delete Audit 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ @@ -5627,6 +5807,44 @@ const docTemplate = `{ "ApplicationType_KUBERNETES_DASHBOARD" ] }, + "domain.AuditResponse": { + "type": "object", + "properties": { + "clientIP": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "group": { + "type": "string" + }, + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.SimpleOrganizationResponse" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "userId": { + "type": "string" + } + } + }, "domain.Axis": { "type": "object", "properties": { @@ -6279,6 +6497,12 @@ const docTemplate = `{ } } }, + "domain.CreateAuditRequest": { + "type": "object" + }, + "domain.CreateAuditResponse": { + "type": "object" + }, "domain.CreateBootstrapKubeconfigResponse": { "type": "object", "properties": { @@ -6948,6 +7172,28 @@ const docTemplate = `{ } } }, + "domain.GetAuditResponse": { + "type": "object", + "properties": { + "audit": { + "$ref": "#/definitions/domain.AuditResponse" + } + } + }, + "domain.GetAuditsResponse": { + "type": "object", + "properties": { + "audits": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AuditResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, "domain.GetBootstrapKubeconfigResponse": { "type": "object", "properties": { @@ -7923,6 +8169,34 @@ const docTemplate = `{ } } }, + "domain.SimpleOrganizationResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "domain.SimpleRoleResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -7966,6 +8240,9 @@ const docTemplate = `{ }, "name": { "type": "string" + }, + "role": { + "$ref": "#/definitions/domain.SimpleRoleResponse" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 54a4cacd..da3b1bc9 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1351,6 +1351,186 @@ } } }, + "/organizations/{organizationId}/audits": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audits", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audits", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filter", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "or", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAuditsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Create Audit", + "parameters": [ + { + "description": "create audit request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/domain.CreateAuditRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.CreateAuditResponse" + } + } + } + } + }, + "/organizations/{organizationId}/audits/{auditId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audit", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetAuditResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Delete Audit 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ @@ -5621,6 +5801,44 @@ "ApplicationType_KUBERNETES_DASHBOARD" ] }, + "domain.AuditResponse": { + "type": "object", + "properties": { + "clientIP": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "group": { + "type": "string" + }, + "id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/domain.SimpleOrganizationResponse" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/domain.SimpleUserResponse" + }, + "userId": { + "type": "string" + } + } + }, "domain.Axis": { "type": "object", "properties": { @@ -6273,6 +6491,12 @@ } } }, + "domain.CreateAuditRequest": { + "type": "object" + }, + "domain.CreateAuditResponse": { + "type": "object" + }, "domain.CreateBootstrapKubeconfigResponse": { "type": "object", "properties": { @@ -6942,6 +7166,28 @@ } } }, + "domain.GetAuditResponse": { + "type": "object", + "properties": { + "audit": { + "$ref": "#/definitions/domain.AuditResponse" + } + } + }, + "domain.GetAuditsResponse": { + "type": "object", + "properties": { + "audits": { + "type": "array", + "items": { + "$ref": "#/definitions/domain.AuditResponse" + } + }, + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + } + } + }, "domain.GetBootstrapKubeconfigResponse": { "type": "object", "properties": { @@ -7917,6 +8163,34 @@ } } }, + "domain.SimpleOrganizationResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "domain.SimpleRoleResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -7960,6 +8234,9 @@ }, "name": { "type": "string" + }, + "role": { + "$ref": "#/definitions/domain.SimpleRoleResponse" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index aa05361a..e3025176 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -309,6 +309,31 @@ definitions: - ApplicationType_HORIZON - ApplicationType_JAEGER - ApplicationType_KUBERNETES_DASHBOARD + domain.AuditResponse: + properties: + clientIP: + type: string + createdAt: + type: string + description: + type: string + group: + type: string + id: + type: string + message: + type: string + organization: + $ref: '#/definitions/domain.SimpleOrganizationResponse' + organizationId: + type: string + updatedAt: + type: string + user: + $ref: '#/definitions/domain.SimpleUserResponse' + userId: + type: string + type: object domain.Axis: properties: data: @@ -750,6 +775,10 @@ definitions: metadata: type: string type: object + domain.CreateAuditRequest: + type: object + domain.CreateAuditResponse: + type: object domain.CreateBootstrapKubeconfigResponse: properties: kubeconfig: @@ -1202,6 +1231,20 @@ definitions: $ref: '#/definitions/domain.ApplicationResponse' type: array type: object + domain.GetAuditResponse: + properties: + audit: + $ref: '#/definitions/domain.AuditResponse' + type: object + domain.GetAuditsResponse: + properties: + audits: + items: + $ref: '#/definitions/domain.AuditResponse' + type: array + pagination: + $ref: '#/definitions/domain.PaginationResponse' + type: object domain.GetBootstrapKubeconfigResponse: properties: kubeconfig: @@ -1843,6 +1886,24 @@ definitions: organizationId: type: string type: object + domain.SimpleOrganizationResponse: + properties: + description: + type: string + id: + type: string + name: + type: string + type: object + domain.SimpleRoleResponse: + properties: + description: + type: string + id: + type: string + name: + type: string + type: object domain.SimpleStackTemplateResponse: properties: cloudService: @@ -1872,6 +1933,8 @@ definitions: type: string name: type: string + role: + $ref: '#/definitions/domain.SimpleRoleResponse' type: object domain.StackConfResponse: properties: @@ -3250,6 +3313,120 @@ paths: summary: Create alert action tags: - Alerts + /organizations/{organizationId}/audits: + get: + consumes: + - application/json + description: Get Audits + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filter + type: array + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: or + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAuditsResponse' + security: + - JWT: [] + summary: Get Audits + tags: + - Audits + post: + consumes: + - application/json + description: Create Audit + parameters: + - description: create audit request + in: body + name: body + required: true + schema: + $ref: '#/definitions/domain.CreateAuditRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.CreateAuditResponse' + security: + - JWT: [] + summary: Create Audit + tags: + - Audits + /organizations/{organizationId}/audits/{auditId}: + delete: + consumes: + - application/json + description: Delete Audit + parameters: + - description: auditId + in: path + name: auditId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete Audit 'NOT IMPLEMENTED' + tags: + - Audits + get: + consumes: + - application/json + description: Get Audit + parameters: + - description: auditId + in: path + name: auditId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetAuditResponse' + security: + - JWT: [] + summary: Get Audit + tags: + - Audits /organizations/{organizationId}/cloud-accounts: get: consumes: diff --git a/internal/database/database.go b/internal/database/database.go index 6777f915..7d3a295c 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -128,5 +128,10 @@ func migrateSchema(db *gorm.DB) error { return err } + // Audit + if err := db.AutoMigrate(&repository.Audit{}); err != nil { + return err + } + return nil } diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 21ee33c4..390088ef 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -150,6 +150,11 @@ const ( UnSetFavoriteProject UnSetFavoriteProjectNamespace GetProjectKubeconfig + + // Audit + GetAudits + GetAudit + DeleteAudit ) var ApiMap = map[Endpoint]EndpointInfo{ @@ -613,6 +618,18 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetProjectKubeconfig", Group: "Project", }, + GetAudits: { + Name: "GetAudits", + Group: "Audit", + }, + GetAudit: { + Name: "GetAudit", + Group: "Audit", + }, + DeleteAudit: { + Name: "DeleteAudit", + Group: "Audit", + }, } func (e Endpoint) String() string { @@ -847,6 +864,12 @@ func (e Endpoint) String() string { return "UnSetFavoriteProjectNamespace" case GetProjectKubeconfig: return "GetProjectKubeconfig" + case GetAudits: + return "GetAudits" + case GetAudit: + return "GetAudit" + case DeleteAudit: + return "DeleteAudit" default: return "" } @@ -1083,6 +1106,12 @@ func GetEndpoint(name string) Endpoint { return UnSetFavoriteProjectNamespace case "GetProjectKubeconfig": return GetProjectKubeconfig + case "GetAudits": + return GetAudits + case "GetAudit": + return GetAudit + case "DeleteAudit": + return DeleteAudit default: return -1 } diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go new file mode 100644 index 00000000..8cdb6924 --- /dev/null +++ b/internal/delivery/http/audit.go @@ -0,0 +1,145 @@ +package http + +import ( + "fmt" + "net/http" + + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" +) + +type AuditHandler struct { + usecase usecase.IAuditUsecase +} + +func NewAuditHandler(h usecase.Usecase) *AuditHandler { + return &AuditHandler{ + usecase: h.Audit, + } +} + +// CreateAudit godoc +// @Tags Audits +// @Summary Create Audit +// @Description Create Audit +// @Accept json +// @Produce json +// @Param body body domain.CreateAuditRequest true "create audit request" +// @Success 200 {object} domain.CreateAuditResponse +// @Router /organizations/{organizationId}/audits [post] +// @Security JWT +func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { + ErrorJSON(w, r, fmt.Errorf("need implementation")) +} + +// GetAudit godoc +// @Tags Audits +// @Summary Get Audits +// @Description Get Audits +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filter query []string false "filters" +// @Param or query []string false "filters" +// @Success 200 {object} domain.GetAuditsResponse +// @Router /organizations/{organizationId}/audits [get] +// @Security JWT +func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + urlParams := r.URL.Query() + pg, err := pagination.NewPagination(&urlParams) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + audits, err := h.usecase.Fetch(r.Context(), organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetAuditsResponse + out.Audits = make([]domain.AuditResponse, len(audits)) + for i, audit := range audits { + if err := serializer.Map(audit, &out.Audits[i]); err != nil { + log.InfoWithContext(r.Context(), err) + } + } + + if out.Pagination, err = pg.Response(); err != nil { + log.InfoWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetAudit godoc +// @Tags Audits +// @Summary Get Audit +// @Description Get Audit +// @Accept json +// @Produce json +// @Param auditId path string true "auditId" +// @Success 200 {object} domain.GetAuditResponse +// @Router /organizations/{organizationId}/audits/{auditId} [get] +// @Security JWT +func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["auditId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid auditId"), "C_INVALID_AUDIT_ID", "")) + return + } + + auditId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_AUDIT_ID", "")) + return + } + + audit, err := h.usecase.Get(r.Context(), auditId) + if err != nil { + ErrorJSON(w, r, err) + return + } + log.Info(audit) + + var out domain.GetAuditResponse + if err := serializer.Map(audit, &out.Audit); err != nil { + log.InfoWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) + +} + +// DeleteAudit godoc +// @Tags Audits +// @Summary Delete Audit 'NOT IMPLEMENTED' +// @Description Delete Audit +// @Accept json +// @Produce json +// @Param auditId path string true "auditId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/audits/{auditId} [delete] +// @Security JWT +func (h *AuditHandler) DeleteAudit(w http.ResponseWriter, r *http.Request) { + ErrorJSON(w, r, fmt.Errorf("need implementation")) +} diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 1b84dbde..07c89240 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -4,7 +4,9 @@ import ( "fmt" "net/http" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal" + "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -27,12 +29,14 @@ type IAuthHandler interface { //Authenticate(next http.Handler) http.Handler } type AuthHandler struct { - usecase usecase.IAuthUsecase + usecase usecase.IAuthUsecase + auditUsecase usecase.IAuditUsecase } func NewAuthHandler(h usecase.Usecase) IAuthHandler { return &AuthHandler{ - usecase: h.Auth, + usecase: h.Auth, + auditUsecase: h.Audit, } } @@ -55,9 +59,28 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { user, err := h.usecase.Login(input.AccountId, input.Password, input.OrganizationId) if err != nil { + errorResponse, _ := httpErrors.ErrorResponse(err) + _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ + OrganizationId: input.OrganizationId, + Group: "Auth", + Message: fmt.Sprintf("[%s]님이 로그인에 실패하였습니다.", input.AccountId), + Description: errorResponse.Text(), + ClientIP: audit.GetClientIpAddress(w, r), + UserId: nil, + }) log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return + } else { + userId, _ := uuid.Parse(user.ID) + _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ + OrganizationId: input.OrganizationId, + Group: "Auth", + Message: fmt.Sprintf("[%s]님이 로그인 하였습니다.", input.AccountId), + Description: "", + ClientIP: audit.GetClientIpAddress(w, r), + UserId: &userId, + }) } var cookies []*http.Cookie diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index 46cdf4db..680c338d 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -3,13 +3,11 @@ package http import ( "encoding/json" "errors" - "fmt" "io" "net/http" ut "github.com/go-playground/universal-translator" validator_ "github.com/go-playground/validator/v10" - "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/validator" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" @@ -41,13 +39,6 @@ func ResponseJSON(w http.ResponseWriter, r *http.Request, httpStatus int, data i w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(httpStatus) - responseStr := helper.ModelToJson(out) - if len(responseStr) > MAX_LOG_LEN { - log.InfoWithContext(r.Context(), fmt.Sprintf("[API_RESPONSE] [%s]", responseStr[:MAX_LOG_LEN-1])) - } else { - log.InfoWithContext(r.Context(), fmt.Sprintf("[API_RESPONSE] [%s]", responseStr)) - } - log.DebugWithContext(r.Context(), fmt.Sprintf("[API_RESPONSE] [%s]", responseStr)) if err := json.NewEncoder(w).Encode(out); err != nil { log.ErrorWithContext(r.Context(), err) } diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go new file mode 100644 index 00000000..85a80d9d --- /dev/null +++ b/internal/middleware/audit/audit-map.go @@ -0,0 +1,67 @@ +package audit + +import ( + "bytes" + "encoding/json" + "fmt" + + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" +) + +type fnAudit = func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) + +var auditMap = map[internalApi.Endpoint]fnAudit{ + internalApi.CreateStack: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateStackRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + + if isSuccess(statusCode) { + return fmt.Sprintf("스택 [%s]을 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("스택 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.CreateProject: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateProjectRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + + if isSuccess(statusCode) { + return fmt.Sprintf("프로젝트 [%s]를 생성하였습니다.", input.Name), "" + } else { + return "프로젝트 [%s]를 생성하는데 실패하였습니다. ", errorText(out) + } + }, internalApi.CreateCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateCloudAccountRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + + if isSuccess(statusCode) { + return fmt.Sprintf("클라우드 어카운트 [%s]를 생성하였습니다.", input.Name), "" + } else { + return "프로젝트 [%s]를 생성하는데 실패하였습니다. ", errorText(out) + } + }, +} + +func errorText(out *bytes.Buffer) string { + var e httpErrors.RestError + if err := json.NewDecoder(out).Decode(&e); err != nil { + log.Error(err) + return "" + } + return e.Text() +} + +func isSuccess(statusCode int) bool { + if statusCode >= 200 && statusCode < 300 { + return true + } + return false +} diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 4b2058c5..55d61511 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -1,29 +1,91 @@ package audit import ( - "github.com/openinfradev/tks-api/internal/repository" + "bytes" + "io" + "net" "net/http" + + "github.com/gorilla/mux" + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/middleware/logging" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" ) type Interface interface { - WithAudit(handler http.Handler) http.Handler + WithAudit(endpoint internalApi.Endpoint, handler http.Handler) http.Handler } type defaultAudit struct { - repo repository.Repository + repo repository.IAuditRepository } func NewDefaultAudit(repo repository.Repository) *defaultAudit { return &defaultAudit{ - repo: repo, + repo: repo.Audit, } } -// TODO: implement audit logic -func (a *defaultAudit) WithAudit(handler http.Handler) http.Handler { +func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // TODO: implement audit logic + user, ok := request.UserFrom(r.Context()) + if !ok { + log.Error("Invalid user token") + return + } + userId := user.GetUserId() + + requestBody := &bytes.Buffer{} + _, _ = io.Copy(requestBody, r.Body) + + lrw := logging.NewLoggingResponseWriter(w) + handler.ServeHTTP(lrw, r) + statusCode := lrw.GetStatusCode() + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + organizationId = user.GetOrganizationId() + } + + message, description := "", "" + if fn, ok := auditMap[endpoint]; ok { + body, err := io.ReadAll(requestBody) + if err != nil { + log.Error(err) + } + message, description = fn(lrw.GetBody(), body, statusCode) + + dto := domain.Audit{ + OrganizationId: organizationId, + Group: internalApi.ApiMap[endpoint].Group, + Message: message, + Description: description, + ClientIP: GetClientIpAddress(w, r), + UserId: &userId, + } + if _, err := a.repo.Create(dto); err != nil { + log.Error(err) + } + } - handler.ServeHTTP(w, r) }) } + +var X_FORWARDED_FOR = "X-Forwarded-For" + +func GetClientIpAddress(w http.ResponseWriter, r *http.Request) string { + xforward := r.Header.Get(X_FORWARDED_FOR) + if xforward != "" { + return xforward + } + + clientAddr, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + return clientAddr + } + return "" +} diff --git a/internal/middleware/auth/request/context.go b/internal/middleware/auth/request/context.go index 61efecfa..d1b8c4c8 100644 --- a/internal/middleware/auth/request/context.go +++ b/internal/middleware/auth/request/context.go @@ -2,6 +2,7 @@ package request import ( "context" + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/middleware/auth/user" ) diff --git a/internal/middleware/logging/logging.go b/internal/middleware/logging/logging.go new file mode 100644 index 00000000..3bda0874 --- /dev/null +++ b/internal/middleware/logging/logging.go @@ -0,0 +1,35 @@ +package logging + +import ( + "bytes" + "context" + "fmt" + "io" + "net/http" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal" + "github.com/openinfradev/tks-api/pkg/log" +) + +func LoggingMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + r = r.WithContext(context.WithValue(ctx, internal.ContextKeyRequestID, uuid.New().String())) + + log.InfoWithContext(r.Context(), fmt.Sprintf("***** START [%s %s] ***** ", r.Method, r.RequestURI)) + + body, err := io.ReadAll(r.Body) + if err == nil { + log.InfoWithContext(r.Context(), fmt.Sprintf("REQUEST BODY : %s", bytes.NewBuffer(body).String())) + } + r.Body = io.NopCloser(bytes.NewBuffer(body)) + lrw := NewLoggingResponseWriter(w) + + next.ServeHTTP(lrw, r) + + statusCode := lrw.GetStatusCode() + log.InfofWithContext(r.Context(), "[API_RESPONSE] [%d][%s][%s]", statusCode, http.StatusText(statusCode), lrw.GetBody().String()) + log.InfofWithContext(r.Context(), "***** END [%s %s] *****", r.Method, r.RequestURI) + }) +} diff --git a/internal/middleware/logging/respose-writer.go b/internal/middleware/logging/respose-writer.go new file mode 100644 index 00000000..97ef7d23 --- /dev/null +++ b/internal/middleware/logging/respose-writer.go @@ -0,0 +1,35 @@ +package logging + +import ( + "bytes" + "net/http" +) + +type loggingResponseWriter struct { + http.ResponseWriter + statusCode int + body bytes.Buffer +} + +func NewLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter { + var buf bytes.Buffer + return &loggingResponseWriter{w, http.StatusOK, buf} +} + +func (lrw *loggingResponseWriter) WriteHeader(code int) { + lrw.statusCode = code + lrw.ResponseWriter.WriteHeader(code) +} + +func (lrw *loggingResponseWriter) Write(buf []byte) (int, error) { + lrw.body.Write(buf) + return lrw.ResponseWriter.Write(buf) +} + +func (lrw *loggingResponseWriter) GetBody() *bytes.Buffer { + return &lrw.body +} + +func (lrw *loggingResponseWriter) GetStatusCode() int { + return lrw.statusCode +} diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go index 86e8899c..554afc2a 100644 --- a/internal/middleware/middleware.go +++ b/internal/middleware/middleware.go @@ -1,12 +1,13 @@ package middleware import ( + "net/http" + internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" - "net/http" ) type Middleware struct { @@ -30,24 +31,23 @@ func NewMiddleware(authenticator authenticator.Interface, } func (m *Middleware) Handle(endpoint internalApi.Endpoint, handle http.Handler) http.Handler { - // pre-handler preHandler := m.authorizer.WithAuthorization(handle) // TODO: this is a temporary solution. check if this is the right place to put audit middleware - preHandler = m.audit.WithAudit(preHandler) + preHandler = m.audit.WithAudit(endpoint, preHandler) preHandler = m.requestRecoder.WithRequestRecoder(endpoint, preHandler) preHandler = m.authenticator.WithAuthentication(preHandler) // post-handler - emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) - // append post-handler below // TODO: this is a temporary solution. check if this is the right place to put audit middleware - postHandler := m.audit.WithAudit(emptyHandler) + + // emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + // postHandler := m.audit.WithAudit(endpoint, emptyHandler) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { preHandler.ServeHTTP(w, r) - postHandler.ServeHTTP(w, r) + // postHandler.ServeHTTP(w, r) }) } diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index d7547d70..69975e9c 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -21,7 +21,9 @@ const SORT_ORDER = "sortOrder" const PAGE_NUMBER = "pageNumber" const PAGE_SIZE = "pageSize" const FILTER = "filter" +const FILTER_ARRAY = "filter[]" const OR = "or" +const OR_ARRAY = "or[]" const COMBINED_FILTER = "combinedFilter" var DEFAULT_LIMIT = 10 @@ -188,7 +190,7 @@ func NewPagination(urlParams *url.Values) (*Pagination, error) { return nil, fmt.Errorf("Invalid query string : combinedFilter ") } } - case FILTER, OR: + case FILTER, FILTER_ARRAY, OR, OR_ARRAY: for _, filterValue := range value { arr := strings.Split(filterValue, "|") @@ -209,7 +211,7 @@ func NewPagination(urlParams *url.Values) (*Pagination, error) { } or := false - if key == OR { + if key == OR || key == OR_ARRAY { or = true } diff --git a/internal/repository/audit.go b/internal/repository/audit.go new file mode 100644 index 00000000..bb0f97a2 --- /dev/null +++ b/internal/repository/audit.go @@ -0,0 +1,112 @@ +package repository + +import ( + "fmt" + + "github.com/google/uuid" + "gorm.io/gorm" + "gorm.io/gorm/clause" + + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" +) + +// Interfaces +type IAuditRepository interface { + Get(auditId uuid.UUID) (domain.Audit, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]domain.Audit, error) + Create(dto domain.Audit) (auditId uuid.UUID, err error) + Delete(auditId uuid.UUID) (err error) +} + +type AuditRepository struct { + db *gorm.DB +} + +func NewAuditRepository(db *gorm.DB) IAuditRepository { + return &AuditRepository{ + db: db, + } +} + +// Models +type Audit struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Group string + Message string + Description string + ClientIP string + UserId *uuid.UUID `gorm:"type:uuid"` + User User `gorm:"foreignKey:UserId"` +} + +func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + +// Logics +func (r *AuditRepository) Get(auditId uuid.UUID) (out domain.Audit, err error) { + var audit Audit + res := r.db.Preload(clause.Associations).First(&audit, "id = ?", auditId) + if res.Error != nil { + return + } + out = reflectAudit(audit) + return +} + +func (r *AuditRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.Audit, err error) { + var audits []Audit + + if pg == nil { + pg = pagination.NewDefaultPagination() + } + + db := r.db.Model(&Audit{}).Preload(clause.Associations).Where("organization_id = ?", organizationId) + _, res := pg.Fetch(db, &audits) + if res.Error != nil { + return nil, res.Error + } + + for _, audit := range audits { + out = append(out, reflectAudit(audit)) + } + + return +} + +func (r *AuditRepository) Create(dto domain.Audit) (auditId uuid.UUID, err error) { + audit := Audit{ + OrganizationId: dto.OrganizationId, + Group: dto.Group, + Message: dto.Message, + Description: dto.Description, + ClientIP: dto.ClientIP, + UserId: dto.UserId} + res := r.db.Create(&audit) + if res.Error != nil { + return uuid.Nil, res.Error + } + return audit.ID, nil +} + +func (r *AuditRepository) Delete(auditId uuid.UUID) (err error) { + return fmt.Errorf("to be implemented") +} + +func reflectAudit(audit Audit) (out domain.Audit) { + if err := serializer.Map(audit.Model, &out); err != nil { + log.Error(err) + } + if err := serializer.Map(audit, &out); err != nil { + log.Error(err) + } + return +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 46c56cef..09ab4035 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -22,6 +22,7 @@ type Repository struct { StackTemplate IStackTemplateRepository Alert IAlertRepository Project IProjectRepository + Audit IAuditRepository } func CombinedGormFilter(table string, filters []pagination.Filter, combinedFilter pagination.CombinedFilter) FilterFunc { diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index dd7be17f..54f52b79 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -6,7 +6,6 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" - "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -97,7 +96,7 @@ func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain */ // paginator, res := filter.Scope(r.db.Order("kube_type DESC,template_type ASC"), pg.GetPaginationRequest(), &stackTemplates) - paginator, res := pg.Fetch(r.db, &stackTemplates) + _, res := pg.Fetch(r.db, &stackTemplates) if res.Error != nil { return nil, res.Error } @@ -106,9 +105,6 @@ func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain out = append(out, reflectStackTemplate(stackTemplate)) } - log.Info(helper.ModelToJson(paginator.Total)) - //log.Info(helper.ModelToJson(stackTemplates)) - return } diff --git a/internal/route/route.go b/internal/route/route.go index e97a514a..d62bda07 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -1,10 +1,6 @@ package route import ( - "bytes" - "context" - "fmt" - "io" "net/http" "time" @@ -12,7 +8,6 @@ import ( "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" - "github.com/google/uuid" "github.com/gorilla/handlers" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" @@ -22,10 +17,10 @@ import ( "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" authKeycloak "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator/keycloak" "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" + "github.com/openinfradev/tks-api/internal/middleware/logging" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/usecase" argowf "github.com/openinfradev/tks-api/pkg/argo-client" - "github.com/openinfradev/tks-api/pkg/log" gcache "github.com/patrickmn/go-cache" "github.com/swaggo/http-swagger" "gorm.io/gorm" @@ -40,16 +35,6 @@ var ( SYSTEM_API_PREFIX = internal.SYSTEM_API_PREFIX ) -type StatusRecorder struct { - http.ResponseWriter - Status int -} - -func (r *StatusRecorder) WriteHeader(status int) { - r.Status = status - r.ResponseWriter.WriteHeader(status) -} - func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloak, asset http.Handler) http.Handler { r := mux.NewRouter() @@ -66,6 +51,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa StackTemplate: repository.NewStackTemplateRepository(db), Alert: repository.NewAlertRepository(db), Project: repository.NewProjectRepository(db), + Audit: repository.NewAuditRepository(db), } usecaseFactory := usecase.Usecase{ @@ -81,6 +67,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Alert: usecase.NewAlertUsecase(repoFactory), Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), Project: usecase.NewProjectUsecase(repoFactory, argoClient), + Audit: usecase.NewAuditUsecase(repoFactory), } customMiddleware := internalMiddleware.NewMiddleware( @@ -89,7 +76,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa requestRecoder.NewDefaultRequestRecoder(), audit.NewDefaultAudit(repoFactory)) - r.Use(loggingMiddleware) + r.Use(logging.LoggingMiddleware) // [TODO] Transaction //r.Use(transactionMiddleware(db)) @@ -238,6 +225,11 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) + auditHandler := delivery.NewAuditHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) + r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) @@ -253,25 +245,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa return handlers.CORS(credentials, headersOk, originsOk, methodsOk)(r) } -func loggingMiddleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - r = r.WithContext(context.WithValue(ctx, internal.ContextKeyRequestID, uuid.New().String())) - - log.InfoWithContext(r.Context(), fmt.Sprintf("***** START [%s %s] ***** ", r.Method, r.RequestURI)) - - body, err := io.ReadAll(r.Body) - if err == nil { - log.InfoWithContext(r.Context(), fmt.Sprintf("REQUEST BODY : %s", bytes.NewBuffer(body).String())) - } - r.Body = io.NopCloser(bytes.NewBuffer(body)) - - next.ServeHTTP(w, r) - - log.InfofWithContext(r.Context(), "***** END [%s %s] *****", r.Method, r.RequestURI) - }) -} - /* func transactionMiddleware(db *gorm.DB) mux.MiddlewareFunc { return func(next http.Handler) http.Handler { diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go new file mode 100644 index 00000000..7461cf05 --- /dev/null +++ b/internal/usecase/audit.go @@ -0,0 +1,68 @@ +package usecase + +import ( + "context" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" +) + +type IAuditUsecase interface { + Get(ctx context.Context, auditId uuid.UUID) (domain.Audit, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Audit, error) + Create(ctx context.Context, dto domain.Audit) (auditId uuid.UUID, err error) + Delete(ctx context.Context, dto domain.Audit) error +} + +type AuditUsecase struct { + repo repository.IAuditRepository +} + +func NewAuditUsecase(r repository.Repository) IAuditUsecase { + return &AuditUsecase{ + repo: r.Audit, + } +} + +func (u *AuditUsecase) Create(ctx context.Context, dto domain.Audit) (auditId uuid.UUID, err error) { + if dto.UserId == nil { + user, ok := request.UserFrom(ctx) + if ok { + userId := user.GetUserId() + dto.UserId = &userId + } + } + auditId, err = u.repo.Create(dto) + if err != nil { + return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") + } + return auditId, nil +} + +func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res domain.Audit, err error) { + res, err = u.repo.Get(auditId) + if err != nil { + return domain.Audit{}, err + } + return +} + +func (u *AuditUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (audits []domain.Audit, err error) { + audits, err = u.repo.Fetch(organizationId, pg) + if err != nil { + return nil, err + } + return +} + +func (u *AuditUsecase) Delete(ctx context.Context, dto domain.Audit) (err error) { + err = u.repo.Delete(dto.ID) + if err != nil { + return httpErrors.NewNotFoundError(err, "", "") + } + return nil +} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index b8838933..66111e99 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -13,4 +13,5 @@ type Usecase struct { Alert IAlertUsecase Stack IStackUsecase Project IProjectUsecase + Audit IAuditUsecase } diff --git a/pkg/domain/audit.go b/pkg/domain/audit.go new file mode 100644 index 00000000..9599ccae --- /dev/null +++ b/pkg/domain/audit.go @@ -0,0 +1,49 @@ +package domain + +import ( + "time" + + "github.com/google/uuid" +) + +// 내부 +type Audit struct { + ID uuid.UUID + OrganizationId string + Organization Organization + Group string + Message string + Description string + ClientIP string + UserId *uuid.UUID + User User + CreatedAt time.Time + UpdatedAt time.Time +} + +type AuditResponse struct { + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Organization SimpleOrganizationResponse `json:"organization"` + Description string `json:"description"` + Group string `json:"group"` + Message string `json:"message"` + ClientIP string `json:"clientIP"` + UserId string `json:"userId"` + User SimpleUserResponse `json:"user"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type CreateAuditRequest struct { +} +type CreateAuditResponse struct { +} + +type GetAuditResponse struct { + Audit AuditResponse `json:"audit"` +} +type GetAuditsResponse struct { + Audits []AuditResponse `json:"audits"` + Pagination PaginationResponse `json:"pagination"` +} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 6e3706da..31667dc3 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -61,6 +61,12 @@ type Organization = struct { UpdatedAt time.Time `json:"updatedAt"` } +type SimpleOrganizationResponse = struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` +} + type CreateOrganizationRequest struct { Name string `json:"name" validate:"required,name"` Description string `json:"description" validate:"omitempty,min=0,max=100"` diff --git a/pkg/domain/user.go b/pkg/domain/user.go index fbea7635..0e79216f 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -32,6 +32,12 @@ type Role = struct { UpdatedAt time.Time `json:"updatedAt"` } +type SimpleRoleResponse = struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` +} + type Policy = struct { ID string `json:"id"` Name string `json:"name"` @@ -59,9 +65,10 @@ type CreateUserRequest struct { } type SimpleUserResponse struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role SimpleRoleResponse `json:"role"` } type CreateUserResponse struct { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index b6c91281..b43f22f8 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -16,6 +16,7 @@ var errorMap = map[ErrorCode]string{ "C_INVALID_ASA_ID": "유효하지 않은 앱서빙앱 아이디입니다. 앱서빙앱 아이디를 확인하세요.", "C_INVALID_ASA_TASK_ID": "유효하지 않은 테스크 아이디입니다. 테스크 아이디를 확인하세요.", "C_INVALID_CLOUD_SERVICE": "유효하지 않은 클라우드서비스입니다.", + "C_INVALID_AUDIT_ID": "유효하지 않은 로그 아이디입니다. 로그 아이디를 확인하세요.", "C_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패했습니다.", // Auth From 0c952d4c1d5d6057d404ef9c34a75b62f2730a4c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 26 Feb 2024 14:10:04 +0900 Subject: [PATCH 045/502] feature. add interface project-namespace-k8s-resources --- api/swagger/docs.go | 98 +++++++++++++++++++++++++++++++ api/swagger/swagger.json | 98 +++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 64 ++++++++++++++++++++ internal/delivery/api/endpoint.go | 9 +++ internal/delivery/http/project.go | 53 +++++++++++++++++ internal/route/route.go | 1 + internal/usecase/project.go | 19 ++++++ pkg/domain/project.go | 16 +++++ 8 files changed, 358 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 25c5a8d6..d071dd1e 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -4117,6 +4117,64 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get k8s resources for project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get k8s resources for project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectNamespaceK8sResourcesResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -7167,6 +7225,14 @@ const docTemplate = `{ } } }, + "domain.GetProjectNamespaceK8sResourcesResponse": { + "type": "object", + "properties": { + "k8sResources": { + "$ref": "#/definitions/domain.ProjectNamespaceK8sResources" + } + } + }, "domain.GetProjectNamespaceResponse": { "type": "object", "properties": { @@ -7714,6 +7780,38 @@ const docTemplate = `{ } } }, + "domain.ProjectNamespaceK8sResources": { + "type": "object", + "properties": { + "cronjobs": { + "type": "integer" + }, + "demonsets": { + "type": "integer" + }, + "deployments": { + "type": "integer" + }, + "ingresses": { + "type": "integer" + }, + "jobs": { + "type": "integer" + }, + "pods": { + "type": "integer" + }, + "pvcs": { + "type": "integer" + }, + "services": { + "type": "integer" + }, + "statefulsets": { + "type": "integer" + } + } + }, "domain.ProjectNamespaceResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 54a4cacd..97c10867 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -4111,6 +4111,64 @@ } } }, + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get k8s resources for project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get k8s resources for project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/domain.GetProjectNamespaceK8sResourcesResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -7161,6 +7219,14 @@ } } }, + "domain.GetProjectNamespaceK8sResourcesResponse": { + "type": "object", + "properties": { + "k8sResources": { + "$ref": "#/definitions/domain.ProjectNamespaceK8sResources" + } + } + }, "domain.GetProjectNamespaceResponse": { "type": "object", "properties": { @@ -7708,6 +7774,38 @@ } } }, + "domain.ProjectNamespaceK8sResources": { + "type": "object", + "properties": { + "cronjobs": { + "type": "integer" + }, + "demonsets": { + "type": "integer" + }, + "deployments": { + "type": "integer" + }, + "ingresses": { + "type": "integer" + }, + "jobs": { + "type": "integer" + }, + "pods": { + "type": "integer" + }, + "pvcs": { + "type": "integer" + }, + "services": { + "type": "integer" + }, + "statefulsets": { + "type": "integer" + } + } + }, "domain.ProjectNamespaceResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index aa05361a..f9abcd33 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1342,6 +1342,11 @@ definitions: $ref: '#/definitions/domain.ProjectMemberResponse' type: array type: object + domain.GetProjectNamespaceK8sResourcesResponse: + properties: + k8sResources: + $ref: '#/definitions/domain.ProjectNamespaceK8sResources' + type: object domain.GetProjectNamespaceResponse: properties: projectNamespace: @@ -1707,6 +1712,27 @@ definitions: updatedAt: type: string type: object + domain.ProjectNamespaceK8sResources: + properties: + cronjobs: + type: integer + demonsets: + type: integer + deployments: + type: integer + ingresses: + type: integer + jobs: + type: integer + pods: + type: integer + pvcs: + type: integer + services: + type: integer + statefulsets: + type: integer + type: object domain.ProjectNamespaceResponse: properties: appCount: @@ -4941,6 +4967,44 @@ paths: summary: Check project namespace exist tags: - Projects + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources: + get: + consumes: + - application/json + description: Get k8s resources for project namespace + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Stack ID + in: path + name: stackId + required: true + type: string + - description: Project Namespace + in: path + name: projectNamespace + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/domain.GetProjectNamespaceK8sResourcesResponse' + security: + - JWT: [] + summary: Get k8s resources for project namespace + tags: + - Projects /organizations/{organizationId}/projects/existence: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 21ee33c4..fe167f60 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -150,6 +150,7 @@ const ( UnSetFavoriteProject UnSetFavoriteProjectNamespace GetProjectKubeconfig + GetProjectNamespaceK8sResources ) var ApiMap = map[Endpoint]EndpointInfo{ @@ -613,6 +614,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetProjectKubeconfig", Group: "Project", }, + GetProjectNamespaceK8sResources: { + Name: "GetProjectNamespaceK8sResources", + Group: "Project", + }, } func (e Endpoint) String() string { @@ -847,6 +852,8 @@ func (e Endpoint) String() string { return "UnSetFavoriteProjectNamespace" case GetProjectKubeconfig: return "GetProjectKubeconfig" + case GetProjectNamespaceK8sResources: + return "GetProjectNamespaceK8sResources" default: return "" } @@ -1083,6 +1090,8 @@ func GetEndpoint(name string) Endpoint { return UnSetFavoriteProjectNamespace case "GetProjectKubeconfig": return GetProjectKubeconfig + case "GetProjectNamespaceK8sResources": + return GetProjectNamespaceK8sResources default: return -1 } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index cc864945..8824422c 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -49,6 +49,7 @@ type IProjectHandler interface { UnSetFavoriteProjectNamespace(w http.ResponseWriter, r *http.Request) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) + GetProjectNamespaceK8sResources(w http.ResponseWriter, r *http.Request) } type ProjectHandler struct { @@ -1359,3 +1360,55 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ ResponseJSON(w, r, http.StatusOK, out) } + +// GetProjectNamespaceK8sResources godoc +// @Tags Projects +// @Summary Get k8s resources for project namespace +// @Description Get k8s resources for project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Stack ID" +// @Param projectNamespace path string true "Project Namespace" +// @Success 200 {object} domain.GetProjectNamespaceK8sResourcesResponse +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources [get] +// @Security JWT +func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found in path"), "C_INVALID_PROJECT_ID", "")) + return + } + + projectNamespace, ok := vars["projectNamespace"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespace"), "C_INVALID_PROJECT_NAMESPACE", "")) + return + } + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), "C_INVALID_STACK_ID", "")) + return + } + + k8sResources, err := p.usecase.GetK8sResources(r.Context(), organizationId, projectId, projectNamespace, stackId) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectNamespaceK8sResourcesResponse + if err = serializer.Map(k8sResources, &out.K8sResources); err != nil { + log.Error(err) + } + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/route/route.go b/internal/route/route.go index e97a514a..95f46961 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -232,6 +232,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role", customMiddleware.Handle(internalApi.UpdateProjectMemberRole, http.HandlerFunc(projectHandler.UpdateProjectMemberRole))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNamespaceExist))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources", customMiddleware.Handle(internalApi.GetProjectNamespaceK8sResources, http.HandlerFunc(projectHandler.GetProjectNamespaceK8sResources))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateProjectNamespace, http.HandlerFunc(projectHandler.UpdateProjectNamespace))).Methods(http.MethodPut) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 4817bff8..7afc25e1 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -1,6 +1,8 @@ package usecase import ( + "context" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/repository" @@ -42,6 +44,7 @@ type IProjectUsecase interface { UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error GetProjectKubeconfig(organizationId string, projectId string) (string, error) + GetK8sResources(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (out domain.ProjectNamespaceK8sResources, err error) } type ProjectUsecase struct { @@ -416,3 +419,19 @@ func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId s return kubernetes.MergeKubeconfigsWithSingleUser(kubeconfigs) } + +func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (out domain.ProjectNamespaceK8sResources, err error) { + + // to be implemented + out.Pods = 1 + out.Deployments = 2 + out.Statefulsets = 3 + out.Demonsets = 4 + out.Jobs = 5 + out.Cronjobs = 6 + out.PVCs = 7 + out.Services = 8 + out.Ingresses = 9 + + return +} diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 10e5d9a4..3fc02157 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -254,3 +254,19 @@ type UpdateProjectNamespaceRequest struct { type GetProjectKubeconfigResponse struct { Kubeconfig string `json:"kubeconfig"` } + +type ProjectNamespaceK8sResources struct { + Pods int `json:"pods"` + Deployments int `json:"deployments"` + Statefulsets int `json:"statefulsets"` + Demonsets int `json:"demonsets"` + Jobs int `json:"jobs"` + Cronjobs int `json:"cronjobs"` + PVCs int `json:"pvcs"` + Services int `json:"services"` + Ingresses int `json:"ingresses"` +} + +type GetProjectNamespaceK8sResourcesResponse struct { + K8sResources ProjectNamespaceK8sResources `json:"k8sResources"` +} From 04be35414a032ba1a3ba8d749c2e7eae876f310a Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 25 Jan 2024 14:17:02 +0900 Subject: [PATCH 046/502] add keycloak setting --- internal/keycloak/keycloak.go | 180 +++++++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 1 deletion(-) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 7c3040a6..34a26a8b 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -36,6 +36,12 @@ type IKeycloak interface { JoinGroup(organizationId string, userId string, groupName string) error LeaveGroup(organizationId string, userId string, groupName string) error + CreateClientRoleWithClientName(organizationId string, clientName string, roleName string) error + DeleteClientRoleWithClientName(organizationId string, clientName string, roleName string) error + + AssignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error + UnassignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error + VerifyAccessToken(token string, organizationId string) (bool, error) GetSessions(userId string, organizationId string) (*[]string, error) } @@ -115,6 +121,7 @@ func (k *Keycloak) InitializeKeycloak() error { return err } + // for _, defaultMapper := range defaultProtocolTksMapper { if err := k.ensureClientProtocolMappers(ctx, token, DefaultMasterRealm, *tksClient.ClientID, "openid", defaultMapper); err != nil { log.Fatal(err) @@ -446,6 +453,151 @@ func (k *Keycloak) LeaveGroup(organizationId string, userId string, groupName st return nil } + +func (k *Keycloak) CreateClientRoleWithClientName(organizationId string, clientName string, roleName string) error { + ctx := context.Background() + token := k.adminCliToken + + clients, err := k.client.GetClients(ctx, token.AccessToken, organizationId, gocloak.GetClientsParams{ + ClientID: &clientName, + }) + if err != nil { + log.Error("Getting Client is failed", err) + return err + } + + targetClient := clients[0] + + role := gocloak.Role{ + Name: gocloak.StringP(roleName), + } + + _, err = k.client.CreateClientRole(ctx, token.AccessToken, organizationId, *targetClient.ID, role) + if err != nil { + log.Error("Creating Client Role is failed", err) + return err + } + + return nil +} + +func (k *Keycloak) DeleteClientRoleWithClientName(organizationId string, clientName string, roleName string) error { + ctx := context.Background() + token := k.adminCliToken + + clients, err := k.client.GetClients(ctx, token.AccessToken, organizationId, gocloak.GetClientsParams{ + ClientID: &clientName, + }) + if err != nil { + log.Error("Getting Client is failed", err) + return err + } + + targetClient := clients[0] + + roles, err := k.client.GetClientRoles(ctx, token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ + Search: &roleName, + }) + if err != nil { + log.Error("Getting Client Role is failed", err) + return err + } + + if len(roles) == 0 { + log.Warn("Client Role not found", roleName) + return nil + } + + err = k.client.DeleteClientRole(ctx, token.AccessToken, organizationId, *targetClient.ID, *roles[0].ID) + if err != nil { + log.Error("Deleting Client Role is failed", err) + return err + } + + return nil +} + +func (k *Keycloak) AssignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error { + ctx := context.Background() + token := k.adminCliToken + + clients, err := k.client.GetClients(ctx, token.AccessToken, organizationId, gocloak.GetClientsParams{ + ClientID: &clientName, + }) + if err != nil { + log.Error("Getting Client is failed", err) + return err + } + if len(clients) == 0 { + log.Warn("Client not found", clientName) + return nil + } + + targetClient := clients[0] + + roles, err := k.client.GetClientRoles(ctx, token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ + Search: &roleName, + }) + if err != nil { + log.Error("Getting Client Role is failed", err) + return err + } + + if len(roles) == 0 { + log.Warn("Client Role not found", roleName) + return nil + } + + err = k.client.AddClientRolesToUser(ctx, token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) + + if err != nil { + log.Error("Assigning Client Role to User is failed", err) + return err + } + + return nil +} + +func (k *Keycloak) UnassignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error { + ctx := context.Background() + token := k.adminCliToken + + clients, err := k.client.GetClients(ctx, token.AccessToken, organizationId, gocloak.GetClientsParams{ + ClientID: &clientName, + }) + if err != nil { + log.Error("Getting Client is failed", err) + return err + } + if len(clients) == 0 { + log.Warn("Client not found", clientName) + return nil + } + + targetClient := clients[0] + + roles, err := k.client.GetClientRoles(ctx, token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ + Search: &roleName, + }) + if err != nil { + log.Error("Getting Client Role is failed", err) + return err + } + + if len(roles) == 0 { + log.Warn("Client Role not found", roleName) + return nil + } + + err = k.client.DeleteClientRolesFromUser(ctx, token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) + if err != nil { + log.Error("Unassigning Client Role to User is failed", err) + return err + } + + return nil +} + func (k *Keycloak) ensureClientProtocolMappers(ctx context.Context, token *gocloak.JWT, realm string, clientId string, scope string, mapper gocloak.ProtocolMapperRepresentation) error { //TODO: Check current logic(if exist, do nothing) is fine @@ -624,6 +776,16 @@ func (k *Keycloak) getClientByClientId(ctx context.Context, accessToken string, return *clients[0].ID, nil } +func (k *Keycloak) createClientRole(ctx context.Context, accessToken string, realm string, clientUuid string, + roleName string) (string, error) { + id, err := k.client.CreateClientRole(ctx, accessToken, realm, clientUuid, gocloak.Role{Name: gocloak.StringP(roleName)}) + if err != nil { + log.Error("Creating Client Role is failed", err) + return "", err + } + return id, nil +} + func (k *Keycloak) getClientRole(ctx context.Context, accessToken string, realm string, clientUuid string, roleName string) (*gocloak.Role, error) { role, err := k.client.GetClientRole(ctx, accessToken, realm, clientUuid, roleName) @@ -695,7 +857,6 @@ func (k *Keycloak) reflectRealmRepresentation(org domain.Organization) *gocloak. } } -// var defaultProtocolTksMapper = make([]gocloak.ProtocolMapperRepresentation, 3) var defaultProtocolTksMapper = []gocloak.ProtocolMapperRepresentation{ { Name: gocloak.StringP("org"), @@ -734,6 +895,23 @@ var defaultProtocolTksMapper = []gocloak.ProtocolMapperRepresentation{ "userinfo.token.claim": "false", }, }, + { + Name: gocloak.StringP("project-role"), + Protocol: gocloak.StringP("openid-connect"), + ProtocolMapper: gocloak.StringP("oidc-usermodel-client-role-mapper"), + Config: &map[string]string{ + "access.token.claim": "true", + "id.token.claim": "false", + "userinfo.token.claim": "false", + + "claim.name": "project-role", + "jsonType.label": "String", + "multivalued": "true", + + "usermodel.clientRoleMapping.clientId": "tks", + "usermodel.clientRoleMapping.role_prefix": "", + }, + }, } func defaultRealmSetting(realmId string) gocloak.RealmRepresentation { From ef5f29c5bfebc53585a3a456612389e100045354 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 29 Jan 2024 12:47:52 +0900 Subject: [PATCH 047/502] add kubernetes setting --- internal/kubernetes/kubernetes.go | 356 ++++++++++++++++++++++++- internal/kubernetes/kubernetes_test.go | 119 ++++++++- 2 files changed, 473 insertions(+), 2 deletions(-) diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index 8addc0b1..15ba1411 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -4,13 +4,14 @@ import ( "bytes" "context" "fmt" - "gopkg.in/yaml.v3" "os" "strings" "github.com/spf13/viper" + rbacV1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/discovery" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -189,6 +190,359 @@ func GetKubernetesVserion() (string, error) { return information.GitVersion, nil } +func GetKubeconfigById(clusterId string) ([]byte, error) { + clientset, err := GetClientAdminCluster() + if err != nil { + return nil, err + } + + secrets, err := clientset.CoreV1().Secrets(clusterId).Get(context.TODO(), clusterId+"-tks-kubeconfig", metav1.GetOptions{}) + if err != nil { + log.Error(err) + return nil, err + } + + return secrets.Data["value"], nil +} + +func GetResourceApiVersion(kubeconfig []byte, kind string) (string, error) { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return "", err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + apiResourceList, err := clientset.Discovery().ServerPreferredResources() + if err != nil { + log.Error(err) + return "", err + } + + for _, apiResource := range apiResourceList { + for _, resource := range apiResource.APIResources { + if resource.Kind == kind { + return resource.Version, nil + } + } + } + + return "", nil +} + +func EnsureClusterRole(kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + // generate clusterrole object + for _, role := range []string{leaderRole, memberRole, viewerRole} { + obj := getClusterRole(role, projectName+"-"+role) + + if _, err := clientset.RbacV1().ClusterRoles().Get(context.Background(), projectName+"-"+role, metav1.GetOptions{}); err != nil { + _, err = clientset.RbacV1().ClusterRoles().Create(context.Background(), obj, metav1.CreateOptions{}) + if err != nil { + log.Error(err) + return err + } + } else { + _, err = clientset.RbacV1().ClusterRoles().Update(context.Background(), obj, metav1.UpdateOptions{}) + if err != nil { + log.Error(err) + return err + } + } + } + + return nil +} + +func EnsureClusterRoleBinding(kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + for _, role := range []string{leaderRole, memberRole, viewerRole} { + obj := generateClusterRoleToClusterRoleBinding(role+"@"+projectName, projectName+"-"+role, projectName+"-"+role) + if _, err = clientset.RbacV1().ClusterRoleBindings().Get(context.Background(), projectName+"-"+role, metav1.GetOptions{}); err != nil { + _, err = clientset.RbacV1().ClusterRoleBindings().Create(context.Background(), obj, metav1.CreateOptions{}) + if err != nil { + log.Error(err) + return err + } + } else { + _, err = clientset.RbacV1().ClusterRoleBindings().Update(context.Background(), obj, metav1.UpdateOptions{}) + if err != nil { + log.Error(err) + return err + } + } + } + + return nil +} + +func RemoveClusterRoleBinding(kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + for _, role := range []string{leaderRole, memberRole, viewerRole} { + if err := clientset.RbacV1().ClusterRoleBindings().Delete(context.Background(), projectName+"-"+role, metav1.DeleteOptions{}); err != nil { + log.Error(err) + } + } + + return nil +} + +func EnsureRoleBinding(kubeconfig []byte, projectName string, namespace string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + for _, role := range []string{leaderRole, memberRole, viewerRole} { + obj := generateClusterRoleToRoleBinding(role+"@"+projectName, projectName+"-"+role, namespace, projectName+"-"+role) + if _, err = clientset.RbacV1().RoleBindings(namespace).Get(context.Background(), projectName+"-"+role, metav1.GetOptions{}); err != nil { + _, err = clientset.RbacV1().RoleBindings(namespace).Create(context.Background(), obj, metav1.CreateOptions{}) + if err != nil { + log.Error(err) + return err + } + } else { + _, err = clientset.RbacV1().RoleBindings(namespace).Update(context.Background(), obj, metav1.UpdateOptions{}) + if err != nil { + log.Error(err) + return err + } + } + } + + return nil +} + +func RemoveRoleBinding(kubeconfig []byte, projectName string, namespace string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + for _, role := range []string{leaderRole, memberRole, viewerRole} { + if err := clientset.RbacV1().RoleBindings(namespace).Delete(context.Background(), projectName+"-"+role, metav1.DeleteOptions{}); err != nil { + log.Error(err) + } + } + + return nil +} + +const ( + leaderRole = "leader" + memberRole = "member" + viewerRole = "viewer" +) + +func getClusterRole(role, objName string) *rbacV1.ClusterRole { + + clusterRole := rbacV1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: objName, + }, + Rules: []rbacV1.PolicyRule{ + { + Verbs: []string{"*"}, + APIGroups: []string{"*"}, + Resources: []string{"*"}, + }, + }, + } + + switch role { + case leaderRole: + clusterRole.Rules[0].Verbs = []string{"*"} + case memberRole: + clusterRole.Rules[0].Verbs = []string{"*"} + case viewerRole: + clusterRole.Rules[0].Verbs = []string{"get", "list", "watch"} + default: + return nil + } + + return &clusterRole +} + +func EnsureCommonClusterRole(kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + obj := generateCommonClusterRole(projectName + "-common") + if _, err = clientset.RbacV1().ClusterRoles().Get(context.Background(), projectName+"-common", metav1.GetOptions{}); err != nil { + _, err = clientset.RbacV1().ClusterRoles().Create(context.Background(), obj, metav1.CreateOptions{}) + if err != nil { + log.Error(err) + return err + } + } else { + _, err = clientset.RbacV1().ClusterRoles().Update(context.Background(), obj, metav1.UpdateOptions{}) + if err != nil { + log.Error(err) + return err + } + } + + return nil +} + +func EnsureCommonClusterRoleBinding(kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + for _, role := range []string{leaderRole, memberRole, viewerRole} { + obj := generateClusterRoleToClusterRoleBinding(role+"@"+projectName, projectName+"-common-"+role, projectName+"-common") + if _, err = clientset.RbacV1().ClusterRoleBindings().Get(context.Background(), projectName+"-common"+"-"+role, metav1.GetOptions{}); err != nil { + _, err = clientset.RbacV1().ClusterRoleBindings().Create(context.Background(), obj, metav1.CreateOptions{}) + if err != nil { + log.Error(err) + return err + } + } else { + _, err = clientset.RbacV1().ClusterRoleBindings().Update(context.Background(), obj, metav1.UpdateOptions{}) + if err != nil { + log.Error(err) + return err + } + } + } + + return nil +} + +func RemoveCommonClusterRoleBinding(kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + for _, role := range []string{leaderRole, memberRole, viewerRole} { + if err := clientset.RbacV1().ClusterRoles().Delete(context.Background(), projectName+"-common-"+role, metav1.DeleteOptions{}); err != nil { + log.Error(err) + return err + } + } + + return nil +} +func generateCommonClusterRole(objName string) *rbacV1.ClusterRole { + clusterRole := rbacV1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: objName, + }, + Rules: []rbacV1.PolicyRule{ + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{""}, + Resources: []string{"namespaces", "nodes", "storageclasses", "persistentvolumes"}, + }, + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{"storage.k8s.io"}, + Resources: []string{"storageclasses"}, + }, + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{"apiextensions.k8s.io"}, + Resources: []string{"customresourcedefinitions"}, + }, + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{"certificates.k8s.io"}, + Resources: []string{"certificatesigningrequests"}, + }, + { + Verbs: []string{"get", "list", "watch"}, + APIGroups: []string{"rbac.authorization.k8s.io"}, + Resources: []string{"clusterroles", "clusterrolebindings"}, + }, + }, + } + + return &clusterRole +} + +func generateClusterRoleToClusterRoleBinding(groupName, objName, roleName string) *rbacV1.ClusterRoleBinding { + clusterRoleBinding := rbacV1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: objName, + }, + Subjects: []rbacV1.Subject{ + { + Kind: "Group", + Name: groupName, + }, + }, + RoleRef: rbacV1.RoleRef{ + Kind: "ClusterRole", + Name: roleName, + }, + } + + return &clusterRoleBinding +} + +func generateClusterRoleToRoleBinding(groupName, objName, roleName, namespace string) *rbacV1.RoleBinding { + roleBinding := rbacV1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: objName, + Namespace: namespace, + }, + Subjects: []rbacV1.Subject{ + { + Kind: "Group", + Name: groupName, + }, + }, + RoleRef: rbacV1.RoleRef{ + Kind: "ClusterRole", + Name: roleName, + }, + } + + return &roleBinding +} + func MergeKubeconfigsWithSingleUser(kubeconfigs []string) (string, error) { type kubeConfigType struct { APIVersion string `yaml:"apiVersion"` diff --git a/internal/kubernetes/kubernetes_test.go b/internal/kubernetes/kubernetes_test.go index 3f8a578a..6e25b0bb 100644 --- a/internal/kubernetes/kubernetes_test.go +++ b/internal/kubernetes/kubernetes_test.go @@ -2,11 +2,128 @@ package kubernetes_test import ( "github.com/openinfradev/tks-api/internal/kubernetes" - "gopkg.in/yaml.v3" + "os" "reflect" "testing" ) +const path = "/Users/1113433/local_vm_kube/kubeconfig" + +func TestGetResourceApiVersionByClusterId(t *testing.T) { + dat, err := os.ReadFile(path) + if err != nil { + t.Errorf("ReadFile() error = %v", err) + return + } + + res, err := kubernetes.GetResourceApiVersion(dat, "ClusterRole") + if err != nil { + t.Errorf("GetResourceApiVersion() error = %v", err) + return + } + + t.Logf("GetResourceApiVersion() result = %v", res) + +} + +func TestEnsureClusterRole(t *testing.T) { + dat, err := os.ReadFile(path) + if err != nil { + t.Errorf("ReadFile() error = %v", err) + return + } + + err = kubernetes.EnsureClusterRole(dat, "p123") + if err != nil { + t.Errorf("EnsureClusterRole() error = %v", err) + return + } +} + +func TestEnsureCommonClusterRole(t *testing.T) { + dat, err := os.ReadFile(path) + if err != nil { + t.Errorf("ReadFile() error = %v", err) + return + } + + err = kubernetes.EnsureCommonClusterRole(dat, "p123") + if err != nil { + t.Errorf("EnsureClusterRole() error = %v", err) + return + } +} + +func TestEnsureCommonClusterRoleBinding(t *testing.T) { + dat, err := os.ReadFile(path) + if err != nil { + t.Errorf("ReadFile() error = %v", err) + return + } + + err = kubernetes.EnsureCommonClusterRoleBinding(dat, "p123") + if err != nil { + t.Errorf("EnsureClusterRole() error = %v", err) + return + } +} + +func TestEnsureClusterRoleBinding(t *testing.T) { + dat, err := os.ReadFile(path) + if err != nil { + t.Errorf("ReadFile() error = %v", err) + return + } + + err = kubernetes.EnsureClusterRoleBinding(dat, "p123") + if err != nil { + t.Errorf("EnsureClusterRole() error = %v", err) + return + } +} + +func TestEnsureRoleBinding(t *testing.T) { + dat, err := os.ReadFile(path) + if err != nil { + t.Errorf("ReadFile() error = %v", err) + return + } + + err = kubernetes.EnsureRoleBinding(dat, "p123", "test") + if err != nil { + t.Errorf("EnsureClusterRole() error = %v", err) + return + } +} + +func TestRemoveClusterRoleBinding(t *testing.T) { + dat, err := os.ReadFile(path) + if err != nil { + t.Errorf("ReadFile() error = %v", err) + return + } + + err = kubernetes.RemoveClusterRoleBinding(dat, "p123") + if err != nil { + t.Errorf("EnsureClusterRole() error = %v", err) + return + } +} + +func TestRemoveRoleBinding(t *testing.T) { + dat, err := os.ReadFile(path) + if err != nil { + t.Errorf("ReadFile() error = %v", err) + return + } + + err = kubernetes.RemoveRoleBinding(dat, "p123", "test") + if err != nil { + t.Errorf("EnsureClusterRole() error = %v", err) + return + } +} + func TestMergeKubeconfigsWithSingleUser(t *testing.T) { type kubeConfigType struct { APIVersion string `yaml:"apiVersion"` From 6ed4c7704b9a65f67d6b1402eab7e97609fe9921 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 29 Jan 2024 12:51:58 +0900 Subject: [PATCH 048/502] mark not to build auto-gen code --- hack/endpoint-codegen.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hack/endpoint-codegen.go b/hack/endpoint-codegen.go index eff018a0..eba0b574 100644 --- a/hack/endpoint-codegen.go +++ b/hack/endpoint-codegen.go @@ -1,3 +1,5 @@ +//go:build ignore + package main import ( From b5017fdb293a4155d563cf3568afc392700ca640 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 16 Feb 2024 15:25:45 +0900 Subject: [PATCH 049/502] implement keycloak & k8s logic --- internal/delivery/http/project.go | 139 ++++++++++++++++ internal/keycloak/keycloak.go | 4 +- internal/kubernetes/kubernetes.go | 36 +++++ internal/usecase/project.go | 258 +++++++++++++++++++++++++++++- 4 files changed, 434 insertions(+), 3 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index cc864945..df18232c 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -374,6 +374,8 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { } func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { + //ToDo: to donggyu. implement cleanup logic for k8s & keycloak + //TODO implement me } @@ -497,6 +499,17 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + var stackIds map[string]struct{} + for _, pn := range pns { + stackIds[pn.StackId] = struct{}{} + } + now := time.Now() for _, pmr := range projectMemberReq.ProjectMemberRequests { pu, err := p.usecase.GetProjectUser(pmr.ProjectUserId) @@ -533,6 +546,15 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } + + // tasks for keycloak & k8s + for stackId := range stackIds { + if err := p.usecase.AssignKeycloakClientRoleToMember(organizationId, projectId, stackId, pmId); err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } } out := domain.CommonProjectResponse{Result: "OK"} @@ -768,6 +790,26 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque "C_INVALID_PROJECT_MEMBER_ID", "")) return } + + // tasks for keycloak & k8s + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + var stackIds map[string]struct{} + for _, pn := range pns { + stackIds[pn.StackId] = struct{}{} + } + for stackId := range stackIds { + if err := p.usecase.UnassignKeycloakClientRoleToMember(organizationId, projectId, stackId, projectMemberId); err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + if err := p.usecase.RemoveProjectMember(projectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -812,8 +854,29 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ return } + // tasks for keycloak & k8s + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + var stackIds map[string]struct{} + for _, pn := range pns { + stackIds[pn.StackId] = struct{}{} + } + // TODO: change multi row delete for _, pm := range projectMemberReq.ProjectMember { + // tasks for keycloak & k8s + for stackId := range stackIds { + if err := p.usecase.UnassignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectMemberId); err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + if err := p.usecase.RemoveProjectMember(pm.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -879,6 +942,25 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R return } + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + var stackIds map[string]struct{} + for _, pn := range pns { + stackIds[pn.StackId] = struct{}{} + } + // tasks for keycloak & k8s. Unassign old role + for stackId := range stackIds { + if err := p.usecase.UnassignKeycloakClientRoleToMember(organizationId, projectId, stackId, projectMemberId); err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + pm.ProjectRoleId = pmrReq.ProjectRoleId pm.ProjectUser = nil pm.ProjectRole = nil @@ -888,6 +970,14 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R ErrorJSON(w, r, err) return } + // tasks for keycloak & k8s. Assign new role + for stackId := range stackIds { + if err := p.usecase.AssignKeycloakClientRoleToMember(organizationId, projectId, stackId, projectMemberId); err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } @@ -929,6 +1019,17 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + if err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + var stackIds map[string]struct{} + for _, pn := range pns { + stackIds[pn.StackId] = struct{}{} + } + for _, pmr := range projectMemberReq.ProjectMemberRoleRequests { pm, err := p.usecase.GetProjectMember(pmr.ProjectMemberId) if err != nil { @@ -942,6 +1043,14 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } + for stackId := range stackIds { + if err := p.usecase.UnassignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ID); err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + pm.ProjectRoleId = pmr.ProjectRoleId pm.ProjectUser = nil pm.ProjectRole = nil @@ -951,6 +1060,14 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. ErrorJSON(w, r, err) return } + + for stackId := range stackIds { + if err := p.usecase.AssignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ID); err != nil { + log.Error(err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } } ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) @@ -1000,6 +1117,16 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re CreatedAt: now, } + // tasks for keycloak & k8s + if err := p.usecase.EnsureRequiredSetupForCluster(organizationId, projectId, projectNamespaceReq.StackId); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if err := p.usecase.CreateK8SNSRoleBinding(organizationId, projectId, projectNamespaceReq.StackId, projectNamespaceReq.Namespace); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if err := p.usecase.CreateProjectNamespace(organizationId, pn); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1267,6 +1394,18 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re // @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] // @Security JWT func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { + + //ToDo: from donggyu. uncomment lines below after implementing usecase.DeleteProjectNamespace. + // tasks for keycloak & k8s + /*if err := p.usecase.DeleteK8SNSRoleBinding(organizationId, projectId, stackId, projectNamespace); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if err := p.usecase.MayRemoveRequiredSetupForCluster(organizationId, projectId, stackId); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + }*/ + //TODO implement me //vars := mux.Vars(r) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 34a26a8b..4c41f89c 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -36,7 +36,7 @@ type IKeycloak interface { JoinGroup(organizationId string, userId string, groupName string) error LeaveGroup(organizationId string, userId string, groupName string) error - CreateClientRoleWithClientName(organizationId string, clientName string, roleName string) error + EnsureClientRoleWithClientName(organizationId string, clientName string, roleName string) error DeleteClientRoleWithClientName(organizationId string, clientName string, roleName string) error AssignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error @@ -454,7 +454,7 @@ func (k *Keycloak) LeaveGroup(organizationId string, userId string, groupName st return nil } -func (k *Keycloak) CreateClientRoleWithClientName(organizationId string, clientName string, roleName string) error { +func (k *Keycloak) EnsureClientRoleWithClientName(organizationId string, clientName string, roleName string) error { ctx := context.Background() token := k.adminCliToken diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index 15ba1411..0fef1084 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -262,6 +262,25 @@ func EnsureClusterRole(kubeconfig []byte, projectName string) error { return nil } +func RemoveClusterRole(kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + // remove clusterrole object + for _, role := range []string{leaderRole, memberRole, viewerRole} { + if err := clientset.RbacV1().ClusterRoles().Delete(context.Background(), projectName+"-"+role, metav1.DeleteOptions{}); err != nil { + log.Error(err) + } + } + + return nil +} + func EnsureClusterRoleBinding(kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { @@ -418,6 +437,23 @@ func EnsureCommonClusterRole(kubeconfig []byte, projectName string) error { return nil } +func RemoveCommonClusterRole(kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + if err := clientset.RbacV1().ClusterRoles().Delete(context.Background(), projectName+"-common", metav1.DeleteOptions{}); err != nil { + log.Error(err) + return err + } + + return nil +} + func EnsureCommonClusterRoleBinding(kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 4817bff8..3da7f748 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -3,6 +3,8 @@ package usecase import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/internal/keycloak" + "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -41,9 +43,18 @@ type IProjectUsecase interface { GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error + + EnsureRequiredSetupForCluster(organizationId string, projectId string, stackId string) error + MayRemoveRequiredSetupForCluster(organizationId string, projectId string, stackId string) error + + CreateK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error + DeleteK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error GetProjectKubeconfig(organizationId string, projectId string) (string, error) } + AssignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error + UnassignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error +} type ProjectUsecase struct { projectRepo repository.IProjectRepository userRepository repository.IUserRepository @@ -52,9 +63,10 @@ type ProjectUsecase struct { appgroupRepository repository.IAppGroupRepository organizationRepository repository.IOrganizationRepository argo argowf.ArgoClient + kc keycloak.IKeycloak } -func NewProjectUsecase(r repository.Repository, argoClient argowf.ArgoClient) IProjectUsecase { +func NewProjectUsecase(r repository.Repository, kc keycloak.IKeycloak, argoClient argowf.ArgoClient) IProjectUsecase { return &ProjectUsecase{ projectRepo: r.Project, userRepository: r.User, @@ -63,6 +75,7 @@ func NewProjectUsecase(r repository.Repository, argoClient argowf.ArgoClient) IP appgroupRepository: r.AppGroup, organizationRepository: r.Organization, argo: argoClient, + kc: kc, } } @@ -72,6 +85,7 @@ func (u *ProjectUsecase) CreateProject(p *domain.Project) (string, error) { log.Error(err) return "", errors.Wrap(err, "Failed to create project.") } + return projectId, nil } @@ -360,6 +374,248 @@ func (u *ProjectUsecase) DeleteProjectNamespace(organizationId string, projectId return nil } +func (u *ProjectUsecase) EnsureRequiredSetupForCluster(organizationId string, projectId string, stackId string) error { + pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + var alreadySetUp bool + for _, pn := range pns { + if pn.StackId == stackId { + alreadySetUp = true + break + } + } + + // if already set up, it means that required setup is already done + if alreadySetUp { + return nil + } + + if err := u.createK8SInitialResource(organizationId, projectId, stackId); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + if err := u.createKeycloakClientRoles(organizationId, projectId, stackId); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + projectMembers, err := u.GetProjectMembersByProjectId(projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + for _, pm := range projectMembers { + err = u.assignEachKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + } + + return nil +} +func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(organizationId string, projectId string, stackId string) error { + pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + var nsCount int + for _, pn := range pns { + if pn.StackId == stackId { + nsCount++ + } + } + + // if there are more than one namespace, it means that required setup is needed on the other namespace + if nsCount > 1 { + return nil + } + + if err := u.deleteK8SInitialResource(organizationId, projectId, stackId); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + projectMembers, err := u.GetProjectMembersByProjectId(projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + for _, pm := range projectMembers { + err = u.unassignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + } + + if err := u.deleteKeycloakClientRoles(organizationId, projectId, stackId); err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + return nil +} +func (u *ProjectUsecase) createK8SInitialResource(organizationId string, projectId string, stackId string) error { + kubeconfig, err := kubernetes.GetKubeConfig(stackId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + pr, err := u.GetProject(organizationId, projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + err = kubernetes.EnsureClusterRole(kubeconfig, pr.Name) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + err = kubernetes.EnsureCommonClusterRole(kubeconfig, pr.Name) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + err = kubernetes.EnsureCommonClusterRoleBinding(kubeconfig, pr.Name) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + return nil +} +func (u *ProjectUsecase) deleteK8SInitialResource(organizationId string, projectId string, stackId string) error { + kubeconfig, err := kubernetes.GetKubeConfig(stackId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + pr, err := u.GetProject(organizationId, projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + err = kubernetes.RemoveClusterRole(kubeconfig, pr.Name) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + err = kubernetes.RemoveCommonClusterRole(kubeconfig, pr.Name) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + err = kubernetes.RemoveCommonClusterRoleBinding(kubeconfig, pr.Name) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + return nil +} +func (u *ProjectUsecase) createKeycloakClientRoles(organizationId string, projectId string, stackId string) error { + // create Roles in keycloak + for _, role := range []string{string(ProjectLeader), string(ProjectMember), string(ProjectViewer)} { + err := u.kc.EnsureClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + } + return nil +} +func (u *ProjectUsecase) deleteKeycloakClientRoles(organizationId string, projectId string, stackId string) error { + // first check whether the stac + + // delete Roles in keycloak + for _, role := range []string{string(ProjectLeader), string(ProjectMember), string(ProjectViewer)} { + err := u.kc.DeleteClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + } + return nil +} +func (u *ProjectUsecase) CreateK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error { + kubeconfig, err := kubernetes.GetKubeConfig(stackId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + pr, err := u.GetProject(organizationId, projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + err = kubernetes.EnsureRoleBinding(kubeconfig, pr.Name, namespace) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + + return nil +} +func (u *ProjectUsecase) DeleteK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error { + //TODO implement me + panic("implement me") +} + +func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error { + pm, err := u.GetProjectMember(projectMemberId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + err = u.assignEachKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + return nil +} + +func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, userId string, roleName string) error { + err := u.kc.AssignClientRoleToUser(organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + return nil +} + +func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error { + pm, err := u.GetProjectMember(projectMemberId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + err = u.unassignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + return nil +} + +func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, userId string, roleName string) error { + err := u.kc.UnassignClientRoleToUser(organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) + if err != nil { + log.Error(err) + return errors.Wrap(err, "Failed to create project namespace.") + } + return nil +} + func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId string) (string, error) { projectNamespaces, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) if err != nil { From a40aff092eb91f81563880812bfc9bf8d3f425cf Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 21 Feb 2024 13:43:48 +0900 Subject: [PATCH 050/502] merge up-to-date commits --- internal/kubernetes/kubernetes.go | 1 + internal/kubernetes/kubernetes_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index 0fef1084..0c8fb3b0 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "gopkg.in/yaml.v3" "os" "strings" diff --git a/internal/kubernetes/kubernetes_test.go b/internal/kubernetes/kubernetes_test.go index 6e25b0bb..9505998b 100644 --- a/internal/kubernetes/kubernetes_test.go +++ b/internal/kubernetes/kubernetes_test.go @@ -2,6 +2,7 @@ package kubernetes_test import ( "github.com/openinfradev/tks-api/internal/kubernetes" + "gopkg.in/yaml.v3" "os" "reflect" "testing" From 89c05f14983acd5e831c0eca3a9a358ff087bf3e Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 21 Feb 2024 13:44:03 +0900 Subject: [PATCH 051/502] merge up-to-date commits --- internal/delivery/http/project.go | 10 +++++----- internal/usecase/project.go | 6 ++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index df18232c..55f3f5de 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -505,7 +505,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - var stackIds map[string]struct{} + stackIds := make(map[string]struct{}) for _, pn := range pns { stackIds[pn.StackId] = struct{}{} } @@ -798,7 +798,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - var stackIds map[string]struct{} + stackIds := make(map[string]struct{}) for _, pn := range pns { stackIds[pn.StackId] = struct{}{} } @@ -861,7 +861,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - var stackIds map[string]struct{} + stackIds := make(map[string]struct{}) for _, pn := range pns { stackIds[pn.StackId] = struct{}{} } @@ -948,7 +948,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - var stackIds map[string]struct{} + stackIds := make(map[string]struct{}) for _, pn := range pns { stackIds[pn.StackId] = struct{}{} } @@ -1025,7 +1025,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - var stackIds map[string]struct{} + stackIds := make(map[string]struct{}) for _, pn := range pns { stackIds[pn.StackId] = struct{}{} } diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 3da7f748..67f9f476 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -2,7 +2,6 @@ package usecase import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/repository" @@ -50,7 +49,6 @@ type IProjectUsecase interface { CreateK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error DeleteK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error GetProjectKubeconfig(organizationId string, projectId string) (string, error) -} AssignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error UnassignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error @@ -404,7 +402,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(organizationId string, pr return errors.Wrap(err, "Failed to create project namespace.") } - projectMembers, err := u.GetProjectMembersByProjectId(projectId) + projectMembers, err := u.GetProjectMembers(projectId, ProjectAll) if err != nil { log.Error(err) return errors.Wrap(err, "Failed to create project namespace.") @@ -442,7 +440,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(organizationId string, return errors.Wrap(err, "Failed to create project namespace.") } - projectMembers, err := u.GetProjectMembersByProjectId(projectId) + projectMembers, err := u.GetProjectMembers(projectId, ProjectAll) if err != nil { log.Error(err) return errors.Wrap(err, "Failed to create project namespace.") From 3c7c91c5157c5639ed802fb41ae3168576861b07 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 26 Feb 2024 14:25:39 +0900 Subject: [PATCH 052/502] remove unused function --- internal/kubernetes/kubernetes.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index 0c8fb3b0..2af15b06 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -191,21 +191,6 @@ func GetKubernetesVserion() (string, error) { return information.GitVersion, nil } -func GetKubeconfigById(clusterId string) ([]byte, error) { - clientset, err := GetClientAdminCluster() - if err != nil { - return nil, err - } - - secrets, err := clientset.CoreV1().Secrets(clusterId).Get(context.TODO(), clusterId+"-tks-kubeconfig", metav1.GetOptions{}) - if err != nil { - log.Error(err) - return nil, err - } - - return secrets.Data["value"], nil -} - func GetResourceApiVersion(kubeconfig []byte, kind string) (string, error) { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { From eedf6b37d186bf5ad26c06baabd8adb299a0d411 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 26 Feb 2024 14:29:27 +0900 Subject: [PATCH 053/502] solve confict --- internal/route/route.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/route/route.go b/internal/route/route.go index e97a514a..e3419bee 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -80,7 +80,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Dashboard: usecase.NewDashboardUsecase(repoFactory, cache), Alert: usecase.NewAlertUsecase(repoFactory), Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), - Project: usecase.NewProjectUsecase(repoFactory, argoClient), + Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), } customMiddleware := internalMiddleware.NewMiddleware( From 4c4f60318c862db5413c6a954430d82d0e8751f9 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 26 Feb 2024 15:46:22 +0900 Subject: [PATCH 054/502] feature. implementation k8s resources for project namespace --- api/swagger/docs.go | 5 +- api/swagger/swagger.json | 5 +- api/swagger/swagger.yaml | 4 +- internal/delivery/http/project.go | 2 +- internal/usecase/project.go | 85 ++++++++++++++++++++++++++----- pkg/domain/project.go | 19 +++---- 6 files changed, 94 insertions(+), 26 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index d071dd1e..9de777d0 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -7786,7 +7786,7 @@ const docTemplate = `{ "cronjobs": { "type": "integer" }, - "demonsets": { + "daemonsets": { "type": "integer" }, "deployments": { @@ -7809,6 +7809,9 @@ const docTemplate = `{ }, "statefulsets": { "type": "integer" + }, + "updatedAt": { + "type": "string" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 97c10867..d4e79637 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -7780,7 +7780,7 @@ "cronjobs": { "type": "integer" }, - "demonsets": { + "daemonsets": { "type": "integer" }, "deployments": { @@ -7803,6 +7803,9 @@ }, "statefulsets": { "type": "integer" + }, + "updatedAt": { + "type": "string" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index f9abcd33..8d7a2d8b 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1716,7 +1716,7 @@ definitions: properties: cronjobs: type: integer - demonsets: + daemonsets: type: integer deployments: type: integer @@ -1732,6 +1732,8 @@ definitions: type: integer statefulsets: type: integer + updatedAt: + type: string type: object domain.ProjectNamespaceResponse: properties: diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 8824422c..ffea742c 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1399,7 +1399,7 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r return } - k8sResources, err := p.usecase.GetK8sResources(r.Context(), organizationId, projectId, projectNamespace, stackId) + k8sResources, err := p.usecase.GetK8sResources(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) ErrorJSON(w, r, err) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 7afc25e1..c08b14dc 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -2,6 +2,8 @@ package usecase import ( "context" + "fmt" + "time" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/kubernetes" @@ -12,6 +14,7 @@ import ( "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gopkg.in/yaml.v3" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( @@ -44,7 +47,7 @@ type IProjectUsecase interface { UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error GetProjectKubeconfig(organizationId string, projectId string) (string, error) - GetK8sResources(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (out domain.ProjectNamespaceK8sResources, err error) + GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) } type ProjectUsecase struct { @@ -420,18 +423,74 @@ func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId s return kubernetes.MergeKubeconfigsWithSingleUser(kubeconfigs) } -func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (out domain.ProjectNamespaceK8sResources, err error) { - - // to be implemented - out.Pods = 1 - out.Deployments = 2 - out.Statefulsets = 3 - out.Demonsets = 4 - out.Jobs = 5 - out.Cronjobs = 6 - out.PVCs = 7 - out.Services = 8 - out.Ingresses = 9 +func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) { + _, err = u.clusterRepository.Get(domain.ClusterId(stackId)) + if err != nil { + return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) + } + + clientset_user, err := kubernetes.GetClientFromClusterId(stackId.String()) + if err != nil { + return out, errors.Wrap(err, fmt.Sprintf("Failed to get clientset : stackId %s", stackId)) + } + + out.UpdatedAt = time.Now() + + pods, err := clientset_user.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + out.Pods = len(pods.Items) + } else { + log.Error("Failed to get pods. err : ", err) + } + + pvcs, err := clientset_user.CoreV1().PersistentVolumeClaims(namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + out.PVCs = len(pvcs.Items) + } else { + log.Error("Failed to get pvcs. err : ", err) + } + + services, err := clientset_user.CoreV1().Services(namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + out.Services = len(services.Items) + } else { + log.Error("Failed to get services. err : ", err) + } + + ingresses, err := clientset_user.NetworkingV1().Ingresses(namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + out.Ingresses = len(ingresses.Items) + } else { + log.Error("Failed to get ingresses. err : ", err) + } + + deployments, err := clientset_user.AppsV1().Deployments(namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + out.Deployments = len(deployments.Items) + } else { + log.Error("Failed to get deployments. err : ", err) + } + + statefulsets, err := clientset_user.AppsV1().StatefulSets(namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + out.Statefulsets = len(statefulsets.Items) + } else { + log.Error("Failed to get statefulsets. err : ", err) + } + + daemonsets, err := clientset_user.AppsV1().DaemonSets(namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + out.Daemonsets = len(daemonsets.Items) + } else { + log.Error("Failed to get daemonsets. err : ", err) + } + + jobs, err := clientset_user.BatchV1().Jobs(namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + out.Jobs = len(jobs.Items) + } else { + log.Error("Failed to get jobs. err : ", err) + } return } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 3fc02157..c5f39620 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -256,15 +256,16 @@ type GetProjectKubeconfigResponse struct { } type ProjectNamespaceK8sResources struct { - Pods int `json:"pods"` - Deployments int `json:"deployments"` - Statefulsets int `json:"statefulsets"` - Demonsets int `json:"demonsets"` - Jobs int `json:"jobs"` - Cronjobs int `json:"cronjobs"` - PVCs int `json:"pvcs"` - Services int `json:"services"` - Ingresses int `json:"ingresses"` + Pods int `json:"pods"` + Deployments int `json:"deployments"` + Statefulsets int `json:"statefulsets"` + Daemonsets int `json:"daemonsets"` + Jobs int `json:"jobs"` + Cronjobs int `json:"cronjobs"` + PVCs int `json:"pvcs"` + Services int `json:"services"` + Ingresses int `json:"ingresses"` + UpdatedAt time.Time `json:"updatedAt"` } type GetProjectNamespaceK8sResourcesResponse struct { From b727f4c02c01d7b342dad365bae811675481ea6b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 26 Feb 2024 18:21:02 +0900 Subject: [PATCH 055/502] trivial. fix login error --- internal/route/route.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/route/route.go b/internal/route/route.go index cdb36272..02e7b2fe 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -67,6 +67,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Alert: usecase.NewAlertUsecase(repoFactory), Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), + Audit: usecase.NewAuditUsecase(repoFactory), } customMiddleware := internalMiddleware.NewMiddleware( From 987c59a334d5b69de830478e04c33c6043db6d69 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 27 Feb 2024 13:30:06 +0900 Subject: [PATCH 056/502] Change project lists to a single SQL statement --- api/swagger/docs.go | 11 ++- api/swagger/swagger.json | 11 ++- api/swagger/swagger.yaml | 8 +- internal/delivery/http/project.go | 82 ++++++++-------- internal/repository/project.go | 154 ++++++++++++++++++++++++++++-- internal/usecase/project.go | 38 +++++++- pkg/domain/project.go | 3 +- 7 files changed, 245 insertions(+), 62 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 5c604834..d81850a4 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -2414,6 +2414,12 @@ const docTemplate = `{ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "(all | only)", + "name": "query", + "in": "query" } ], "responses": { @@ -7935,7 +7941,7 @@ const docTemplate = `{ "type": "object", "properties": { "createdAt": { - "description": "NamespaceCount int ` + "`" + `json:\"namespaceCount\"` + "`" + `\nAppCount int ` + "`" + `json:\"appCount\"` + "`" + `\nMemberCount int ` + "`" + `json:\"memberCount\"` + "`" + `", + "description": "AppCount int ` + "`" + `json:\"appCount\"` + "`" + `\nNamespaceCount int ` + "`" + `json:\"namespaceCount\"` + "`" + `\nMemberCount int ` + "`" + `json:\"memberCount\"` + "`" + `", "type": "string" }, "description": { @@ -8105,6 +8111,9 @@ const docTemplate = `{ "id": { "type": "string" }, + "isMyProject": { + "type": "string" + }, "memberCount": { "type": "integer" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 6cd5537e..e512de5e 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -2408,6 +2408,12 @@ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "(all | only)", + "name": "query", + "in": "query" } ], "responses": { @@ -7929,7 +7935,7 @@ "type": "object", "properties": { "createdAt": { - "description": "NamespaceCount int `json:\"namespaceCount\"`\nAppCount int `json:\"appCount\"`\nMemberCount int `json:\"memberCount\"`", + "description": "AppCount int `json:\"appCount\"`\nNamespaceCount int `json:\"namespaceCount\"`\nMemberCount int `json:\"memberCount\"`", "type": "string" }, "description": { @@ -8099,6 +8105,9 @@ "id": { "type": "string" }, + "isMyProject": { + "type": "string" + }, "memberCount": { "type": "integer" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ed26d241..447ebfd8 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1693,8 +1693,8 @@ definitions: properties: createdAt: description: |- + AppCount int `json:"appCount"` NamespaceCount int `json:"namespaceCount"` - AppCount int `json:"appCount"` MemberCount int `json:"memberCount"` type: string description: @@ -1807,6 +1807,8 @@ definitions: type: string id: type: string + isMyProject: + type: string memberCount: type: integer name: @@ -4006,6 +4008,10 @@ paths: name: organizationId required: true type: string + - description: (all | only) + in: query + name: query + type: string produces: - application/json responses: diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 7e0cc416..a354cbb7 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -148,6 +148,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param query query string false "(all | only)" // @Success 200 {object} domain.GetProjectsResponse // @Router /organizations/{organizationId}/projects [get] // @Security JWT @@ -160,49 +161,27 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { return } - ps, err := p.usecase.GetProjects(organizationId) - if err != nil { - log.ErrorWithContext(r.Context(), "Failed to retrieve projects ", err) - ErrorJSON(w, r, err) - return + urlParams := r.URL.Query() + queryName := urlParams.Get("query") + onlyMyProject := false + if queryName == "only" { + onlyMyProject = true } // get myUserId from login component requestUserInfo, ok := request.UserFrom(r.Context()) myUserId := requestUserInfo.GetUserId().String() - prs := make([]domain.ProjectResponse, 0) - for _, project := range ps { - var projectRoleId, projectRoleName string - for _, pm := range project.ProjectMembers { - if myUserId == pm.ProjectUserId.String() { - projectRoleId = pm.ProjectRoleId - projectRoleName = pm.ProjectRole.Name - continue - } - } - // TODO: implement AppCount - pr := domain.ProjectResponse{ - ID: project.ID, - OrganizationId: project.OrganizationId, - Name: project.Name, - Description: project.Description, - ProjectRoleId: projectRoleId, - ProjectRoleName: projectRoleName, - NamespaceCount: len(project.ProjectNamespaces), - AppCount: 0, - MemberCount: len(project.ProjectMembers), - CreatedAt: project.CreatedAt, - } - prs = append(prs, pr) + pr, err := p.usecase.GetProjects(organizationId, myUserId, onlyMyProject) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to retrieve projects ", err) + ErrorJSON(w, r, err) + return } - var out domain.GetProjectsResponse - out.Projects = prs - - if ps == nil { - ResponseJSON(w, r, http.StatusNotFound, out) + if pr == nil { + ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectsResponse{}) } else { - ResponseJSON(w, r, http.StatusOK, out) + ResponseJSON(w, r, http.StatusOK, pr) } } @@ -239,6 +218,13 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { return } + //appCount, err := p.usecase.GetAppCount(organizationId, projectId) + //if err != nil { + // log.ErrorWithContext(r.Context(), "Failed to retrieve app count", err) + // ErrorJSON(w, r, err) + // return + //} + var out domain.GetProjectResponse if project == nil { ResponseJSON(w, r, http.StatusNotFound, out) @@ -268,10 +254,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { pdr.ProjectLeaderDepartment = projectLeaderDepartment pdr.ProjectRoleId = projectRoleId pdr.ProjectRoleName = projectRoleName - //pdr.NamespaceCount = len(project.ProjectNamespaces) - //pdr.MemberCount = len(project.ProjectMembers) - ////TODO implement AppCount - //pdr.AppCount = 0 + //pdr.AppCount = appCount out.Project = &pdr ResponseJSON(w, r, http.StatusOK, out) @@ -1234,10 +1217,15 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ ErrorJSON(w, r, err) return } - pnr.StackName = pn.Stack.Name - //TODO: implement AppCount - pnr.AppCount = 0 + appCount, err := p.usecase.GetAppCount(organizationId, projectId, pn.Namespace) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to retrieve app count", err) + ErrorJSON(w, r, err) + return + } + pnr.StackName = pn.Stack.Name + pnr.AppCount = appCount pnrs = append(pnrs, pnr) } @@ -1293,6 +1281,13 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque return } + appCount, err := p.usecase.GetAppCount(organizationId, projectId, projectNamespace) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to retrieve app count", err) + ErrorJSON(w, r, err) + return + } + var out domain.GetProjectNamespaceResponse if pn == nil { ResponseJSON(w, r, http.StatusNotFound, out) @@ -1306,8 +1301,7 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque return } pnr.StackName = pn.Stack.Name - //TODO: implement AppCount - pnr.AppCount = 0 + pnr.AppCount = appCount out.ProjectNamespace = &pnr ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/repository/project.go b/internal/repository/project.go index d28d5310..6802f0dd 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -2,6 +2,7 @@ package repository import ( "database/sql" + "github.com/google/uuid" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" @@ -10,7 +11,8 @@ import ( type IProjectRepository interface { CreateProject(p *domain.Project) (string, error) - GetProjects(organizationId string) ([]domain.Project, error) + GetProjects(organizationId string, userId uuid.UUID) ([]domain.ProjectResponse, error) + GetProjectsByUserId(organizationId string, userId uuid.UUID) ([]domain.ProjectResponse, error) GetProjectById(organizationId string, projectId string) (*domain.Project, error) GetProjectByIdAndLeader(organizationId string, projectId string) (*domain.Project, error) GetProjectByName(organizationId string, projectName string) (*domain.Project, error) @@ -32,6 +34,8 @@ type IProjectRepository interface { GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error + GetAppCountByProjectId(organizationId string, projectId string) (int, error) + GetAppCountByNamespace(organizationId string, projectId string, namespace string) (int, error) } type ProjectRepository struct { @@ -53,13 +57,73 @@ func (r *ProjectRepository) CreateProject(p *domain.Project) (string, error) { return p.ID, nil } -func (r *ProjectRepository) GetProjects(organizationId string) (ps []domain.Project, err error) { - res := r.db.Where("organization_id = ?", organizationId). - Preload("ProjectMembers"). - Preload("ProjectMembers.ProjectRole"). - Preload("ProjectMembers.ProjectUser"). - Preload("ProjectNamespaces"). - Find(&ps) +func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID) (pr []domain.ProjectResponse, err error) { + res := r.db.Raw(""+ + "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ + " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ + " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ + " from projects as p, "+ + " (select pm.project_id, pm.project_user_id, pm.project_role_id, pm.created_at, pm.is_project_leader, "+ + " pr.name as pr_name "+ + " from project_members as pm "+ + " left join project_roles as pr on pr.id = pm.project_role_id "+ + " left join users on users.id = pm.project_user_id "+ + " where pm.project_user_id = @userId) as pm, "+ + " (select count(pn.stack_id || pn.project_id) as count "+ + " from project_namespaces as pn "+ + " left join projects as p on pn.project_id = p.id "+ + " left join project_members as pm on pn.project_id = pm.project_id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id = @userId) as pn, "+ + " (select count(asa.id) as count "+ + " from app_serve_apps as asa "+ + " left join projects as p on asa.project_id = p.id "+ + " left join project_members as pm on asa.project_id = pm.project_id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id = @userId) as asa, "+ + " (select count(pm.id) as count "+ + " from project_members as pm "+ + " left join projects as p on pm.project_id = p.id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id = @userId) as pm_count "+ + " where p.id = pm.project_id "+ + " and p.organization_id = @organizationId "+ + "union "+ + "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ + " false as is_my_project, '' as project_role_id, '' as project_role_name, "+ + " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ + " from projects as p, "+ + " (select pm.project_id, pm.project_user_id, pm.project_role_id, pm.created_at, pm.is_project_leader, "+ + " pr.name as pr_name "+ + " from project_members as pm "+ + " left join project_roles as pr on pr.id = pm.project_role_id "+ + " left join users on users.id = pm.project_user_id "+ + " where pm.project_user_id <> @userId) as pm, "+ + " (select count(pn.stack_id || pn.project_id) as count "+ + " from project_namespaces as pn "+ + " left join projects as p on pn.project_id = p.id "+ + " left join project_members as pm on pn.project_id = pm.project_id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id <> @userId) as pn, "+ + " (select count(asa.id) as count "+ + " from app_serve_apps as asa "+ + " left join projects as p on asa.project_id = p.id "+ + " left join project_members as pm on asa.project_id = pm.project_id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id <> @userId) as asa, "+ + " (select count(pm.id) as count "+ + " from project_members as pm "+ + " left join projects as p on pm.project_id = p.id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id <> @userId) as pm_count "+ + " where p.id = pm.project_id "+ + " and p.organization_id = @organizationId "+ + " and p.id not in (select projects.id "+ + " from projects "+ + " left join project_members on project_members.project_id = projects.id "+ + " where project_members.project_user_id = @userId) ", + sql.Named("organizationId", organizationId), sql.Named("userId", userId)). + Scan(&pr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project") @@ -70,7 +134,53 @@ func (r *ProjectRepository) GetProjects(organizationId string) (ps []domain.Proj } } - return ps, nil + return pr, nil +} + +func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uuid.UUID) (pr []domain.ProjectResponse, err error) { + res := r.db.Raw(""+ + "select p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ + " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ + " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ + " from projects as p, "+ + " (select pm.project_id, pm.project_user_id, pm.project_role_id, pm.created_at, pm.is_project_leader, "+ + " pr.name as pr_name "+ + " from project_members as pm "+ + " left join project_roles as pr on pr.id = pm.project_role_id "+ + " left join users on users.id = pm.project_user_id "+ + " where pm.project_user_id = @userId) as pm, "+ + " (select count(pn.stack_id || pn.project_id) as count "+ + " from project_namespaces as pn "+ + " left join projects as p on pn.project_id = p.id "+ + " left join project_members as pm on pn.project_id = pm.project_id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id = @userId) as pn, "+ + " (select count(asa.id) as count "+ + " from app_serve_apps as asa "+ + " left join projects as p on asa.project_id = p.id "+ + " left join project_members as pm on asa.project_id = pm.project_id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id = @userId) as asa, "+ + " (select count(pm.id) as count "+ + " from project_members as pm "+ + " left join projects as p on pm.project_id = p.id "+ + " where p.organization_id = @organizationId "+ + " and pm.project_user_id = @userId) as pm_count "+ + " where p.id = pm.project_id "+ + " and p.organization_id = @organizationId", sql.Named("organizationId", organizationId), sql.Named("userId", userId)). + Scan(&pr) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pr, nil } func (r *ProjectRepository) GetProjectById(organizationId string, projectId string) (p *domain.Project, err error) { @@ -412,3 +522,29 @@ func (r *ProjectRepository) DeleteProjectNamespace(organizationId string, projec return nil } + +func (r *ProjectRepository) GetAppCountByProjectId(organizationId string, projectId string) (appCount int, err error) { + res := r.db.Select("count(*) as app_count"). + Table("app_serve_apps"). + Where("organization_id = ? and project_Id = ?", organizationId, projectId). + Find(&appCount) + if res.Error != nil { + log.Error(res.Error) + return 0, res.Error + } + + return appCount, nil +} + +func (r *ProjectRepository) GetAppCountByNamespace(organizationId string, projectId string, namespace string) (appCount int, err error) { + res := r.db.Select("count(*) as app_count"). + Table("app_serve_apps"). + Where("organization_id = ? and project_Id = ? and namespace = ?", organizationId, projectId, namespace). + Find(&appCount) + if res.Error != nil { + log.Error(res.Error) + return 0, res.Error + } + + return appCount, nil +} diff --git a/internal/usecase/project.go b/internal/usecase/project.go index bc85e1bd..0ad49670 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -24,7 +24,7 @@ const ( type IProjectUsecase interface { CreateProject(*domain.Project) (string, error) - GetProjects(organizationId string) ([]domain.Project, error) + GetProjects(organizationId string, userId string, onlyMyProject bool) ([]domain.ProjectResponse, error) GetProject(organizationId string, projectId string) (*domain.Project, error) GetProjectWithLeader(organizationId string, projectId string) (*domain.Project, error) IsProjectNameExist(organizationId string, projectName string) (bool, error) @@ -44,6 +44,7 @@ type IProjectUsecase interface { GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error + GetAppCount(organizationId string, projectId string, namespace string) (appCount int, err error) EnsureRequiredSetupForCluster(organizationId string, projectId string, stackId string) error MayRemoveRequiredSetupForCluster(organizationId string, projectId string, stackId string) error @@ -90,13 +91,26 @@ func (u *ProjectUsecase) CreateProject(p *domain.Project) (string, error) { return projectId, nil } -func (u *ProjectUsecase) GetProjects(organizationId string) (ps []domain.Project, err error) { - ps, err = u.projectRepo.GetProjects(organizationId) +func (u *ProjectUsecase) GetProjects(organizationId string, userId string, onlyMyProject bool) (pr []domain.ProjectResponse, err error) { + userUuid, err := uuid.Parse(userId) if err != nil { log.Error(err) - return nil, errors.Wrap(err, "Failed to get projects.") + return nil, errors.Wrap(err, "Failed to parse uuid to string") + } + if onlyMyProject == false { + pr, err = u.projectRepo.GetProjects(organizationId, userUuid) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to get projects.") + } + } else { + pr, err = u.projectRepo.GetProjectsByUserId(organizationId, userUuid) + if err != nil { + log.Error(err) + return nil, errors.Wrap(err, "Failed to get projects.") + } } - return ps, err + return pr, err } func (u *ProjectUsecase) GetProject(organizationId string, projectId string) (*domain.Project, error) { @@ -375,6 +389,20 @@ func (u *ProjectUsecase) DeleteProjectNamespace(organizationId string, projectId return nil } +func (u *ProjectUsecase) GetAppCount(organizationId string, projectId string, namespace string) (appCount int, err error) { + if namespace == "" { + appCount, err = u.projectRepo.GetAppCountByProjectId(organizationId, projectId) + } else { + appCount, err = u.projectRepo.GetAppCountByNamespace(organizationId, projectId, namespace) + } + if err != nil { + log.Error(err) + return 0, errors.Wrap(err, "Failed to retrieve app count.") + } + + return appCount, nil +} + func (u *ProjectUsecase) EnsureRequiredSetupForCluster(organizationId string, projectId string, stackId string) error { pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) if err != nil { diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 3fc02157..9660622e 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -48,6 +48,7 @@ type ProjectResponse struct { OrganizationId string `json:"organizationId"` Name string `json:"name"` Description string `json:"description"` + IsMyProject string `json:"isMyProject"` ProjectRoleId string `json:"projectRoleId"` ProjectRoleName string `json:"projectRoleName"` NamespaceCount int `json:"namespaceCount"` @@ -71,8 +72,8 @@ type ProjectDetailResponse struct { ProjectLeaderDepartment string `json:"projectLeaderDepartment"` ProjectRoleId string `json:"projectRoleId"` ProjectRoleName string `json:"projectRoleName"` + //AppCount int `json:"appCount"` //NamespaceCount int `json:"namespaceCount"` - //AppCount int `json:"appCount"` //MemberCount int `json:"memberCount"` CreatedAt time.Time `json:"createdAt"` UpdatedAt *time.Time `json:"updatedAt"` From 464b6e62e348ec8ef0bc4e177fc0556b9da6eaab Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 27 Feb 2024 13:24:41 +0900 Subject: [PATCH 057/502] feature. apply filter to list api. --- api/swagger/docs.go | 6 ++ api/swagger/swagger.json | 6 ++ api/swagger/swagger.yaml | 4 + internal/delivery/http/alert.go | 17 +-- internal/delivery/http/app-group.go | 8 +- internal/delivery/http/app-serve-app.go | 17 +-- internal/delivery/http/audit.go | 7 +- internal/delivery/http/cloud-account.go | 8 +- internal/delivery/http/cluster.go | 8 +- internal/delivery/http/organization.go | 9 +- internal/delivery/http/project.go | 36 +++++-- internal/delivery/http/stack-template.go | 7 +- internal/delivery/http/stack.go | 8 +- internal/delivery/http/user.go | 8 +- internal/pagination/pagination.go | 132 +++++++++++------------ internal/repository/alert.go | 14 +-- internal/repository/app-group.go | 16 +-- internal/repository/app-serve-app.go | 27 ++--- internal/repository/audit.go | 2 +- internal/repository/cloud-account.go | 13 +-- internal/repository/cluster.go | 44 ++------ internal/repository/organization.go | 14 +-- internal/repository/project.go | 62 ++++++----- internal/repository/stack-template.go | 20 +--- internal/repository/user.go | 14 +-- internal/usecase/project.go | 37 +++---- pkg/domain/project.go | 4 +- 27 files changed, 222 insertions(+), 326 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index d81850a4..a03dcc39 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -7469,6 +7469,9 @@ const docTemplate = `{ "domain.GetProjectMembersResponse": { "type": "object", "properties": { + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + }, "projectMembers": { "type": "array", "items": { @@ -7534,6 +7537,9 @@ const docTemplate = `{ "domain.GetProjectsResponse": { "type": "object", "properties": { + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + }, "projects": { "type": "array", "items": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index e512de5e..23c41d4f 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -7463,6 +7463,9 @@ "domain.GetProjectMembersResponse": { "type": "object", "properties": { + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + }, "projectMembers": { "type": "array", "items": { @@ -7528,6 +7531,9 @@ "domain.GetProjectsResponse": { "type": "object", "properties": { + "pagination": { + "$ref": "#/definitions/domain.PaginationResponse" + }, "projects": { "type": "array", "items": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 447ebfd8..91ba3f8e 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1380,6 +1380,8 @@ definitions: type: object domain.GetProjectMembersResponse: properties: + pagination: + $ref: '#/definitions/domain.PaginationResponse' projectMembers: items: $ref: '#/definitions/domain.ProjectMemberResponse' @@ -1421,6 +1423,8 @@ definitions: type: object domain.GetProjectsResponse: properties: + pagination: + $ref: '#/definitions/domain.PaginationResponse' projects: items: $ref: '#/definitions/domain.ProjectResponse' diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index 3591c4dd..4e0c78e4 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -95,11 +95,7 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { } urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } + pg := pagination.NewPagination(&urlParams) // convert status for i, filter := range pg.GetFilters() { if filter.Column == "status" { @@ -143,18 +139,9 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } - /* - outFilters := make([]domain.FilterResponse, len(pg.Filters)) - for j, filter := range pg.Filters { - if err := serializer.Map(filter, &outFilters[j]); err != nil { - log.InfoWithContext(r.Context(), err) - } - } - out.Pagination.Filters = outFilters - */ ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 1efd767a..84a22bee 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -82,11 +82,7 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid clusterId"), "C_INVALID_CLUSTER_ID", "")) return } - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } + pg := pagination.NewPagination(&urlParams) appGroups, err := h.usecase.Fetch(r.Context(), domain.ClusterId(clusterId), pg) if err != nil { @@ -103,7 +99,7 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index b2bd74d0..75b20722 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -253,12 +253,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ ErrorJSON(w, r, err) return } - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - + pg := pagination.NewPagination(&urlParams) apps, err := h.usecase.GetAppServeApps(organizationId, showAll, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get Failed to get app-serve-apps ", err) @@ -269,7 +264,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ var out domain.GetAppServeAppsResponse out.AppServeApps = apps - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } @@ -452,11 +447,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r } urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } + pg := pagination.NewPagination(&urlParams) tasks, err := h.usecase.GetAppServeAppTasks(appId, pg) if err != nil { @@ -468,7 +459,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r var out domain.GetAppServeAppTasksResponse out.AppServeAppTasks = tasks - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 8cdb6924..a262445e 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -63,12 +63,7 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { } urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - + pg := pagination.NewPagination(&urlParams) audits, err := h.usecase.Fetch(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index dfce7a78..0548625e 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -94,11 +94,7 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re } urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } + pg := pagination.NewPagination(&urlParams) cloudAccounts, err := h.usecase.Fetch(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) @@ -114,7 +110,7 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 5cd1848a..e953cf84 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -43,11 +43,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() organizationId := urlParams.Get("organizationId") - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } + pg := pagination.NewPagination(&urlParams) clusters, err := h.usecase.Fetch(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) @@ -63,7 +59,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 1d90f6a0..038a1a1e 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -91,12 +91,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. // @Security JWT func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - + pg := pagination.NewPagination(&urlParams) organizations, err := h.usecase.Fetch(pg) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -116,7 +111,7 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re log.InfoWithContext(r.Context(), organization) } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index a354cbb7..eb51a81d 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/gorilla/mux" @@ -168,20 +169,28 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { onlyMyProject = true } + pg := pagination.NewPagination(&urlParams) + // get myUserId from login component requestUserInfo, ok := request.UserFrom(r.Context()) myUserId := requestUserInfo.GetUserId().String() - pr, err := p.usecase.GetProjects(organizationId, myUserId, onlyMyProject) + pr, err := p.usecase.GetProjects(organizationId, myUserId, onlyMyProject, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to retrieve projects ", err) ErrorJSON(w, r, err) return } + var out domain.GetProjectsResponse + out.Projects = pr + if out.Pagination, err = pg.Response(); err != nil { + log.InfoWithContext(r.Context(), err) + } + if pr == nil { ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectsResponse{}) } else { - ResponseJSON(w, r, http.StatusOK, pr) + ResponseJSON(w, r, http.StatusOK, out) } } @@ -483,7 +492,9 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, pg) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -660,7 +671,8 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request return } - pms, err := p.usecase.GetProjectMembers(projectId, query) + pg := pagination.NewPagination(&urlParams) + pms, err := p.usecase.GetProjectMembers(projectId, query, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project members ", err) ErrorJSON(w, r, err) @@ -692,6 +704,10 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request } out = domain.GetProjectMembersResponse{ProjectMembers: pmrs} + if out.Pagination, err = pg.Response(); err != nil { + log.InfoWithContext(r.Context(), err) + } + ResponseJSON(w, r, http.StatusOK, out) } @@ -776,7 +792,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } // tasks for keycloak & k8s - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -839,7 +855,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ } // tasks for keycloak & k8s - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -926,7 +942,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R return } - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -1003,7 +1019,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -1197,7 +1213,9 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ return } - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId) + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project namespaces.", err) ErrorJSON(w, r, err) diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 4e699d35..419a48e6 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -56,12 +56,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt // @Security JWT func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - + pg := pagination.NewPagination(&urlParams) stackTemplates, err := h.usecase.Fetch(r.Context(), pg) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 1ec8987d..225a678d 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -112,11 +112,7 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } + pg := pagination.NewPagination(&urlParams) stacks, err := h.usecase.Fetch(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) @@ -137,7 +133,7 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 85ad3ce4..1d21bdab 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -176,11 +176,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { } urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } + pg := pagination.NewPagination(&urlParams) users, err := u.usecase.ListWithPagination(r.Context(), organizationId, pg) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -196,7 +192,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 69975e9c..956257e5 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -1,7 +1,6 @@ package pagination import ( - "fmt" "net/url" "strconv" "strings" @@ -151,87 +150,88 @@ func (p *Pagination) Response() (out domain.PaginationResponse, err error) { return out, err } -func NewPagination(urlParams *url.Values) (*Pagination, error) { - pg := NewDefaultPagination() +func NewPagination(urlParams *url.Values) *Pagination { + pg := newDefaultPagination() - for key, value := range *urlParams { - switch key { - case SORT_COLUMN: - if value[0] != "" { - pg.SortColumn = value[0] - } - case SORT_ORDER: - if value[0] != "" { - pg.SortOrder = value[0] - } - case PAGE_NUMBER: - if value[0] != "" { - pg.Page, _ = strconv.Atoi(value[0]) - } - case PAGE_SIZE: - if value[0] == "" { - if limitNum, err := strconv.Atoi(value[0]); err == nil { - pg.Limit = limitNum + if urlParams != nil { + for key, value := range *urlParams { + switch key { + case SORT_COLUMN: + if value[0] != "" { + pg.SortColumn = value[0] } - } - case COMBINED_FILTER: - if len(value[0]) > 0 { - //"combinedFilter=key1,key2:value" - filterArray := strings.Split(value[0], ":") - if len(filterArray) == 2 { - keys := strings.Split(helper.ToSnakeCase(strings.Replace(filterArray[0], "[]", "", -1)), ",") - value := filterArray[1] - - pg.CombinedFilter = CombinedFilter{ - Columns: keys, - Value: value, + case SORT_ORDER: + if value[0] != "" { + pg.SortOrder = value[0] + } + case PAGE_NUMBER: + if value[0] != "" { + pg.Page, _ = strconv.Atoi(value[0]) + } + case PAGE_SIZE: + if value[0] == "" { + if limitNum, err := strconv.Atoi(value[0]); err == nil { + pg.Limit = limitNum } - } else { - return nil, fmt.Errorf("Invalid query string : combinedFilter ") } - } - case FILTER, FILTER_ARRAY, OR, OR_ARRAY: - for _, filterValue := range value { - arr := strings.Split(filterValue, "|") - - column := arr[0] - releation := "" - arrColumns := strings.Split(column, ".") - if len(arrColumns) > 1 { - releation = arrColumns[0] - column = arrColumns[1] + case COMBINED_FILTER: + if len(value[0]) > 0 { + //"combinedFilter=key1,key2:value" + filterArray := strings.Split(value[0], ":") + if len(filterArray) == 2 { + keys := strings.Split(helper.ToSnakeCase(strings.Replace(filterArray[0], "[]", "", -1)), ",") + value := filterArray[1] + + pg.CombinedFilter = CombinedFilter{ + Columns: keys, + Value: value, + } + } else { + return nil + } } + case FILTER, FILTER_ARRAY, OR, OR_ARRAY: + for _, filterValue := range value { + arr := strings.Split(filterValue, "|") + + column := arr[0] + releation := "" + arrColumns := strings.Split(column, ".") + if len(arrColumns) > 1 { + releation = arrColumns[0] + column = arrColumns[1] + } - trimmedStr := strings.Trim(arr[1], "[]") - values := strings.Split(trimmedStr, ",") + trimmedStr := strings.Trim(arr[1], "[]") + values := strings.Split(trimmedStr, ",") - op := "$cont" - if len(arr) == 3 { - op = arr[2] - } + op := "$cont" + if len(arr) == 3 { + op = arr[2] + } - or := false - if key == OR || key == OR_ARRAY { - or = true - } + or := false + if key == OR || key == OR_ARRAY { + or = true + } - pg.Filters = append(pg.Filters, Filter{ - Column: helper.ToSnakeCase(strings.Replace(column, "[]", "", -1)), - Relation: releation, - Operator: op, - Values: values, - Or: or, - }) + pg.Filters = append(pg.Filters, Filter{ + Column: helper.ToSnakeCase(strings.Replace(column, "[]", "", -1)), + Relation: releation, + Operator: op, + Values: values, + Or: or, + }) + } } } } - pg.MakePaginationRequest() - return pg, nil + return pg } -func NewDefaultPagination() *Pagination { +func newDefaultPagination() *Pagination { return &Pagination{ SortColumn: "created_at", SortOrder: "DESC", diff --git a/internal/repository/alert.go b/internal/repository/alert.go index f1ffd971..0db9a350 100644 --- a/internal/repository/alert.go +++ b/internal/repository/alert.go @@ -1,8 +1,6 @@ package repository import ( - "fmt" - "math" "time" "github.com/google/uuid" @@ -108,24 +106,18 @@ func (r *AlertRepository) GetByName(organizationId string, name string) (out dom func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.Alert, err error) { var alerts []Alert if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("alerts", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&Alert{}). + _, res := pg.Fetch(r.db.Model(&Alert{}). Preload("AlertActions", func(db *gorm.DB) *gorm.DB { return db.Order("created_at ASC") }).Preload("AlertActions.Taker"). Preload("Cluster", "status = 2"). Preload("Organization"). Joins("join clusters on clusters.id = alerts.cluster_id AND clusters.status = 2"). - Where("alerts.organization_id = ?", organizationId)) + Where("alerts.organization_id = ?", organizationId), &alerts) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&alerts) if res.Error != nil { return nil, res.Error } diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index e999ae99..be160e53 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -2,7 +2,6 @@ package repository import ( "fmt" - "math" "github.com/google/uuid" "gorm.io/datatypes" @@ -80,20 +79,11 @@ func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (out []domain.AppGroup, err error) { var appGroups []AppGroup if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("app_groups", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&AppGroup{}). - Where("cluster_id = ?", clusterId)) - db.Count(&pg.TotalRows) - - r.db.Model(&AppGroup{}). - Where("cluster_id = ?", clusterId).Where("id").Where("app_groups.status").Where("app_groups.deleted") - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&appGroups) + _, res := pg.Fetch(r.db.Model(&AppGroup{}). + Where("cluster_id = ?", clusterId), &appGroups) if res.Error != nil { return nil, res.Error } diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index f761b6a7..50c97b45 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -2,7 +2,6 @@ package repository import ( "fmt" - "math" "time" "github.com/openinfradev/tks-api/internal/pagination" @@ -64,18 +63,12 @@ func (r *AppServeAppRepository) CreateTask( func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) (apps []domain.AppServeApp, err error) { var clusters []Cluster if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - // TODO: should return different records based on showAll param - filterFunc := CombinedGormFilter("app_serve_apps", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.AppServeApp{}). - Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId)) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&apps) + // TODO: should return different records based on showAll param + _, res := pg.Fetch(r.db.Model(&domain.AppServeApp{}). + Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId), &clusters) if res.Error != nil { return nil, fmt.Errorf("error while finding appServeApps with organizationId: %s", organizationId) } @@ -132,17 +125,11 @@ func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppSer func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []domain.AppServeAppTask, err error) { if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("app_serve_app_tasks", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.AppServeAppTask{}). - Where("app_serve_app_tasks.app_serve_app_id = ?", appId)) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&tasks) + _, res := pg.Fetch(r.db.Model(&domain.AppServeAppTask{}). + Where("app_serve_app_tasks.app_serve_app_id = ?", appId), &tasks) if res.Error != nil { return nil, fmt.Errorf("Error while finding tasks with appId: %s", appId) } diff --git a/internal/repository/audit.go b/internal/repository/audit.go index bb0f97a2..5e2d684c 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -66,7 +66,7 @@ func (r *AuditRepository) Fetch(organizationId string, pg *pagination.Pagination var audits []Audit if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } db := r.db.Model(&Audit{}).Preload(clause.Associations).Where("organization_id = ?", organizationId) diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index 786e9f53..a6dd6102 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -2,7 +2,6 @@ package repository import ( "fmt" - "math" "github.com/google/uuid" "gorm.io/gorm" @@ -99,17 +98,11 @@ func (r *CloudAccountRepository) GetByAwsAccountId(awsAccountId string) (out dom func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.CloudAccount, err error) { var cloudAccounts []CloudAccount if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("cloud_accounts", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&CloudAccount{}). + _, res := pg.Fetch(r.db.Model(&CloudAccount{}). Preload(clause.Associations). - Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED)) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&cloudAccounts) + Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED), &cloudAccounts) if res.Error != nil { return nil, res.Error } diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index df6a7213..66de2205 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -2,7 +2,6 @@ package repository import ( "fmt" - "math" "github.com/google/uuid" "gorm.io/gorm" @@ -111,19 +110,14 @@ func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []domain.Cluster, err error) { var clusters []Cluster if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("clusters", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&Cluster{})) - db.Count(&pg.TotalRows) - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&clusters) + _, res := pg.Fetch(r.db, &clusters) if res.Error != nil { return nil, res.Error } + for _, cluster := range clusters { outCluster := reflectCluster(cluster) out = append(out, outCluster) @@ -134,21 +128,15 @@ func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []domain.Clust func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { var clusters []Cluster if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - pg.SortColumn = "created_at" - pg.SortOrder = "DESC" - filterFunc := CombinedGormFilter("clusters", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&Cluster{}). + + _, res := pg.Fetch(r.db.Model(&Cluster{}). Preload(clause.Associations). Joins("left outer join cluster_favorites on clusters.id = cluster_favorites.cluster_id AND cluster_favorites.user_id = ?", userId). - Where("organization_id = ? AND status != ?", organizationId, domain.ClusterStatus_DELETED)) + Where("organization_id = ? AND status != ?", organizationId, domain.ClusterStatus_DELETED). + Order("cluster_favorites.cluster_id"), &clusters) - db.Count(&pg.TotalRows) - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order("cluster_favorites.cluster_id").Order(orderQuery).Find(&clusters) if res.Error != nil { return nil, res.Error } @@ -157,26 +145,16 @@ func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId out = append(out, outCluster) } - //log.Info(helper.ModelToJson(clusters)) return } func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { var clusters []Cluster if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - pg.SortColumn = "created_at" - pg.SortOrder = "DESC" - filterFunc := CombinedGormFilter("clusters", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&Cluster{}).Preload("CloudAccount"). - Where("cloud_account_id = ?", cloudAccountId)) - - db.Count(&pg.TotalRows) - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&clusters) + _, res := pg.Fetch(r.db.Model(&Cluster{}).Preload("CloudAccount"). + Where("cloud_account_id = ?", cloudAccountId), &clusters) if res.Error != nil { return nil, res.Error } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 75cc2e7a..e37fc7e4 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -1,9 +1,6 @@ package repository import ( - "fmt" - "math" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" @@ -76,19 +73,14 @@ func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (*[]domain.Org var organizations []Organization var out []domain.Organization if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("organizations", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&Organization{})) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&organizations) + _, res := pg.Fetch(r.db, &organizations) if res.Error != nil { return nil, res.Error } + for _, organization := range organizations { outOrganization := r.reflect(organization) out = append(out, outOrganization) diff --git a/internal/repository/project.go b/internal/repository/project.go index 6802f0dd..c042cdc2 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -2,7 +2,10 @@ package repository import ( "database/sql" + "github.com/google/uuid" + + "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" @@ -11,8 +14,8 @@ import ( type IProjectRepository interface { CreateProject(p *domain.Project) (string, error) - GetProjects(organizationId string, userId uuid.UUID) ([]domain.ProjectResponse, error) - GetProjectsByUserId(organizationId string, userId uuid.UUID) ([]domain.ProjectResponse, error) + GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) GetProjectById(organizationId string, projectId string) (*domain.Project, error) GetProjectByIdAndLeader(organizationId string, projectId string) (*domain.Project, error) GetProjectByName(organizationId string, projectName string) (*domain.Project, error) @@ -21,8 +24,8 @@ type IProjectRepository interface { GetProjectRoleByName(name string) (*domain.ProjectRole, error) GetProjectRoleById(id string) (*domain.ProjectRole, error) AddProjectMember(*domain.ProjectMember) (string, error) - GetProjectMembersByProjectId(projectId string) ([]domain.ProjectMember, error) - GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string) ([]domain.ProjectMember, error) + GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) ([]domain.ProjectMember, error) + GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) ([]domain.ProjectMember, error) GetProjectMemberCountByProjectId(projectId string) (*domain.GetProjectMemberCountResponse, error) GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) GetProjectMemberByUserId(projectId string, projectUserId string) (pm *domain.ProjectMember, err error) @@ -30,7 +33,7 @@ type IProjectRepository interface { UpdateProjectMemberRole(pm *domain.ProjectMember) error CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error GetProjectNamespaceByName(organizationId string, projectId string, stackId string, projectNamespace string) (*domain.ProjectNamespace, error) - GetProjectNamespaces(organizationId string, projectId string) ([]domain.ProjectNamespace, error) + GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error @@ -57,7 +60,10 @@ func (r *ProjectRepository) CreateProject(p *domain.Project) (string, error) { return p.ID, nil } -func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } res := r.db.Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ @@ -127,17 +133,15 @@ func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project") - return nil, nil - } else { - log.Error(res.Error) - return nil, res.Error } } - return pr, nil } -func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uuid.UUID) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } res := r.db.Raw(""+ "select p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ @@ -299,14 +303,14 @@ func (r *ProjectRepository) AddProjectMember(pm *domain.ProjectMember) (string, return pm.ID, nil } -func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string) (pms []domain.ProjectMember, err error) { - //res := r.db.Preload("ProjectUser"). - // Joins("ProjectRole").Where("project_id = ?", projectId).Find(&pms) - res := r.db.Joins("ProjectUser"). +func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) (pms []domain.ProjectMember, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + _, res := pg.Fetch(r.db.Joins("ProjectUser"). Joins("ProjectRole"). Where("project_members.project_id = ?", projectId). - Order("project_members.created_at ASC"). - Find(&pms) + Order("project_members.created_at ASC"), &pms) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project member") @@ -320,13 +324,15 @@ func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string) (pms return pms, nil } -func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string) (pms []domain.ProjectMember, err error) { - res := r.db.Joins("ProjectUser"). - //Joins("ProjectRole"). - //Find(&pms, "project_members.project_id = ? and \"ProjectRole\".name = ?", projectId, memberRole) +func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) (pms []domain.ProjectMember, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + _, res := pg.Fetch(r.db.Joins("ProjectUser"). InnerJoins("ProjectRole", r.db.Where(&domain.ProjectRole{Name: memberRole})). Order("project_members.created_at ASC"). - Find(&pms, "project_members.project_id = ?", projectId) + Where("project_members.project_id = ?", projectId), &pms) + if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project member") @@ -467,10 +473,12 @@ func (r *ProjectRepository) GetProjectNamespaceByName(organizationId string, pro return pn, nil } -func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectId string) (pns []domain.ProjectNamespace, err error) { - res := r.db.Where("project_id = ?", projectId). - Preload("Stack"). - Find(&pns) +func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) (pns []domain.ProjectNamespace, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + _, res := pg.Fetch(r.db.Where("project_id = ?", projectId). + Preload("Stack"), &pns) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Not found project namespaces") diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 54f52b79..4d3004c8 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -75,27 +75,9 @@ func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain var stackTemplates []StackTemplate if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - /* - filterFunc := CombinedGormFilter("stack_templates", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&StackTemplate{})) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order("kube_type DESC,template_type ASC").Order(orderQuery).Find(&stackTemplates) - if res.Error != nil { - return nil, res.Error - } - - for _, stackTemplate := range stackTemplates { - out = append(out, reflectStackTemplate(stackTemplate)) - } - */ - - // paginator, res := filter.Scope(r.db.Order("kube_type DESC,template_type ASC"), pg.GetPaginationRequest(), &stackTemplates) _, res := pg.Fetch(r.db, &stackTemplates) if res.Error != nil { return nil, res.Error diff --git a/internal/repository/user.go b/internal/repository/user.go index c4c254c3..84120da9 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -1,8 +1,6 @@ package repository import ( - "fmt" - "math" "time" "github.com/google/uuid" @@ -147,6 +145,7 @@ func (r *UserRepository) NameFilter(name string) FilterFunc { func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { var users []User var res *gorm.DB + if filters == nil { res = r.db.Model(&User{}).Preload("Organization").Preload("Role").Find(&users) } else { @@ -161,6 +160,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { cFunc := combinedFilter(filters...) res = cFunc(r.db.Model(&User{}).Preload("Organization").Preload("Role")).Find(&users) } + if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error @@ -181,16 +181,10 @@ func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizat var users []User if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("users", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&User{}).Where("organization_id = ?", organizationId)) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Preload("Organization").Preload("Role").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&users) + _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&User{}).Where("organization_id = ?", organizationId), &users) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 0ad49670..a186e0ef 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -6,6 +6,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -24,7 +25,7 @@ const ( type IProjectUsecase interface { CreateProject(*domain.Project) (string, error) - GetProjects(organizationId string, userId string, onlyMyProject bool) ([]domain.ProjectResponse, error) + GetProjects(organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) ([]domain.ProjectResponse, error) GetProject(organizationId string, projectId string) (*domain.Project, error) GetProjectWithLeader(organizationId string, projectId string) (*domain.Project, error) IsProjectNameExist(organizationId string, projectName string) (bool, error) @@ -34,13 +35,13 @@ type IProjectUsecase interface { AddProjectMember(pm *domain.ProjectMember) (string, error) GetProjectUser(projectUserId string) (*domain.ProjectUser, error) GetProjectMember(projectMemberId string) (*domain.ProjectMember, error) - GetProjectMembers(projectId string, query int) ([]domain.ProjectMember, error) + GetProjectMembers(projectId string, query int, pg *pagination.Pagination) ([]domain.ProjectMember, error) GetProjectMemberCount(projectMemberId string) (*domain.GetProjectMemberCountResponse, error) RemoveProjectMember(projectMemberId string) error UpdateProjectMemberRole(pm *domain.ProjectMember) error CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error IsProjectNamespaceExist(organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) - GetProjectNamespaces(organizationId string, projectId string) ([]domain.ProjectNamespace, error) + GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) UpdateProjectNamespace(pn *domain.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error @@ -91,20 +92,20 @@ func (u *ProjectUsecase) CreateProject(p *domain.Project) (string, error) { return projectId, nil } -func (u *ProjectUsecase) GetProjects(organizationId string, userId string, onlyMyProject bool) (pr []domain.ProjectResponse, err error) { +func (u *ProjectUsecase) GetProjects(organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { userUuid, err := uuid.Parse(userId) if err != nil { log.Error(err) return nil, errors.Wrap(err, "Failed to parse uuid to string") } if onlyMyProject == false { - pr, err = u.projectRepo.GetProjects(organizationId, userUuid) + pr, err = u.projectRepo.GetProjects(organizationId, userUuid, pg) if err != nil { log.Error(err) return nil, errors.Wrap(err, "Failed to get projects.") } } else { - pr, err = u.projectRepo.GetProjectsByUserId(organizationId, userUuid) + pr, err = u.projectRepo.GetProjectsByUserId(organizationId, userUuid, pg) if err != nil { log.Error(err) return nil, errors.Wrap(err, "Failed to get projects.") @@ -285,15 +286,15 @@ func (u *ProjectUsecase) GetProjectMember(projectMemberId string) (pm *domain.Pr return pm, nil } -func (u *ProjectUsecase) GetProjectMembers(projectId string, query int) (pms []domain.ProjectMember, err error) { +func (u *ProjectUsecase) GetProjectMembers(projectId string, query int, pg *pagination.Pagination) (pms []domain.ProjectMember, err error) { if query == ProjectLeader { - pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-leader") + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-leader", pg) } else if query == ProjectMember { - pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-member") + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-member", pg) } else if query == ProjectViewer { - pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-viewer") + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-viewer", pg) } else { - pms, err = u.projectRepo.GetProjectMembersByProjectId(projectId) + pms, err = u.projectRepo.GetProjectMembersByProjectId(projectId, pg) } if err != nil { log.Error(err) @@ -352,8 +353,8 @@ func (u *ProjectUsecase) IsProjectNamespaceExist(organizationId string, projectI return exist, nil } -func (u *ProjectUsecase) GetProjectNamespaces(organizationId string, projectId string) ([]domain.ProjectNamespace, error) { - pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) +func (u *ProjectUsecase) GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) { + pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, pg) if err != nil { log.Error(err) return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") @@ -404,7 +405,7 @@ func (u *ProjectUsecase) GetAppCount(organizationId string, projectId string, na } func (u *ProjectUsecase) EnsureRequiredSetupForCluster(organizationId string, projectId string, stackId string) error { - pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) + pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { log.Error(err) return errors.Wrap(err, "Failed to create project namespace.") @@ -433,7 +434,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(organizationId string, pr return errors.Wrap(err, "Failed to create project namespace.") } - projectMembers, err := u.GetProjectMembers(projectId, ProjectAll) + projectMembers, err := u.GetProjectMembers(projectId, ProjectAll, nil) if err != nil { log.Error(err) return errors.Wrap(err, "Failed to create project namespace.") @@ -449,7 +450,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(organizationId string, pr return nil } func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(organizationId string, projectId string, stackId string) error { - pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) + pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { log.Error(err) return errors.Wrap(err, "Failed to create project namespace.") @@ -471,7 +472,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(organizationId string, return errors.Wrap(err, "Failed to create project namespace.") } - projectMembers, err := u.GetProjectMembers(projectId, ProjectAll) + projectMembers, err := u.GetProjectMembers(projectId, ProjectAll, nil) if err != nil { log.Error(err) return errors.Wrap(err, "Failed to create project namespace.") @@ -646,7 +647,7 @@ func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(organizationId strin } func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId string) (string, error) { - projectNamespaces, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId) + projectNamespaces, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { log.Error(err) return "", errors.Wrap(err, "Failed to retrieve project namespaces.") diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 9660622e..bfb13715 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -58,7 +58,8 @@ type ProjectResponse struct { } type GetProjectsResponse struct { - Projects []ProjectResponse `json:"projects"` + Projects []ProjectResponse `json:"projects"` + Pagination PaginationResponse `json:"pagination"` } type ProjectDetailResponse struct { @@ -192,6 +193,7 @@ type GetProjectMemberResponse struct { type GetProjectMembersResponse struct { ProjectMembers []ProjectMemberResponse `json:"projectMembers"` + Pagination PaginationResponse `json:"pagination"` } type GetProjectMemberCountResponse struct { From bc71d681a8a5017df758aae0c1c22de818b4e9ae Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 27 Feb 2024 16:27:13 +0900 Subject: [PATCH 058/502] trivial. pass context to usecase from handler --- internal/delivery/http/project.go | 92 ++++----- internal/usecase/project.go | 306 +++++++++++++++--------------- 2 files changed, 198 insertions(+), 200 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 3f35c27f..321d20ce 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -98,7 +98,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { } log.Infof("Processing CREATE request for project '%s'...", project.Name) - projectId, err := p.usecase.CreateProject(project) + projectId, err := p.usecase.CreateProject(r.Context(), project) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -112,7 +112,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } - prs, err := p.usecase.GetProjectRoles(usecase.ProjectLeader) + prs, err := p.usecase.GetProjectRoles(r.Context(), usecase.ProjectLeader) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to retrieve project-leader id")) @@ -130,7 +130,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { CreatedAt: now, } - projectMemberId, err := p.usecase.AddProjectMember(pm) + projectMemberId, err := p.usecase.AddProjectMember(r.Context(), pm) if err != nil { log.Errorf("projectMemberId: %v", projectMemberId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -174,7 +174,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { // get myUserId from login component requestUserInfo, ok := request.UserFrom(r.Context()) myUserId := requestUserInfo.GetUserId().String() - pr, err := p.usecase.GetProjects(organizationId, myUserId, onlyMyProject, pg) + pr, err := p.usecase.GetProjects(r.Context(), organizationId, myUserId, onlyMyProject, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to retrieve projects ", err) ErrorJSON(w, r, err) @@ -220,7 +220,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { return } - project, err := p.usecase.GetProjectWithLeader(organizationId, projectId) + project, err := p.usecase.GetProjectWithLeader(r.Context(), organizationId, projectId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to retrieve project", err) ErrorJSON(w, r, err) @@ -293,7 +293,7 @@ func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Reques urlParams := r.URL.Query() projectName := urlParams.Get("value") - exist, err := p.usecase.IsProjectNameExist(organizationId, projectName) + exist, err := p.usecase.IsProjectNameExist(r.Context(), organizationId, projectName) if err != nil { ErrorJSON(w, r, err) return @@ -341,13 +341,13 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { } now := time.Now() - project, err := p.usecase.GetProjectWithLeader(organizationId, projectId) + project, err := p.usecase.GetProjectWithLeader(r.Context(), organizationId, projectId) if err != nil { ErrorJSON(w, r, err) return } if project == nil { - project, err = p.usecase.GetProject(organizationId, projectId) + project, err = p.usecase.GetProject(r.Context(), organizationId, projectId) if err != nil { ErrorJSON(w, r, err) return @@ -358,7 +358,7 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { project.Description = projectReq.Description project.UpdatedAt = &now - if err := p.usecase.UpdateProject(project, projectReq.ProjectLeaderId); err != nil { + if err := p.usecase.UpdateProject(r.Context(), project, projectReq.ProjectLeaderId); err != nil { ErrorJSON(w, r, err) return } @@ -401,7 +401,7 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { return } - pr, err := p.usecase.GetProjectRole(projectRoleId) + pr, err := p.usecase.GetProjectRole(r.Context(), projectRoleId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project roles ", err) ErrorJSON(w, r, err) @@ -445,7 +445,7 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) return } - prs, err := p.usecase.GetProjectRoles(query) + prs, err := p.usecase.GetProjectRoles(r.Context(), query) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project roles ", err) ErrorJSON(w, r, err) @@ -494,7 +494,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, pg) + pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, pg) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -507,7 +507,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) now := time.Now() for _, pmr := range projectMemberReq.ProjectMemberRequests { - pu, err := p.usecase.GetProjectUser(pmr.ProjectUserId) + pu, err := p.usecase.GetProjectUser(r.Context(), pmr.ProjectUserId) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectUserId"), @@ -515,7 +515,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } - pr, err := p.usecase.GetProjectRole(pmr.ProjectRoleId) + pr, err := p.usecase.GetProjectRole(r.Context(), pmr.ProjectRoleId) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -535,7 +535,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) ProjectRole: nil, CreatedAt: now, } - pmId, err := p.usecase.AddProjectMember(pm) + pmId, err := p.usecase.AddProjectMember(r.Context(), pm) if err != nil { log.Errorf("projectMemberId: %s", pmId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -544,7 +544,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(organizationId, projectId, stackId, pmId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pmId); err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -594,7 +594,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) return } - pm, err := p.usecase.GetProjectMember(projectMemberId) + pm, err := p.usecase.GetProjectMember(r.Context(), projectMemberId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project member ", err) ErrorJSON(w, r, err) @@ -672,7 +672,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request } pg := pagination.NewPagination(&urlParams) - pms, err := p.usecase.GetProjectMembers(projectId, query, pg) + pms, err := p.usecase.GetProjectMembers(r.Context(), projectId, query, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project members ", err) ErrorJSON(w, r, err) @@ -739,7 +739,7 @@ func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Req return } - pmcr, err := p.usecase.GetProjectMemberCount(projectId) + pmcr, err := p.usecase.GetProjectMemberCount(r.Context(), projectId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project member count", err) ErrorJSON(w, r, err) @@ -792,7 +792,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } // tasks for keycloak & k8s - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, nil) + pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -803,14 +803,14 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque stackIds[pn.StackId] = struct{}{} } for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } } - if err := p.usecase.RemoveProjectMember(projectMemberId); err != nil { + if err := p.usecase.RemoveProjectMember(r.Context(), projectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -855,7 +855,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ } // tasks for keycloak & k8s - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, nil) + pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -870,14 +870,14 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ for _, pm := range projectMemberReq.ProjectMember { // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ProjectMemberId); err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } } - if err := p.usecase.RemoveProjectMember(pm.ProjectMemberId); err != nil { + if err := p.usecase.RemoveProjectMember(r.Context(), pm.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -930,7 +930,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } now := time.Now() - pm, err := p.usecase.GetProjectMember(projectMemberId) + pm, err := p.usecase.GetProjectMember(r.Context(), projectMemberId) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -942,7 +942,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R return } - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, nil) + pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -954,7 +954,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } // tasks for keycloak & k8s. Unassign old role for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -966,13 +966,13 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R pm.ProjectRole = nil pm.UpdatedAt = &now - if err := p.usecase.UpdateProjectMemberRole(pm); err != nil { + if err := p.usecase.UpdateProjectMemberRole(r.Context(), pm); err != nil { ErrorJSON(w, r, err) return } // tasks for keycloak & k8s. Assign new role for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1019,7 +1019,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, nil) + pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -1031,7 +1031,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } for _, pmr := range projectMemberReq.ProjectMemberRoleRequests { - pm, err := p.usecase.GetProjectMember(pmr.ProjectMemberId) + pm, err := p.usecase.GetProjectMember(r.Context(), pmr.ProjectMemberId) if err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -1044,7 +1044,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ID); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1056,13 +1056,13 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. pm.ProjectRole = nil pm.UpdatedAt = &now - if err := p.usecase.UpdateProjectMemberRole(pm); err != nil { + if err := p.usecase.UpdateProjectMemberRole(r.Context(), pm); err != nil { ErrorJSON(w, r, err) return } for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ID); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { log.Error(err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1118,16 +1118,16 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re } // tasks for keycloak & k8s - if err := p.usecase.EnsureRequiredSetupForCluster(organizationId, projectId, projectNamespaceReq.StackId); err != nil { + if err := p.usecase.EnsureRequiredSetupForCluster(r.Context(), organizationId, projectId, projectNamespaceReq.StackId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - if err := p.usecase.CreateK8SNSRoleBinding(organizationId, projectId, projectNamespaceReq.StackId, projectNamespaceReq.Namespace); err != nil { + if err := p.usecase.CreateK8SNSRoleBinding(r.Context(), organizationId, projectId, projectNamespaceReq.StackId, projectNamespaceReq.Namespace); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - if err := p.usecase.CreateProjectNamespace(organizationId, pn); err != nil { + if err := p.usecase.CreateProjectNamespace(r.Context(), organizationId, pn); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1175,7 +1175,7 @@ func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.R return } - exist, err := p.usecase.IsProjectNamespaceExist(organizationId, projectId, stackId, projectNamespace) + exist, err := p.usecase.IsProjectNamespaceExist(r.Context(), organizationId, projectId, stackId, projectNamespace) if err != nil { ErrorJSON(w, r, err) return @@ -1215,7 +1215,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - pns, err := p.usecase.GetProjectNamespaces(organizationId, projectId, pg) + pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project namespaces.", err) ErrorJSON(w, r, err) @@ -1235,7 +1235,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ ErrorJSON(w, r, err) return } - appCount, err := p.usecase.GetAppCount(organizationId, projectId, pn.Namespace) + appCount, err := p.usecase.GetAppCount(r.Context(), organizationId, projectId, pn.Namespace) if err != nil { log.ErrorWithContext(r.Context(), "Failed to retrieve app count", err) ErrorJSON(w, r, err) @@ -1292,14 +1292,14 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque return } - pn, err := p.usecase.GetProjectNamespace(organizationId, projectId, projectNamespace, stackId) + pn, err := p.usecase.GetProjectNamespace(r.Context(), organizationId, projectId, projectNamespace, stackId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project namespace.", err) ErrorJSON(w, r, err) return } - appCount, err := p.usecase.GetAppCount(organizationId, projectId, projectNamespace) + appCount, err := p.usecase.GetAppCount(r.Context(), organizationId, projectId, projectNamespace) if err != nil { log.ErrorWithContext(r.Context(), "Failed to retrieve app count", err) ErrorJSON(w, r, err) @@ -1375,7 +1375,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re } now := time.Now() - pn, err := p.usecase.GetProjectNamespace(organizationId, projectId, projectNamespace, stackId) + pn, err := p.usecase.GetProjectNamespace(r.Context(), organizationId, projectId, projectNamespace, stackId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project namespace.", err) ErrorJSON(w, r, err) @@ -1385,7 +1385,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re pn.Description = projectNamespaceReq.Description pn.UpdatedAt = &now - if err := p.usecase.UpdateProjectNamespace(pn); err != nil { + if err := p.usecase.UpdateProjectNamespace(r.Context(), pn); err != nil { ErrorJSON(w, r, err) return } @@ -1498,7 +1498,7 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ return } - kubeconfig, err := p.usecase.GetProjectKubeconfig(organizationId, projectId) + kubeconfig, err := p.usecase.GetProjectKubeconfig(r.Context(), organizationId, projectId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project kubeconfig.", err) ErrorJSON(w, r, err) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index fdd67fe9..a955be00 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -27,40 +27,38 @@ const ( ) type IProjectUsecase interface { - CreateProject(*domain.Project) (string, error) - GetProjects(organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) ([]domain.ProjectResponse, error) - GetProject(organizationId string, projectId string) (*domain.Project, error) - GetProjectWithLeader(organizationId string, projectId string) (*domain.Project, error) - IsProjectNameExist(organizationId string, projectName string) (bool, error) - UpdateProject(p *domain.Project, newLeaderId string) error - GetProjectRole(id string) (*domain.ProjectRole, error) - GetProjectRoles(int) ([]domain.ProjectRole, error) - AddProjectMember(pm *domain.ProjectMember) (string, error) - GetProjectUser(projectUserId string) (*domain.ProjectUser, error) - GetProjectMember(projectMemberId string) (*domain.ProjectMember, error) - GetProjectMembers(projectId string, query int, pg *pagination.Pagination) ([]domain.ProjectMember, error) - GetProjectMemberCount(projectMemberId string) (*domain.GetProjectMemberCountResponse, error) - RemoveProjectMember(projectMemberId string) error - UpdateProjectMemberRole(pm *domain.ProjectMember) error - CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error - IsProjectNamespaceExist(organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) - GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) - GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) - UpdateProjectNamespace(pn *domain.ProjectNamespace) error - DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error - GetAppCount(organizationId string, projectId string, namespace string) (appCount int, err error) - - EnsureRequiredSetupForCluster(organizationId string, projectId string, stackId string) error - MayRemoveRequiredSetupForCluster(organizationId string, projectId string, stackId string) error - - CreateK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error - DeleteK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error - GetProjectKubeconfig(organizationId string, projectId string) (string, error) + CreateProject(ctx context.Context, p *domain.Project) (string, error) + GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProject(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) + GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) + IsProjectNameExist(ctx context.Context, organizationId string, projectName string) (bool, error) + UpdateProject(ctx context.Context, p *domain.Project, newLeaderId string) error + GetProjectRole(ctx context.Context, id string) (*domain.ProjectRole, error) + GetProjectRoles(ctx context.Context, query int) ([]domain.ProjectRole, error) + AddProjectMember(ctx context.Context, pm *domain.ProjectMember) (string, error) + GetProjectUser(ctx context.Context, projectUserId string) (*domain.ProjectUser, error) + GetProjectMember(ctx context.Context, projectMemberId string) (*domain.ProjectMember, error) + GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) ([]domain.ProjectMember, error) + GetProjectMemberCount(ctx context.Context, projectMemberId string) (*domain.GetProjectMemberCountResponse, error) + RemoveProjectMember(ctx context.Context, projectMemberId string) error + UpdateProjectMemberRole(ctx context.Context, pm *domain.ProjectMember) error + CreateProjectNamespace(ctx context.Context, organizationId string, pn *domain.ProjectNamespace) error + IsProjectNamespaceExist(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) + GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) + GetProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) + UpdateProjectNamespace(ctx context.Context, pn *domain.ProjectNamespace) error + DeleteProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) error + GetAppCount(ctx context.Context, organizationId string, projectId string, namespace string) (appCount int, err error) + EnsureRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error + MayRemoveRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error + CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error + DeleteK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error + GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) - - AssignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error - UnassignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error + AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error + UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error } + type ProjectUsecase struct { projectRepo repository.IProjectRepository userRepository repository.IUserRepository @@ -85,61 +83,61 @@ func NewProjectUsecase(r repository.Repository, kc keycloak.IKeycloak, argoClien } } -func (u *ProjectUsecase) CreateProject(p *domain.Project) (string, error) { +func (u *ProjectUsecase) CreateProject(ctx context.Context, p *domain.Project) (string, error) { projectId, err := u.projectRepo.CreateProject(p) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to create project.") } return projectId, nil } -func (u *ProjectUsecase) GetProjects(organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { userUuid, err := uuid.Parse(userId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to parse uuid to string") } if onlyMyProject == false { pr, err = u.projectRepo.GetProjects(organizationId, userUuid, pg) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") } } else { pr, err = u.projectRepo.GetProjectsByUserId(organizationId, userUuid, pg) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") } } return pr, err } -func (u *ProjectUsecase) GetProject(organizationId string, projectId string) (*domain.Project, error) { +func (u *ProjectUsecase) GetProject(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) { p, err := u.projectRepo.GetProjectById(organizationId, projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") } return p, err } -func (u *ProjectUsecase) GetProjectWithLeader(organizationId string, projectId string) (*domain.Project, error) { +func (u *ProjectUsecase) GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) { p, err := u.projectRepo.GetProjectByIdAndLeader(organizationId, projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") } return p, err } -func (u *ProjectUsecase) IsProjectNameExist(organizationId string, projectName string) (bool, error) { +func (u *ProjectUsecase) IsProjectNameExist(ctx context.Context, organizationId string, projectName string) (bool, error) { exist := true p, err := u.projectRepo.GetProjectByName(organizationId, projectName) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) exist = false return exist, errors.Wrap(err, "Failed to retrieve project name.") } @@ -149,7 +147,7 @@ func (u *ProjectUsecase) IsProjectNameExist(organizationId string, projectName s return exist, nil } -func (u *ProjectUsecase) UpdateProject(p *domain.Project, newLeaderId string) error { +func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *domain.Project, newLeaderId string) error { var currentMemberId, currentLeaderId, projectRoleId string for _, pm := range p.ProjectMembers { @@ -161,17 +159,17 @@ func (u *ProjectUsecase) UpdateProject(p *domain.Project, newLeaderId string) er p.ProjectMembers = nil if err := u.projectRepo.UpdateProject(p); err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to update project.") } if newLeaderId != "" && currentLeaderId != newLeaderId { - if err := u.RemoveProjectMember(currentMemberId); err != nil { - log.Error(err) + if err := u.RemoveProjectMember(ctx, currentMemberId); err != nil { + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to remove project member.") } - pu, err := u.GetProjectUser(newLeaderId) + pu, err := u.GetProjectUser(ctx, newLeaderId) if err != nil { return err } @@ -193,7 +191,7 @@ func (u *ProjectUsecase) UpdateProject(p *domain.Project, newLeaderId string) er IsProjectLeader: true, CreatedAt: *p.UpdatedAt, } - res, err := u.AddProjectMember(newPm) + res, err := u.AddProjectMember(ctx, newPm) if err != nil { return err } @@ -205,7 +203,7 @@ func (u *ProjectUsecase) UpdateProject(p *domain.Project, newLeaderId string) er pm.UpdatedAt = p.UpdatedAt pm.ProjectUser = nil pm.ProjectRole = nil - err := u.UpdateProjectMemberRole(pm) + err := u.UpdateProjectMemberRole(ctx, pm) if err != nil { return err } @@ -215,17 +213,17 @@ func (u *ProjectUsecase) UpdateProject(p *domain.Project, newLeaderId string) er return nil } -func (u *ProjectUsecase) GetProjectRole(id string) (*domain.ProjectRole, error) { +func (u *ProjectUsecase) GetProjectRole(ctx context.Context, id string) (*domain.ProjectRole, error) { pr, err := u.projectRepo.GetProjectRoleById(id) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get project roles.") } return pr, nil } -func (u *ProjectUsecase) GetProjectRoles(query int) (prs []domain.ProjectRole, err error) { +func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs []domain.ProjectRole, err error) { var pr *domain.ProjectRole if query == ProjectLeader { @@ -238,7 +236,7 @@ func (u *ProjectUsecase) GetProjectRoles(query int) (prs []domain.ProjectRole, e prs, err = u.projectRepo.GetAllProjectRoles() } if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get project roles.") } @@ -249,47 +247,47 @@ func (u *ProjectUsecase) GetProjectRoles(query int) (prs []domain.ProjectRole, e return prs, nil } -func (u *ProjectUsecase) AddProjectMember(pm *domain.ProjectMember) (string, error) { +func (u *ProjectUsecase) AddProjectMember(ctx context.Context, pm *domain.ProjectMember) (string, error) { projectMemberId, err := u.projectRepo.AddProjectMember(pm) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to add project member to project.") } return projectMemberId, nil } -func (u *ProjectUsecase) GetProjectUser(projectUserId string) (*domain.ProjectUser, error) { +func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId string) (*domain.ProjectUser, error) { var uid uuid.UUID uid, err := uuid.Parse(projectUserId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to parse uuid to string") } user, err := u.userRepository.GetByUuid(uid) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve user by id") } var pu domain.ProjectUser if err = serializer.Map(user, &pu); err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, err } return &pu, nil } -func (u *ProjectUsecase) GetProjectMember(projectMemberId string) (pm *domain.ProjectMember, err error) { +func (u *ProjectUsecase) GetProjectMember(ctx context.Context, projectMemberId string) (pm *domain.ProjectMember, err error) { pm, err = u.projectRepo.GetProjectMemberById(projectMemberId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return pm, errors.Wrap(err, "Failed to get project member.") } return pm, nil } -func (u *ProjectUsecase) GetProjectMembers(projectId string, query int, pg *pagination.Pagination) (pms []domain.ProjectMember, err error) { +func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) (pms []domain.ProjectMember, err error) { if query == ProjectLeader { pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-leader", pg) } else if query == ProjectMember { @@ -300,53 +298,53 @@ func (u *ProjectUsecase) GetProjectMembers(projectId string, query int, pg *pagi pms, err = u.projectRepo.GetProjectMembersByProjectId(projectId, pg) } if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get project members.") } return pms, nil } -func (u *ProjectUsecase) GetProjectMemberCount(projectMemberId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { +func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMemberId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { pmcr, err = u.projectRepo.GetProjectMemberCountByProjectId(projectMemberId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return pmcr, errors.Wrap(err, "Failed to get project member count.") } return pmcr, nil } -func (u *ProjectUsecase) RemoveProjectMember(projectMemberId string) error { +func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, projectMemberId string) error { if err := u.projectRepo.RemoveProjectMember(projectMemberId); err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to remove project member to project.") } return nil } -func (u *ProjectUsecase) UpdateProjectMemberRole(pm *domain.ProjectMember) error { +func (u *ProjectUsecase) UpdateProjectMemberRole(ctx context.Context, pm *domain.ProjectMember) error { if err := u.projectRepo.UpdateProjectMemberRole(pm); err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to remove project member to project.") } return nil } -func (u *ProjectUsecase) CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error { +func (u *ProjectUsecase) CreateProjectNamespace(ctx context.Context, organizationId string, pn *domain.ProjectNamespace) error { if err := u.projectRepo.CreateProjectNamespace(organizationId, pn); err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil } -func (u *ProjectUsecase) IsProjectNamespaceExist(organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) { +func (u *ProjectUsecase) IsProjectNamespaceExist(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) { exist := true pn, err := u.projectRepo.GetProjectNamespaceByName(organizationId, projectId, stackId, projectNamespace) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) exist = false return exist, errors.Wrap(err, "Failed to retrieve project namespace.") } @@ -356,61 +354,61 @@ func (u *ProjectUsecase) IsProjectNamespaceExist(organizationId string, projectI return exist, nil } -func (u *ProjectUsecase) GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) { +func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) { pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, pg) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") } return pns, nil } -func (u *ProjectUsecase) GetProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) { +func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) { pn, err := u.projectRepo.GetProjectNamespaceByPrimaryKey(organizationId, projectId, projectNamespace, stackId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve project namespace.") } return pn, nil } -func (u *ProjectUsecase) UpdateProjectNamespace(pn *domain.ProjectNamespace) error { +func (u *ProjectUsecase) UpdateProjectNamespace(ctx context.Context, pn *domain.ProjectNamespace) error { if err := u.projectRepo.UpdateProjectNamespace(pn); err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to update project namespace") } return nil } -func (u *ProjectUsecase) DeleteProjectNamespace(organizationId string, projectId string, +func (u *ProjectUsecase) DeleteProjectNamespace(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) error { if err := u.projectRepo.DeleteProjectNamespace(organizationId, projectId, projectNamespace, stackId); err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to delete project namespace.") } return nil } -func (u *ProjectUsecase) GetAppCount(organizationId string, projectId string, namespace string) (appCount int, err error) { +func (u *ProjectUsecase) GetAppCount(ctx context.Context, organizationId string, projectId string, namespace string) (appCount int, err error) { if namespace == "" { appCount, err = u.projectRepo.GetAppCountByProjectId(organizationId, projectId) } else { appCount, err = u.projectRepo.GetAppCountByNamespace(organizationId, projectId, namespace) } if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return 0, errors.Wrap(err, "Failed to retrieve app count.") } return appCount, nil } -func (u *ProjectUsecase) EnsureRequiredSetupForCluster(organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error { pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -427,35 +425,35 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(organizationId string, pr return nil } - if err := u.createK8SInitialResource(organizationId, projectId, stackId); err != nil { - log.Error(err) + if err := u.createK8SInitialResource(ctx, organizationId, projectId, stackId); err != nil { + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - if err := u.createKeycloakClientRoles(organizationId, projectId, stackId); err != nil { - log.Error(err) + if err := u.createKeycloakClientRoles(ctx, organizationId, projectId, stackId); err != nil { + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - projectMembers, err := u.GetProjectMembers(projectId, ProjectAll, nil) + projectMembers, err := u.GetProjectMembers(ctx, projectId, ProjectAll, nil) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } for _, pm := range projectMembers { - err = u.assignEachKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } } return nil } -func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error { pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } var nsCount int @@ -470,189 +468,189 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(organizationId string, return nil } - if err := u.deleteK8SInitialResource(organizationId, projectId, stackId); err != nil { - log.Error(err) + if err := u.deleteK8SInitialResource(ctx, organizationId, projectId, stackId); err != nil { + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - projectMembers, err := u.GetProjectMembers(projectId, ProjectAll, nil) + projectMembers, err := u.GetProjectMembers(ctx, projectId, ProjectAll, nil) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } for _, pm := range projectMembers { - err = u.unassignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } } - if err := u.deleteKeycloakClientRoles(organizationId, projectId, stackId); err != nil { - log.Error(err) + if err := u.deleteKeycloakClientRoles(ctx, organizationId, projectId, stackId); err != nil { + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil } -func (u *ProjectUsecase) createK8SInitialResource(organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { kubeconfig, err := kubernetes.GetKubeConfig(stackId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - pr, err := u.GetProject(organizationId, projectId) + pr, err := u.GetProject(ctx, organizationId, projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.EnsureClusterRole(kubeconfig, pr.Name) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.EnsureCommonClusterRole(kubeconfig, pr.Name) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.EnsureCommonClusterRoleBinding(kubeconfig, pr.Name) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil } -func (u *ProjectUsecase) deleteK8SInitialResource(organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { kubeconfig, err := kubernetes.GetKubeConfig(stackId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - pr, err := u.GetProject(organizationId, projectId) + pr, err := u.GetProject(ctx, organizationId, projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.RemoveClusterRole(kubeconfig, pr.Name) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.RemoveCommonClusterRole(kubeconfig, pr.Name) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.RemoveCommonClusterRoleBinding(kubeconfig, pr.Name) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil } -func (u *ProjectUsecase) createKeycloakClientRoles(organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, stackId string) error { // create Roles in keycloak for _, role := range []string{string(ProjectLeader), string(ProjectMember), string(ProjectViewer)} { err := u.kc.EnsureClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } } return nil } -func (u *ProjectUsecase) deleteKeycloakClientRoles(organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, stackId string) error { // first check whether the stac // delete Roles in keycloak for _, role := range []string{string(ProjectLeader), string(ProjectMember), string(ProjectViewer)} { err := u.kc.DeleteClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } } return nil } -func (u *ProjectUsecase) CreateK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error { +func (u *ProjectUsecase) CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error { kubeconfig, err := kubernetes.GetKubeConfig(stackId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - pr, err := u.GetProject(organizationId, projectId) + pr, err := u.GetProject(ctx, organizationId, projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.EnsureRoleBinding(kubeconfig, pr.Name, namespace) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil } -func (u *ProjectUsecase) DeleteK8SNSRoleBinding(organizationId string, projectId string, stackId string, namespace string) error { +func (u *ProjectUsecase) DeleteK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error { //TODO implement me panic("implement me") } -func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error { - pm, err := u.GetProjectMember(projectMemberId) +func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { + pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.assignEachKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) return nil } -func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, userId string, roleName string) error { +func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { err := u.kc.AssignClientRoleToUser(organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil } -func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, projectMemberId string) error { - pm, err := u.GetProjectMember(projectMemberId) +func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { + pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.unassignKeycloakClientRoleToMember(organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) return nil } -func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(organizationId string, projectId string, stackId string, userId string, roleName string) error { +func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { err := u.kc.UnassignClientRoleToUser(organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil } -func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId string) (string, error) { +func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) { projectNamespaces, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to retrieve project namespaces.") } @@ -682,21 +680,21 @@ func (u *ProjectUsecase) GetProjectKubeconfig(organizationId string, projectId s for _, pn := range projectNamespaces { kubeconfig, err := kubernetes.GetKubeConfig(pn.StackId) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to retrieve kubeconfig.") } var config kubeConfigType err = yaml.Unmarshal(kubeconfig, &config) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to unmarshal kubeconfig.") } config.Contexts[0].Context.Namespace = pn.Namespace kubeconfig, err = yaml.Marshal(config) if err != nil { - log.Error(err) + log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to marshal kubeconfig.") } @@ -723,56 +721,56 @@ func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId str if err == nil { out.Pods = len(pods.Items) } else { - log.Error("Failed to get pods. err : ", err) + log.ErrorWithContext(ctx, "Failed to get pods. err : ", err) } pvcs, err := clientset_user.CoreV1().PersistentVolumeClaims(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.PVCs = len(pvcs.Items) } else { - log.Error("Failed to get pvcs. err : ", err) + log.ErrorWithContext(ctx, "Failed to get pvcs. err : ", err) } services, err := clientset_user.CoreV1().Services(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Services = len(services.Items) } else { - log.Error("Failed to get services. err : ", err) + log.ErrorWithContext(ctx, "Failed to get services. err : ", err) } ingresses, err := clientset_user.NetworkingV1().Ingresses(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Ingresses = len(ingresses.Items) } else { - log.Error("Failed to get ingresses. err : ", err) + log.ErrorWithContext(ctx, "Failed to get ingresses. err : ", err) } deployments, err := clientset_user.AppsV1().Deployments(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Deployments = len(deployments.Items) } else { - log.Error("Failed to get deployments. err : ", err) + log.ErrorWithContext(ctx, "Failed to get deployments. err : ", err) } statefulsets, err := clientset_user.AppsV1().StatefulSets(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Statefulsets = len(statefulsets.Items) } else { - log.Error("Failed to get statefulsets. err : ", err) + log.ErrorWithContext(ctx, "Failed to get statefulsets. err : ", err) } daemonsets, err := clientset_user.AppsV1().DaemonSets(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Daemonsets = len(daemonsets.Items) } else { - log.Error("Failed to get daemonsets. err : ", err) + log.ErrorWithContext(ctx, "Failed to get daemonsets. err : ", err) } jobs, err := clientset_user.BatchV1().Jobs(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Jobs = len(jobs.Items) } else { - log.Error("Failed to get jobs. err : ", err) + log.ErrorWithContext(ctx, "Failed to get jobs. err : ", err) } return From 03361c0d7295212f2618c0d495853cb3e18ad3f5 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 29 Feb 2024 10:40:05 +0900 Subject: [PATCH 059/502] bugfix. minor fix for pagination --- internal/repository/app-serve-app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 50c97b45..479f4e77 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -68,7 +68,7 @@ func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll b // TODO: should return different records based on showAll param _, res := pg.Fetch(r.db.Model(&domain.AppServeApp{}). - Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId), &clusters) + Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId), &apps) if res.Error != nil { return nil, fmt.Errorf("error while finding appServeApps with organizationId: %s", organizationId) } From 726af0e0da794e24866e33ff98abd59256ac612c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 29 Feb 2024 11:14:44 +0900 Subject: [PATCH 060/502] bugfix. fix middleware; --- internal/middleware/audit/audit.go | 6 ++---- internal/route/route.go | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 55d61511..bd0d2c25 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -38,9 +38,6 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han } userId := user.GetUserId() - requestBody := &bytes.Buffer{} - _, _ = io.Copy(requestBody, r.Body) - lrw := logging.NewLoggingResponseWriter(w) handler.ServeHTTP(lrw, r) statusCode := lrw.GetStatusCode() @@ -53,11 +50,12 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han message, description := "", "" if fn, ok := auditMap[endpoint]; ok { - body, err := io.ReadAll(requestBody) + body, err := io.ReadAll(r.Body) if err != nil { log.Error(err) } message, description = fn(lrw.GetBody(), body, statusCode) + r.Body = io.NopCloser(bytes.NewBuffer(body)) dto := domain.Audit{ OrganizationId: organizationId, diff --git a/internal/route/route.go b/internal/route/route.go index 02e7b2fe..4382baa1 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -7,6 +7,7 @@ import ( internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/requestRecoder" + "github.com/openinfradev/tks-api/internal/middleware/logging" "github.com/gorilla/handlers" "github.com/gorilla/mux" @@ -17,12 +18,11 @@ import ( "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" authKeycloak "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator/keycloak" "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" - "github.com/openinfradev/tks-api/internal/middleware/logging" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/usecase" argowf "github.com/openinfradev/tks-api/pkg/argo-client" gcache "github.com/patrickmn/go-cache" - "github.com/swaggo/http-swagger" + httpSwagger "github.com/swaggo/http-swagger" "gorm.io/gorm" ) From 82113eb1559c4fa55f04073c0d3c148a87e012b7 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 29 Feb 2024 16:08:39 +0900 Subject: [PATCH 061/502] trivial. workarround fix that incorrectly recorded in audit --- internal/middleware/audit/audit.go | 35 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index bd0d2c25..428f8d35 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -50,23 +50,26 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han message, description := "", "" if fn, ok := auditMap[endpoint]; ok { - body, err := io.ReadAll(r.Body) - if err != nil { - log.Error(err) - } - message, description = fn(lrw.GetBody(), body, statusCode) - r.Body = io.NopCloser(bytes.NewBuffer(body)) + // workarround pingtoken + if endpoint != internalApi.PingToken { + body, err := io.ReadAll(r.Body) + if err != nil { + log.Error(err) + } + message, description = fn(lrw.GetBody(), body, statusCode) + r.Body = io.NopCloser(bytes.NewBuffer(body)) - dto := domain.Audit{ - OrganizationId: organizationId, - Group: internalApi.ApiMap[endpoint].Group, - Message: message, - Description: description, - ClientIP: GetClientIpAddress(w, r), - UserId: &userId, - } - if _, err := a.repo.Create(dto); err != nil { - log.Error(err) + dto := domain.Audit{ + OrganizationId: organizationId, + Group: internalApi.ApiMap[endpoint].Group, + Message: message, + Description: description, + ClientIP: GetClientIpAddress(w, r), + UserId: &userId, + } + if _, err := a.repo.Create(dto); err != nil { + log.Error(err) + } } } From b34eb3d5cb12a4fe1902b53a1cb539a1f60ee2d6 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 4 Mar 2024 14:45:40 +0900 Subject: [PATCH 062/502] trivial. change swagger base path to "/" from "/api/1.0/" --- api/swagger/docs.go | 154 +++++++++++------------ api/swagger/swagger.json | 154 +++++++++++------------ api/swagger/swagger.yaml | 154 +++++++++++------------ cmd/server/main.go | 2 +- internal/delivery/http/alert.go | 10 +- internal/delivery/http/app-group.go | 12 +- internal/delivery/http/app-serve-app.go | 28 ++--- internal/delivery/http/audit.go | 8 +- internal/delivery/http/auth.go | 16 +-- internal/delivery/http/cloud-account.go | 18 +-- internal/delivery/http/cluster.go | 20 +-- internal/delivery/http/dashboard.go | 8 +- internal/delivery/http/organization.go | 12 +- internal/delivery/http/project.go | 46 +++---- internal/delivery/http/stack-template.go | 10 +- internal/delivery/http/stack.go | 20 +-- internal/delivery/http/user.go | 26 ++-- 17 files changed, 349 insertions(+), 349 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 1f9abb53..798c0e73 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -22,7 +22,7 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/app-groups": { + "/api/1.0/app-groups": { "get": { "security": [ { @@ -163,7 +163,7 @@ const docTemplate = `{ } } }, - "/app-groups/{appGroupId}": { + "/api/1.0/app-groups/{appGroupId}": { "get": { "security": [ { @@ -200,7 +200,7 @@ const docTemplate = `{ } } }, - "/app-groups/{appGroupId}/applications": { + "/api/1.0/app-groups/{appGroupId}/applications": { "get": { "security": [ { @@ -278,7 +278,7 @@ const docTemplate = `{ } } }, - "/auth/find-id/code": { + "/api/1.0/auth/find-id/code": { "post": { "description": "This API allows users to verify their identity for lost id by submitting required information", "consumes": [ @@ -318,7 +318,7 @@ const docTemplate = `{ } } }, - "/auth/find-id/verification": { + "/api/1.0/auth/find-id/verification": { "post": { "description": "This API allows users to find their account ID by submitting required information", "consumes": [ @@ -358,7 +358,7 @@ const docTemplate = `{ } } }, - "/auth/find-password/code": { + "/api/1.0/auth/find-password/code": { "post": { "description": "This API allows users to verify their identity for lost password by submitting required information", "consumes": [ @@ -398,7 +398,7 @@ const docTemplate = `{ } } }, - "/auth/find-password/verification": { + "/api/1.0/auth/find-password/verification": { "post": { "description": "This API allows users to reset their forgotten password by submitting required information", "consumes": [ @@ -435,7 +435,7 @@ const docTemplate = `{ } } }, - "/auth/login": { + "/api/1.0/auth/login": { "post": { "description": "login", "consumes": [ @@ -469,7 +469,7 @@ const docTemplate = `{ } } }, - "/auth/logout": { + "/api/1.0/auth/logout": { "post": { "security": [ { @@ -497,7 +497,7 @@ const docTemplate = `{ } } }, - "/auth/ping": { + "/api/1.0/auth/ping": { "post": { "description": "ping with token", "consumes": [ @@ -528,7 +528,7 @@ const docTemplate = `{ } } }, - "/clusters": { + "/api/1.0/clusters": { "get": { "security": [ { @@ -635,7 +635,7 @@ const docTemplate = `{ } } }, - "/clusters/import": { + "/api/1.0/clusters/import": { "post": { "security": [ { @@ -674,7 +674,7 @@ const docTemplate = `{ } } }, - "/clusters/{clusterId}": { + "/api/1.0/clusters/{clusterId}": { "get": { "security": [ { @@ -746,7 +746,7 @@ const docTemplate = `{ } } }, - "/clusters/{clusterId}/bootstrap-kubeconfig": { + "/api/1.0/clusters/{clusterId}/bootstrap-kubeconfig": { "get": { "security": [ { @@ -800,7 +800,7 @@ const docTemplate = `{ } } }, - "/clusters/{clusterId}/install": { + "/api/1.0/clusters/{clusterId}/install": { "post": { "security": [ { @@ -834,7 +834,7 @@ const docTemplate = `{ } } }, - "/clusters/{clusterId}/nodes": { + "/api/1.0/clusters/{clusterId}/nodes": { "get": { "security": [ { @@ -871,7 +871,7 @@ const docTemplate = `{ } } }, - "/clusters/{clusterId}/site-values": { + "/api/1.0/clusters/{clusterId}/site-values": { "get": { "security": [ { @@ -908,7 +908,7 @@ const docTemplate = `{ } } }, - "/organizations": { + "/api/1.0/organizations": { "get": { "security": [ { @@ -1012,7 +1012,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}": { + "/api/1.0/organizations/{organizationId}": { "get": { "security": [ { @@ -1128,7 +1128,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/alerts": { + "/api/1.0/organizations/{organizationId}/alerts": { "get": { "security": [ { @@ -1199,7 +1199,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/alerts/{alertId}": { + "/api/1.0/organizations/{organizationId}/alerts/{alertId}": { "get": { "security": [ { @@ -1323,7 +1323,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/alerts/{alertId}/actions": { + "/api/1.0/organizations/{organizationId}/alerts/{alertId}/actions": { "post": { "security": [ { @@ -1357,7 +1357,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/audits": { + "/api/1.0/organizations/{organizationId}/audits": { "get": { "security": [ { @@ -1468,7 +1468,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/audits/{auditId}": { + "/api/1.0/organizations/{organizationId}/audits/{auditId}": { "get": { "security": [ { @@ -1537,7 +1537,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/cloud-accounts": { + "/api/1.0/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ { @@ -1652,7 +1652,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { "get": { "security": [ { @@ -1696,7 +1696,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { "get": { "security": [ { @@ -1740,7 +1740,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { "get": { "security": [ { @@ -1873,7 +1873,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { "delete": { "security": [ { @@ -1914,7 +1914,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { "get": { "security": [ { @@ -1958,7 +1958,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboard/charts": { + "/api/1.0/organizations/{organizationId}/dashboard/charts": { "get": { "security": [ { @@ -2015,7 +2015,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboard/charts/{chartType}": { + "/api/1.0/organizations/{organizationId}/dashboard/charts/{chartType}": { "get": { "security": [ { @@ -2073,7 +2073,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboard/resources": { + "/api/1.0/organizations/{organizationId}/dashboard/resources": { "get": { "security": [ { @@ -2110,7 +2110,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboard/stacks": { + "/api/1.0/organizations/{organizationId}/dashboard/stacks": { "get": { "security": [ { @@ -2147,7 +2147,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/my-profile": { + "/api/1.0/organizations/{organizationId}/my-profile": { "get": { "security": [ { @@ -2263,7 +2263,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/my-profile/next-password-change": { + "/api/1.0/organizations/{organizationId}/my-profile/next-password-change": { "put": { "security": [ { @@ -2303,7 +2303,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/my-profile/password": { + "/api/1.0/organizations/{organizationId}/my-profile/password": { "put": { "security": [ { @@ -2346,7 +2346,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/primary-cluster": { + "/api/1.0/organizations/{organizationId}/primary-cluster": { "patch": { "security": [ { @@ -2389,7 +2389,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects": { + "/api/1.0/organizations/{organizationId}/projects": { "get": { "security": [ { @@ -2476,7 +2476,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/existence": { + "/api/1.0/organizations/{organizationId}/projects/existence": { "get": { "security": [ { @@ -2526,7 +2526,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/project-roles": { + "/api/1.0/organizations/{organizationId}/projects/project-roles": { "get": { "security": [ { @@ -2569,7 +2569,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "/api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { "get": { "security": [ { @@ -2613,7 +2613,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}": { "get": { "security": [ { @@ -2708,7 +2708,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { "get": { "security": [ { @@ -2846,7 +2846,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { "get": { "security": [ { @@ -2897,7 +2897,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { "get": { "security": [ { @@ -2948,7 +2948,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { "get": { "security": [ { @@ -3106,7 +3106,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { "patch": { "security": [ { @@ -3166,7 +3166,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { "get": { "security": [ { @@ -3210,7 +3210,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { "get": { "security": [ { @@ -3261,7 +3261,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { "post": { "security": [ { @@ -3321,7 +3321,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { "patch": { "security": [ { @@ -3381,7 +3381,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { "get": { "security": [ { @@ -3462,7 +3462,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { "get": { "security": [ { @@ -3520,7 +3520,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig": { "get": { "security": [ { @@ -3564,7 +3564,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/members": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/members": { "get": { "security": [ { @@ -3767,7 +3767,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/members/count": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/count": { "get": { "security": [ { @@ -3811,7 +3811,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { "get": { "security": [ { @@ -3911,7 +3911,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { "put": { "security": [ { @@ -3971,7 +3971,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces": { "get": { "security": [ { @@ -4066,7 +4066,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { "get": { "security": [ { @@ -4245,7 +4245,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { "get": { "security": [ { @@ -4303,7 +4303,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { "get": { "security": [ { @@ -4361,7 +4361,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks": { + "/api/1.0/organizations/{organizationId}/stacks": { "get": { "security": [ { @@ -4472,7 +4472,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { + "/api/1.0/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ { @@ -4520,7 +4520,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/{stackId}": { + "/api/1.0/organizations/{organizationId}/stacks/{stackId}": { "get": { "security": [ { @@ -4651,7 +4651,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/{stackId}/favorite": { + "/api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite": { "post": { "security": [ { @@ -4731,7 +4731,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "/api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config": { "get": { "security": [ { @@ -4775,7 +4775,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/{stackId}/status": { + "/api/1.0/organizations/{organizationId}/stacks/{stackId}/status": { "get": { "security": [ { @@ -4819,7 +4819,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/users": { + "/api/1.0/organizations/{organizationId}/users": { "get": { "security": [ { @@ -4937,7 +4937,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "/api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence": { "get": { "security": [ { @@ -4978,7 +4978,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/users/email/{email}/existence": { + "/api/1.0/organizations/{organizationId}/users/email/{email}/existence": { "get": { "security": [ { @@ -5019,7 +5019,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/users/{accountId}": { + "/api/1.0/organizations/{organizationId}/users/{accountId}": { "get": { "security": [ { @@ -5156,7 +5156,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/users/{accountId}/reset-password": { + "/api/1.0/organizations/{organizationId}/users/{accountId}/reset-password": { "put": { "security": [ { @@ -5197,7 +5197,7 @@ const docTemplate = `{ } } }, - "/stack-templates": { + "/api/1.0/stack-templates": { "get": { "security": [ { @@ -5298,7 +5298,7 @@ const docTemplate = `{ } } }, - "/stack-templates/{stackTemplateId}": { + "/api/1.0/stack-templates/{stackTemplateId}": { "get": { "security": [ { @@ -9149,7 +9149,7 @@ const docTemplate = `{ var SwaggerInfo = &swag.Spec{ Version: "1.0", Host: "tks-api-dev.taco-cat.xyz", - BasePath: "/api/1.0/", + BasePath: "/", Schemes: []string{}, Title: "tks-api service", Description: "This is backend api service for tks platform", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index a2778ccf..b2f2b027 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -14,9 +14,9 @@ "version": "1.0" }, "host": "tks-api-dev.taco-cat.xyz", - "basePath": "/api/1.0/", + "basePath": "/", "paths": { - "/app-groups": { + "/api/1.0/app-groups": { "get": { "security": [ { @@ -157,7 +157,7 @@ } } }, - "/app-groups/{appGroupId}": { + "/api/1.0/app-groups/{appGroupId}": { "get": { "security": [ { @@ -194,7 +194,7 @@ } } }, - "/app-groups/{appGroupId}/applications": { + "/api/1.0/app-groups/{appGroupId}/applications": { "get": { "security": [ { @@ -272,7 +272,7 @@ } } }, - "/auth/find-id/code": { + "/api/1.0/auth/find-id/code": { "post": { "description": "This API allows users to verify their identity for lost id by submitting required information", "consumes": [ @@ -312,7 +312,7 @@ } } }, - "/auth/find-id/verification": { + "/api/1.0/auth/find-id/verification": { "post": { "description": "This API allows users to find their account ID by submitting required information", "consumes": [ @@ -352,7 +352,7 @@ } } }, - "/auth/find-password/code": { + "/api/1.0/auth/find-password/code": { "post": { "description": "This API allows users to verify their identity for lost password by submitting required information", "consumes": [ @@ -392,7 +392,7 @@ } } }, - "/auth/find-password/verification": { + "/api/1.0/auth/find-password/verification": { "post": { "description": "This API allows users to reset their forgotten password by submitting required information", "consumes": [ @@ -429,7 +429,7 @@ } } }, - "/auth/login": { + "/api/1.0/auth/login": { "post": { "description": "login", "consumes": [ @@ -463,7 +463,7 @@ } } }, - "/auth/logout": { + "/api/1.0/auth/logout": { "post": { "security": [ { @@ -491,7 +491,7 @@ } } }, - "/auth/ping": { + "/api/1.0/auth/ping": { "post": { "description": "ping with token", "consumes": [ @@ -522,7 +522,7 @@ } } }, - "/clusters": { + "/api/1.0/clusters": { "get": { "security": [ { @@ -629,7 +629,7 @@ } } }, - "/clusters/import": { + "/api/1.0/clusters/import": { "post": { "security": [ { @@ -668,7 +668,7 @@ } } }, - "/clusters/{clusterId}": { + "/api/1.0/clusters/{clusterId}": { "get": { "security": [ { @@ -740,7 +740,7 @@ } } }, - "/clusters/{clusterId}/bootstrap-kubeconfig": { + "/api/1.0/clusters/{clusterId}/bootstrap-kubeconfig": { "get": { "security": [ { @@ -794,7 +794,7 @@ } } }, - "/clusters/{clusterId}/install": { + "/api/1.0/clusters/{clusterId}/install": { "post": { "security": [ { @@ -828,7 +828,7 @@ } } }, - "/clusters/{clusterId}/nodes": { + "/api/1.0/clusters/{clusterId}/nodes": { "get": { "security": [ { @@ -865,7 +865,7 @@ } } }, - "/clusters/{clusterId}/site-values": { + "/api/1.0/clusters/{clusterId}/site-values": { "get": { "security": [ { @@ -902,7 +902,7 @@ } } }, - "/organizations": { + "/api/1.0/organizations": { "get": { "security": [ { @@ -1006,7 +1006,7 @@ } } }, - "/organizations/{organizationId}": { + "/api/1.0/organizations/{organizationId}": { "get": { "security": [ { @@ -1122,7 +1122,7 @@ } } }, - "/organizations/{organizationId}/alerts": { + "/api/1.0/organizations/{organizationId}/alerts": { "get": { "security": [ { @@ -1193,7 +1193,7 @@ } } }, - "/organizations/{organizationId}/alerts/{alertId}": { + "/api/1.0/organizations/{organizationId}/alerts/{alertId}": { "get": { "security": [ { @@ -1317,7 +1317,7 @@ } } }, - "/organizations/{organizationId}/alerts/{alertId}/actions": { + "/api/1.0/organizations/{organizationId}/alerts/{alertId}/actions": { "post": { "security": [ { @@ -1351,7 +1351,7 @@ } } }, - "/organizations/{organizationId}/audits": { + "/api/1.0/organizations/{organizationId}/audits": { "get": { "security": [ { @@ -1462,7 +1462,7 @@ } } }, - "/organizations/{organizationId}/audits/{auditId}": { + "/api/1.0/organizations/{organizationId}/audits/{auditId}": { "get": { "security": [ { @@ -1531,7 +1531,7 @@ } } }, - "/organizations/{organizationId}/cloud-accounts": { + "/api/1.0/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ { @@ -1646,7 +1646,7 @@ } } }, - "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { "get": { "security": [ { @@ -1690,7 +1690,7 @@ } } }, - "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { "get": { "security": [ { @@ -1734,7 +1734,7 @@ } } }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { "get": { "security": [ { @@ -1867,7 +1867,7 @@ } } }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { "delete": { "security": [ { @@ -1908,7 +1908,7 @@ } } }, - "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { + "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { "get": { "security": [ { @@ -1952,7 +1952,7 @@ } } }, - "/organizations/{organizationId}/dashboard/charts": { + "/api/1.0/organizations/{organizationId}/dashboard/charts": { "get": { "security": [ { @@ -2009,7 +2009,7 @@ } } }, - "/organizations/{organizationId}/dashboard/charts/{chartType}": { + "/api/1.0/organizations/{organizationId}/dashboard/charts/{chartType}": { "get": { "security": [ { @@ -2067,7 +2067,7 @@ } } }, - "/organizations/{organizationId}/dashboard/resources": { + "/api/1.0/organizations/{organizationId}/dashboard/resources": { "get": { "security": [ { @@ -2104,7 +2104,7 @@ } } }, - "/organizations/{organizationId}/dashboard/stacks": { + "/api/1.0/organizations/{organizationId}/dashboard/stacks": { "get": { "security": [ { @@ -2141,7 +2141,7 @@ } } }, - "/organizations/{organizationId}/my-profile": { + "/api/1.0/organizations/{organizationId}/my-profile": { "get": { "security": [ { @@ -2257,7 +2257,7 @@ } } }, - "/organizations/{organizationId}/my-profile/next-password-change": { + "/api/1.0/organizations/{organizationId}/my-profile/next-password-change": { "put": { "security": [ { @@ -2297,7 +2297,7 @@ } } }, - "/organizations/{organizationId}/my-profile/password": { + "/api/1.0/organizations/{organizationId}/my-profile/password": { "put": { "security": [ { @@ -2340,7 +2340,7 @@ } } }, - "/organizations/{organizationId}/primary-cluster": { + "/api/1.0/organizations/{organizationId}/primary-cluster": { "patch": { "security": [ { @@ -2383,7 +2383,7 @@ } } }, - "/organizations/{organizationId}/projects": { + "/api/1.0/organizations/{organizationId}/projects": { "get": { "security": [ { @@ -2470,7 +2470,7 @@ } } }, - "/organizations/{organizationId}/projects/existence": { + "/api/1.0/organizations/{organizationId}/projects/existence": { "get": { "security": [ { @@ -2520,7 +2520,7 @@ } } }, - "/organizations/{organizationId}/projects/project-roles": { + "/api/1.0/organizations/{organizationId}/projects/project-roles": { "get": { "security": [ { @@ -2563,7 +2563,7 @@ } } }, - "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "/api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { "get": { "security": [ { @@ -2607,7 +2607,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}": { "get": { "security": [ { @@ -2702,7 +2702,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { "get": { "security": [ { @@ -2840,7 +2840,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { "get": { "security": [ { @@ -2891,7 +2891,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { "get": { "security": [ { @@ -2942,7 +2942,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { "get": { "security": [ { @@ -3100,7 +3100,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { "patch": { "security": [ { @@ -3160,7 +3160,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { "get": { "security": [ { @@ -3204,7 +3204,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { "get": { "security": [ { @@ -3255,7 +3255,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { "post": { "security": [ { @@ -3315,7 +3315,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { "patch": { "security": [ { @@ -3375,7 +3375,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { "get": { "security": [ { @@ -3456,7 +3456,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { "get": { "security": [ { @@ -3514,7 +3514,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig": { "get": { "security": [ { @@ -3558,7 +3558,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/members": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/members": { "get": { "security": [ { @@ -3761,7 +3761,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/members/count": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/count": { "get": { "security": [ { @@ -3805,7 +3805,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { "get": { "security": [ { @@ -3905,7 +3905,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { "put": { "security": [ { @@ -3965,7 +3965,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces": { "get": { "security": [ { @@ -4060,7 +4060,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { "get": { "security": [ { @@ -4239,7 +4239,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { "get": { "security": [ { @@ -4297,7 +4297,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { "get": { "security": [ { @@ -4355,7 +4355,7 @@ } } }, - "/organizations/{organizationId}/stacks": { + "/api/1.0/organizations/{organizationId}/stacks": { "get": { "security": [ { @@ -4466,7 +4466,7 @@ } } }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { + "/api/1.0/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ { @@ -4514,7 +4514,7 @@ } } }, - "/organizations/{organizationId}/stacks/{stackId}": { + "/api/1.0/organizations/{organizationId}/stacks/{stackId}": { "get": { "security": [ { @@ -4645,7 +4645,7 @@ } } }, - "/organizations/{organizationId}/stacks/{stackId}/favorite": { + "/api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite": { "post": { "security": [ { @@ -4725,7 +4725,7 @@ } } }, - "/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "/api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config": { "get": { "security": [ { @@ -4769,7 +4769,7 @@ } } }, - "/organizations/{organizationId}/stacks/{stackId}/status": { + "/api/1.0/organizations/{organizationId}/stacks/{stackId}/status": { "get": { "security": [ { @@ -4813,7 +4813,7 @@ } } }, - "/organizations/{organizationId}/users": { + "/api/1.0/organizations/{organizationId}/users": { "get": { "security": [ { @@ -4931,7 +4931,7 @@ } } }, - "/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "/api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence": { "get": { "security": [ { @@ -4972,7 +4972,7 @@ } } }, - "/organizations/{organizationId}/users/email/{email}/existence": { + "/api/1.0/organizations/{organizationId}/users/email/{email}/existence": { "get": { "security": [ { @@ -5013,7 +5013,7 @@ } } }, - "/organizations/{organizationId}/users/{accountId}": { + "/api/1.0/organizations/{organizationId}/users/{accountId}": { "get": { "security": [ { @@ -5150,7 +5150,7 @@ } } }, - "/organizations/{organizationId}/users/{accountId}/reset-password": { + "/api/1.0/organizations/{organizationId}/users/{accountId}/reset-password": { "put": { "security": [ { @@ -5191,7 +5191,7 @@ } } }, - "/stack-templates": { + "/api/1.0/stack-templates": { "get": { "security": [ { @@ -5292,7 +5292,7 @@ } } }, - "/stack-templates/{stackTemplateId}": { + "/api/1.0/stack-templates/{stackTemplateId}": { "get": { "security": [ { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 820b7c37..dddeedec 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1,4 +1,4 @@ -basePath: /api/1.0/ +basePath: / definitions: domain.ActionResponse: properties: @@ -2495,7 +2495,7 @@ info: title: tks-api service version: "1.0" paths: - /app-groups: + /api/1.0/app-groups: delete: consumes: - application/json @@ -2584,7 +2584,7 @@ paths: summary: Install appGroup tags: - AppGroups - /app-groups/{appGroupId}: + /api/1.0/app-groups/{appGroupId}: get: consumes: - application/json @@ -2607,7 +2607,7 @@ paths: summary: Get appGroup detail tags: - AppGroups - /app-groups/{appGroupId}/applications: + /api/1.0/app-groups/{appGroupId}/applications: get: consumes: - application/json @@ -2656,7 +2656,7 @@ paths: summary: Create application tags: - AppGroups - /auth/find-id/code: + /api/1.0/auth/find-id/code: post: consumes: - application/json @@ -2684,7 +2684,7 @@ paths: summary: Request to verify identity for lost id tags: - Auth - /auth/find-id/verification: + /api/1.0/auth/find-id/verification: post: consumes: - application/json @@ -2712,7 +2712,7 @@ paths: summary: Request to find forgotten ID tags: - Auth - /auth/find-password/code: + /api/1.0/auth/find-password/code: post: consumes: - application/json @@ -2740,7 +2740,7 @@ paths: summary: Request to verify identity for lost password tags: - Auth - /auth/find-password/verification: + /api/1.0/auth/find-password/verification: post: consumes: - application/json @@ -2766,7 +2766,7 @@ paths: summary: Request to find forgotten password tags: - Auth - /auth/login: + /api/1.0/auth/login: post: consumes: - application/json @@ -2788,7 +2788,7 @@ paths: summary: login tags: - Auth - /auth/logout: + /api/1.0/auth/logout: post: consumes: - application/json @@ -2805,7 +2805,7 @@ paths: summary: logout tags: - Auth - /auth/ping: + /api/1.0/auth/ping: post: consumes: - application/json @@ -2825,7 +2825,7 @@ paths: summary: ping with token tags: - Auth - /clusters: + /api/1.0/clusters: get: consumes: - application/json @@ -2893,7 +2893,7 @@ paths: summary: Create cluster tags: - Clusters - /clusters/{clusterId}: + /api/1.0/clusters/{clusterId}: delete: consumes: - application/json @@ -2938,7 +2938,7 @@ paths: summary: Get cluster tags: - Clusters - /clusters/{clusterId}/bootstrap-kubeconfig: + /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig: get: consumes: - application/json @@ -2971,7 +2971,7 @@ paths: summary: Create bootstrap kubeconfig for BYOH tags: - Clusters - /clusters/{clusterId}/install: + /api/1.0/clusters/{clusterId}/install: post: consumes: - application/json @@ -2992,7 +2992,7 @@ paths: summary: Install cluster on tks cluster tags: - Clusters - /clusters/{clusterId}/nodes: + /api/1.0/clusters/{clusterId}/nodes: get: consumes: - application/json @@ -3015,7 +3015,7 @@ paths: summary: Get nodes information for BYOH tags: - Clusters - /clusters/{clusterId}/site-values: + /api/1.0/clusters/{clusterId}/site-values: get: consumes: - application/json @@ -3038,7 +3038,7 @@ paths: summary: Get cluster site values for creating tags: - Clusters - /clusters/import: + /api/1.0/clusters/import: post: consumes: - application/json @@ -3062,7 +3062,7 @@ paths: summary: Import cluster tags: - Clusters - /organizations: + /api/1.0/organizations: get: consumes: - application/json @@ -3128,7 +3128,7 @@ paths: summary: Create organization tags: - Organizations - /organizations/{organizationId}: + /api/1.0/organizations/{organizationId}: delete: consumes: - application/json @@ -3201,7 +3201,7 @@ paths: summary: Update organization detail tags: - Organizations - /organizations/{organizationId}/alerts: + /api/1.0/organizations/{organizationId}/alerts: get: consumes: - application/json @@ -3247,7 +3247,7 @@ paths: summary: Get Alerts tags: - Alerts - /organizations/{organizationId}/alerts/{alertId}: + /api/1.0/organizations/{organizationId}/alerts/{alertId}: delete: consumes: - application/json @@ -3326,7 +3326,7 @@ paths: summary: Update Alert tags: - Alerts - /organizations/{organizationId}/alerts/{alertId}/actions: + /api/1.0/organizations/{organizationId}/alerts/{alertId}/actions: post: consumes: - application/json @@ -3347,7 +3347,7 @@ paths: summary: Create alert action tags: - Alerts - /organizations/{organizationId}/audits: + /api/1.0/organizations/{organizationId}/audits: get: consumes: - application/json @@ -3418,7 +3418,7 @@ paths: summary: Create Audit tags: - Audits - /organizations/{organizationId}/audits/{auditId}: + /api/1.0/organizations/{organizationId}/audits/{auditId}: delete: consumes: - application/json @@ -3461,7 +3461,7 @@ paths: summary: Get Audit tags: - Audits - /organizations/{organizationId}/cloud-accounts: + /api/1.0/organizations/{organizationId}/cloud-accounts: get: consumes: - application/json @@ -3535,7 +3535,7 @@ paths: summary: Create CloudAccount tags: - CloudAccounts - /organizations/{organizationId}/cloud-accounts/{cloudAccountId}: + /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}: delete: consumes: - application/json @@ -3620,7 +3620,7 @@ paths: summary: Update CloudAccount tags: - CloudAccounts - /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error: + /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error: delete: consumes: - application/json @@ -3646,7 +3646,7 @@ paths: summary: Delete Force CloudAccount tags: - CloudAccounts - /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota: + /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota: get: consumes: - application/json @@ -3674,7 +3674,7 @@ paths: summary: Get resource quota by cloudAccount tags: - CloudAccounts - /organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence: + /api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence: get: consumes: - application/json @@ -3702,7 +3702,7 @@ paths: summary: Check awsAccountId for cloudAccount tags: - CloudAccounts - /organizations/{organizationId}/cloud-accounts/name/{name}/existence: + /api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence: get: consumes: - application/json @@ -3730,7 +3730,7 @@ paths: summary: Check name for cloudAccount tags: - CloudAccounts - /organizations/{organizationId}/dashboard/charts: + /api/1.0/organizations/{organizationId}/dashboard/charts: get: consumes: - application/json @@ -3767,7 +3767,7 @@ paths: summary: Get charts data tags: - Dashboards - /organizations/{organizationId}/dashboard/charts/{chartType}: + /api/1.0/organizations/{organizationId}/dashboard/charts/{chartType}: get: consumes: - application/json @@ -3805,7 +3805,7 @@ paths: summary: Get chart data tags: - Dashboards - /organizations/{organizationId}/dashboard/resources: + /api/1.0/organizations/{organizationId}/dashboard/resources: get: consumes: - application/json @@ -3828,7 +3828,7 @@ paths: summary: Get resources tags: - Dashboards - /organizations/{organizationId}/dashboard/stacks: + /api/1.0/organizations/{organizationId}/dashboard/stacks: get: consumes: - application/json @@ -3851,7 +3851,7 @@ paths: summary: Get stacks tags: - Dashboards - /organizations/{organizationId}/my-profile: + /api/1.0/organizations/{organizationId}/my-profile: delete: consumes: - application/json @@ -3924,7 +3924,7 @@ paths: summary: Update my profile detail tags: - My-profile - /organizations/{organizationId}/my-profile/next-password-change: + /api/1.0/organizations/{organizationId}/my-profile/next-password-change: put: consumes: - application/json @@ -3949,7 +3949,7 @@ paths: summary: Update user's password expired date to current date tags: - My-profile - /organizations/{organizationId}/my-profile/password: + /api/1.0/organizations/{organizationId}/my-profile/password: put: consumes: - application/json @@ -3976,7 +3976,7 @@ paths: summary: Update user password detail tags: - My-profile - /organizations/{organizationId}/primary-cluster: + /api/1.0/organizations/{organizationId}/primary-cluster: patch: consumes: - application/json @@ -4003,7 +4003,7 @@ paths: summary: Update primary cluster tags: - Organizations - /organizations/{organizationId}/projects: + /api/1.0/organizations/{organizationId}/projects: get: consumes: - application/json @@ -4058,7 +4058,7 @@ paths: summary: Create new project tags: - Projects - /organizations/{organizationId}/projects/{projectId}: + /api/1.0/organizations/{organizationId}/projects/{projectId}: get: consumes: - application/json @@ -4119,7 +4119,7 @@ paths: summary: Update project tags: - Projects - /organizations/{organizationId}/projects/{projectId}/app-serve-apps: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps: get: consumes: - application/json @@ -4209,7 +4209,7 @@ paths: summary: Install appServeApp tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}: delete: consumes: - application/json @@ -4312,7 +4312,7 @@ paths: summary: Update appServeApp tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint: patch: consumes: - application/json @@ -4351,7 +4351,7 @@ paths: summary: Update app endpoint tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist: get: consumes: - application/json @@ -4379,7 +4379,7 @@ paths: summary: Get appServeApp tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task: get: consumes: - application/json @@ -4412,7 +4412,7 @@ paths: summary: Get latest task from appServeApp tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback: post: consumes: - application/json @@ -4451,7 +4451,7 @@ paths: summary: Rollback appServeApp tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status: patch: consumes: - application/json @@ -4490,7 +4490,7 @@ paths: summary: Update app status tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks: get: consumes: - application/json @@ -4543,7 +4543,7 @@ paths: summary: Get appServeAppTask list tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}: get: consumes: - application/json @@ -4581,7 +4581,7 @@ paths: summary: Get task detail from appServeApp tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/count: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count: get: consumes: - application/json @@ -4614,7 +4614,7 @@ paths: summary: Get number of apps on given stack tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence: + /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence: get: consumes: - application/json @@ -4647,7 +4647,7 @@ paths: summary: Check duplicate appServeAppName tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/kubeconfig: + /api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig: get: consumes: - application/json @@ -4675,7 +4675,7 @@ paths: summary: Get project kubeconfig tags: - Projects - /organizations/{organizationId}/projects/{projectId}/members: + /api/1.0/organizations/{organizationId}/projects/{projectId}/members: delete: consumes: - application/json @@ -4807,7 +4807,7 @@ paths: summary: Update project member Role tags: - Projects - /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}: + /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}: delete: consumes: - application/json @@ -4872,7 +4872,7 @@ paths: summary: Get project member tags: - Projects - /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role: + /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role: put: consumes: - application/json @@ -4911,7 +4911,7 @@ paths: summary: Update project member Role tags: - Projects - /organizations/{organizationId}/projects/{projectId}/members/count: + /api/1.0/organizations/{organizationId}/projects/{projectId}/members/count: get: consumes: - application/json @@ -4939,7 +4939,7 @@ paths: summary: Get project member count group by project role tags: - Projects - /organizations/{organizationId}/projects/{projectId}/namespaces: + /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces: get: consumes: - application/json @@ -5000,7 +5000,7 @@ paths: summary: Create project namespace tags: - Projects - /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}: + /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}: delete: consumes: - application/json @@ -5118,7 +5118,7 @@ paths: summary: Update project namespace tags: - Projects - /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence: + /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence: get: consumes: - application/json @@ -5156,7 +5156,7 @@ paths: summary: Check project namespace exist tags: - Projects - /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources: + /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources: get: consumes: - application/json @@ -5194,7 +5194,7 @@ paths: summary: Get k8s resources for project namespace tags: - Projects - /organizations/{organizationId}/projects/existence: + /api/1.0/organizations/{organizationId}/projects/existence: get: consumes: - application/json @@ -5226,7 +5226,7 @@ paths: summary: Check project name exist tags: - Projects - /organizations/{organizationId}/projects/project-roles: + /api/1.0/organizations/{organizationId}/projects/project-roles: get: consumes: - application/json @@ -5254,7 +5254,7 @@ paths: summary: Get project roles tags: - Projects - /organizations/{organizationId}/projects/project-roles/{projectRoleId}: + /api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId}: get: consumes: - application/json @@ -5282,7 +5282,7 @@ paths: summary: Get project role tags: - Projects - /organizations/{organizationId}/stacks: + /api/1.0/organizations/{organizationId}/stacks: get: consumes: - application/json @@ -5353,7 +5353,7 @@ paths: summary: Create Stack tags: - Stacks - /organizations/{organizationId}/stacks/{stackId}: + /api/1.0/organizations/{organizationId}/stacks/{stackId}: delete: consumes: - application/json @@ -5437,7 +5437,7 @@ paths: summary: Update Stack tags: - Stacks - /organizations/{organizationId}/stacks/{stackId}/favorite: + /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite: delete: consumes: - application/json @@ -5488,7 +5488,7 @@ paths: summary: Set favorite stack tags: - Stacks - /organizations/{organizationId}/stacks/{stackId}/kube-config: + /api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config: get: consumes: - application/json @@ -5516,7 +5516,7 @@ paths: summary: Get KubeConfig by stack tags: - Stacks - /organizations/{organizationId}/stacks/{stackId}/status: + /api/1.0/organizations/{organizationId}/stacks/{stackId}/status: get: consumes: - application/json @@ -5544,7 +5544,7 @@ paths: summary: Get Stack Status tags: - Stacks - /organizations/{organizationId}/stacks/name/{name}/existence: + /api/1.0/organizations/{organizationId}/stacks/name/{name}/existence: get: consumes: - application/json @@ -5575,7 +5575,7 @@ paths: summary: Check name for stack tags: - Stacks - /organizations/{organizationId}/users: + /api/1.0/organizations/{organizationId}/users: get: consumes: - application/json @@ -5651,7 +5651,7 @@ paths: summary: Create user tags: - Users - /organizations/{organizationId}/users/{accountId}: + /api/1.0/organizations/{organizationId}/users/{accountId}: delete: consumes: - application/json @@ -5739,7 +5739,7 @@ paths: summary: Update user tags: - Users - /organizations/{organizationId}/users/{accountId}/reset-password: + /api/1.0/organizations/{organizationId}/users/{accountId}/reset-password: put: consumes: - application/json @@ -5766,7 +5766,7 @@ paths: summary: Reset user's password as temporary password by admin tags: - Users - /organizations/{organizationId}/users/account-id/{accountId}/existence: + /api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence: get: description: return true when accountId exists parameters: @@ -5792,7 +5792,7 @@ paths: summary: Get user id existence tags: - Users - /organizations/{organizationId}/users/email/{email}/existence: + /api/1.0/organizations/{organizationId}/users/email/{email}/existence: get: description: return true when email exists parameters: @@ -5818,7 +5818,7 @@ paths: summary: Get user email existence tags: - Users - /stack-templates: + /api/1.0/stack-templates: get: consumes: - application/json @@ -5882,7 +5882,7 @@ paths: summary: Create StackTemplate 'NOT IMPLEMENTED' tags: - StackTemplates - /stack-templates/{stackTemplateId}: + /api/1.0/stack-templates/{stackTemplateId}: delete: consumes: - application/json diff --git a/cmd/server/main.go b/cmd/server/main.go index 13d060cf..a194abf8 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -100,7 +100,7 @@ func init() { // @name Authorization // @host tks-api-dev.taco-cat.xyz -// @BasePath /api/1.0/ +// @BasePath / func main() { log.Info("*** Arguments *** ") for i, s := range viper.AllSettings() { diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index 4e0c78e4..b88964fc 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -84,7 +84,7 @@ func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetAlertsResponse -// @Router /organizations/{organizationId}/alerts [get] +// @Router /api/1.0/organizations/{organizationId}/alerts [get] // @Security JWT func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -155,7 +155,7 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param alertId path string true "alertId" // @Success 200 {object} domain.GetAlertResponse -// @Router /organizations/{organizationId}/alerts/{alertId} [get] +// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [get] // @Security JWT func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -202,7 +202,7 @@ func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param body body domain.UpdateAlertRequest true "Update cloud setting request" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId} [put] +// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [put] // @Security JWT func (h *AlertHandler) UpdateAlert(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("Need implementation")) @@ -217,7 +217,7 @@ func (h *AlertHandler) UpdateAlert(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param alertId path string true "alertId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId} [delete] +// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [delete] // @Security JWT func (h *AlertHandler) DeleteAlert(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("Need implementation")) @@ -241,7 +241,7 @@ func (h *AlertHandler) AlertTest(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId}/actions [post] +// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId}/actions [post] // @Security JWT func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 84a22bee..8d60c7bc 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -32,7 +32,7 @@ func NewAppGroupHandler(h usecase.Usecase) *AppGroupHandler { // @Produce json // @Param body body domain.CreateAppGroupRequest true "create appgroup request" // @Success 200 {object} domain.CreateAppGroupResponse -// @Router /app-groups [post] +// @Router /api/1.0/app-groups [post] // @Security JWT func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) { input := domain.CreateAppGroupRequest{} @@ -72,7 +72,7 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetAppGroupsResponse -// @Router /app-groups [get] +// @Router /api/1.0/app-groups [get] // @Security JWT func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -114,7 +114,7 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param appGroupId path string true "appGroupId" // @Success 200 {object} domain.GetAppGroupResponse -// @Router /app-groups/{appGroupId} [get] +// @Router /api/1.0/app-groups/{appGroupId} [get] // @Security JWT func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -150,7 +150,7 @@ func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param object body string true "body" // @Success 200 {object} nil -// @Router /app-groups [delete] +// @Router /api/1.0/app-groups [delete] // @Security JWT func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -185,7 +185,7 @@ func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) // @Param appGroupId path string true "appGroupId" // @Param applicationType query string true "applicationType" // @Success 200 {object} domain.GetApplicationsResponse -// @Router /app-groups/{appGroupId}/applications [get] +// @Router /api/1.0/app-groups/{appGroupId}/applications [get] // @Security JWT func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -236,7 +236,7 @@ func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request // @Produce json // @Param object body domain.CreateApplicationRequest true "body" // @Success 200 {object} nil -// @Router /app-groups/{appGroupId}/applications [post] +// @Router /api/1.0/app-groups/{appGroupId}/applications [post] // @Security JWT func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 75b20722..3ab28a32 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -87,7 +87,7 @@ func NewAppServeAppHandler(h usecase.Usecase) *AppServeAppHandler { // @Param projectId path string true "Project ID" // @Param object body domain.CreateAppServeAppRequest true "Request body to create app" // @Success 200 {object} string -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [post] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps [post] // @Security JWT func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -229,7 +229,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.AppServeApp -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -281,7 +281,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ // @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} domain.GetAppServeAppResponse -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Request) { ////////////////////////////////////////////////////////////////////////////////////////// @@ -344,7 +344,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque // @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} domain.GetAppServeAppTaskResponse -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -388,7 +388,7 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * // @Param projectId path string true "Project ID" // @Param stackId query string true "Stack ID" // @Success 200 {object} int64 -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/count [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count [get] // @Security JWT func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -430,7 +430,7 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.AppServeApp -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -477,7 +477,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r // @Param appId path string true "App ID" // @Param taskId path string true "Task ID" // @Success 200 {object} domain.GetAppServeAppTaskResponse -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId} [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId} [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -643,7 +643,7 @@ func makeStage(task *domain.AppServeAppTask, app *domain.AppServeApp, pl string) // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} bool -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist [get] // @Security JWT func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -685,7 +685,7 @@ func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.R // @Param projectId path string true "Project ID" // @Param name path string true "name" // @Success 200 {object} bool -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence [get] // @Security JWT func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -726,7 +726,7 @@ func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *ht // @Param appId path string true "App ID" // @Param object body domain.UpdateAppServeAppRequest true "Request body to update app" // @Success 200 {object} string -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [put] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [put] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -836,7 +836,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re // @Param appId path string true "App ID" // @Param body body domain.UpdateAppServeAppStatusRequest true "Request body to update app status" // @Success 200 {object} string -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status [patch] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status [patch] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -880,7 +880,7 @@ func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *h // @Param appId path string true "appId" // @Param body body domain.UpdateAppServeAppEndpointRequest true "Request body to update app endpoint" // @Success 200 {object} string -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint [patch] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint [patch] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -928,7 +928,7 @@ func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r // @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} string -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [delete] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [delete] // @Security JWT func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -966,7 +966,7 @@ func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Re // @Param appId path string true "App ID" // @Param object body domain.RollbackAppServeAppRequest true "Request body to rollback app" // @Success 200 {object} string -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback [post] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback [post] // @Security JWT func (h *AppServeAppHandler) RollbackAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index a262445e..7871fe88 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -33,7 +33,7 @@ func NewAuditHandler(h usecase.Usecase) *AuditHandler { // @Produce json // @Param body body domain.CreateAuditRequest true "create audit request" // @Success 200 {object} domain.CreateAuditResponse -// @Router /organizations/{organizationId}/audits [post] +// @Router /api/1.0/organizations/{organizationId}/audits [post] // @Security JWT func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) @@ -52,7 +52,7 @@ func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { // @Param filter query []string false "filters" // @Param or query []string false "filters" // @Success 200 {object} domain.GetAuditsResponse -// @Router /organizations/{organizationId}/audits [get] +// @Router /api/1.0/organizations/{organizationId}/audits [get] // @Security JWT func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -93,7 +93,7 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} domain.GetAuditResponse -// @Router /organizations/{organizationId}/audits/{auditId} [get] +// @Router /api/1.0/organizations/{organizationId}/audits/{auditId} [get] // @Security JWT func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -133,7 +133,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/audits/{auditId} [delete] +// @Router /api/1.0/organizations/{organizationId}/audits/{auditId} [delete] // @Security JWT func (h *AuditHandler) DeleteAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 07c89240..c44247de 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -48,7 +48,7 @@ func NewAuthHandler(h usecase.Usecase) IAuthHandler { // @Produce json // @Param body body domain.LoginRequest true "account info" // @Success 200 {object} domain.LoginResponse "user detail" -// @Router /auth/login [post] +// @Router /api/1.0/auth/login [post] func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { input := domain.LoginRequest{} err := UnmarshalRequestInput(r, &input) @@ -111,7 +111,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Success 200 {object} domain.LogoutResponse -// @Router /auth/logout [post] +// @Router /api/1.0/auth/logout [post] // @Security JWT func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -172,7 +172,7 @@ func (h *AuthHandler) RefreshToken(w http.ResponseWriter, r *http.Request) { // @Param body body domain.FindIdRequest true "Request body for finding the account ID including {organization ID, email, username, 6 digit code}" // @Success 200 {object} domain.FindIdResponse // @Failure 400 {object} httpErrors.RestError -// @Router /auth/find-id/verification [post] +// @Router /api/1.0/auth/find-id/verification [post] func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { input := domain.FindIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -203,7 +203,7 @@ func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { // @Param body body domain.FindPasswordRequest true "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}" // @Success 200 // @Failure 400 {object} httpErrors.RestError -// @Router /auth/find-password/verification [post] +// @Router /api/1.0/auth/find-password/verification [post] func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { input := domain.FindPasswordRequest{} err := UnmarshalRequestInput(r, &input) @@ -231,7 +231,7 @@ func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { // @Param body body domain.VerifyIdentityForLostIdRequest true "Request body for verifying identity for lost id including {organization ID, email, username}" // @Success 200 {object} domain.VerifyIdentityForLostIdResponse // @Failure 400 {object} httpErrors.RestError -// @Router /auth/find-id/code [post] +// @Router /api/1.0/auth/find-id/code [post] func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Request) { input := domain.VerifyIdentityForLostIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -261,7 +261,7 @@ func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Req // @Param body body domain.VerifyIdentityForLostPasswordRequest true "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}" // @Success 200 {object} domain.VerifyIdentityForLostPasswordResponse // @Failure 400 {object} httpErrors.RestError -// @Router /auth/find-password/code [post] +// @Router /api/1.0/auth/find-password/code [post] func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *http.Request) { input := domain.VerifyIdentityForLostPasswordRequest{} err := UnmarshalRequestInput(r, &input) @@ -290,7 +290,7 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht // @Produce json // @Param body body domain.PingTokenRequest true "token info" // @Success 200 {object} nil -// @Router /auth/ping [post] +// @Router /api/1.0/auth/ping [post] func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { input := domain.PingTokenRequest{} err := UnmarshalRequestInput(r, &input) @@ -315,7 +315,7 @@ func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { // @Description verify token // @Success 200 {object} nil // @Failure 401 {object} nil -// @Router /auth/verify-token [get] +// @Router /api/1.0/auth/verify-token [get] func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { token, ok := request.TokenFrom(r.Context()) diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 0548625e..c9b6315d 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -35,7 +35,7 @@ func NewCloudAccountHandler(h usecase.Usecase) *CloudAccountHandler { // @Param organizationId path string true "organizationId" // @Param body body domain.CreateCloudAccountRequest true "create cloud setting request" // @Success 200 {object} domain.CreateCloudAccountResponse -// @Router /organizations/{organizationId}/cloud-accounts [post] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts [post] // @Security JWT func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -83,7 +83,7 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetCloudAccountsResponse -// @Router /organizations/{organizationId}/cloud-accounts [get] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts [get] // @Security JWT func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -126,7 +126,7 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re // @Param organizationId path string true "organizationId" // @Param cloudAccountId path string true "cloudAccountId" // @Success 200 {object} domain.GetCloudAccountResponse -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [get] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [get] // @Security JWT func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -165,7 +165,7 @@ func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Req // @Param organizationId path string true "organizationId" // @Param body body domain.UpdateCloudAccountRequest true "Update cloud setting request" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [put] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [put] // @Security JWT func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -220,7 +220,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. // @Param body body domain.DeleteCloudAccountRequest true "Delete cloud setting request" // @Param cloudAccountId path string true "cloudAccountId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [delete] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [delete] // @Security JWT func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -267,7 +267,7 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. // @Param organizationId path string true "organizationId" // @Param cloudAccountId path string true "cloudAccountId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error [delete] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error [delete] // @Security JWT func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -301,7 +301,7 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * // @Param organizationId path string true "organizationId" // @Param name path string true "name" // @Success 200 {object} domain.CheckCloudAccountNameResponse -// @Router /organizations/{organizationId}/cloud-accounts/name/{name}/existence [GET] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence [GET] // @Security JWT func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *http.Request) { user, ok := request.UserFrom(r.Context()) @@ -343,7 +343,7 @@ func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *ht // @Param organizationId path string true "organizationId" // @Param awsAccountId path string true "awsAccountId" // @Success 200 {object} domain.CheckCloudAccountAwsAccountIdResponse -// @Router /organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence [GET] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence [GET] // @Security JWT func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -379,7 +379,7 @@ func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.R // @Param organizationId path string true "organizationId" // @Param cloudAccountId path string true "cloudAccountId" // @Success 200 {object} domain.GetCloudAccountResourceQuotaResponse -// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota [GET] +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota [GET] // @Security JWT func (h *CloudAccountHandler) GetResourceQuota(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index e953cf84..528dcefe 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -37,7 +37,7 @@ func NewClusterHandler(h usecase.Usecase) *ClusterHandler { // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetClustersResponse -// @Router /clusters [get] +// @Router /api/1.0/clusters [get] // @Security JWT func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -74,7 +74,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} domain.Cluster -// @Router /clusters/{clusterId} [get] +// @Router /api/1.0/clusters/{clusterId} [get] // @Security JWT func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -106,7 +106,7 @@ func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} domain.ClusterSiteValuesResponse -// @Router /clusters/{clusterId}/site-values [get] +// @Router /api/1.0/clusters/{clusterId}/site-values [get] // @Security JWT func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -136,7 +136,7 @@ func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Req // @Produce json // @Param body body domain.CreateClusterRequest true "create cluster request" // @Success 200 {object} domain.CreateClusterResponse -// @Router /clusters [post] +// @Router /api/1.0/clusters [post] // @Security JWT func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { input := domain.CreateClusterRequest{} @@ -195,7 +195,7 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param body body domain.ImportClusterRequest true "import cluster request" // @Success 200 {object} domain.ImportClusterResponse -// @Router /clusters/import [post] +// @Router /api/1.0/clusters/import [post] // @Security JWT func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { input := domain.ImportClusterRequest{} @@ -237,7 +237,7 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} nil -// @Router /clusters/{clusterId}/install [post] +// @Router /api/1.0/clusters/{clusterId}/install [post] // @Security JWT func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -264,7 +264,7 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} domain.Cluster -// @Router /clusters/{clusterId} [delete] +// @Router /api/1.0/clusters/{clusterId} [delete] // @Security JWT func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -290,7 +290,7 @@ func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Success 200 {object} domain.CreateBootstrapKubeconfigResponse -// @Router /clusters/{clusterId}/bootstrap-kubeconfig [post] +// @Router /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig [post] // @Security JWT func (h *ClusterHandler) CreateBootstrapKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -318,7 +318,7 @@ func (h *ClusterHandler) CreateBootstrapKubeconfig(w http.ResponseWriter, r *htt // @Accept json // @Produce json // @Success 200 {object} domain.GetBootstrapKubeconfigResponse -// @Router /clusters/{clusterId}/bootstrap-kubeconfig [get] +// @Router /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig [get] // @Security JWT func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -348,7 +348,7 @@ func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.R // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} domain.GetClusterNodesResponse -// @Router /clusters/{clusterId}/nodes [get] +// @Router /api/1.0/clusters/{clusterId}/nodes [get] // @Security JWT func (h *ClusterHandler) GetNodes(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index babc03ae..ef1ba0d7 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -34,7 +34,7 @@ func NewDashboardHandler(h usecase.Usecase) *DashboardHandler { // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardChartsResponse -// @Router /organizations/{organizationId}/dashboard/charts [get] +// @Router /api/1.0/organizations/{organizationId}/dashboard/charts [get] // @Security JWT func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -93,7 +93,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardChartResponse -// @Router /organizations/{organizationId}/dashboard/charts/{chartType} [get] +// @Router /api/1.0/organizations/{organizationId}/dashboard/charts/{chartType} [get] // @Security JWT func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -166,7 +166,7 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetDashboardStacksResponse -// @Router /organizations/{organizationId}/dashboard/stacks [get] +// @Router /api/1.0/organizations/{organizationId}/dashboard/stacks [get] // @Security JWT func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -207,7 +207,7 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetDashboardResourcesResponse -// @Router /organizations/{organizationId}/dashboard/resources [get] +// @Router /api/1.0/organizations/{organizationId}/dashboard/resources [get] // @Security JWT func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 038a1a1e..569d5145 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -34,7 +34,7 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { // @Produce json // @Param body body domain.CreateOrganizationRequest true "create organization request" // @Success 200 {object} object -// @Router /organizations [post] +// @Router /api/1.0/organizations [post] // @Security JWT func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http.Request) { input := domain.CreateOrganizationRequest{} @@ -87,7 +87,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.ListOrganizationBody -// @Router /organizations [get] +// @Router /api/1.0/organizations [get] // @Security JWT func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -126,7 +126,7 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetOrganizationResponse -// @Router /organizations/{organizationId} [get] +// @Router /api/1.0/organizations/{organizationId} [get] // @Security JWT func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -163,7 +163,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.Organization -// @Router /organizations/{organizationId} [delete] +// @Router /api/1.0/organizations/{organizationId} [delete] // @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -211,7 +211,7 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. // @Param organizationId path string true "organizationId" // @Param body body domain.UpdateOrganizationRequest true "update organization request" // @Success 200 {object} domain.UpdateOrganizationResponse -// @Router /organizations/{organizationId} [put] +// @Router /api/1.0/organizations/{organizationId} [put] // @Security JWT func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -256,7 +256,7 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. // @Param organizationId path string true "organizationId" // @Param body body domain.UpdatePrimaryClusterRequest true "update primary cluster request" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/primary-cluster [patch] +// @Router /api/1.0/organizations/{organizationId}/primary-cluster [patch] // @Security JWT func (h *OrganizationHandler) UpdatePrimaryCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 321d20ce..dc11d64b 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -72,7 +72,7 @@ func NewProjectHandler(u usecase.Usecase) IProjectHandler { // @Param organizationId path string true "Organization ID" // @Param request body domain.CreateProjectRequest true "Request body to create project" // @Success 200 {object} domain.CreateProjectResponse -// @Router /organizations/{organizationId}/projects [post] +// @Router /api/1.0/organizations/{organizationId}/projects [post] // @Security JWT func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -151,7 +151,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param query query string false "(all | only)" // @Success 200 {object} domain.GetProjectsResponse -// @Router /organizations/{organizationId}/projects [get] +// @Router /api/1.0/organizations/{organizationId}/projects [get] // @Security JWT func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -203,7 +203,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} domain.GetProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId} [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId} [get] // @Security JWT func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -279,7 +279,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { // @Param type query string false "type (name)" // @Param value query string true "value (project name)" // @Success 200 {object} domain.CheckExistedResponse -// @Router /organizations/{organizationId}/projects/existence [get] +// @Router /api/1.0/organizations/{organizationId}/projects/existence [get] // @Security JWT func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -315,7 +315,7 @@ func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Reques // @Param projectId path string true "Project ID" // @Param request body domain.UpdateProjectRequest true "Request body to update project" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId} [put] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId} [put] // @Security JWT func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -381,7 +381,7 @@ func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param projectRoleId path string true "Project Role ID" // @Success 200 {object} domain.GetProjectRoleResponse -// @Router /organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] +// @Router /api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] // @Security JWT func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -423,7 +423,7 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" // @Success 200 {object} domain.GetProjectRolesResponse -// @Router /organizations/{organizationId}/projects/project-roles [get] +// @Router /api/1.0/organizations/{organizationId}/projects/project-roles [get] // @Security JWT func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -468,7 +468,7 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) // @Param projectId path string true "Project ID" // @Param request body domain.AddProjectMemberRequest true "Request body to add project member" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members [post] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [post] // @Security JWT func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -566,7 +566,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" // @Success 200 {object} domain.GetProjectMemberResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] // @Security JWT func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -633,7 +633,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) // @Param projectId path string true "Project ID" // @Param query query string false "project member search by query (query=all), (query=leader), (query=member), (query=viewer)" // @Success 200 {object} domain.GetProjectMembersResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [get] // @Security JWT func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -720,7 +720,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} domain.GetProjectMemberCountResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members/count [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/count [get] // @Security JWT func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -763,7 +763,7 @@ func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Req // @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] // @Security JWT func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -828,7 +828,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque // @Param projectId path string true "Project ID" // @Param request body domain.RemoveProjectMemberRequest true "Request body to remove project member" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members [delete] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [delete] // @Security JWT func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -896,7 +896,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // @Param projectMemberId path string true "Project Member ID" // @Param request body domain.UpdateProjectMemberRoleRequest true "Request body to update project member role" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] // @Security JWT func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -992,7 +992,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R // @Param projectId path string true "Project ID" // @Param request body domain.UpdateProjectMembersRoleRequest true "Request body to update project member role" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/members [put] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [put] // @Security JWT func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1083,7 +1083,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. // @Param projectId path string true "Project ID" // @Param request body domain.CreateProjectNamespaceRequest true "Request body to create project namespace" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces [post] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [post] // @Security JWT func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1146,7 +1146,7 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re // @Param stackId path string true "Project Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} domain.CheckExistedResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence [get] // @Security JWT func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1196,7 +1196,7 @@ func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.R // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} domain.GetProjectNamespacesResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1263,7 +1263,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ // @Param projectNamespace path string true "Project Namespace" // @Param stackId path string true "Project Stack ID" // @Success 200 {object} domain.GetProjectNamespaceResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [get] // @Security JWT func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1338,7 +1338,7 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque // @Param stackId path string true "Project Stack ID" // @Param request body domain.UpdateProjectNamespaceRequest true "Request body to update project namespace" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] // @Security JWT func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1404,7 +1404,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} domain.CommonProjectResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] // @Security JWT func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { @@ -1480,7 +1480,7 @@ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r * // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} domain.GetProjectKubeconfigResponse -// @Router /organizations/{organizationId}/projects/{projectId}/kubeconfig [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig [get] // @Security JWT func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1523,7 +1523,7 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} domain.GetProjectNamespaceK8sResourcesResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources [get] +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 419a48e6..79952471 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -34,7 +34,7 @@ func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { // @Produce json // @Param body body domain.CreateStackTemplateRequest true "create stack template request" // @Success 200 {object} domain.CreateStackTemplateResponse -// @Router /stack-templates [post] +// @Router /api/1.0/stack-templates [post] // @Security JWT func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) @@ -52,7 +52,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetStackTemplatesResponse -// @Router /stack-templates [get] +// @Router /api/1.0/stack-templates [get] // @Security JWT func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -91,7 +91,7 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. // @Produce json // @Param stackTemplateId path string true "stackTemplateId" // @Success 200 {object} domain.GetStackTemplateResponse -// @Router /stack-templates/{stackTemplateId} [get] +// @Router /api/1.0/stack-templates/{stackTemplateId} [get] // @Security JWT func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -134,7 +134,7 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R // @Produce json // @Param body body domain.UpdateStackTemplateRequest true "Update stack template request" // @Success 200 {object} nil -// @Router /stack-templates/{stackTemplateId} [put] +// @Router /api/1.0/stack-templates/{stackTemplateId} [put] // @Security JWT func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *http.Request) { /* @@ -175,7 +175,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt // @Produce json // @Param stackTemplateId path string true "stackTemplateId" // @Success 200 {object} nil -// @Router /stack-templates/{stackTemplateId} [delete] +// @Router /api/1.0/stack-templates/{stackTemplateId} [delete] // @Security JWT func (h *StackTemplateHandler) DeleteStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 225a678d..480ae3bf 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -33,7 +33,7 @@ func NewStackHandler(h usecase.Usecase) *StackHandler { // @Param organizationId path string true "organizationId" // @Param body body domain.CreateStackRequest true "create cloud setting request" // @Success 200 {object} domain.CreateStackResponse -// @Router /organizations/{organizationId}/stacks [post] +// @Router /api/1.0/organizations/{organizationId}/stacks [post] // @Security JWT func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -101,7 +101,7 @@ func (h *StackHandler) InstallStack(w http.ResponseWriter, r *http.Request) { // @Param sortOrder query string false "sortOrder" // @Param combinedFilter query string false "combinedFilter" // @Success 200 {object} domain.GetStacksResponse -// @Router /organizations/{organizationId}/stacks [get] +// @Router /api/1.0/organizations/{organizationId}/stacks [get] // @Security JWT func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -149,7 +149,7 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} domain.GetStackResponse -// @Router /organizations/{organizationId}/stacks/{stackId} [get] +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [get] // @Security JWT func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -187,7 +187,7 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} domain.GetStackStatusResponse -// @Router /organizations/{organizationId}/stacks/{stackId}/status [get] +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/status [get] // @Security JWT func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -226,7 +226,7 @@ func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { // @Param stackId path string true "stackId" // @Param body body domain.UpdateStackRequest true "Update cloud setting request" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/{stackId} [put] +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [put] // @Security JWT func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -280,7 +280,7 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/{stackId} [delete] +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [delete] // @Security JWT func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -319,7 +319,7 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { // @Param stackId path string true "stackId" // @Param name path string true "name" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/name/{name}/existence [GET] +// @Router /api/1.0/organizations/{organizationId}/stacks/name/{name}/existence [GET] // @Security JWT func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -361,7 +361,7 @@ func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "organizationId" // @Success 200 {object} domain.GetStackKubeConfigResponse -// @Router /organizations/{organizationId}/stacks/{stackId}/kube-config [get] +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config [get] // @Security JWT func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -404,7 +404,7 @@ func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/{stackId}/favorite [post] +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite [post] // @Security JWT func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -431,7 +431,7 @@ func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/stacks/{stackId}/favorite [delete] +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite [delete] // @Security JWT func (h *StackHandler) DeleteFavorite(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 1d21bdab..f4463ab5 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -52,7 +52,7 @@ func NewUserHandler(h usecase.Usecase) IUserHandler { // @Param organizationId path string true "organizationId" // @Param body body domain.CreateUserRequest true "create user request" // @Success 200 {object} domain.CreateUserResponse "create user response" -// @Router /organizations/{organizationId}/users [post] +// @Router /api/1.0/organizations/{organizationId}/users [post] // @Security JWT func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -116,7 +116,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 {object} domain.GetUserResponse -// @Router /organizations/{organizationId}/users/{accountId} [get] +// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [get] // @Security JWT func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -165,7 +165,7 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.ListUserBody -// @Router /organizations/{organizationId}/users [get] +// @Router /api/1.0/organizations/{organizationId}/users [get] // @Security JWT func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -208,7 +208,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 {object} domain.User -// @Router /organizations/{organizationId}/users/{accountId} [delete] +// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [delete] // @Security JWT func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -248,7 +248,7 @@ func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { // @Param accountId path string true "accountId" // @Param body body domain.UpdateUserRequest true "input" // @Success 200 {object} domain.UpdateUserResponse -// @Router /organizations/{organizationId}/users/{accountId} [put] +// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [put] // @Security JWT func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -314,7 +314,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 -// @Router /organizations/{organizationId}/users/{accountId}/reset-password [put] +// @Router /api/1.0/organizations/{organizationId}/users/{accountId}/reset-password [put] // @Security JWT func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -346,7 +346,7 @@ func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetMyProfileResponse -// @Router /organizations/{organizationId}/my-profile [get] +// @Router /api/1.0/organizations/{organizationId}/my-profile [get] // @Security JWT func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -379,7 +379,7 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param body body domain.UpdateMyProfileRequest true "Required fields: password due to double-check" // @Success 200 {object} domain.UpdateMyProfileResponse -// @Router /organizations/{organizationId}/my-profile [put] +// @Router /api/1.0/organizations/{organizationId}/my-profile [put] // @Security JWT func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -444,7 +444,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param body body domain.UpdatePasswordRequest true "update user password request" // @Success 200 -// @Router /organizations/{organizationId}/my-profile/password [put] +// @Router /api/1.0/organizations/{organizationId}/my-profile/password [put] // @Security JWT func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -494,7 +494,7 @@ func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Success 200 // @Failure 400 {object} httpErrors.RestError -// @Router /organizations/{organizationId}/my-profile/next-password-change [put] +// @Router /api/1.0/organizations/{organizationId}/my-profile/next-password-change [put] // @Security JWT func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -521,7 +521,7 @@ func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Req // @Param organizationId path string true "organizationId" // @Success 200 // @Failure 400 -// @Router /organizations/{organizationId}/my-profile [delete] +// @Router /api/1.0/organizations/{organizationId}/my-profile [delete] // @Security JWT func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -545,7 +545,7 @@ func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 {object} domain.CheckExistedResponse -// @Router /organizations/{organizationId}/users/account-id/{accountId}/existence [get] +// @Router /api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence [get] // @Security JWT func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -585,7 +585,7 @@ func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "email" // @Success 200 {object} domain.CheckExistedResponse -// @Router /organizations/{organizationId}/users/email/{email}/existence [get] +// @Router /api/1.0/organizations/{organizationId}/users/email/{email}/existence [get] // @Security JWT func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) From d494e46d93bd87381c153ab99476cedf2901ea52 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 7 Feb 2024 17:00:01 +0900 Subject: [PATCH 063/502] improve role mgnt. logic --- internal/delivery/api/endpoint.go | 87 ++++ internal/delivery/http/auth.go | 1 + internal/delivery/http/role.go | 523 +++++++++++++++++++++++ internal/helper/util.go | 8 + internal/middleware/auth/role/default.go | 324 ++++++++++++++ internal/middleware/auth/role/role.go | 37 +- internal/repository/endpoint.go | 140 ++++++ internal/repository/endpoint_test.go | 75 ++++ internal/repository/organization.go | 21 + internal/repository/permission.go | 219 ++++++++++ internal/repository/permission_test.go | 445 +++++++++++++++++++ internal/repository/repository.go | 1 + internal/repository/role.go | 303 +++++++++++++ internal/repository/role_test.go | 28 ++ internal/repository/user.go | 23 +- internal/route/route.go | 13 + internal/usecase/permission.go | 45 ++ internal/usecase/role.go | 126 ++++++ internal/usecase/role_test.go | 217 ++++++++++ internal/usecase/user.go | 8 +- pkg/domain/endpoint.go | 11 + pkg/domain/permmision.go | 18 + pkg/domain/role.go | 109 +++++ pkg/domain/user.go | 9 - 24 files changed, 2750 insertions(+), 41 deletions(-) create mode 100644 internal/delivery/http/role.go create mode 100644 internal/middleware/auth/role/default.go create mode 100644 internal/repository/endpoint.go create mode 100644 internal/repository/endpoint_test.go create mode 100644 internal/repository/permission.go create mode 100644 internal/repository/permission_test.go create mode 100644 internal/repository/role.go create mode 100644 internal/repository/role_test.go create mode 100644 internal/usecase/permission.go create mode 100644 internal/usecase/role.go create mode 100644 internal/usecase/role_test.go create mode 100644 pkg/domain/endpoint.go create mode 100644 pkg/domain/permmision.go create mode 100644 pkg/domain/role.go diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 36edf66a..00cfc5a4 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -156,6 +156,13 @@ const ( GetAudits GetAudit DeleteAudit + + // Role + CreateTksRole + ListTksRoles + GetTksRole + DeleteTksRole + UpdateTksRole ) var ApiMap = map[Endpoint]EndpointInfo{ @@ -635,6 +642,46 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "DeleteAudit", Group: "Audit", }, + CreateTksRole: { + Name: "CreateTksRole", + Group: "Role", + }, + CreateProjectRole: { + Name: "CreateProjectRole", + Group: "Role", + }, + ListTksRoles: { + Name: "ListTksRoles", + Group: "Role", + }, + ListProjectRoles: { + Name: "ListProjectRoles", + Group: "Role", + }, + GetTksRole: { + Name: "GetTksRole", + Group: "Role", + }, + GetProjectRole: { + Name: "GetProjectRole", + Group: "Role", + }, + DeleteTksRole: { + Name: "DeleteTksRole", + Group: "Role", + }, + DeleteProjectRole: { + Name: "DeleteProjectRole", + Group: "Role", + }, + UpdateTksRole: { + Name: "UpdateTksRole", + Group: "Role", + }, + UpdateProjectRole: { + Name: "UpdateProjectRole", + Group: "Role", + }, } func (e Endpoint) String() string { @@ -877,6 +924,26 @@ func (e Endpoint) String() string { return "GetAudit" case DeleteAudit: return "DeleteAudit" + case CreateTksRole: + return "CreateTksRole" + case CreateProjectRole: + return "CreateProjectRole" + case ListTksRoles: + return "ListTksRoles" + case ListProjectRoles: + return "ListProjectRoles" + case GetTksRole: + return "GetTksRole" + case GetProjectRole: + return "GetProjectRole" + case DeleteTksRole: + return "DeleteTksRole" + case DeleteProjectRole: + return "DeleteProjectRole" + case UpdateTksRole: + return "UpdateTksRole" + case UpdateProjectRole: + return "UpdateProjectRole" default: return "" } @@ -1121,6 +1188,26 @@ func GetEndpoint(name string) Endpoint { return GetAudit case "DeleteAudit": return DeleteAudit + case "CreateTksRole": + return CreateTksRole + case "CreateProjectRole": + return CreateProjectRole + case "ListTksRoles": + return ListTksRoles + case "ListProjectRoles": + return ListProjectRoles + case "GetTksRole": + return GetTksRole + case "GetProjectRole": + return GetProjectRole + case "DeleteTksRole": + return DeleteTksRole + case "DeleteProjectRole": + return DeleteProjectRole + case "UpdateTksRole": + return UpdateTksRole + case "UpdateProjectRole": + return UpdateProjectRole default: return -1 } diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index c44247de..a7566312 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -18,6 +18,7 @@ import ( type IAuthHandler interface { Login(w http.ResponseWriter, r *http.Request) Logout(w http.ResponseWriter, r *http.Request) + // Deprecated: PingToken is deprecated. Use VerifyToken instead. PingToken(w http.ResponseWriter, r *http.Request) RefreshToken(w http.ResponseWriter, r *http.Request) FindId(w http.ResponseWriter, r *http.Request) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go new file mode 100644 index 00000000..c254b7ec --- /dev/null +++ b/internal/delivery/http/role.go @@ -0,0 +1,523 @@ +package http + +import ( + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "net/http" +) + +type IRoleHandler interface { + CreateTksRole(w http.ResponseWriter, r *http.Request) + CreateProjectRole(w http.ResponseWriter, r *http.Request) + + ListTksRoles(w http.ResponseWriter, r *http.Request) + ListProjectRoles(w http.ResponseWriter, r *http.Request) + + GetTksRole(w http.ResponseWriter, r *http.Request) + GetProjectRole(w http.ResponseWriter, r *http.Request) + + DeleteTksRole(w http.ResponseWriter, r *http.Request) + DeleteProjectRole(w http.ResponseWriter, r *http.Request) + + UpdateTksRole(w http.ResponseWriter, r *http.Request) + UpdateProjectRole(w http.ResponseWriter, r *http.Request) +} + +type RoleHandler struct { + roleUsecase usecase.IRoleUsecase +} + +func NewRoleHandler(roleUsecase usecase.IRoleUsecase) *RoleHandler { + return &RoleHandler{ + roleUsecase: roleUsecase, + } +} + +// CreateTksRole godoc +// @Tags Role +// @Summary Create Tks Role +// @Description Create Tks Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param body body domain.CreateTksRoleRequest true "Create Tks Role Request" +// @Success 200 {object} domain.CreateTksRoleResponse +// @Router /organizations/{organizationId}/roles [post] + +func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { + // path parameter + var organizationId string + + vars := mux.Vars(r) + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + // request body + input := domain.CreateTksRoleRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // input to dto + dto := domain.TksRole{ + Role: domain.Role{ + OrganizationID: organizationId, + Name: input.Name, + Description: input.Description, + Type: string(domain.RoleTypeTks), + }, + } + + if err := h.roleUsecase.CreateTksRole(&dto); err != nil { + ErrorJSON(w, r, err) + return + } + +} + +// CreateTksRole godoc +// @Tags Role +// @Summary Create Project Role +// @Description Create Project Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param body body domain.CreateProjectRoleRequest true "Create Project Role Request" +// @Success 200 {object} domain.CreateProjectRoleResponse +// @Router /organizations/{organizationId}/projects/{projectId}/roles [post] + +func (h RoleHandler) CreateProjectRole(w http.ResponseWriter, r *http.Request) { + // path parameter + var organizationId, projectId string + + vars := mux.Vars(r) + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + if v, ok := vars["projectId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + projectId = v + } + + // request body + input := domain.CreateProjectRoleRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // input to dto + projectIdUuid, err := uuid.Parse(projectId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + dto := domain.ProjectRole{ + Role: domain.Role{ + OrganizationID: organizationId, + Name: input.Name, + Description: input.Description, + Type: string(domain.RoleTypeProject), + }, + ProjectID: projectIdUuid, + } + + if err := h.roleUsecase.CreateProjectRole(&dto); err != nil { + ErrorJSON(w, r, err) + return + } +} + +// ListTksRoles godoc +// @Tags Role +// @Summary List Tks Roles +// @Description List Tks Roles +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.ListTksRoleResponse +// @Router /organizations/{organizationId}/roles [get] +func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { + // path parameter + var organizationId string + + vars := mux.Vars(r) + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + // query parameter + urlParams := r.URL.Query() + pg, err := pagination.NewPagination(&urlParams) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + // list roles + roles, err := h.roleUsecase.ListTksRoles(organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ListTksRoleResponse + out.Roles = make([]domain.GetTksRoleResponse, len(roles)) + for i, role := range roles { + out.Roles[i] = domain.GetTksRoleResponse{ + ID: role.ID.String(), + Name: role.Name, + OrganizationID: role.OrganizationID, + Description: role.Description, + Creator: role.Creator.String(), + CreatedAt: role.CreatedAt, + UpdatedAt: role.UpdatedAt, + } + } + + if err := serializer.Map(*pg, &out.Pagination); err != nil { + log.InfoWithContext(r.Context(), err) + } + + // response + ResponseJSON(w, r, http.StatusOK, out) +} + +// ListProjectRoles godoc +// @Tags Role +// @Summary List Project Roles +// @Description List Project Roles +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} domain.ListProjectRoleResponse +// @Router /organizations/{organizationId}/projects/{projectId}/roles [get] + +func (h RoleHandler) ListProjectRoles(w http.ResponseWriter, r *http.Request) { + // path parameter + var projectId string + + vars := mux.Vars(r) + if v, ok := vars["projectId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + projectId = v + } + + // query parameter + urlParams := r.URL.Query() + pg, err := pagination.NewPagination(&urlParams) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + // list roles + roles, err := h.roleUsecase.ListProjectRoles(projectId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ListProjectRoleResponse + out.Roles = make([]domain.GetProjectRoleResponse, len(roles)) + for i, role := range roles { + out.Roles[i] = domain.GetProjectRoleResponse{ + ID: role.RoleID.String(), + Name: role.Role.Name, + OrganizationID: role.Role.OrganizationID, + ProjectID: role.ProjectID.String(), + Description: role.Role.Description, + Creator: role.Role.Creator.String(), + CreatedAt: role.Role.CreatedAt, + UpdatedAt: role.Role.UpdatedAt, + } + } + + if err := serializer.Map(*pg, &out.Pagination); err != nil { + log.InfoWithContext(r.Context(), err) + } + + // response + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetTksRole godoc +// @Tags Role +// @Summary Get Tks Role +// @Description Get Tks Role +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 {object} domain.GetTksRoleResponse +// @Router /organizations/{organizationId}/roles/{roleId} [get] + +func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + } else { + roleId = v + } + + // get role + role, err := h.roleUsecase.GetTksRole(roleId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // response + out := domain.GetTksRoleResponse{ + ID: role.ID.String(), + Name: role.Name, + OrganizationID: role.OrganizationID, + Description: role.Description, + Creator: role.Creator.String(), + CreatedAt: role.CreatedAt, + UpdatedAt: role.UpdatedAt, + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetProjectRole godoc +// @Tags Role +// @Summary Get Project Role +// @Description Get Project Role +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param roleId path string true "Role ID" +// @Success 200 {object} domain.GetProjectRoleResponse +// @Router /organizations/{organizationId}/projects/{projectId}/roles/{roleId} [get] + +func (h RoleHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + // get role + role, err := h.roleUsecase.GetProjectRole(roleId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // response + out := domain.GetProjectRoleResponse{ + ID: role.RoleID.String(), + Name: role.Role.Name, + OrganizationID: role.Role.OrganizationID, + ProjectID: role.ProjectID.String(), + Description: role.Role.Description, + Creator: role.Role.Creator.String(), + CreatedAt: role.Role.CreatedAt, + UpdatedAt: role.Role.UpdatedAt, + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// DeleteTksRole godoc +// @Tags Role +// @Summary Delete Tks Role +// @Description Delete Tks Role +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 +// @Router /organizations/{organizationId}/roles/{roleId} [delete] + +func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + // delete role + if err := h.roleUsecase.DeleteTksRole(roleId); err != nil { + ErrorJSON(w, r, err) + return + } + + // response + ResponseJSON(w, r, http.StatusOK, nil) +} + +// DeleteProjectRole godoc +// @Tags Role +// @Summary Delete Project Role +// @Description Delete Project Role +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param roleId path string true "Role ID" +// @Success 200 +// @Router /organizations/{organizationId}/projects/{projectId}/roles/{roleId} [delete] + +func (h RoleHandler) DeleteProjectRole(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + // delete role + if err := h.roleUsecase.DeleteProjectRole(roleId); err != nil { + ErrorJSON(w, r, err) + return + } + + // response + ResponseJSON(w, r, http.StatusOK, nil) +} + +// UpdateTksRole godoc +// @Tags Role +// @Summary Update Tks Role +// @Description Update Tks Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Param body body domain.UpdateTksRoleRequest true "Update Tks Role Request" +// @Success 200 +// @Router /organizations/{organizationId}/roles/{roleId} [put] + +func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + // request body + input := domain.UpdateTksRoleRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // input to dto + roleIdUuid, err := uuid.Parse(roleId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + dto := domain.TksRole{ + Role: domain.Role{ + ID: roleIdUuid, + Name: input.Name, + Description: input.Description, + }, + } + + // update role + if err := h.roleUsecase.UpdateTksRole(&dto); err != nil { + ErrorJSON(w, r, err) + return + } + + // response + ResponseJSON(w, r, http.StatusOK, nil) +} + +// UpdateProjectRole godoc +// @Tags Role +// @Summary Update Project Role +// @Description Update Project Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param roleId path string true "Role ID" +// @Param body body domain.UpdateProjectRoleRequest true "Update Project Role Request" +// @Success 200 +// @Router /organizations/{organizationId}/projects/{projectId}/roles/{roleId} [put] + +func (h RoleHandler) UpdateProjectRole(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + // request body + input := domain.UpdateProjectRoleRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // input to dto + roleIdUuid, err := uuid.Parse(roleId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + dto := domain.ProjectRole{ + Role: domain.Role{ + ID: roleIdUuid, + Name: input.Name, + Description: input.Description, + }, + } + + // update role + if err := h.roleUsecase.UpdateProjectRole(&dto); err != nil { + ErrorJSON(w, r, err) + return + } + + // response + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/helper/util.go b/internal/helper/util.go index 59933cbf..5919d7b7 100644 --- a/internal/helper/util.go +++ b/internal/helper/util.go @@ -91,3 +91,11 @@ func ToSnakeCase(str string) string { snake = matchAllCap.ReplaceAllString(snake, "${1}_${2}") return strings.ToLower(snake) } + +func BoolP(value bool) *bool { + return &value +} + +func UUIDP(value uuid.UUID) *uuid.UUID { + return &value +} diff --git a/internal/middleware/auth/role/default.go b/internal/middleware/auth/role/default.go new file mode 100644 index 00000000..41bf5652 --- /dev/null +++ b/internal/middleware/auth/role/default.go @@ -0,0 +1,324 @@ +package role + +import internalApi "github.com/openinfradev/tks-api/internal/delivery/api" + +var defaults = []*defaultPermission{ + &defaultPermissionOfAdminInMaster, + &defaultPermissionOfUserInMaster, + &defaultPermissionOfAdmin, + &defaultPermissionOfUser, + &defaultLeaderPermission, + &defaultMemberPermission, + &defaultViewerPermission, +} + +func getDefaultPermissions() []*defaultPermission { + return defaults +} + +type defaultPermission struct { + role Role + permissions *[]internalApi.Endpoint +} + +var defaultPermissionOfAdminInMaster = defaultPermission{ + role: Admin, + permissions: &[]internalApi.Endpoint{}, +} + +var defaultPermissionOfUserInMaster = defaultPermission{ + role: User, + permissions: &[]internalApi.Endpoint{}, +} + +var defaultPermissionOfAdmin = defaultPermission{ + role: Admin, + permissions: &[]internalApi.Endpoint{ + // Auth + internalApi.Logout, + internalApi.RefreshToken, + internalApi.VerifyToken, + + // User + internalApi.CreateUser, + internalApi.ListUser, + internalApi.GetUser, + internalApi.DeleteUser, + internalApi.UpdateUser, + internalApi.ResetPassword, + internalApi.CheckId, + internalApi.CheckEmail, + + // MyProfile + internalApi.GetMyProfile, + internalApi.UpdateMyProfile, + internalApi.UpdateMyPassword, + internalApi.RenewPasswordExpiredDate, + internalApi.DeleteMyProfile, + + // Organization + internalApi.CreateOrganization, + internalApi.GetOrganizations, + internalApi.GetOrganization, + internalApi.DeleteOrganization, + internalApi.UpdateOrganization, + + // Cluster + internalApi.UpdatePrimaryCluster, + internalApi.CreateCluster, + internalApi.GetClusters, + internalApi.ImportCluster, + internalApi.GetCluster, + internalApi.DeleteCluster, + internalApi.GetClusterSiteValues, + internalApi.InstallCluster, + internalApi.CreateBootstrapKubeconfig, + internalApi.GetBootstrapKubeconfig, + internalApi.GetNodes, + + // Appgroup + internalApi.CreateAppgroup, + internalApi.GetAppgroups, + internalApi.GetAppgroup, + internalApi.DeleteAppgroup, + internalApi.GetApplications, + internalApi.CreateApplication, + + // AppServeApp + internalApi.CreateAppServeApp, + internalApi.GetAppServeApps, + internalApi.GetNumOfAppsOnStack, + internalApi.GetAppServeApp, + internalApi.GetAppServeAppLatestTask, + internalApi.IsAppServeAppExist, + internalApi.IsAppServeAppNameExist, + internalApi.DeleteAppServeApp, + internalApi.UpdateAppServeApp, + internalApi.UpdateAppServeAppStatus, + internalApi.UpdateAppServeAppEndpoint, + internalApi.RollbackAppServeApp, + + // CloudAccount + internalApi.GetCloudAccounts, + internalApi.CreateCloudAccount, + internalApi.CheckCloudAccountName, + internalApi.CheckAwsAccountId, + internalApi.GetCloudAccount, + internalApi.UpdateCloudAccount, + internalApi.DeleteCloudAccount, + internalApi.DeleteForceCloudAccount, + internalApi.GetResourceQuota, + + // StackTemplate + internalApi.GetStackTemplates, + internalApi.CreateStackTemplate, + internalApi.GetStackTemplate, + internalApi.UpdateStackTemplate, + internalApi.DeleteStackTemplate, + + // Dashboard + internalApi.GetChartsDashboard, + internalApi.GetChartDashboard, + internalApi.GetStacksDashboard, + internalApi.GetResourcesDashboard, + + // Alert + internalApi.CreateAlert, + internalApi.GetAlerts, + internalApi.GetAlert, + internalApi.DeleteAlert, + internalApi.UpdateAlert, + internalApi.CreateAlertAction, + + // Stack + internalApi.GetStacks, + internalApi.CreateStack, + internalApi.CheckStackName, + internalApi.GetStack, + internalApi.UpdateStack, + internalApi.DeleteStack, + internalApi.GetStackKubeConfig, + internalApi.GetStackStatus, + internalApi.SetFavoriteStack, + internalApi.DeleteFavoriteStack, + internalApi.InstallStack, + + // Project + internalApi.CreateProject, + internalApi.GetProjects, + internalApi.GetProject, + internalApi.UpdateProject, + internalApi.DeleteProject, + internalApi.AddProjectMember, + internalApi.GetProjectMembers, + internalApi.RemoveProjectMember, + internalApi.UpdateProjectMemberRole, + internalApi.CreateProjectNamespace, + internalApi.GetProjectNamespaces, + internalApi.GetProjectNamespace, + internalApi.DeleteProjectNamespace, + internalApi.SetFavoriteProject, + internalApi.SetFavoriteProjectNamespace, + internalApi.UnSetFavoriteProject, + internalApi.UnSetFavoriteProjectNamespace, + }, +} + +// TODO: check-up the permission of User +var defaultPermissionOfUser = defaultPermission{ + role: User, + permissions: &[]internalApi.Endpoint{ + // Auth + internalApi.Logout, + internalApi.RefreshToken, + internalApi.VerifyToken, + + // User + internalApi.ListUser, + internalApi.GetUser, + internalApi.CheckId, + internalApi.CheckEmail, + + // MyProfile + internalApi.GetMyProfile, + internalApi.UpdateMyProfile, + internalApi.UpdateMyPassword, + internalApi.RenewPasswordExpiredDate, + internalApi.DeleteMyProfile, + + // Organization + internalApi.GetOrganizations, + internalApi.GetOrganization, + + // Cluster + internalApi.GetClusters, + internalApi.GetCluster, + internalApi.GetClusterSiteValues, + internalApi.GetBootstrapKubeconfig, + internalApi.GetNodes, + + // Appgroup + internalApi.CreateAppgroup, + internalApi.GetAppgroups, + internalApi.GetAppgroup, + internalApi.DeleteAppgroup, + internalApi.GetApplications, + internalApi.CreateApplication, + + // AppServeApp + internalApi.CreateAppServeApp, + internalApi.GetAppServeApps, + internalApi.GetNumOfAppsOnStack, + internalApi.GetAppServeApp, + internalApi.GetAppServeAppLatestTask, + internalApi.IsAppServeAppExist, + internalApi.IsAppServeAppNameExist, + internalApi.DeleteAppServeApp, + internalApi.UpdateAppServeApp, + internalApi.UpdateAppServeAppStatus, + internalApi.UpdateAppServeAppEndpoint, + internalApi.RollbackAppServeApp, + + // CloudAccount + internalApi.GetCloudAccounts, + internalApi.GetCloudAccount, + internalApi.GetResourceQuota, + + // StackTemplate + internalApi.GetStackTemplates, + internalApi.GetStackTemplate, + + // Dashboard + internalApi.GetChartsDashboard, + internalApi.GetChartDashboard, + internalApi.GetStacksDashboard, + internalApi.GetResourcesDashboard, + + // Alert + internalApi.GetAlerts, + internalApi.GetAlert, + + // Stack + internalApi.GetStacks, + internalApi.GetStack, + internalApi.GetStackKubeConfig, + internalApi.GetStackStatus, + internalApi.SetFavoriteStack, + internalApi.DeleteFavoriteStack, + + // Project + internalApi.CreateProject, + internalApi.GetProjects, + internalApi.GetProject, + internalApi.UpdateProject, + internalApi.DeleteProject, + internalApi.AddProjectMember, + internalApi.GetProjectMembers, + internalApi.RemoveProjectMember, + internalApi.UpdateProjectMemberRole, + internalApi.CreateProjectNamespace, + internalApi.GetProjectNamespaces, + internalApi.GetProjectNamespace, + internalApi.DeleteProjectNamespace, + internalApi.SetFavoriteProject, + internalApi.SetFavoriteProjectNamespace, + internalApi.UnSetFavoriteProject, + internalApi.UnSetFavoriteProjectNamespace, + }, +} + +var defaultLeaderPermission = defaultPermission{ + role: leader, + permissions: &[]internalApi.Endpoint{ + // Project + internalApi.CreateProject, + internalApi.GetProjects, + internalApi.GetProject, + internalApi.UpdateProject, + internalApi.DeleteProject, + internalApi.AddProjectMember, + internalApi.GetProjectMembers, + internalApi.RemoveProjectMember, + internalApi.UpdateProjectMemberRole, + internalApi.CreateProjectNamespace, + internalApi.GetProjectNamespaces, + internalApi.GetProjectNamespace, + internalApi.DeleteProjectNamespace, + internalApi.SetFavoriteProject, + internalApi.SetFavoriteProjectNamespace, + internalApi.UnSetFavoriteProject, + internalApi.UnSetFavoriteProjectNamespace, + }, +} + +var defaultMemberPermission = defaultPermission{ + role: member, + permissions: &[]internalApi.Endpoint{ + // Project + internalApi.GetProjects, + internalApi.GetProject, + internalApi.GetProjectMembers, + internalApi.GetProjectNamespaces, + internalApi.GetProjectNamespace, + internalApi.SetFavoriteProject, + internalApi.SetFavoriteProjectNamespace, + internalApi.UnSetFavoriteProject, + internalApi.UnSetFavoriteProjectNamespace, + }, +} + +var defaultViewerPermission = defaultPermission{ + role: viewer, + permissions: &[]internalApi.Endpoint{ + // Project + internalApi.GetProjects, + internalApi.GetProject, + internalApi.GetProjectMembers, + internalApi.GetProjectNamespaces, + internalApi.GetProjectNamespace, + internalApi.SetFavoriteProject, + internalApi.SetFavoriteProjectNamespace, + internalApi.UnSetFavoriteProject, + internalApi.UnSetFavoriteProjectNamespace, + }, +} diff --git a/internal/middleware/auth/role/role.go b/internal/middleware/auth/role/role.go index b8908590..986de7d1 100644 --- a/internal/middleware/auth/role/role.go +++ b/internal/middleware/auth/role/role.go @@ -8,20 +8,34 @@ const ( Admin Role = "admin" User Role = "user" leader Role = "leader" + member Role = "member" + viewer Role = "viewer" ) +func init() { + RBAC = make(map[internalApi.Endpoint]map[Role]struct{}) + + defaultPermissions := getDefaultPermissions() + registerRole(defaultPermissions...) +} + func (r Role) String() string { return string(r) } -var RBAC = map[internalApi.Endpoint][]Role{ - internalApi.CreateProject: {Admin, User, leader}, - internalApi.UpdateProject: {Admin, User, leader}, - internalApi.DeleteProject: {Admin, User, leader}, - internalApi.GetProject: {Admin, User, leader}, - internalApi.GetProjects: {Admin, User, leader}, +func registerRole(dps ...*defaultPermission) { + for _, dp := range dps { + for _, endpoint := range *dp.permissions { + if RBAC[endpoint] == nil { + RBAC[endpoint] = make(map[Role]struct{}) + } + RBAC[endpoint][dp.role] = struct{}{} + } + } } +var RBAC map[internalApi.Endpoint]map[Role]struct{} + func StrToRole(role string) Role { switch role { case "admin": @@ -35,10 +49,13 @@ func StrToRole(role string) Role { } } func IsRoleAllowed(endpoint internalApi.Endpoint, role Role) bool { - for _, r := range RBAC[endpoint] { - if r == role { - return true - } + if RBAC[endpoint] == nil { + return false } + + if _, ok := RBAC[endpoint][role]; ok { + return true + } + return false } diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go new file mode 100644 index 00000000..16fd5968 --- /dev/null +++ b/internal/repository/endpoint.go @@ -0,0 +1,140 @@ +package repository + +import ( + "fmt" + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" + "math" +) + +type IEndpointRepository interface { + Create(endpoint *domain.Endpoint) error + List(pg *pagination.Pagination) ([]*domain.Endpoint, error) + Get(id uuid.UUID) (*domain.Endpoint, error) + Update(endpoint *domain.Endpoint) error + Delete(id uuid.UUID) error +} + +type EndpointRepository struct { + db *gorm.DB +} + +func NewEndpointRepository(db *gorm.DB) *EndpointRepository { + return &EndpointRepository{ + db: db, + } +} + +type Endpoint struct { + gorm.Model + + ID uuid.UUID `gorm:"type:uuid;primary_key;"` + + Name string `gorm:"type:text;not null;unique"` + Group string `gorm:"type:text;"` + PermissionID uuid.UUID `gorm:"type:uuid;"` + Permission Permission `gorm:"foreignKey:PermissionID;"` +} + +func (e *Endpoint) BeforeCreate(tx *gorm.DB) error { + e.ID = uuid.New() + return nil +} + +func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { + obj := &Endpoint{ + Name: endpoint.Name, + Group: endpoint.Group, + PermissionID: endpoint.PermissionID, + } + + if err := e.db.Create(obj).Error; err != nil { + return err + } + + return nil +} + +func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint, error) { + var endpoints []*domain.Endpoint + var objs []*Endpoint + + if pg == nil { + pg = pagination.NewDefaultPagination() + } + filterFunc := CombinedGormFilter("endpoints", pg.GetFilters(), pg.CombinedFilter) + db := filterFunc(e.db.Model(&Endpoint{})) + + db.Count(&pg.TotalRows) + pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) + + orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) + res := db.Preload("Permissions").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + if res.Error != nil { + return nil, res.Error + } + for _, obj := range objs { + endpoints = append(endpoints, &domain.Endpoint{ + ID: obj.ID, + Name: obj.Name, + Group: obj.Group, + PermissionID: obj.PermissionID, + Permission: *ConvertRepoToDomainPermission(&obj.Permission), + }) + } + + return endpoints, nil +} + +func (e *EndpointRepository) Get(id uuid.UUID) (*domain.Endpoint, error) { + var obj Endpoint + + if err := e.db.Preload("Permission").First(&obj, "id = ?", id).Error; err != nil { + return nil, err + } + + return &domain.Endpoint{ + ID: obj.ID, + Name: obj.Name, + Group: obj.Group, + }, nil +} + +func (e *EndpointRepository) Update(endpoint *domain.Endpoint) error { + obj := &Endpoint{ + ID: endpoint.ID, + Name: endpoint.Name, + Group: endpoint.Group, + PermissionID: endpoint.PermissionID, + } + + if err := e.db.Save(obj).Error; err != nil { + return err + } + + return nil +} + +// domain.Endpoint to repository.Endpoint +func ConvertDomainToRepoEndpoint(endpoint *domain.Endpoint) *Endpoint { + return &Endpoint{ + ID: endpoint.ID, + Name: endpoint.Name, + Group: endpoint.Group, + PermissionID: endpoint.PermissionID, + Permission: *ConvertDomainToRepoPermission(&endpoint.Permission), + } +} + +// repository.Endpoint to domain.Endpoint +func ConvertRepoToDomainEndpoint(endpoint *Endpoint) *domain.Endpoint { + return &domain.Endpoint{ + ID: endpoint.ID, + Name: endpoint.Name, + Group: endpoint.Group, + PermissionID: endpoint.PermissionID, + Permission: *ConvertRepoToDomainPermission(&endpoint.Permission), + } +} diff --git a/internal/repository/endpoint_test.go b/internal/repository/endpoint_test.go new file mode 100644 index 00000000..f27a9f06 --- /dev/null +++ b/internal/repository/endpoint_test.go @@ -0,0 +1,75 @@ +package repository_test + +import ( + "fmt" + myRepository "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm_test/config" + "testing" +) + +func TestNewEndpointRepository(t *testing.T) { + conf := config.NewDefaultConfig() + dsn := fmt.Sprintf( + "host=%s dbname=%s user=%s password=%s port=%d sslmode=disable TimeZone=Asia/Seoul", + conf.Address, conf.Database, conf.AdminId, conf.AdminPassword, conf.Port, + ) + + t.Logf("dsn: %s", dsn) + + db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) + if err != nil { + panic(err) + } + + if err = db.AutoMigrate(&myRepository.Endpoint{}); err != nil { + panic(err) + } + + dbClient := myRepository.NewEndpointRepository(db) + + // create + endpoint := &domain.Endpoint{ + Name: "test", + Group: "test", + } + + if err := dbClient.Create(endpoint); err != nil { + panic(err) + } + + t.Log("list") + // list + endpoints, err := dbClient.List(nil) + if err != nil { + panic(err) + } + + for _, endpoint := range endpoints { + t.Logf("endpoint: %+v", endpoint) + } + + t.Log("get") + // get + for _, endpoint := range endpoints { + endpoint, err := dbClient.Get(endpoint.ID) + if err != nil { + panic(err) + } + t.Logf("endpoint: %+v", endpoint) + } + + t.Log("update") + // update + for _, endpoint := range endpoints { + endpoint.Name = "test2" + t.Logf("BeforeUpdate: %+v", endpoint) + if err := dbClient.Update(endpoint); err != nil { + panic(err) + } else { + t.Logf("AfterUpdate: %+v", endpoint) + } + } +} diff --git a/internal/repository/organization.go b/internal/repository/organization.go index e37fc7e4..12e31962 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -168,3 +168,24 @@ func (r *OrganizationRepository) reflect(organization Organization) (out domain. return } + +func ConvertDomainToRepoOrganization(organization *domain.Organization) *Organization { + + return &Organization{ + ID: organization.ID, + Name: organization.Name, + Description: organization.Description, + Phone: organization.Phone, + Creator: uuid.MustParse(organization.Creator), + } +} + +func ConvertRepoToDomainOrganization(organization *Organization) *domain.Organization { + return &domain.Organization{ + ID: organization.ID, + Name: organization.Name, + Description: organization.Description, + Phone: organization.Phone, + Creator: organization.Creator.String(), + } +} diff --git a/internal/repository/permission.go b/internal/repository/permission.go new file mode 100644 index 00000000..0580244c --- /dev/null +++ b/internal/repository/permission.go @@ -0,0 +1,219 @@ +package repository + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +type IPermissionRepository interface { + Create(permission *domain.Permission) error + List() ([]*domain.Permission, error) + Get(id uuid.UUID) (*domain.Permission, error) + Delete(id uuid.UUID) error + Update(permission *domain.Permission) error +} + +type PermissionRepository struct { + db *gorm.DB +} + +func NewPermissionRepository(db *gorm.DB) *PermissionRepository { + return &PermissionRepository{ + db: db, + } +} + +type Permission struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid;"` + Name string + + IsAllowed *bool `gorm:"type:boolean;"` + RoleID *uuid.UUID + Role *Role `gorm:"foreignKey:RoleID;references:ID;"` + Endpoints []*Endpoint `gorm:"one2many:endpoints;"` + + ParentID *uuid.UUID + Parent *Permission `gorm:"foreignKey:ParentID;references:ID;"` + Children []*Permission `gorm:"foreignKey:ParentID;references:ID;"` +} + +func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { + if p.ID == uuid.Nil { + p.ID = uuid.New() + } + return nil +} + +func (r PermissionRepository) Create(p *domain.Permission) error { + //var parent *Permission + //var children []*Permission + // + //if p.Parent != nil { + // parent = &Permission{} + // result := r.db.First(&parent, "id = ?", p.Parent.ID) + // if result.Error != nil { + // return result.Error + // } + //} + //if p.Children != nil { + // for _, child := range p.Children { + // newChild := &Permission{} + // result := r.db.First(&newChild, "id = ?", child.ID) + // if result.Error != nil { + // return result.Error + // } + // children = append(children, newChild) + // } + //} + + permission := ConvertDomainToRepoPermission(p) + + return r.db.Create(permission).Error +} + +func (r PermissionRepository) List() ([]*domain.Permission, error) { + var permissions []*Permission + var outs []*domain.Permission + + err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL").Find(&permissions).Error + if err != nil { + return nil, err + } + + for _, permission := range permissions { + outs = append(outs, ConvertRepoToDomainPermission(permission)) + } + return outs, nil +} + +func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { + permission := &Permission{} + result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) + if result.Error != nil { + return nil, result.Error + } + + return ConvertRepoToDomainPermission(permission), nil +} + +func (r PermissionRepository) Delete(id uuid.UUID) error { + return r.db.Delete(&Permission{}, id).Error +} + +func (r PermissionRepository) Update(p *domain.Permission) error { + permission := ConvertDomainToRepoPermission(p) + + return r.db.Updates(permission).Error + + //var parent *Permission + //var children []*Permission + // + //if p.Parent != nil { + // parent = &Permission{} + // result := r.db.First(&parent, "id = ?", p.Parent.ID) + // if result.Error != nil { + // return result.Error + // } + //} + //if p.Children != nil { + // for _, child := range p.Children { + // newChild := &Permission{} + // result := r.db.First(&newChild, "id = ?", child.ID) + // if result.Error != nil { + // return result.Error + // } + // children = append(children, newChild) + // } + //} + // + //permission := &Permission{} + // + //result := r.db.First(&permission, "id = ?", p.ID) + //if result.Error != nil { + // return result.Error + //} + // + //permission.Name = p.Name + //permission.Parent = parent + //permission.Children = children + //permission.IsAllowed = p.IsAllowed + // + //return r.db.Save(permission).Error +} + +// repository.Permission to domain.Permission +func ConvertRepoToDomainPermission(repoPerm *Permission) *domain.Permission { + if repoPerm == nil { + return nil + } + + if repoPerm.Endpoints == nil { + repoPerm.Endpoints = []*Endpoint{} + } + var domainEndpoints []*domain.Endpoint + for _, endpoint := range repoPerm.Endpoints { + domainEndpoints = append(domainEndpoints, ConvertRepoToDomainEndpoint(endpoint)) + } + + // Domain Permission 객체 생성 + domainPerm := &domain.Permission{ + ID: repoPerm.ID, + Name: repoPerm.Name, + ParentID: repoPerm.ParentID, + IsAllowed: repoPerm.IsAllowed, + Endpoints: domainEndpoints, + } + + // 자식 권한들 변환 + for _, child := range repoPerm.Children { + domainChild := ConvertRepoToDomainPermission(child) + domainPerm.Children = append(domainPerm.Children, domainChild) + } + + // 부모 권한 변환 (부모 권한이 있을 경우만) + if repoPerm.Parent != nil { + domainPerm.Parent = ConvertRepoToDomainPermission(repoPerm.Parent) + } + + return domainPerm +} + +// domain.Permission to repository.Permission +func ConvertDomainToRepoPermission(domainPerm *domain.Permission) *Permission { + if domainPerm == nil { + return nil + } + + if domainPerm.Endpoints == nil { + domainPerm.Endpoints = []*domain.Endpoint{} + } + var repoEndpoints []*Endpoint + for _, endpoint := range domainPerm.Endpoints { + repoEndpoints = append(repoEndpoints, ConvertDomainToRepoEndpoint(endpoint)) + } + + // Domain Permission 객체 생성 + repoPerm := &Permission{ + ID: domainPerm.ID, + Name: domainPerm.Name, + ParentID: domainPerm.ParentID, + IsAllowed: domainPerm.IsAllowed, + Endpoints: repoEndpoints, + } + + // 자식 권한들 변환 + for _, child := range domainPerm.Children { + repoChild := ConvertDomainToRepoPermission(child) + repoPerm.Children = append(repoPerm.Children, repoChild) + } + + // 부모 권한 변환 (부모 권한이 있을 경우만) + if domainPerm.Parent != nil { + repoPerm.Parent = ConvertDomainToRepoPermission(domainPerm.Parent) + } + + return repoPerm +} diff --git a/internal/repository/permission_test.go b/internal/repository/permission_test.go new file mode 100644 index 00000000..dad9d96e --- /dev/null +++ b/internal/repository/permission_test.go @@ -0,0 +1,445 @@ +package repository_test + +import ( + "encoding/json" + "fmt" + "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm_test/config" + "testing" +) + +func TestPermission(t *testing.T) { + db := db_connection() + + db.AutoMigrate(&repository.Permission{}) + + //model := domain.Permission{ + // Name: "대시보드", + //} + + repo := repository.NewPermissionRepository(db) + + permissions, err := repo.List() + if err != nil { + t.Fatal(err) + } + out, err := json.MarshalIndent(permissions, "", " ") + if err != nil { + t.Fatal(err) + } + t.Log("start") + t.Logf("permission: %s", string(out)) + t.Log("end") + + //t.Logf("permission: %+v", permissions) + + // + //for _, permission := range permissions { + // // encoding to json + // b, err := json.Marshal(permission) + // if err != nil { + // t.Fatal(err) + // } + // t.Logf("permission: %s", string(b)) + //} + // + ////create + + //if err := repo.Create(dashboard); err != nil { + // t.Fatal(err) + //} + //if err := repo.Create(stack); err != nil { + // t.Fatal(err) + //} + //if err := repo.Create(security_policy); err != nil { + // t.Fatal(err) + //} + //if err := repo.Create(projectManagement); err != nil { + // t.Fatal(err) + //} + //if err := repo.Create(notification); err != nil { + // t.Fatal(err) + //} + //if err := repo.Create(configuration); err != nil { + // t.Fatal(err) + //} + + // get + //permission, err := repo.Get(uuid.MustParse("fd4363a7-d1d2-4feb-b976-b87d99a775c4")) + //if err != nil { + // t.Fatal(err) + //} + //out, err := json.Marshal(permission) + //if err != nil { + // t.Fatal(err) + //} + //t.Logf("permission: %s", string(out)) + + // print json pretty + //out, err := json.MarshalIndent(permission, "", " ") + //if err != nil { + // t.Fatal(err) + //} + //t.Logf("permission: %s", string(out)) + +} + +func db_connection() *gorm.DB { + conf := config.NewDefaultConfig() + dsn := fmt.Sprintf( + "host=%s dbname=%s user=%s password=%s port=%d sslmode=disable TimeZone=Asia/Seoul", + conf.Address, conf.Database, conf.AdminId, conf.AdminPassword, conf.Port, + ) + + db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) + if err != nil { + panic(err) + } + + return db +} + +var dashboard = &domain.Permission{ + Name: "대시보드", + Children: []*domain.Permission{ + { + Name: "대시보드", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "대시보드 설정", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, +} + +var stack = &domain.Permission{ + Name: "스택 관리", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, +} + +var security_policy = &domain.Permission{ + Name: "보안/정책 관리", + Children: []*domain.Permission{ + { + Name: "보안/정책", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, +} + +var projectManagement = &domain.Permission{ + Name: "프로젝트 관리", + Children: []*domain.Permission{ + { + Name: "프로젝트", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "앱 서빙", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "빌드", + IsAllowed: helper.BoolP(false), + }, + { + Name: "배포", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "설정-일반", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "설정-멤버", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "설정-네임스페이스", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, +} + +var notification = &domain.Permission{ + Name: "알림", + Children: []*domain.Permission{ + { + Name: "시스템 경고", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "보안/정책 감사로그", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, +} + +var configuration = &domain.Permission{ + Name: "설정", + Children: []*domain.Permission{ + { + Name: "일반", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "클라우드 계정", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "스택 템플릿", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "프로젝트 관리", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자 권한 관리", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "알림 설정", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 09ab4035..e176a7c8 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -21,6 +21,7 @@ type Repository struct { CloudAccount ICloudAccountRepository StackTemplate IStackTemplateRepository Alert IAlertRepository + Role IRoleRepository Project IProjectRepository Audit IAuditRepository } diff --git a/internal/repository/role.go b/internal/repository/role.go new file mode 100644 index 00000000..f8906c11 --- /dev/null +++ b/internal/repository/role.go @@ -0,0 +1,303 @@ +package repository + +import ( + "fmt" + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" + "math" +) + +type Role struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid;"` + Name string + OrganizationID string + Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;"` + Type string + Creator uuid.UUID + Description string +} + +func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { + if r.ID == uuid.Nil { + r.ID = uuid.New() + } + return nil +} + +type TksRole struct { + RoleID uuid.UUID `gorm:"type:uuid;primary_key;"` + Role Role `gorm:"foreignKey:RoleID;references:ID;"` +} + +type ProjectRole struct { + RoleID uuid.UUID `gorm:"type:uuid;primary_key;"` + Role Role `gorm:"foreignKey:RoleID;references:ID;"` + ProjectID uuid.UUID + Project Project `gorm:"foreignKey:ProjectID;references:ID;"` +} + +type IRoleRepository interface { + Create(roleObj interface{}) error + List(pg *pagination.Pagination) ([]*domain.Role, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) + ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) + Get(id uuid.UUID) (*domain.Role, error) + GetTksRole(id uuid.UUID) (*domain.TksRole, error) + GetProjectRole(id uuid.UUID) (*domain.ProjectRole, error) + DeleteCascade(id uuid.UUID) error + Update(roleObj interface{}) error +} + +type RoleRepository struct { + db *gorm.DB +} + +func (r RoleRepository) Create(roleObj interface{}) error { + if roleObj == nil { + return fmt.Errorf("roleObj is nil") + } + switch roleObj.(type) { + case *domain.TksRole: + inputRole := roleObj.(*domain.TksRole) + role := ConvertDomainToRepoTksRole(inputRole) + if err := r.db.Create(role).Error; err != nil { + return err + } + + case *domain.ProjectRole: + inputRole := roleObj.(*domain.ProjectRole) + role := ConvertDomainToRepoProjectRole(inputRole) + if err := r.db.Create(role).Error; err != nil { + return err + } + } + + return nil +} + +func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) { + var roles []*domain.Role + var objs []*Role + + if pg == nil { + pg = pagination.NewDefaultPagination() + } + filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) + db := filterFunc(r.db.Model(&Role{})) + + db.Count(&pg.TotalRows) + pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) + + orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) + //res := db.Joins("JOIN roles as r on r.id = tks_roles.role_id"). + // Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + + if res.Error != nil { + return nil, res.Error + } + for _, role := range objs { + roles = append(roles, ConvertRepoToDomainRole(role)) + } + + return roles, nil +} + +func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) { + var roles []*domain.TksRole + var objs []*TksRole + + if pg == nil { + pg = pagination.NewDefaultPagination() + } + filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) + db := filterFunc(r.db.Model(&TksRole{})) + + db.Count(&pg.TotalRows) + pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) + + orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) + res := db.Joins("JOIN roles as r on r.id = tks_roles.role_id"). + Where("r.organization_id = ?", organizationId). + Offset(pg.GetOffset()). + Limit(pg.GetLimit()). + Order(orderQuery). + Find(&objs) + //res := db.Preload("Role").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + if res.Error != nil { + return nil, res.Error + } + for _, role := range objs { + roles = append(roles, ConvertRepoToDomainTksRole(role)) + } + + return roles, nil +} + +func (r RoleRepository) ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) { + var roles []*domain.ProjectRole + var objs []*ProjectRole + + if pg == nil { + pg = pagination.NewDefaultPagination() + } + filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) + db := filterFunc(r.db.Model(&ProjectRole{})) + + db.Count(&pg.TotalRows) + pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) + + orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) + res := db.Joins("JOIN roles as r on r.id = project_roles.role_id"). + Where("project_roles.project_id = ?", projectId). + Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + //res := db.Preload("Role").Preload("Project").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + if res.Error != nil { + return nil, res.Error + } + for _, role := range objs { + roles = append(roles, ConvertRepoToDomainProjectRole(role)) + } + + return roles, nil +} + +func (r RoleRepository) Get(id uuid.UUID) (*domain.Role, error) { + var role Role + if err := r.db.First(&role, "id = ?", id).Error; err != nil { + return nil, err + } + + return ConvertRepoToDomainRole(&role), nil +} + +func (r RoleRepository) GetTksRole(id uuid.UUID) (*domain.TksRole, error) { + var role TksRole + if err := r.db.Preload("Role").First(&role, "role_id = ?", id).Error; err != nil { + return nil, err + } + + return ConvertRepoToDomainTksRole(&role), nil +} + +func (r RoleRepository) GetProjectRole(id uuid.UUID) (*domain.ProjectRole, error) { + var role ProjectRole + if err := r.db.Preload("Role").Preload("Project").First(&role, "role_id = ?", id).Error; err != nil { + return nil, err + } + + return ConvertRepoToDomainProjectRole(&role), nil +} + +func (r RoleRepository) DeleteCascade(id uuid.UUID) error { + // manual cascade delete + if err := r.db.Delete(&TksRole{}, "role_id = ?", id).Error; err != nil { + return err + } + if err := r.db.Delete(&ProjectRole{}, "role_id = ?", id).Error; err != nil { + return err + } + + if err := r.db.Delete(&Role{}, "id = ?", id).Error; err != nil { + return err + } + + return nil +} + +func (r RoleRepository) Update(roleObj interface{}) error { + switch roleObj.(type) { + case *TksRole: + inputRole := roleObj.(*TksRole) + role := ConvertRepoToDomainTksRole(inputRole) + if err := r.db.Model(&TksRole{}).Where("id = ?", role.ID).Updates(Role{ + Name: role.Name, + Description: role.Description, + }).Error; err != nil { + return err + } + + case *ProjectRole: + inputRole := roleObj.(*ProjectRole) + projectRole := ConvertRepoToDomainProjectRole(inputRole) + // update role + if err := r.db.Model(&ProjectRole{}).Where("role_id = ?", projectRole.RoleID).Updates(Role{ + Name: projectRole.Role.Name, + Description: projectRole.Role.Description, + }).Error; err != nil { + return err + } + } + + return nil +} + +func NewRoleRepository(db *gorm.DB) IRoleRepository { + return &RoleRepository{ + db: db, + } +} + +// domain.Role to repository.Role +func ConverDomainToRepoRole(domainRole *domain.Role) *Role { + return &Role{ + ID: domainRole.ID, + Name: domainRole.Name, + OrganizationID: domainRole.OrganizationID, + Type: domainRole.Type, + Creator: domainRole.Creator, + Description: domainRole.Description, + } +} + +// repository.Role to domain.Role +func ConvertRepoToDomainRole(repoRole *Role) *domain.Role { + return &domain.Role{ + ID: repoRole.ID, + Name: repoRole.Name, + OrganizationID: repoRole.OrganizationID, + Type: repoRole.Type, + Creator: repoRole.Creator, + Description: repoRole.Description, + } +} + +// domain.TksRole to repository.TksRole +func ConvertDomainToRepoTksRole(domainRole *domain.TksRole) *TksRole { + return &TksRole{ + RoleID: domainRole.Role.ID, + Role: *ConverDomainToRepoRole(&domainRole.Role), + } +} + +// repository.TksRole to domain.TksRole +func ConvertRepoToDomainTksRole(repoRole *TksRole) *domain.TksRole { + return &domain.TksRole{ + RoleID: repoRole.RoleID, + Role: *ConvertRepoToDomainRole(&repoRole.Role), + } +} + +// domain.ProjectRole to repository.ProjectRole +func ConvertDomainToRepoProjectRole(domainRole *domain.ProjectRole) *ProjectRole { + return &ProjectRole{ + RoleID: domainRole.RoleID, + ProjectID: domainRole.ProjectID, + Role: *ConverDomainToRepoRole(&domainRole.Role), + Project: *ConvertDomainToRepoProject(&domainRole.Project), + } +} + +// repository.ProjectRole to domain.ProjectRole +func ConvertRepoToDomainProjectRole(repoRole *ProjectRole) *domain.ProjectRole { + return &domain.ProjectRole{ + RoleID: repoRole.RoleID, + ProjectID: repoRole.ProjectID, + Role: *ConvertRepoToDomainRole(&repoRole.Role), + Project: *ConvertRepoToDomainProject(&repoRole.Project), + } +} diff --git a/internal/repository/role_test.go b/internal/repository/role_test.go new file mode 100644 index 00000000..8c9d78a8 --- /dev/null +++ b/internal/repository/role_test.go @@ -0,0 +1,28 @@ +package repository_test + +import ( + "encoding/json" + "github.com/openinfradev/tks-api/internal/repository" + "testing" +) + +func TestRole(t *testing.T) { + db := db_connection() + + db.AutoMigrate(&repository.Role{}, &repository.Organization{}, &repository.Project{}, &repository.User{}, &repository.TksRole{}, &repository.ProjectRole{}) + + repo := repository.NewRoleRepository(db) + + roles, err := repo.List() + if err != nil { + t.Fatal(err) + } + out, err := json.MarshalIndent(roles, "", " ") + if err != nil { + t.Fatal(err) + } + t.Log("start") + t.Logf("role: %s", string(out)) + t.Log("end") + +} diff --git a/internal/repository/user.go b/internal/repository/user.go index 84120da9..5bf6ad10 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -276,20 +276,7 @@ func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { return nil } -type Role struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid;"` - Name string - Description string - Creator uuid.UUID -} - -func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { - r.ID = uuid.New() - return nil -} - +// Deprecated: type Policy struct { gorm.Model @@ -431,10 +418,10 @@ func (r *UserRepository) getRoleByName(roleName string) (Role, error) { func (r *UserRepository) reflect(user User) domain.User { role := domain.Role{ - ID: user.Role.ID.String(), + ID: user.Role.ID, Name: user.Role.Name, Description: user.Role.Description, - Creator: user.Role.Creator.String(), + Creator: user.Role.Creator, CreatedAt: user.Role.CreatedAt, UpdatedAt: user.Role.UpdatedAt, } @@ -492,10 +479,10 @@ func (r *UserRepository) reflect(user User) domain.User { func (r *UserRepository) reflectRole(role Role) domain.Role { return domain.Role{ - ID: role.ID.String(), + ID: role.ID, Name: role.Name, Description: role.Description, - Creator: role.Creator.String(), + Creator: role.Creator, CreatedAt: role.CreatedAt, UpdatedAt: role.UpdatedAt, } diff --git a/internal/route/route.go b/internal/route/route.go index 4382baa1..ede3ff36 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -50,6 +50,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa CloudAccount: repository.NewCloudAccountRepository(db), StackTemplate: repository.NewStackTemplateRepository(db), Alert: repository.NewAlertRepository(db), + Role: repository.NewRoleRepository(db), Project: repository.NewProjectRepository(db), Audit: repository.NewAuditRepository(db), } @@ -231,6 +232,18 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) + roleHandler := delivery.NewRoleHandler(usecase.NewRoleUsecase(repoFactory)) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.CreateTksRole, http.HandlerFunc(roleHandler.CreateTksRole))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.ListTksRoles, http.HandlerFunc(roleHandler.ListTksRoles))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.GetTksRole, http.HandlerFunc(roleHandler.GetTksRole))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.DeleteTksRole, http.HandlerFunc(roleHandler.DeleteTksRole))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateTksRole, http.HandlerFunc(roleHandler.UpdateTksRole))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles", customMiddleware.Handle(internalApi.CreateProjectRole, http.HandlerFunc(roleHandler.CreateProjectRole))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles", customMiddleware.Handle(internalApi.ListProjectRoles, http.HandlerFunc(roleHandler.ListProjectRoles))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles/{roleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(roleHandler.GetProjectRole))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles/{roleId}", customMiddleware.Handle(internalApi.DeleteProjectRole, http.HandlerFunc(roleHandler.DeleteProjectRole))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateProjectRole, http.HandlerFunc(roleHandler.UpdateProjectRole))).Methods(http.MethodPut) + r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go new file mode 100644 index 00000000..df3c8072 --- /dev/null +++ b/internal/usecase/permission.go @@ -0,0 +1,45 @@ +package usecase + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" +) + +type IPermissionUsecase interface { + CreatePermission(permission *domain.Permission) error + ListPermissions() ([]*domain.Permission, error) + GetPermission(id uuid.UUID) (*domain.Permission, error) + DeletePermission(id uuid.UUID) error + UpdatePermission(permission *domain.Permission) error +} + +type PermissionUsecase struct { + repo repository.IPermissionRepository +} + +func NewPermissionUsecase(repo repository.IPermissionRepository) *PermissionUsecase { + return &PermissionUsecase{ + repo: repo, + } +} + +func (p PermissionUsecase) CreatePermission(permission *domain.Permission) error { + return p.repo.Create(permission) +} + +func (p PermissionUsecase) ListPermissions() ([]*domain.Permission, error) { + return p.repo.List() +} + +func (p PermissionUsecase) GetPermission(id uuid.UUID) (*domain.Permission, error) { + return p.repo.Get(id) +} + +func (p PermissionUsecase) DeletePermission(id uuid.UUID) error { + return p.repo.Delete(id) +} + +func (p PermissionUsecase) UpdatePermission(permission *domain.Permission) error { + return p.repo.Update(permission) +} diff --git a/internal/usecase/role.go b/internal/usecase/role.go new file mode 100644 index 00000000..fb6dbc56 --- /dev/null +++ b/internal/usecase/role.go @@ -0,0 +1,126 @@ +package usecase + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" +) + +type IRoleUsecase interface { + CreateTksRole(role *domain.TksRole) error + CreateProjectRole(role *domain.ProjectRole) error + ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) + ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) + GetTksRole(id string) (*domain.TksRole, error) + GetProjectRole(id string) (*domain.ProjectRole, error) + DeleteTksRole(id string) error + DeleteProjectRole(id string) error + UpdateTksRole(role *domain.TksRole) error + UpdateProjectRole(role *domain.ProjectRole) error +} + +type RoleUsecase struct { + repo repository.IRoleRepository +} + +func NewRoleUsecase(repo repository.Repository) *RoleUsecase { + return &RoleUsecase{ + repo: repo.Role, + } +} + +func (r RoleUsecase) CreateTksRole(role *domain.TksRole) error { + return r.repo.Create(role) +} + +func (r RoleUsecase) CreateProjectRole(role *domain.ProjectRole) error { + return r.repo.Create(role) +} + +func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) { + roles, err := r.repo.ListTksRoles(organizationId, pg) + if err != nil { + return nil, err + } + + return roles, nil +} + +func (r RoleUsecase) ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) { + roles, err := r.repo.ListProjectRoles(projectId, pg) + if err != nil { + return nil, err + } + + return roles, nil +} + +func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) { + return r.repo.List(nil) +} + +func (r RoleUsecase) GetTksRole(id string) (*domain.TksRole, error) { + roldId, err := uuid.Parse(id) + if err != nil { + return nil, err + } + + role, err := r.repo.GetTksRole(roldId) + if err != nil { + return nil, err + } + + return role, nil +} + +func (r RoleUsecase) GetProjectRole(id string) (*domain.ProjectRole, error) { + roleId, err := uuid.Parse(id) + if err != nil { + return nil, err + } + + role, err := r.repo.GetProjectRole(roleId) + if err != nil { + return nil, err + } + + return role, nil +} + +func (r RoleUsecase) DeleteTksRole(id string) error { + roleId, err := uuid.Parse(id) + if err != nil { + return err + } + + return r.repo.DeleteCascade(roleId) +} + +func (r RoleUsecase) DeleteProjectRole(id string) error { + roleId, err := uuid.Parse(id) + if err != nil { + return err + } + + return r.repo.DeleteCascade(roleId) +} + +func (r RoleUsecase) UpdateTksRole(role *domain.TksRole) error { + err := r.repo.Update(role) + if err != nil { + return err + } + + return nil +} + +func (r RoleUsecase) UpdateProjectRole(role *domain.ProjectRole) error { + err := r.repo.Update(role) + if err != nil { + return err + } + + return nil +} diff --git a/internal/usecase/role_test.go b/internal/usecase/role_test.go new file mode 100644 index 00000000..10e746c7 --- /dev/null +++ b/internal/usecase/role_test.go @@ -0,0 +1,217 @@ +package usecase_test + +import ( + "fmt" + "github.com/google/uuid" + myRepository "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm_test/config" + "testing" +) + +func TestNewRoleUsecase(t *testing.T) { + conf := config.NewDefaultConfig() + dsn := fmt.Sprintf( + "host=%s dbname=%s user=%s password=%s port=%d sslmode=disable TimeZone=Asia/Seoul", + conf.Address, conf.Database, conf.AdminId, conf.AdminPassword, conf.Port, + ) + + t.Logf("dsn: %s", dsn) + + db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) + if err != nil { + panic(err) + } + + if err = db.AutoMigrate(&myRepository.Organization{}); err != nil { + panic(err) + } + if err = db.AutoMigrate(&myRepository.Role{}); err != nil { + panic(err) + } + if err = db.AutoMigrate(&myRepository.TksRole{}); err != nil { + panic(err) + } + if err = db.AutoMigrate(&myRepository.ProjectRole{}); err != nil { + panic(err) + } + + orgaizationRepository := myRepository.NewOrganizationRepository(db) + roleDbClient := myRepository.NewRoleRepository(db) + + roleUsecase := usecase.NewRoleUsecase(roleDbClient) + + // create organization + // organizationId = "test" + if _, err := orgaizationRepository.Get("test"); err != nil { + if _, err := orgaizationRepository.Create("test", "test", uuid.New(), "test", "test"); err != nil { + panic(err) + } + } + + // create project + // projectName = "testProject" + projectRepository := myRepository.NewProjectRepository(db) + projectFound := false + if projects, err := projectRepository.List(); err != nil { + panic(err) + } else { + for _, project := range projects { + if project.Name == "testProject" { + projectFound = true + break + } + } + } + + if !projectFound { + project := &domain.Project{ + Name: "testProject", + OrganizationID: "test", + Description: "testDesc", + } + if err := projectRepository.Create(project); err != nil { + panic(err) + } + } + + // get id of project + projects, err := projectRepository.List() + if err != nil { + panic(err) + } + var projectId uuid.UUID + for _, project := range projects { + if project.Name == "testProject" { + projectId = project.ID + break + } + } + + // create tks role + tksRoles, err := roleUsecase.ListTksRoles() + if err != nil { + panic(err) + } + tksRoleFound := false + for _, role := range tksRoles { + if role.Name == "testTksRole" { + tksRoleFound = true + break + } + } + if !tksRoleFound { + role := &domain.TksRole{ + Role: domain.Role{ + Name: "testTksRole", + OrganizationID: "test", + Description: "testDesc", + }, + } + if err := roleUsecase.CreateTksRole(role); err != nil { + panic(err) + } + } + + // create project role + projectRoles, err := roleUsecase.ListProjectRoles() + if err != nil { + panic(err) + } + + projectRoleFound := false + for _, role := range projectRoles { + if role.Role.Name == "testProjectRole" { + projectRoleFound = true + break + } + } + + if !projectRoleFound { + role := &domain.ProjectRole{ + Role: domain.Role{ + Name: "testProjectRole", + OrganizationID: "test", + Description: "testDesc", + }, + ProjectID: projectId, + } + if err := roleUsecase.CreateProjectRole(role); err != nil { + panic(err) + } + } + + // list tks role + tksRoles, err = roleUsecase.ListTksRoles() + if err != nil { + panic(err) + } + for i, role := range tksRoles { + t.Logf("index: %d, tksRole: %+v", i, role) + } + + // list project role + projectRoles, err = roleUsecase.ListProjectRoles() + if err != nil { + panic(err) + } + for i, role := range projectRoles { + t.Logf("index: %d, projectRole: %+v", i, role) + } + + // list all role + roles, err := roleUsecase.ListRoles() + if err != nil { + panic(err) + } + for i, role := range roles { + t.Logf("index: %d, role: %+v", i, role) + } + + t.Logf("now delete all roles") + + // delete tks role + for _, role := range tksRoles { + if err := roleDbClient.Delete(role.RoleID); err != nil { + panic(err) + } + } + + // delete project role + for _, role := range projectRoles { + if err := roleDbClient.Delete(role.RoleID); err != nil { + panic(err) + } + } + + // print tks role + tksRoles, err = roleUsecase.ListTksRoles() + if err != nil { + panic(err) + } + for i, role := range tksRoles { + t.Logf("index: %d, tksRole: %+v", i, role) + } + + // print project role + projectRoles, err = roleUsecase.ListProjectRoles() + if err != nil { + panic(err) + } + for i, role := range projectRoles { + t.Logf("index: %d, projectRole: %+v", i, role) + } + + // print all role + roles, err = roleUsecase.ListRoles() + if err != nil { + panic(err) + } + for i, role := range roles { + t.Logf("index: %d, role: %+v", i, role) + } + +} diff --git a/internal/usecase/user.go b/internal/usecase/user.go index f507a7eb..12cfa33a 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -258,7 +258,7 @@ func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*domain. user.Role.ID = role.ID } } - roleUuid, err := uuid.Parse(user.Role.ID) + roleUuid := user.Role.ID if err != nil { return nil, err } @@ -444,7 +444,7 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u originPassword := (*users)[0].Password - roleUuid, err := uuid.Parse((*users)[0].Role.ID) + roleUuid := (*users)[0].Role.ID if err != nil { return nil, err } @@ -548,7 +548,7 @@ func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.Us user.Role.ID = role.ID } } - roleUuid, err := uuid.Parse(user.Role.ID) + roleUuid := user.Role.ID if err != nil { return nil, err } @@ -623,7 +623,7 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st user.Role.ID = role.ID } } - roleUuid, err := uuid.Parse(user.Role.ID) + roleUuid := user.Role.ID if err != nil { return nil, err } diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go new file mode 100644 index 00000000..84006eac --- /dev/null +++ b/pkg/domain/endpoint.go @@ -0,0 +1,11 @@ +package domain + +import "github.com/google/uuid" + +type Endpoint struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Group string `json:"group"` + PermissionID uuid.UUID `json:"permissionId"` + Permission Permission `json:"permission"` +} diff --git a/pkg/domain/permmision.go b/pkg/domain/permmision.go new file mode 100644 index 00000000..c9b40762 --- /dev/null +++ b/pkg/domain/permmision.go @@ -0,0 +1,18 @@ +package domain + +import "github.com/google/uuid" + +type Permission struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + + IsAllowed *bool `json:"is_allowed,omitempty"` + RoleID *uuid.UUID `json:"role_id,omitempty"` + Role *Role `json:"role,omitempty"` + Endpoints []*Endpoint `json:"endpoints,omitempty"` + // omit empty + + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Parent *Permission `json:"parent,omitempty"` + Children []*Permission `json:"children,omitempty"` +} diff --git a/pkg/domain/role.go b/pkg/domain/role.go new file mode 100644 index 00000000..d2025254 --- /dev/null +++ b/pkg/domain/role.go @@ -0,0 +1,109 @@ +package domain + +import ( + "github.com/google/uuid" + "time" +) + +type RoleType string + +const ( + RoleTypeDefault RoleType = "default" + RoleTypeTks RoleType = "tks" + RoleTypeProject RoleType = "project" +) + +type Role struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + OrganizationID string `json:"organizationId"` + Organization Organization `json:"organization"` + Type string `json:"type"` + Description string `json:"description"` + Creator uuid.UUID `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type TksRole struct { + RoleID uuid.UUID `json:"roleId"` + Role +} + +type ProjectRole struct { + RoleID uuid.UUID `json:"roleId"` + Role Role `json:"role"` + ProjectID uuid.UUID `json:"projectID"` + Project Project `json:"project"` +} + +//type Role = struct { +// ID uuid.UUID `json:"id"` +// Name string `json:"name"` +// OrganizationID string `json:"organizationId"` +// Organization Organization `json:"organization"` +// Type string `json:"type"` +// Description string `json:"description"` +// Creator uuid.UUID `json:"creator"` +// CreatedAt time.Time `json:"createdAt"` +// UpdatedAt time.Time `json:"updatedAt"` +//} + +type CreateTksRoleRequest struct { + Name string `json:"name" validate:"required"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` +} + +type CreateTksRoleResponse struct { + ID string `json:"id"` +} + +type GetTksRoleResponse struct { + ID string `json:"id"` + Name string `json:"name"` + OrganizationID string `json:"organizationId"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type ListTksRoleResponse struct { + Roles []GetTksRoleResponse `json:"roles"` + Pagination PaginationResponse `json:"pagination"` +} + +type UpdateTksRoleRequest struct { + Name string `json:"name" validate:"required"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` +} + +type CreateProjectRoleRequest struct { + Name string `json:"name" validate:"required"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` +} + +type CreateProjectRoleResponse struct { + ID string `json:"id"` +} + +type GetProjectRoleResponse struct { + ID string `json:"id"` + Name string `json:"name"` + OrganizationID string `json:"organizationId"` + ProjectID string `json:"projectId"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type ListProjectRoleResponse struct { + Roles []GetProjectRoleResponse `json:"roles"` + Pagination PaginationResponse `json:"pagination"` +} + +type UpdateProjectRoleRequest struct { + Name string `json:"name" validate:"required"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` +} diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 0e79216f..138b0edc 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -23,15 +23,6 @@ type User = struct { Description string `json:"description"` } -type Role = struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - type SimpleRoleResponse = struct { ID string `json:"id"` Name string `json:"name"` From 51a0a62e08aa56a3db02103a13e18fe9100eba6a Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 8 Feb 2024 11:08:43 +0900 Subject: [PATCH 064/502] merge with project api --- internal/delivery/http/project.go | 3 +- internal/repository/project.go | 50 +------------------------------ internal/repository/role.go | 8 ++--- pkg/domain/project.go | 21 +------------ 4 files changed, 8 insertions(+), 74 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index dc11d64b..5f724ce5 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -54,7 +54,8 @@ type IProjectHandler interface { } type ProjectHandler struct { - usecase usecase.IProjectUsecase + usecase usecase.IProjectUsecase + roleUsecase usecase.IRoleUsecase } func NewProjectHandler(u usecase.Usecase) IProjectHandler { diff --git a/internal/repository/project.go b/internal/repository/project.go index c042cdc2..67f57e95 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -20,9 +20,6 @@ type IProjectRepository interface { GetProjectByIdAndLeader(organizationId string, projectId string) (*domain.Project, error) GetProjectByName(organizationId string, projectName string) (*domain.Project, error) UpdateProject(p *domain.Project) error - GetAllProjectRoles() ([]domain.ProjectRole, error) - GetProjectRoleByName(name string) (*domain.ProjectRole, error) - GetProjectRoleById(id string) (*domain.ProjectRole, error) AddProjectMember(*domain.ProjectMember) (string, error) GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) ([]domain.ProjectMember, error) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) ([]domain.ProjectMember, error) @@ -206,6 +203,7 @@ func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, proje res := r.db.Limit(1). Preload("ProjectMembers", "is_project_leader = ?", true). Preload("ProjectMembers.ProjectRole"). + Preload("ProjectMembers.ProjectRole.Role"). Preload("ProjectMembers.ProjectUser"). First(&p, "organization_id = ? and id = ?", organizationId, projectId) @@ -248,52 +246,6 @@ func (r *ProjectRepository) UpdateProject(p *domain.Project) error { return nil } -func (r *ProjectRepository) GetProjectRoleById(id string) (*domain.ProjectRole, error) { - var pr = &domain.ProjectRole{ID: id} - res := r.db.First(pr) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project role") - return nil, nil - } else { - log.Error(res.Error) - return nil, res.Error - } - } - - return pr, nil -} - -func (r *ProjectRepository) GetAllProjectRoles() (prs []domain.ProjectRole, err error) { - res := r.db.Find(&prs) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project roles") - return nil, nil - } else { - log.Error(res.Error) - return nil, res.Error - } - } - - return prs, nil -} - -func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *domain.ProjectRole, err error) { - res := r.db.Where("name = ?", name).First(&pr) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project roles") - return nil, nil - } else { - log.Error(res.Error) - return nil, res.Error - } - } - - return pr, nil -} - func (r *ProjectRepository) AddProjectMember(pm *domain.ProjectMember) (string, error) { res := r.db.Create(&pm) if res.Error != nil { diff --git a/internal/repository/role.go b/internal/repository/role.go index f8906c11..03736c67 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -37,7 +37,7 @@ type ProjectRole struct { RoleID uuid.UUID `gorm:"type:uuid;primary_key;"` Role Role `gorm:"foreignKey:RoleID;references:ID;"` ProjectID uuid.UUID - Project Project `gorm:"foreignKey:ProjectID;references:ID;"` + Project domain.Project `gorm:"foreignKey:ProjectID;references:ID;"` } type IRoleRepository interface { @@ -164,7 +164,7 @@ func (r RoleRepository) ListProjectRoles(projectId string, pg *pagination.Pagina } return roles, nil -} +}- func (r RoleRepository) Get(id uuid.UUID) (*domain.Role, error) { var role Role @@ -288,7 +288,7 @@ func ConvertDomainToRepoProjectRole(domainRole *domain.ProjectRole) *ProjectRole RoleID: domainRole.RoleID, ProjectID: domainRole.ProjectID, Role: *ConverDomainToRepoRole(&domainRole.Role), - Project: *ConvertDomainToRepoProject(&domainRole.Project), + Project: domainRole.Project, } } @@ -298,6 +298,6 @@ func ConvertRepoToDomainProjectRole(repoRole *ProjectRole) *domain.ProjectRole { RoleID: repoRole.RoleID, ProjectID: repoRole.ProjectID, Role: *ConvertRepoToDomainRole(&repoRole.Role), - Project: *ConvertRepoToDomainProject(&repoRole.Project), + Project: repoRole.Project, } } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 23882b28..38e670e6 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -1,10 +1,9 @@ package domain import ( - "time" - "github.com/google/uuid" "gorm.io/gorm" + "time" ) func (a *Project) BeforeCreate(*gorm.DB) (err error) { @@ -12,11 +11,6 @@ func (a *Project) BeforeCreate(*gorm.DB) (err error) { return nil } -func (t *ProjectRole) BeforeCreate(*gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} - func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { t.ID = uuid.New().String() return nil @@ -84,15 +78,6 @@ type GetProjectResponse struct { Project *ProjectDetailResponse `json:"project"` } -type ProjectRole struct { - ID string `gorm:"primarykey" json:"id"` - Name string `json:"name"` // project-leader, project-member, project-viewer - Description string `json:"description,omitempty"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` -} - type ProjectUser struct { ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` @@ -157,10 +142,6 @@ type UpdateProjectRequest struct { CreateProjectRequest } -type GetProjectRoleResponse struct { - ProjectRole ProjectRole `json:"projectRole"` -} - type GetProjectRolesResponse struct { ProjectRoles []ProjectRole `json:"projectRoles"` } From 27871ee0a16aee7125f5c2e96854f6d7e2c0d4e6 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 15 Feb 2024 14:33:51 +0900 Subject: [PATCH 065/502] refactoring: merge gorm object with domain object --- internal/database/database.go | 24 +- internal/delivery/api/endpoint.go | 23 +- internal/delivery/http/role.go | 58 ++-- internal/repository/alert.go | 6 +- internal/repository/app-group.go | 8 +- internal/repository/cloud-account.go | 14 +- internal/repository/cluster.go | 18 +- internal/repository/endpoint.go | 80 +++--- internal/repository/organization.go | 81 +++--- internal/repository/permission.go | 387 +++++++++++++------------- internal/repository/role.go | 168 +++++------ internal/repository/role_test.go | 28 -- internal/repository/stack-template.go | 14 +- internal/repository/user.go | 213 ++++++-------- internal/usecase/auth.go | 28 +- internal/usecase/user.go | 42 +-- pkg/domain/endpoint.go | 20 +- pkg/domain/organization.go | 7 +- pkg/domain/permmision.go | 28 +- pkg/domain/project.go | 2 +- pkg/domain/role.go | 24 +- pkg/domain/user.go | 69 +++-- 22 files changed, 617 insertions(+), 725 deletions(-) delete mode 100644 internal/repository/role_test.go diff --git a/internal/database/database.go b/internal/database/database.go index 7d3a295c..6e27de84 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -57,18 +57,15 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&repository.CacheEmailCode{}); err != nil { return err } - if err := db.AutoMigrate(&repository.User{}); err != nil { + if err := db.AutoMigrate(&domain.User{}); err != nil { return err } - if err := db.AutoMigrate(&repository.Role{}); err != nil { - return err - } - if err := db.AutoMigrate(&repository.Policy{}); err != nil { + if err := db.AutoMigrate(&domain.Role{}); err != nil { return err } // Organization - if err := db.AutoMigrate(&repository.Organization{}); err != nil { + if err := db.AutoMigrate(&domain.Organization{}); err != nil { return err } @@ -114,13 +111,24 @@ func migrateSchema(db *gorm.DB) error { return err } - // Project - if err := db.AutoMigrate(&domain.Project{}); err != nil { + // Role + if err := db.AutoMigrate(&domain.Role{}); err != nil { + return err + } + if err := db.AutoMigrate(&domain.Permission{}); err != nil { return err } if err := db.AutoMigrate(&domain.ProjectRole{}); err != nil { return err } + if err := db.AutoMigrate(&domain.Endpoint{}); err != nil { + return err + } + + // Project + if err := db.AutoMigrate(&domain.Project{}); err != nil { + return err + } if err := db.AutoMigrate(&domain.ProjectMember{}); err != nil { return err } diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 00cfc5a4..2a20f6ed 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -20,6 +20,7 @@ const ( VerifyIdentityForLostId VerifyIdentityForLostPassword VerifyToken + DeleteToken // User CreateUser @@ -129,8 +130,6 @@ const ( // Project CreateProject - GetProjectRoles - GetProjectRole GetProjects GetProject UpdateProject @@ -202,6 +201,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "VerifyToken", Group: "Auth", }, + DeleteToken: { + Name: "DeleteToken", + Group: "Auth", + }, CreateUser: { Name: "CreateUser", Group: "User", @@ -542,14 +545,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CreateProject", Group: "Project", }, - GetProjectRoles: { - Name: "GetProjectRoles", - Group: "Project", - }, - GetProjectRole: { - Name: "GetProjectRole", - Group: "Project", - }, GetProjects: { Name: "GetProjects", Group: "Project", @@ -704,6 +699,8 @@ func (e Endpoint) String() string { return "VerifyIdentityForLostPassword" case VerifyToken: return "VerifyToken" + case DeleteToken: + return "DeleteToken" case CreateUser: return "CreateUser" case ListUser: @@ -874,10 +871,6 @@ func (e Endpoint) String() string { return "InstallStack" case CreateProject: return "CreateProject" - case GetProjectRoles: - return "GetProjectRoles" - case GetProjectRole: - return "GetProjectRole" case GetProjects: return "GetProjects" case GetProject: @@ -968,6 +961,8 @@ func GetEndpoint(name string) Endpoint { return VerifyIdentityForLostPassword case "VerifyToken": return VerifyToken + case "DeleteToken": + return DeleteToken case "CreateUser": return CreateUser case "ListUser": diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index c254b7ec..605005e9 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -1,7 +1,6 @@ package http import ( - "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" @@ -125,11 +124,6 @@ func (h RoleHandler) CreateProjectRole(w http.ResponseWriter, r *http.Request) { } // input to dto - projectIdUuid, err := uuid.Parse(projectId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } dto := domain.ProjectRole{ Role: domain.Role{ OrganizationID: organizationId, @@ -137,7 +131,7 @@ func (h RoleHandler) CreateProjectRole(w http.ResponseWriter, r *http.Request) { Description: input.Description, Type: string(domain.RoleTypeProject), }, - ProjectID: projectIdUuid, + ProjectID: projectId, } if err := h.roleUsecase.CreateProjectRole(&dto); err != nil { @@ -185,13 +179,13 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { out.Roles = make([]domain.GetTksRoleResponse, len(roles)) for i, role := range roles { out.Roles[i] = domain.GetTksRoleResponse{ - ID: role.ID.String(), - Name: role.Name, - OrganizationID: role.OrganizationID, - Description: role.Description, - Creator: role.Creator.String(), - CreatedAt: role.CreatedAt, - UpdatedAt: role.UpdatedAt, + ID: role.Role.ID, + Name: role.Role.Name, + OrganizationID: role.Role.OrganizationID, + Description: role.Role.Description, + Creator: role.Role.Creator.String(), + CreatedAt: role.Role.CreatedAt, + UpdatedAt: role.Role.UpdatedAt, } } @@ -244,10 +238,10 @@ func (h RoleHandler) ListProjectRoles(w http.ResponseWriter, r *http.Request) { out.Roles = make([]domain.GetProjectRoleResponse, len(roles)) for i, role := range roles { out.Roles[i] = domain.GetProjectRoleResponse{ - ID: role.RoleID.String(), + ID: role.RoleID, Name: role.Role.Name, OrganizationID: role.Role.OrganizationID, - ProjectID: role.ProjectID.String(), + ProjectID: role.ProjectID, Description: role.Role.Description, Creator: role.Role.Creator.String(), CreatedAt: role.Role.CreatedAt, @@ -292,13 +286,13 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // response out := domain.GetTksRoleResponse{ - ID: role.ID.String(), - Name: role.Name, - OrganizationID: role.OrganizationID, - Description: role.Description, - Creator: role.Creator.String(), - CreatedAt: role.CreatedAt, - UpdatedAt: role.UpdatedAt, + ID: role.Role.ID, + Name: role.Role.Name, + OrganizationID: role.Role.OrganizationID, + Description: role.Role.Description, + Creator: role.Role.Creator.String(), + CreatedAt: role.Role.CreatedAt, + UpdatedAt: role.Role.UpdatedAt, } ResponseJSON(w, r, http.StatusOK, out) @@ -335,10 +329,10 @@ func (h RoleHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { // response out := domain.GetProjectRoleResponse{ - ID: role.RoleID.String(), + ID: role.RoleID, Name: role.Role.Name, OrganizationID: role.Role.OrganizationID, - ProjectID: role.ProjectID.String(), + ProjectID: role.ProjectID, Description: role.Role.Description, Creator: role.Role.Creator.String(), CreatedAt: role.Role.CreatedAt, @@ -443,14 +437,9 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - roleIdUuid, err := uuid.Parse(roleId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } dto := domain.TksRole{ Role: domain.Role{ - ID: roleIdUuid, + ID: roleId, Name: input.Name, Description: input.Description, }, @@ -499,14 +488,9 @@ func (h RoleHandler) UpdateProjectRole(w http.ResponseWriter, r *http.Request) { } // input to dto - roleIdUuid, err := uuid.Parse(roleId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } dto := domain.ProjectRole{ Role: domain.Role{ - ID: roleIdUuid, + ID: roleId, Name: input.Name, Description: input.Description, }, diff --git a/internal/repository/alert.go b/internal/repository/alert.go index 0db9a350..4e8c8575 100644 --- a/internal/repository/alert.go +++ b/internal/repository/alert.go @@ -43,7 +43,7 @@ type Alert struct { ID uuid.UUID `gorm:"primarykey"` OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` Name string Code string Description string @@ -72,8 +72,8 @@ type AlertAction struct { AlertId uuid.UUID Content string Status domain.AlertActionStatus - TakerId *uuid.UUID `gorm:"type:uuid"` - Taker User `gorm:"foreignKey:TakerId"` + TakerId *uuid.UUID `gorm:"type:uuid"` + Taker domain.User `gorm:"foreignKey:TakerId"` } func (c *AlertAction) BeforeCreate(tx *gorm.DB) (err error) { diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index be160e53..d78aa1bc 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -49,10 +49,10 @@ type AppGroup struct { WorkflowId string Status domain.AppGroupStatus StatusDesc string - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` } func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index a6dd6102..5d9a7de9 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -41,9 +41,9 @@ type CloudAccount struct { ID uuid.UUID `gorm:"primarykey"` OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - Name string `gorm:"index"` - Description string `gorm:"index"` + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` + Name string `gorm:"index"` + Description string `gorm:"index"` Resource string CloudService string WorkflowId string @@ -51,10 +51,10 @@ type CloudAccount struct { StatusDesc string AwsAccountId string CreatedIAM bool - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` } func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 66de2205..e637c040 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -53,8 +53,8 @@ type Cluster struct { Name string `gorm:"index"` CloudService string `gorm:"default:AWS"` OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - Description string `gorm:"index"` + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` + Description string `gorm:"index"` WorkflowId string Status domain.ClusterStatus StatusDesc string @@ -76,10 +76,10 @@ type Cluster struct { TksUserNode int TksUserNodeMax int TksUserNodeType string - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` } type ClusterFavorite struct { @@ -87,9 +87,9 @@ type ClusterFavorite struct { ID uuid.UUID `gorm:"primarykey;type:uuid"` ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - UserId uuid.UUID `gorm:"type:uuid"` - User User `gorm:"foreignKey:UserId"` + Cluster Cluster `gorm:"foreignKey:ClusterId"` + UserId uuid.UUID `gorm:"type:uuid"` + User domain.User `gorm:"foreignKey:UserId"` } func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go index 16fd5968..1bd4d4cc 100644 --- a/internal/repository/endpoint.go +++ b/internal/repository/endpoint.go @@ -27,24 +27,19 @@ func NewEndpointRepository(db *gorm.DB) *EndpointRepository { } } -type Endpoint struct { - gorm.Model - - ID uuid.UUID `gorm:"type:uuid;primary_key;"` - - Name string `gorm:"type:text;not null;unique"` - Group string `gorm:"type:text;"` - PermissionID uuid.UUID `gorm:"type:uuid;"` - Permission Permission `gorm:"foreignKey:PermissionID;"` -} - -func (e *Endpoint) BeforeCreate(tx *gorm.DB) error { - e.ID = uuid.New() - return nil -} +//type Endpoint struct { +// gorm.Model +// +// ID uuid.UUID `gorm:"type:uuid;primary_key;"` +// +// Name string `gorm:"type:text;not null;unique"` +// Group string `gorm:"type:text;"` +// PermissionID uuid.UUID `gorm:"type:uuid;"` +// Permission Permission `gorm:"foreignKey:PermissionID;"` +//} func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { - obj := &Endpoint{ + obj := &domain.Endpoint{ Name: endpoint.Name, Group: endpoint.Group, PermissionID: endpoint.PermissionID, @@ -59,13 +54,13 @@ func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint, error) { var endpoints []*domain.Endpoint - var objs []*Endpoint + var objs []*domain.Endpoint if pg == nil { pg = pagination.NewDefaultPagination() } filterFunc := CombinedGormFilter("endpoints", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(e.db.Model(&Endpoint{})) + db := filterFunc(e.db.Model(&domain.Endpoint{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -81,7 +76,7 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint Name: obj.Name, Group: obj.Group, PermissionID: obj.PermissionID, - Permission: *ConvertRepoToDomainPermission(&obj.Permission), + Permission: obj.Permission, }) } @@ -89,7 +84,7 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint } func (e *EndpointRepository) Get(id uuid.UUID) (*domain.Endpoint, error) { - var obj Endpoint + var obj domain.Endpoint if err := e.db.Preload("Permission").First(&obj, "id = ?", id).Error; err != nil { return nil, err @@ -103,7 +98,7 @@ func (e *EndpointRepository) Get(id uuid.UUID) (*domain.Endpoint, error) { } func (e *EndpointRepository) Update(endpoint *domain.Endpoint) error { - obj := &Endpoint{ + obj := &domain.Endpoint{ ID: endpoint.ID, Name: endpoint.Name, Group: endpoint.Group, @@ -117,24 +112,25 @@ func (e *EndpointRepository) Update(endpoint *domain.Endpoint) error { return nil } -// domain.Endpoint to repository.Endpoint -func ConvertDomainToRepoEndpoint(endpoint *domain.Endpoint) *Endpoint { - return &Endpoint{ - ID: endpoint.ID, - Name: endpoint.Name, - Group: endpoint.Group, - PermissionID: endpoint.PermissionID, - Permission: *ConvertDomainToRepoPermission(&endpoint.Permission), - } -} - -// repository.Endpoint to domain.Endpoint -func ConvertRepoToDomainEndpoint(endpoint *Endpoint) *domain.Endpoint { - return &domain.Endpoint{ - ID: endpoint.ID, - Name: endpoint.Name, - Group: endpoint.Group, - PermissionID: endpoint.PermissionID, - Permission: *ConvertRepoToDomainPermission(&endpoint.Permission), - } -} +// +//// domain.Endpoint to repository.Endpoint +//func ConvertDomainToRepoEndpoint(endpoint *domain.Endpoint) *Endpoint { +// return &Endpoint{ +// ID: endpoint.ID, +// Name: endpoint.Name, +// Group: endpoint.Group, +// PermissionID: endpoint.PermissionID, +// Permission: *ConvertDomainToRepoPermission(&endpoint.Permission), +// } +//} +// +//// repository.Endpoint to domain.Endpoint +//func ConvertRepoToDomainEndpoint(endpoint *Endpoint) *domain.Endpoint { +// return &domain.Endpoint{ +// ID: endpoint.ID, +// Name: endpoint.Name, +// Group: endpoint.Group, +// PermissionID: endpoint.PermissionID, +// Permission: *ConvertRepoToDomainPermission(&endpoint.Permission), +// } +//} diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 12e31962..2c23b54b 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -30,20 +30,21 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { } } -// Models -type Organization struct { - gorm.Model - - ID string `gorm:"primarykey;type:varchar(36);not null"` - Name string - Description string - Phone string - WorkflowId string - Status domain.OrganizationStatus - StatusDesc string - Creator uuid.UUID - PrimaryClusterId string // allow null -} +// +//// Models +//type Organization struct { +// gorm.Model +// +// ID string `gorm:"primarykey;type:varchar(36);not null"` +// Name string +// Description string +// Phone string +// WorkflowId string +// Status domain.OrganizationStatus +// StatusDesc string +// Creator uuid.UUID +// PrimaryClusterId string // allow null +//} //func (c *Organization) BeforeCreate(tx *gorm.DB) (err error) { // c.ID = helper.GenerateOrganizationId() @@ -52,10 +53,10 @@ type Organization struct { func (r *OrganizationRepository) Create(organizationId string, name string, creator uuid.UUID, phone string, description string) (domain.Organization, error) { - organization := Organization{ + organization := domain.Organization{ ID: organizationId, Name: name, - Creator: creator, + Creator: creator.String(), Phone: phone, Description: description, Status: domain.OrganizationStatus_PENDING, @@ -70,12 +71,19 @@ func (r *OrganizationRepository) Create(organizationId string, name string, crea } func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (*[]domain.Organization, error) { - var organizations []Organization + var organizations []domain.Organization var out []domain.Organization if pg == nil { pg = pagination.NewPagination(nil) } + filterFunc := CombinedGormFilter("organizations", pg.GetFilters(), pg.CombinedFilter) + db := filterFunc(r.db.Model(&domain.Organization{})) + db.Count(&pg.TotalRows) + + pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) + orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) + res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&organizations) _, res := pg.Fetch(r.db, &organizations) if res.Error != nil { return nil, res.Error @@ -89,7 +97,7 @@ func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (*[]domain.Org } func (r *OrganizationRepository) Get(id string) (domain.Organization, error) { - var organization Organization + var organization domain.Organization res := r.db.First(&organization, "id = ?", id) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) @@ -100,8 +108,8 @@ func (r *OrganizationRepository) Get(id string) (domain.Organization, error) { } func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) { - var organization Organization - res := r.db.Model(&Organization{}). + var organization domain.Organization + res := r.db.Model(&domain.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "name": in.Name, @@ -113,7 +121,7 @@ func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateO log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return domain.Organization{}, res.Error } - res = r.db.Model(&Organization{}).Where("id = ?", organizationId).Find(&organization) + res = r.db.Model(&domain.Organization{}).Where("id = ?", organizationId).Find(&organization) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return domain.Organization{}, res.Error @@ -123,7 +131,7 @@ func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateO } func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error { - res := r.db.Model(&Organization{}). + res := r.db.Model(&domain.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "primary_cluster_id": primaryClusterId, @@ -137,7 +145,7 @@ func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, p } func (r *OrganizationRepository) Delete(organizationId string) error { - res := r.db.Delete(&Organization{}, "id = ?", organizationId) + res := r.db.Delete(&domain.Organization{}, "id = ?", organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -147,7 +155,7 @@ func (r *OrganizationRepository) Delete(organizationId string) error { } func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error { - res := r.db.Model(&Organization{}). + res := r.db.Model(&domain.Organization{}). Where("ID = ?", organizationId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) if res.Error != nil { @@ -157,35 +165,14 @@ func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId return nil } -func (r *OrganizationRepository) reflect(organization Organization) (out domain.Organization) { +func (r *OrganizationRepository) reflect(organization domain.Organization) (out domain.Organization) { if err := serializer.Map(organization.Model, &out); err != nil { log.Error(err) } if err := serializer.Map(organization, &out); err != nil { log.Error(err) } - out.Creator = organization.Creator.String() + out.Creator = organization.Creator return } - -func ConvertDomainToRepoOrganization(organization *domain.Organization) *Organization { - - return &Organization{ - ID: organization.ID, - Name: organization.Name, - Description: organization.Description, - Phone: organization.Phone, - Creator: uuid.MustParse(organization.Creator), - } -} - -func ConvertRepoToDomainOrganization(organization *Organization) *domain.Organization { - return &domain.Organization{ - ID: organization.ID, - Name: organization.Name, - Description: organization.Description, - Phone: organization.Phone, - Creator: organization.Creator.String(), - } -} diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 0580244c..5a28a708 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -24,196 +24,197 @@ func NewPermissionRepository(db *gorm.DB) *PermissionRepository { } } -type Permission struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid;"` - Name string - - IsAllowed *bool `gorm:"type:boolean;"` - RoleID *uuid.UUID - Role *Role `gorm:"foreignKey:RoleID;references:ID;"` - Endpoints []*Endpoint `gorm:"one2many:endpoints;"` - - ParentID *uuid.UUID - Parent *Permission `gorm:"foreignKey:ParentID;references:ID;"` - Children []*Permission `gorm:"foreignKey:ParentID;references:ID;"` -} - -func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { - if p.ID == uuid.Nil { - p.ID = uuid.New() - } - return nil -} - -func (r PermissionRepository) Create(p *domain.Permission) error { - //var parent *Permission - //var children []*Permission - // - //if p.Parent != nil { - // parent = &Permission{} - // result := r.db.First(&parent, "id = ?", p.Parent.ID) - // if result.Error != nil { - // return result.Error - // } - //} - //if p.Children != nil { - // for _, child := range p.Children { - // newChild := &Permission{} - // result := r.db.First(&newChild, "id = ?", child.ID) - // if result.Error != nil { - // return result.Error - // } - // children = append(children, newChild) - // } - //} - - permission := ConvertDomainToRepoPermission(p) - - return r.db.Create(permission).Error -} - -func (r PermissionRepository) List() ([]*domain.Permission, error) { - var permissions []*Permission - var outs []*domain.Permission - - err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL").Find(&permissions).Error - if err != nil { - return nil, err - } - - for _, permission := range permissions { - outs = append(outs, ConvertRepoToDomainPermission(permission)) - } - return outs, nil -} - -func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { - permission := &Permission{} - result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) - if result.Error != nil { - return nil, result.Error - } - - return ConvertRepoToDomainPermission(permission), nil -} - -func (r PermissionRepository) Delete(id uuid.UUID) error { - return r.db.Delete(&Permission{}, id).Error -} - -func (r PermissionRepository) Update(p *domain.Permission) error { - permission := ConvertDomainToRepoPermission(p) - - return r.db.Updates(permission).Error - - //var parent *Permission - //var children []*Permission - // - //if p.Parent != nil { - // parent = &Permission{} - // result := r.db.First(&parent, "id = ?", p.Parent.ID) - // if result.Error != nil { - // return result.Error - // } - //} - //if p.Children != nil { - // for _, child := range p.Children { - // newChild := &Permission{} - // result := r.db.First(&newChild, "id = ?", child.ID) - // if result.Error != nil { - // return result.Error - // } - // children = append(children, newChild) - // } - //} - // - //permission := &Permission{} - // - //result := r.db.First(&permission, "id = ?", p.ID) - //if result.Error != nil { - // return result.Error - //} - // - //permission.Name = p.Name - //permission.Parent = parent - //permission.Children = children - //permission.IsAllowed = p.IsAllowed - // - //return r.db.Save(permission).Error -} - -// repository.Permission to domain.Permission -func ConvertRepoToDomainPermission(repoPerm *Permission) *domain.Permission { - if repoPerm == nil { - return nil - } - - if repoPerm.Endpoints == nil { - repoPerm.Endpoints = []*Endpoint{} - } - var domainEndpoints []*domain.Endpoint - for _, endpoint := range repoPerm.Endpoints { - domainEndpoints = append(domainEndpoints, ConvertRepoToDomainEndpoint(endpoint)) - } - - // Domain Permission 객체 생성 - domainPerm := &domain.Permission{ - ID: repoPerm.ID, - Name: repoPerm.Name, - ParentID: repoPerm.ParentID, - IsAllowed: repoPerm.IsAllowed, - Endpoints: domainEndpoints, - } - - // 자식 권한들 변환 - for _, child := range repoPerm.Children { - domainChild := ConvertRepoToDomainPermission(child) - domainPerm.Children = append(domainPerm.Children, domainChild) - } - - // 부모 권한 변환 (부모 권한이 있을 경우만) - if repoPerm.Parent != nil { - domainPerm.Parent = ConvertRepoToDomainPermission(repoPerm.Parent) - } - - return domainPerm -} - -// domain.Permission to repository.Permission -func ConvertDomainToRepoPermission(domainPerm *domain.Permission) *Permission { - if domainPerm == nil { - return nil - } - - if domainPerm.Endpoints == nil { - domainPerm.Endpoints = []*domain.Endpoint{} - } - var repoEndpoints []*Endpoint - for _, endpoint := range domainPerm.Endpoints { - repoEndpoints = append(repoEndpoints, ConvertDomainToRepoEndpoint(endpoint)) - } - - // Domain Permission 객체 생성 - repoPerm := &Permission{ - ID: domainPerm.ID, - Name: domainPerm.Name, - ParentID: domainPerm.ParentID, - IsAllowed: domainPerm.IsAllowed, - Endpoints: repoEndpoints, - } - - // 자식 권한들 변환 - for _, child := range domainPerm.Children { - repoChild := ConvertDomainToRepoPermission(child) - repoPerm.Children = append(repoPerm.Children, repoChild) - } - - // 부모 권한 변환 (부모 권한이 있을 경우만) - if domainPerm.Parent != nil { - repoPerm.Parent = ConvertDomainToRepoPermission(domainPerm.Parent) - } - - return repoPerm -} +// +//type Permission struct { +// gorm.Model +// +// ID uuid.UUID `gorm:"primarykey;type:uuid;"` +// Name string +// +// IsAllowed *bool `gorm:"type:boolean;"` +// RoleID string +// Role *Role `gorm:"foreignKey:RoleID;references:ID;"` +// Endpoints []*Endpoint `gorm:"one2many:endpoints;"` +// +// ParentID *uuid.UUID +// Parent *Permission `gorm:"foreignKey:ParentID;references:ID;"` +// Children []*Permission `gorm:"foreignKey:ParentID;references:ID;"` +//} +// +//func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { +// if p.ID == uuid.Nil { +// p.ID = uuid.New() +// } +// return nil +//} +// +//func (r PermissionRepository) Create(p *domain.Permission) error { +// //var parent *Permission +// //var children []*Permission +// // +// //if p.Parent != nil { +// // parent = &Permission{} +// // result := r.db.First(&parent, "id = ?", p.Parent.ID) +// // if result.Error != nil { +// // return result.Error +// // } +// //} +// //if p.Children != nil { +// // for _, child := range p.Children { +// // newChild := &Permission{} +// // result := r.db.First(&newChild, "id = ?", child.ID) +// // if result.Error != nil { +// // return result.Error +// // } +// // children = append(children, newChild) +// // } +// //} +// +// permission := ConvertDomainToRepoPermission(p) +// +// return r.db.Create(permission).Error +//} +// +//func (r PermissionRepository) List() ([]*domain.Permission, error) { +// var permissions []*domain.Permission +// var outs []*domain.Permission +// +// err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL").Find(&permissions).Error +// if err != nil { +// return nil, err +// } +// +// for _, permission := range permissions { +// outs = append(outs, ConvertRepoToDomainPermission(permission)) +// } +// return outs, nil +//} +// +//func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { +// permission := &domain.Permission{} +// result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) +// if result.Error != nil { +// return nil, result.Error +// } +// +// return ConvertRepoToDomainPermission(permission), nil +//} +// +//func (r PermissionRepository) Delete(id uuid.UUID) error { +// return r.db.Delete(&Permission{}, id).Error +//} + +//func (r PermissionRepository) Update(p *domain.Permission) error { +// permission := ConvertDomainToRepoPermission(p) +// +// return r.db.Updates(permission).Error +// +// //var parent *Permission +// //var children []*Permission +// // +// //if p.Parent != nil { +// // parent = &Permission{} +// // result := r.db.First(&parent, "id = ?", p.Parent.ID) +// // if result.Error != nil { +// // return result.Error +// // } +// //} +// //if p.Children != nil { +// // for _, child := range p.Children { +// // newChild := &Permission{} +// // result := r.db.First(&newChild, "id = ?", child.ID) +// // if result.Error != nil { +// // return result.Error +// // } +// // children = append(children, newChild) +// // } +// //} +// // +// //permission := &Permission{} +// // +// //result := r.db.First(&permission, "id = ?", p.ID) +// //if result.Error != nil { +// // return result.Error +// //} +// // +// //permission.Name = p.Name +// //permission.Parent = parent +// //permission.Children = children +// //permission.IsAllowed = p.IsAllowed +// // +// //return r.db.Save(permission).Error +//} +// +//// repository.Permission to domain.Permission +//func ConvertRepoToDomainPermission(repoPerm *domain.Permission) *domain.Permission { +// if repoPerm == nil { +// return nil +// } +// +// if repoPerm.Endpoints == nil { +// repoPerm.Endpoints = []*Endpoint{} +// } +// var domainEndpoints []*domain.Endpoint +// for _, endpoint := range repoPerm.Endpoints { +// domainEndpoints = append(domainEndpoints, ConvertRepoToDomainEndpoint(endpoint)) +// } +// +// // Domain Permission 객체 생성 +// domainPerm := &domain.Permission{ +// ID: repoPerm.ID, +// Name: repoPerm.Name, +// ParentID: repoPerm.ParentID, +// IsAllowed: repoPerm.IsAllowed, +// Endpoints: domainEndpoints, +// } +// +// // 자식 권한들 변환 +// for _, child := range repoPerm.Children { +// domainChild := ConvertRepoToDomainPermission(child) +// domainPerm.Children = append(domainPerm.Children, domainChild) +// } +// +// // 부모 권한 변환 (부모 권한이 있을 경우만) +// if repoPerm.Parent != nil { +// domainPerm.Parent = ConvertRepoToDomainPermission(repoPerm.Parent) +// } +// +// return domainPerm +//} +// +//// domain.Permission to repository.Permission +//func ConvertDomainToRepoPermission(domainPerm *domain.Permission) *Permission { +// if domainPerm == nil { +// return nil +// } +// +// if domainPerm.Endpoints == nil { +// domainPerm.Endpoints = []*domain.Endpoint{} +// } +// var repoEndpoints []*Endpoint +// for _, endpoint := range domainPerm.Endpoints { +// repoEndpoints = append(repoEndpoints, ConvertDomainToRepoEndpoint(endpoint)) +// } +// +// // Domain Permission 객체 생성 +// repoPerm := &Permission{ +// ID: domainPerm.ID, +// Name: domainPerm.Name, +// ParentID: domainPerm.ParentID, +// IsAllowed: domainPerm.IsAllowed, +// Endpoints: repoEndpoints, +// } +// +// // 자식 권한들 변환 +// for _, child := range domainPerm.Children { +// repoChild := ConvertDomainToRepoPermission(child) +// repoPerm.Children = append(repoPerm.Children, repoChild) +// } +// +// // 부모 권한 변환 (부모 권한이 있을 경우만) +// if domainPerm.Parent != nil { +// repoPerm.Parent = ConvertDomainToRepoPermission(domainPerm.Parent) +// } +// +// return repoPerm +//} diff --git a/internal/repository/role.go b/internal/repository/role.go index 03736c67..bd61871b 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -9,36 +9,35 @@ import ( "math" ) -type Role struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid;"` - Name string - OrganizationID string - Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;"` - Type string - Creator uuid.UUID - Description string -} - -func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { - if r.ID == uuid.Nil { - r.ID = uuid.New() - } - return nil -} - -type TksRole struct { - RoleID uuid.UUID `gorm:"type:uuid;primary_key;"` - Role Role `gorm:"foreignKey:RoleID;references:ID;"` -} - -type ProjectRole struct { - RoleID uuid.UUID `gorm:"type:uuid;primary_key;"` - Role Role `gorm:"foreignKey:RoleID;references:ID;"` - ProjectID uuid.UUID - Project domain.Project `gorm:"foreignKey:ProjectID;references:ID;"` -} +// +//type Role struct { +// gorm.Model +// +// ID string `gorm:"primarykey;"` +// Name string +// OrganizationID string +// Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;"` +// Type string +// Creator uuid.UUID +// Description string +//} +// +//func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { +// r.ID = uuid.New().String() +// return nil +//} +// +//type TksRole struct { +// RoleID string `gorm:"primarykey;"` +// Role Role `gorm:"foreignKey:RoleID;references:ID;"` +//} + +//type ProjectRole struct { +// RoleID string `gorm:"primarykey;"` +// Role Role `gorm:"foreignKey:RoleID;references:ID;"` +// ProjectID string +// Project domain.Project `gorm:"foreignKey:ProjectID;references:ID;"` +//} type IRoleRepository interface { Create(roleObj interface{}) error @@ -70,8 +69,11 @@ func (r RoleRepository) Create(roleObj interface{}) error { case *domain.ProjectRole: inputRole := roleObj.(*domain.ProjectRole) - role := ConvertDomainToRepoProjectRole(inputRole) - if err := r.db.Create(role).Error; err != nil { + //role := ConvertDomainToRepoProjectRole(inputRole) + //if err := r.db.Create(role).Error; err != nil { + // return err + //} + if err := r.db.Create(inputRole).Error; err != nil { return err } } @@ -81,13 +83,13 @@ func (r RoleRepository) Create(roleObj interface{}) error { func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) { var roles []*domain.Role - var objs []*Role + var objs []*domain.Role if pg == nil { pg = pagination.NewDefaultPagination() } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&Role{})) + db := filterFunc(r.db.Model(&domain.Role{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -109,13 +111,13 @@ func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) { var roles []*domain.TksRole - var objs []*TksRole + var objs []*domain.TksRole if pg == nil { pg = pagination.NewDefaultPagination() } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&TksRole{})) + db := filterFunc(r.db.Model(&domain.TksRole{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -140,13 +142,13 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin func (r RoleRepository) ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) { var roles []*domain.ProjectRole - var objs []*ProjectRole + var objs []*domain.ProjectRole if pg == nil { pg = pagination.NewDefaultPagination() } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&ProjectRole{})) + db := filterFunc(r.db.Model(&domain.ProjectRole{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -160,14 +162,14 @@ func (r RoleRepository) ListProjectRoles(projectId string, pg *pagination.Pagina return nil, res.Error } for _, role := range objs { - roles = append(roles, ConvertRepoToDomainProjectRole(role)) + roles = append(roles, role) } return roles, nil -}- +} func (r RoleRepository) Get(id uuid.UUID) (*domain.Role, error) { - var role Role + var role domain.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } @@ -176,7 +178,7 @@ func (r RoleRepository) Get(id uuid.UUID) (*domain.Role, error) { } func (r RoleRepository) GetTksRole(id uuid.UUID) (*domain.TksRole, error) { - var role TksRole + var role domain.TksRole if err := r.db.Preload("Role").First(&role, "role_id = ?", id).Error; err != nil { return nil, err } @@ -185,24 +187,24 @@ func (r RoleRepository) GetTksRole(id uuid.UUID) (*domain.TksRole, error) { } func (r RoleRepository) GetProjectRole(id uuid.UUID) (*domain.ProjectRole, error) { - var role ProjectRole + var role domain.ProjectRole if err := r.db.Preload("Role").Preload("Project").First(&role, "role_id = ?", id).Error; err != nil { return nil, err } - return ConvertRepoToDomainProjectRole(&role), nil + return &role, nil } func (r RoleRepository) DeleteCascade(id uuid.UUID) error { // manual cascade delete - if err := r.db.Delete(&TksRole{}, "role_id = ?", id).Error; err != nil { + if err := r.db.Delete(&domain.TksRole{}, "role_id = ?", id).Error; err != nil { return err } - if err := r.db.Delete(&ProjectRole{}, "role_id = ?", id).Error; err != nil { + if err := r.db.Delete(&domain.ProjectRole{}, "role_id = ?", id).Error; err != nil { return err } - if err := r.db.Delete(&Role{}, "id = ?", id).Error; err != nil { + if err := r.db.Delete(&domain.Role{}, "id = ?", id).Error; err != nil { return err } @@ -211,23 +213,23 @@ func (r RoleRepository) DeleteCascade(id uuid.UUID) error { func (r RoleRepository) Update(roleObj interface{}) error { switch roleObj.(type) { - case *TksRole: - inputRole := roleObj.(*TksRole) + case *domain.TksRole: + inputRole := roleObj.(*domain.TksRole) role := ConvertRepoToDomainTksRole(inputRole) - if err := r.db.Model(&TksRole{}).Where("id = ?", role.ID).Updates(Role{ - Name: role.Name, - Description: role.Description, + if err := r.db.Model(&domain.TksRole{}).Where("id = ?", role.RoleID).Updates(domain.Role{ + Name: role.Role.Name, + Description: role.Role.Description, }).Error; err != nil { return err } - case *ProjectRole: - inputRole := roleObj.(*ProjectRole) - projectRole := ConvertRepoToDomainProjectRole(inputRole) + case *domain.ProjectRole: + inputRole := roleObj.(*domain.ProjectRole) + //projectRole := ConvertRepoToDomainProjectRole(inputRole) // update role - if err := r.db.Model(&ProjectRole{}).Where("role_id = ?", projectRole.RoleID).Updates(Role{ - Name: projectRole.Role.Name, - Description: projectRole.Role.Description, + if err := r.db.Model(&domain.ProjectRole{}).Where("role_id = ?", inputRole.RoleID).Updates(domain.Role{ + Name: inputRole.Role.Name, + Description: inputRole.Role.Description, }).Error; err != nil { return err } @@ -243,8 +245,8 @@ func NewRoleRepository(db *gorm.DB) IRoleRepository { } // domain.Role to repository.Role -func ConverDomainToRepoRole(domainRole *domain.Role) *Role { - return &Role{ +func ConverDomainToRepoRole(domainRole *domain.Role) *domain.Role { + return &domain.Role{ ID: domainRole.ID, Name: domainRole.Name, OrganizationID: domainRole.OrganizationID, @@ -255,7 +257,7 @@ func ConverDomainToRepoRole(domainRole *domain.Role) *Role { } // repository.Role to domain.Role -func ConvertRepoToDomainRole(repoRole *Role) *domain.Role { +func ConvertRepoToDomainRole(repoRole *domain.Role) *domain.Role { return &domain.Role{ ID: repoRole.ID, Name: repoRole.Name, @@ -267,37 +269,37 @@ func ConvertRepoToDomainRole(repoRole *Role) *domain.Role { } // domain.TksRole to repository.TksRole -func ConvertDomainToRepoTksRole(domainRole *domain.TksRole) *TksRole { - return &TksRole{ +func ConvertDomainToRepoTksRole(domainRole *domain.TksRole) *domain.TksRole { + return &domain.TksRole{ RoleID: domainRole.Role.ID, Role: *ConverDomainToRepoRole(&domainRole.Role), } } // repository.TksRole to domain.TksRole -func ConvertRepoToDomainTksRole(repoRole *TksRole) *domain.TksRole { +func ConvertRepoToDomainTksRole(repoRole *domain.TksRole) *domain.TksRole { return &domain.TksRole{ RoleID: repoRole.RoleID, Role: *ConvertRepoToDomainRole(&repoRole.Role), } } -// domain.ProjectRole to repository.ProjectRole -func ConvertDomainToRepoProjectRole(domainRole *domain.ProjectRole) *ProjectRole { - return &ProjectRole{ - RoleID: domainRole.RoleID, - ProjectID: domainRole.ProjectID, - Role: *ConverDomainToRepoRole(&domainRole.Role), - Project: domainRole.Project, - } -} - -// repository.ProjectRole to domain.ProjectRole -func ConvertRepoToDomainProjectRole(repoRole *ProjectRole) *domain.ProjectRole { - return &domain.ProjectRole{ - RoleID: repoRole.RoleID, - ProjectID: repoRole.ProjectID, - Role: *ConvertRepoToDomainRole(&repoRole.Role), - Project: repoRole.Project, - } -} +//// domain.ProjectRole to repository.ProjectRole +//func ConvertDomainToRepoProjectRole(domainRole *domain.ProjectRole) *ProjectRole { +// return &ProjectRole{ +// RoleID: domainRole.RoleID, +// ProjectID: domainRole.ProjectID, +// Role: *ConverDomainToRepoRole(&domainRole.Role), +// Project: domainRole.Project, +// } +//} +// +//// repository.ProjectRole to domain.ProjectRole +//func ConvertRepoToDomainProjectRole(repoRole *ProjectRole) *domain.ProjectRole { +// return &domain.ProjectRole{ +// RoleID: repoRole.RoleID, +// ProjectID: repoRole.ProjectID, +// Role: *ConvertRepoToDomainRole(&repoRole.Role), +// Project: repoRole.Project, +// } +//} diff --git a/internal/repository/role_test.go b/internal/repository/role_test.go deleted file mode 100644 index 8c9d78a8..00000000 --- a/internal/repository/role_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package repository_test - -import ( - "encoding/json" - "github.com/openinfradev/tks-api/internal/repository" - "testing" -) - -func TestRole(t *testing.T) { - db := db_connection() - - db.AutoMigrate(&repository.Role{}, &repository.Organization{}, &repository.Project{}, &repository.User{}, &repository.TksRole{}, &repository.ProjectRole{}) - - repo := repository.NewRoleRepository(db) - - roles, err := repo.List() - if err != nil { - t.Fatal(err) - } - out, err := json.MarshalIndent(roles, "", " ") - if err != nil { - t.Fatal(err) - } - t.Log("start") - t.Logf("role: %s", string(out)) - t.Log("end") - -} diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 4d3004c8..bb8b28ad 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -37,9 +37,9 @@ type StackTemplate struct { ID uuid.UUID `gorm:"primarykey"` OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - Name string `gorm:"index"` - Description string `gorm:"index"` + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` + Name string `gorm:"index"` + Description string `gorm:"index"` Template string TemplateType string Version string @@ -48,10 +48,10 @@ type StackTemplate struct { KubeVersion string KubeType string Services datatypes.JSON - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` } func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { diff --git a/internal/repository/user.go b/internal/repository/user.go index 5bf6ad10..4663f30a 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -15,24 +15,22 @@ import ( type IUserRepository interface { Create(accountId string, organizationId string, password string, name string) (domain.User, error) CreateWithUuid(uuid uuid.UUID, accountId string, name string, password string, email string, - department string, description string, organizationId string, roleId uuid.UUID) (domain.User, error) + department string, description string, organizationId string, roleId string) (domain.User, error) List(filters ...FilterFunc) (out *[]domain.User, err error) ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]domain.User, err error) Get(accountId string, organizationId string) (domain.User, error) GetByUuid(userId uuid.UUID) (domain.User, error) - UpdateWithUuid(uuid uuid.UUID, accountId string, name string, password string, roleId uuid.UUID, email string, + UpdateWithUuid(uuid uuid.UUID, accountId string, name string, password string, roleId string, email string, department string, description string) (domain.User, error) UpdatePassword(userId uuid.UUID, organizationId string, password string, isTemporary bool) error DeleteWithUuid(uuid uuid.UUID) error Flush(organizationId string) error FetchRoles() (out *[]domain.Role, err error) - AssignRole(accountId string, organizationId string, roleName string) error AccountIdFilter(accountId string) FilterFunc OrganizationFilter(organization string) FilterFunc EmailFilter(email string) FilterFunc NameFilter(name string) FilterFunc - AssignRoleWithUuid(uuid uuid.UUID, roleName string) error } type UserRepository struct { @@ -40,7 +38,7 @@ type UserRepository struct { } func (r *UserRepository) Flush(organizationId string) error { - res := r.db.Where("organization_id = ?", organizationId).Delete(&User{}) + res := r.db.Where("organization_id = ?", organizationId).Delete(&domain.User{}) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -54,34 +52,34 @@ func NewUserRepository(db *gorm.DB) IUserRepository { } } -// Models -type User struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid"` - AccountId string - Name string - Password string - AuthType string `gorm:"authType"` - RoleId uuid.UUID - Role Role `gorm:"foreignKey:RoleId;references:ID"` - OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId;references:ID"` - Creator uuid.UUID - Email string - Department string - Description string - - PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` -} - -func (g *User) BeforeCreate(tx *gorm.DB) (err error) { - g.PasswordUpdatedAt = time.Now() - return nil -} +//// Models +//type User struct { +// gorm.Model +// +// ID uuid.UUID `gorm:"primarykey;type:uuid"` +// AccountId string +// Name string +// Password string +// AuthType string `gorm:"authType"` +// RoleId uuid.UUID +// Role Role `gorm:"foreignKey:RoleId;references:ID"` +// OrganizationId string +// Organization Organization `gorm:"foreignKey:OrganizationId;references:ID"` +// Creator uuid.UUID +// Email string +// Department string +// Description string +// +// PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` +//} + +//func (g *User) BeforeCreate(tx *gorm.DB) (err error) { +// g.PasswordUpdatedAt = time.Now() +// return nil +//} func (r *UserRepository) Create(accountId string, organizationId string, password string, name string) (domain.User, error) { - newUser := User{ + newUser := domain.User{ AccountId: accountId, Password: password, OrganizationId: organizationId, @@ -96,9 +94,9 @@ func (r *UserRepository) Create(accountId string, organizationId string, passwor return r.reflect(newUser), nil } func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name string, password string, email string, - department string, description string, organizationId string, roleId uuid.UUID) (domain.User, error) { + department string, description string, organizationId string, roleId string) (domain.User, error) { - newUser := User{ + newUser := domain.User{ ID: uuid, AccountId: accountId, Password: password, @@ -143,11 +141,11 @@ func (r *UserRepository) NameFilter(name string) FilterFunc { } func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { - var users []User + var users []domain.User var res *gorm.DB if filters == nil { - res = r.db.Model(&User{}).Preload("Organization").Preload("Role").Find(&users) + res = r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Find(&users) } else { combinedFilter := func(filters ...FilterFunc) FilterFunc { return func(user *gorm.DB) *gorm.DB { @@ -158,7 +156,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { } } cFunc := combinedFilter(filters...) - res = cFunc(r.db.Model(&User{}).Preload("Organization").Preload("Role")).Find(&users) + res = cFunc(r.db.Model(&domain.User{}).Preload("Organization").Preload("Role")).Find(&users) } if res.Error != nil { @@ -178,7 +176,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { } func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizationId string) (*[]domain.User, error) { - var users []User + var users []domain.User if pg == nil { pg = pagination.NewPagination(nil) @@ -207,8 +205,8 @@ func (r *UserRepository) Get(accountId string, organizationId string) (domain.Us return r.reflect(user), nil } func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser domain.User, err error) { - user := User{} - res := r.db.Model(&User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) + user := domain.User{} + res := r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) @@ -220,10 +218,10 @@ func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser domain.User, err return r.reflect(user), nil } -func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, password string, roleId uuid.UUID, +func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, password string, roleId string, email string, department string, description string) (domain.User, error) { - var user User - res := r.db.Model(&User{}).Where("id = ?", uuid).Updates(User{ + var user domain.User + res := r.db.Model(&domain.User{}).Where("id = ?", uuid).Updates(domain.User{ AccountId: accountId, Name: name, Password: password, @@ -239,14 +237,14 @@ func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name s log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return domain.User{}, res.Error } - res = r.db.Model(&User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) + res = r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) if res.Error != nil { return domain.User{}, res.Error } return r.reflect(user), nil } func (r *UserRepository) UpdatePassword(userId uuid.UUID, organizationId string, password string, isTemporary bool) error { - var updateUser = User{ + var updateUser = domain.User{ Password: password, } if isTemporary { @@ -254,7 +252,7 @@ func (r *UserRepository) UpdatePassword(userId uuid.UUID, organizationId string, } else { updateUser.PasswordUpdatedAt = time.Now() } - res := r.db.Model(&User{}).Where("id = ? AND organization_id = ?", userId, organizationId). + res := r.db.Model(&domain.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). Select("password", "password_updated_at").Updates(updateUser) if res.RowsAffected == 0 || res.Error != nil { @@ -268,88 +266,33 @@ func (r *UserRepository) UpdatePassword(userId uuid.UUID, organizationId string, return nil } func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { - res := r.db.Unscoped().Delete(&User{}, "id = ?", uuid) - if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return res.Error - } - return nil -} - -// Deprecated: -type Policy struct { - gorm.Model - - //ID uuid.UUID `gorm:"primarykey;type:uuid;"` - RoleId uuid.UUID - Role Role `gorm:"references:ID"` - Name string - Description string - Create bool `gorm:"column:c"` - CreatePriviledge string - Update bool `gorm:"column:u"` - UpdatePriviledge string - Read bool `gorm:"column:r"` - ReadPriviledge string - Delete bool `gorm:"column:d"` - DeletePriviledge string - Creator uuid.UUID -} - -type UserRole struct { - UserId uuid.UUID - User User - RoleId uuid.UUID - Role Role -} - -func (r *UserRepository) AssignRoleWithUuid(uuid uuid.UUID, roleName string) error { - _, err := r.GetByUuid(uuid) - if err != nil { - return err - } - - role, err := r.getRoleByName(roleName) - if err != nil { - return err - } - - newRole := UserRole{ - UserId: uuid, - RoleId: role.ID, - } - res := r.db.Create(&newRole) + res := r.db.Unscoped().Delete(&domain.User{}, "id = ?", uuid) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error } - return nil } -func (r *UserRepository) AssignRole(accountId string, organizationId string, roleName string) error { - user, err := r.getUserByAccountId(accountId, organizationId) - if err != nil { - return err - } - - role, err := r.getRoleByName(roleName) - if err != nil { - return err - } - - newRole := UserRole{ - UserId: user.ID, - RoleId: role.ID, - } - res := r.db.Create(&newRole) - if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return res.Error - } - - return nil -} +//// Deprecated: +//type Policy struct { +// gorm.Model +// +// //ID uuid.UUID `gorm:"primarykey;type:uuid;"` +// RoleId uuid.UUID +// Role Role `gorm:"references:ID"` +// Name string +// Description string +// Create bool `gorm:"column:c"` +// CreatePriviledge string +// Update bool `gorm:"column:u"` +// UpdatePriviledge string +// Read bool `gorm:"column:r"` +// ReadPriviledge string +// Delete bool `gorm:"column:d"` +// DeletePriviledge string +// Creator uuid.UUID +//} func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { role, err := r.getRoleByName(roleName) @@ -361,7 +304,7 @@ func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { } func (r *UserRepository) FetchRoles() (*[]domain.Role, error) { - var roles []Role + var roles []domain.Role res := r.db.Find(&roles) if res.Error != nil { @@ -383,30 +326,30 @@ func (r *UserRepository) FetchRoles() (*[]domain.Role, error) { } // private members -func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (User, error) { - user := User{} - res := r.db.Model(&User{}).Preload("Organization").Preload("Role"). +func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (domain.User, error) { + user := domain.User{} + res := r.db.Model(&domain.User{}).Preload("Organization").Preload("Role"). Find(&user, "account_id = ? AND organization_id = ?", accountId, organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return User{}, res.Error + return domain.User{}, res.Error } if res.RowsAffected == 0 { - return User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } return user, nil } -func (r *UserRepository) getRoleByName(roleName string) (Role, error) { - role := Role{} +func (r *UserRepository) getRoleByName(roleName string) (domain.Role, error) { + role := domain.Role{} res := r.db.First(&role, "name = ?", roleName) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return Role{}, res.Error + return domain.Role{}, res.Error } if res.RowsAffected == 0 { - return Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return domain.Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } //if res.RowsAffected == 0 { @@ -416,7 +359,7 @@ func (r *UserRepository) getRoleByName(roleName string) (Role, error) { return role, nil } -func (r *UserRepository) reflect(user User) domain.User { +func (r *UserRepository) reflect(user domain.User) domain.User { role := domain.Role{ ID: user.Role.ID, Name: user.Role.Name, @@ -444,7 +387,7 @@ func (r *UserRepository) reflect(user User) domain.User { Phone: user.Organization.Phone, Status: user.Organization.Status, StatusDesc: user.Organization.StatusDesc, - Creator: user.Organization.Creator.String(), + Creator: user.Organization.Creator, CreatedAt: user.Organization.CreatedAt, UpdatedAt: user.Organization.UpdatedAt, } @@ -461,13 +404,13 @@ func (r *UserRepository) reflect(user User) domain.User { //} return domain.User{ - ID: user.ID.String(), + ID: user.ID, AccountId: user.AccountId, Password: user.Password, Name: user.Name, Role: role, Organization: organization, - Creator: user.Creator.String(), + Creator: user.Creator, CreatedAt: user.CreatedAt, UpdatedAt: user.UpdatedAt, Email: user.Email, @@ -477,7 +420,7 @@ func (r *UserRepository) reflect(user User) domain.User { } } -func (r *UserRepository) reflectRole(role Role) domain.Role { +func (r *UserRepository) reflectRole(role domain.Role) domain.Role { return domain.Role{ ID: role.ID, Name: role.Name, diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index a641fbee..141df683 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -173,11 +173,7 @@ func (u *AuthUsecase) FindId(code string, email string, userName string, organiz if err != nil { return "", httpErrors.NewInternalServerError(err, "", "") } - userUuid, err := uuid.Parse((*users)[0].ID) - if err != nil { - return "", httpErrors.NewInternalServerError(err, "", "") - } - emailCode, err := u.authRepository.GetEmailCode(userUuid) + emailCode, err := u.authRepository.GetEmailCode((*users)[0].ID) if err != nil { return "", httpErrors.NewInternalServerError(err, "", "") } @@ -187,7 +183,7 @@ func (u *AuthUsecase) FindId(code string, email string, userName string, organiz if emailCode.Code != code { return "", httpErrors.NewBadRequestError(fmt.Errorf("invalid code"), "A_INVALID_CODE", "") } - if err := u.authRepository.DeleteEmailCode(userUuid); err != nil { + if err := u.authRepository.DeleteEmailCode((*users)[0].ID); err != nil { return "", httpErrors.NewInternalServerError(err, "", "") } @@ -205,11 +201,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, return httpErrors.NewInternalServerError(err, "", "") } user := (*users)[0] - userUuid, err := uuid.Parse(user.ID) - if err != nil { - return httpErrors.NewInternalServerError(err, "", "") - } - emailCode, err := u.authRepository.GetEmailCode(userUuid) + emailCode, err := u.authRepository.GetEmailCode(user.ID) if err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -239,7 +231,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, if user.Password, err = helper.HashPassword(randomPassword); err != nil { return httpErrors.NewInternalServerError(err, "", "") } - if err = u.userRepository.UpdatePassword(userUuid, organizationId, user.Password, true); err != nil { + if err = u.userRepository.UpdatePassword(user.ID, organizationId, user.Password, true); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -255,7 +247,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, return httpErrors.NewInternalServerError(err, "", "") } - if err = u.authRepository.DeleteEmailCode(userUuid); err != nil { + if err = u.authRepository.DeleteEmailCode(user.ID); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -285,17 +277,13 @@ func (u *AuthUsecase) VerifyIdentity(accountId string, email string, userName st if err != nil { return httpErrors.NewInternalServerError(err, "", "") } - userUuid, err := uuid.Parse((*users)[0].ID) - if err != nil { - return httpErrors.NewInternalServerError(err, "", "") - } - _, err = u.authRepository.GetEmailCode(userUuid) + _, err = u.authRepository.GetEmailCode((*users)[0].ID) if err != nil { - if err := u.authRepository.CreateEmailCode(userUuid, code); err != nil { + if err := u.authRepository.CreateEmailCode((*users)[0].ID, code); err != nil { return httpErrors.NewInternalServerError(err, "", "") } } else { - if err := u.authRepository.UpdateEmailCode(userUuid, code); err != nil { + if err := u.authRepository.UpdateEmailCode((*users)[0].ID, code); err != nil { return httpErrors.NewInternalServerError(err, "", "") } } diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 12cfa33a..1c1ce670 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -77,11 +77,7 @@ func (u *UserUsecase) RenewalPasswordExpiredTimeByAccountId(ctx context.Context, } return httpErrors.NewInternalServerError(err, "", "") } - userId, err := uuid.Parse(user.ID) - if err != nil { - return httpErrors.NewInternalServerError(err, "", "") - } - return u.RenewalPasswordExpiredTime(ctx, userId) + return u.RenewalPasswordExpiredTime(ctx, user.ID) } func (u *UserUsecase) ResetPassword(userId uuid.UUID) error { @@ -141,11 +137,7 @@ func (u *UserUsecase) ResetPasswordByAccountId(accountId string, organizationId } return httpErrors.NewInternalServerError(err, "", "") } - userId, err := uuid.Parse(user.ID) - if err != nil { - return httpErrors.NewInternalServerError(err, "", "") - } - return u.ResetPassword(userId) + return u.ResetPassword(user.ID) } func (u *UserUsecase) ValidateAccount(userId uuid.UUID, password string, organizationId string) error { @@ -322,16 +314,12 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s if err != nil { return errors.Wrap(err, "getting user from repository failed") } - userUuid, err := uuid.Parse(user.ID) - if err != nil { - return errors.Wrap(err, "parsing uuid failed") - } hashedPassword, err := helper.HashPassword(newPassword) if err != nil { return errors.Wrap(err, "hashing password failed") } - err = u.userRepository.UpdatePassword(userUuid, organizationId, hashedPassword, false) + err = u.userRepository.UpdatePassword(user.ID, organizationId, hashedPassword, false) if err != nil { return errors.Wrap(err, "updating user in repository failed") } @@ -437,11 +425,6 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u return nil, fmt.Errorf("multiple users found") } - userUuid, err := uuid.Parse((*users)[0].ID) - if err != nil { - return nil, err - } - originPassword := (*users)[0].Password roleUuid := (*users)[0].Role.ID @@ -449,7 +432,7 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u return nil, err } - *user, err = u.userRepository.UpdateWithUuid(userUuid, user.AccountId, user.Name, originPassword, roleUuid, user.Email, + *user, err = u.userRepository.UpdateWithUuid((*users)[0].ID, user.AccountId, user.Name, originPassword, roleUuid, user.Email, user.Department, user.Description) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") @@ -483,11 +466,7 @@ func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, o return err } - userUuid, err := uuid.Parse(user.ID) - if err != nil { - return err - } - err = u.userRepository.DeleteWithUuid(userUuid) + err = u.userRepository.DeleteWithUuid(user.ID) if err != nil { return err } @@ -597,21 +576,16 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st if user.Role.Name != (*users)[0].Role.Name { originGroupName := fmt.Sprintf("%s@%s", (*users)[0].Role.Name, userInfo.GetOrganizationId()) newGroupName := fmt.Sprintf("%s@%s", user.Role.Name, userInfo.GetOrganizationId()) - if err := u.kc.LeaveGroup(userInfo.GetOrganizationId(), (*users)[0].ID, originGroupName); err != nil { + if err := u.kc.LeaveGroup(userInfo.GetOrganizationId(), (*users)[0].ID.String(), originGroupName); err != nil { log.ErrorfWithContext(ctx, "leave group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } - if err := u.kc.JoinGroup(userInfo.GetOrganizationId(), (*users)[0].ID, newGroupName); err != nil { + if err := u.kc.JoinGroup(userInfo.GetOrganizationId(), (*users)[0].ID.String(), newGroupName); err != nil { log.ErrorfWithContext(ctx, "join group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } } - userUuid, err := uuid.Parse((*users)[0].ID) - if err != nil { - return nil, err - } - originPassword := (*users)[0].Password roles, err := u.userRepository.FetchRoles() @@ -628,7 +602,7 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st return nil, err } - *user, err = u.userRepository.UpdateWithUuid(userUuid, user.AccountId, user.Name, originPassword, roleUuid, user.Email, + *user, err = u.userRepository.UpdateWithUuid((*users)[0].ID, user.AccountId, user.Name, originPassword, roleUuid, user.Email, user.Department, user.Description) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index 84006eac..6926dbe5 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -1,11 +1,19 @@ package domain -import "github.com/google/uuid" +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) type Endpoint struct { - ID uuid.UUID `json:"id"` - Name string `json:"name"` - Group string `json:"group"` - PermissionID uuid.UUID `json:"permissionId"` - Permission Permission `json:"permission"` + ID uuid.UUID `gorm:"type:uuid;primaryKey;" json:"id"` + Name string `gorm:"type:text;not null;unique" json:"name"` + Group string `gorm:"type:text;" json:"group"` + PermissionID uuid.UUID `gorm:"type:uuid;" json:"permissionId"` + Permission *Permission `gorm:"foreignKey:PermissionID;" json:"permission"` +} + +func (e *Endpoint) BeforeCreate(tx *gorm.DB) error { + e.ID = uuid.New() + return nil } diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 31667dc3..87f94611 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -1,6 +1,7 @@ package domain import ( + "gorm.io/gorm" "time" ) @@ -48,8 +49,10 @@ func (m OrganizationStatus) FromString(s string) OrganizationStatus { return OrganizationStatus_ERROR } -type Organization = struct { - ID string `json:"id"` +type Organization struct { + gorm.Model + + ID string `gorm:"primarykey;type:varchar(36);not null" json:"id"` Name string `json:"name"` Description string `json:"description"` Phone string `json:"phone"` diff --git a/pkg/domain/permmision.go b/pkg/domain/permmision.go index c9b40762..c3cf0d84 100644 --- a/pkg/domain/permmision.go +++ b/pkg/domain/permmision.go @@ -1,18 +1,30 @@ package domain -import "github.com/google/uuid" +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) type Permission struct { - ID uuid.UUID `json:"id"` + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"id"` Name string `json:"name"` - IsAllowed *bool `json:"is_allowed,omitempty"` - RoleID *uuid.UUID `json:"role_id,omitempty"` - Role *Role `json:"role,omitempty"` - Endpoints []*Endpoint `json:"endpoints,omitempty"` + IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` + RoleID *string `json:"role_id,omitempty"` + Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` + Endpoints []*Endpoint `gorm:"one2many:endpoints;" json:"endpoints,omitempty"` // omit empty ParentID *uuid.UUID `json:"parent_id,omitempty"` - Parent *Permission `json:"parent,omitempty"` - Children []*Permission `json:"children,omitempty"` + Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` + Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` +} + +func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { + if p.ID == uuid.Nil { + p.ID = uuid.New() + } + return nil } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 38e670e6..c55d0a3d 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -99,7 +99,7 @@ type ProjectMember struct { ProjectUserId uuid.UUID `json:"projectUserId"` ProjectUser *ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectUser"` ProjectRoleId string `json:"projectRoleId"` - ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` + ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:RoleID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` IsProjectLeader bool `gorm:"default:false" json:"projectLeader"` CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` diff --git a/pkg/domain/role.go b/pkg/domain/role.go index d2025254..a733e9a5 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -2,6 +2,7 @@ package domain import ( "github.com/google/uuid" + "gorm.io/gorm" "time" ) @@ -13,11 +14,18 @@ const ( RoleTypeProject RoleType = "project" ) +func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { + r.ID = uuid.New().String() + return nil +} + type Role struct { - ID uuid.UUID `json:"id"` + gorm.Model + + ID string `gorm:"primarykey;" json:"id"` Name string `json:"name"` OrganizationID string `json:"organizationId"` - Organization Organization `json:"organization"` + Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;" json:"organization"` Type string `json:"type"` Description string `json:"description"` Creator uuid.UUID `json:"creator"` @@ -26,15 +34,15 @@ type Role struct { } type TksRole struct { - RoleID uuid.UUID `json:"roleId"` - Role + RoleID string `gorm:"primarykey;" json:"roleId"` + Role Role `gorm:"foreignKey:RoleID;references:ID;"` } type ProjectRole struct { - RoleID uuid.UUID `json:"roleId"` - Role Role `json:"role"` - ProjectID uuid.UUID `json:"projectID"` - Project Project `json:"project"` + RoleID string `gorm:"primaryKey" json:"roleId"` + Role Role `gorm:"foreignKey:RoleID;references:ID;" json:"role"` + ProjectID string `json:"projectID"` + Project Project `gorm:"foreignKey:ProjectID;references:ID;" json:"project"` } //type Role = struct { diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 138b0edc..77c9092b 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -1,17 +1,21 @@ package domain import ( + "github.com/google/uuid" + "gorm.io/gorm" "time" ) -type User = struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Password string `json:"password"` - Name string `json:"name"` - Token string `json:"token"` - Role Role `json:"role"` - Organization Organization `json:"organization"` +type User struct { + ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` + AccountId string `json:"accountId"` + Password string `json:"password"` + Name string `json:"name"` + Token string `json:"token"` + RoleId string + Role Role `gorm:"foreignKey:RoleId;references:ID" json:"role"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` Creator string `json:"creator"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` @@ -23,27 +27,28 @@ type User = struct { Description string `json:"description"` } -type SimpleRoleResponse = struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` -} - -type Policy = struct { - ID string `json:"id"` - Name string `json:"name"` - Create bool `json:"create"` - CreatePriviledge string `json:"createPriviledge"` - Update bool `json:"update"` - UpdatePriviledge string `json:"updatePriviledge"` - Read bool `json:"read"` - ReadPriviledge string `json:"readPriviledge"` - Delete bool `json:"delete"` - DeletePriviledge string `json:"deletePriviledge"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} +func (g *User) BeforeCreate(tx *gorm.DB) (err error) { + g.PasswordUpdatedAt = time.Now() + return nil +} + +// +//// Deprecated: Policy is deprecated, use Permission instead. +//type Policy = struct { +// ID string `json:"id"` +// Name string `json:"name"` +// Create bool `json:"create"` +// CreatePriviledge string `json:"createPriviledge"` +// Update bool `json:"update"` +// UpdatePriviledge string `json:"updatePriviledge"` +// Read bool `json:"read"` +// ReadPriviledge string `json:"readPriviledge"` +// Delete bool `json:"delete"` +// DeletePriviledge string `json:"deletePriviledge"` +// Creator string `json:"creator"` +// CreatedAt time.Time `json:"createdAt"` +// UpdatedAt time.Time `json:"updatedAt"` +//} type CreateUserRequest struct { AccountId string `json:"accountId" validate:"required"` @@ -55,6 +60,12 @@ type CreateUserRequest struct { Description string `json:"description" validate:"min=0,max=100"` } +type SimpleRoleResponse = struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` +} + type SimpleUserResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` From fa75ab629b5e6dc2cb817a11c02d462efc5d0b9c Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 15 Feb 2024 15:55:19 +0900 Subject: [PATCH 066/502] refactoring: remove pw validation on DB which is duplicated action --- internal/usecase/auth.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 141df683..564601a1 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -74,16 +74,19 @@ func (u *AuthUsecase) Login(accountId string, password string, organizationId st if err != nil { return domain.User{}, httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") } - if !helper.CheckPasswordHash(user.Password, password) { - return domain.User{}, httpErrors.NewBadRequestError(fmt.Errorf("Mismatch password"), "A_INVALID_PASSWORD", "") - } + var accountToken *domain.User - // Authentication with Keycloak - if organizationId == "master" && accountId == "admin" { - accountToken, err = u.kc.LoginAdmin(accountId, password) - } else { - accountToken, err = u.kc.Login(accountId, password, organizationId) + accountToken, err = u.kc.Login(accountId, password, organizationId) + if err != nil { + apiErr, ok := err.(*gocloak.APIError) + if ok { + if apiErr.Code == 401 { + return domain.User{}, httpErrors.NewBadRequestError(fmt.Errorf("Mismatch password"), "A_INVALID_PASSWORD", "") + } + } + return domain.User{}, httpErrors.NewInternalServerError(err, "", "") } + log.Errorf("err: %v", err) if err != nil { //TODO: implement not found handling return domain.User{}, err From 49f32a12ad25bc08cbe03499f62167ce8f2e53e1 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 15 Feb 2024 16:01:37 +0900 Subject: [PATCH 067/502] improvement: add/remove tks roles on creation/deletion of organization --- internal/usecase/organization.go | 58 +++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 3e4cc97d..ad074123 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -28,16 +28,18 @@ type IOrganizationUsecase interface { } type OrganizationUsecase struct { - repo repository.IOrganizationRepository - argo argowf.ArgoClient - kc keycloak.IKeycloak + repo repository.IOrganizationRepository + roleRepo repository.IRoleRepository + argo argowf.ArgoClient + kc keycloak.IKeycloak } func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClient, kc keycloak.IKeycloak) IOrganizationUsecase { return &OrganizationUsecase{ - repo: r.Organization, - argo: argoClient, - kc: kc, + repo: r.Organization, + roleRepo: r.Role, + argo: argoClient, + kc: kc, } } @@ -55,10 +57,36 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *domain.Organizatio return "", err } + // Create organization in DB _, err = u.repo.Create(organizationId, in.Name, creator, in.Phone, in.Description) if err != nil { return "", err } + + // Create admin roles in DB + if err := u.roleRepo.Create(domain.TksRole{ + Role: domain.Role{ + OrganizationID: organizationId, + Name: "admin", + Description: "admin", + Type: string(domain.RoleTypeTks), + }, + }); err != nil { + return "", err + } + + // Create user roles in DB + if err := u.roleRepo.Create(domain.TksRole{ + Role: domain.Role{ + OrganizationID: organizationId, + Name: "user", + Description: "user", + Type: string(domain.RoleTypeTks), + }, + }); err != nil { + return "", err + } + workflowId, err := u.argo.SumbitWorkflowFromWftpl( "tks-create-contract-repo", argowf.SubmitOptions{ @@ -106,8 +134,22 @@ func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) return err } - // [TODO] validation - // cluster 나 appgroup 등이 삭제 되었는지 확인 + // delete roles in DB + roles, err := u.roleRepo.ListTksRoles(organizationId, nil) + if err != nil { + return err + } + for _, role := range roles { + uuid, err := uuid.Parse(role.RoleID) + if err != nil { + return err + } + if err := u.roleRepo.DeleteCascade(uuid); err != nil { + return err + } + } + + // delete organization in DB err = u.repo.Delete(organizationId) if err != nil { return err From 6c0f93de5e5341a29c14b3a04b870a3e7239b8b4 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 15 Feb 2024 17:54:35 +0900 Subject: [PATCH 068/502] refactoring: remove pw on DB which is duplicated in keycloak --- internal/keycloak/keycloak.go | 10 +- internal/repository/role.go | 10 ++ internal/repository/user.go | 79 ++++++-------- internal/usecase/auth.go | 14 +-- internal/usecase/user.go | 188 ++++++++++------------------------ pkg/domain/user.go | 2 +- 6 files changed, 98 insertions(+), 205 deletions(-) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 4c41f89c..8d2252f5 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -28,7 +28,7 @@ type IKeycloak interface { DeleteRealm(organizationId string) error UpdateRealm(organizationId string, organizationConfig domain.Organization) error - CreateUser(organizationId string, user *gocloak.User) error + CreateUser(organizationId string, user *gocloak.User) (string, error) GetUser(organizationId string, userAccountId string) (*gocloak.User, error) GetUsers(organizationId string) ([]*gocloak.User, error) DeleteUser(organizationId string, userAccountId string) error @@ -297,16 +297,16 @@ func (k *Keycloak) DeleteRealm(organizationId string) error { return nil } -func (k *Keycloak) CreateUser(organizationId string, user *gocloak.User) error { +func (k *Keycloak) CreateUser(organizationId string, user *gocloak.User) (string, error) { ctx := context.Background() token := k.adminCliToken user.Enabled = gocloak.BoolP(true) - _, err := k.client.CreateUser(ctx, token.AccessToken, organizationId, *user) + uuid, err := k.client.CreateUser(ctx, token.AccessToken, organizationId, *user) if err != nil { - return err + return "", err } - return nil + return uuid, nil } func (k *Keycloak) GetUser(organizationId string, accountId string) (*gocloak.User, error) { diff --git a/internal/repository/role.go b/internal/repository/role.go index bd61871b..9f63ba2a 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -46,6 +46,7 @@ type IRoleRepository interface { ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) Get(id uuid.UUID) (*domain.Role, error) GetTksRole(id uuid.UUID) (*domain.TksRole, error) + GetTksRoleByRoleName(roleName string) (*domain.TksRole, error) GetProjectRole(id uuid.UUID) (*domain.ProjectRole, error) DeleteCascade(id uuid.UUID) error Update(roleObj interface{}) error @@ -55,6 +56,15 @@ type RoleRepository struct { db *gorm.DB } +func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.TksRole, error) { + var role domain.TksRole + if err := r.db.Preload("Role").First(&role, "Role.name = ?", roleName).Error; err != nil { + return nil, err + } + + return ConvertRepoToDomainTksRole(&role), nil +} + func (r RoleRepository) Create(roleObj interface{}) error { if roleObj == nil { return fmt.Errorf("roleObj is nil") diff --git a/internal/repository/user.go b/internal/repository/user.go index 4663f30a..9de16cd2 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -13,20 +13,18 @@ import ( // Interface type IUserRepository interface { - Create(accountId string, organizationId string, password string, name string) (domain.User, error) - CreateWithUuid(uuid uuid.UUID, accountId string, name string, password string, email string, + CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, department string, description string, organizationId string, roleId string) (domain.User, error) List(filters ...FilterFunc) (out *[]domain.User, err error) ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]domain.User, err error) Get(accountId string, organizationId string) (domain.User, error) GetByUuid(userId uuid.UUID) (domain.User, error) - UpdateWithUuid(uuid uuid.UUID, accountId string, name string, password string, roleId string, email string, + UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, email string, department string, description string) (domain.User, error) - UpdatePassword(userId uuid.UUID, organizationId string, password string, isTemporary bool) error + UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error DeleteWithUuid(uuid uuid.UUID) error Flush(organizationId string) error - FetchRoles() (out *[]domain.Role, err error) AccountIdFilter(accountId string) FilterFunc OrganizationFilter(organization string) FilterFunc EmailFilter(email string) FilterFunc @@ -78,28 +76,12 @@ func NewUserRepository(db *gorm.DB) IUserRepository { // return nil //} -func (r *UserRepository) Create(accountId string, organizationId string, password string, name string) (domain.User, error) { - newUser := domain.User{ - AccountId: accountId, - Password: password, - OrganizationId: organizationId, - Name: name, - } - res := r.db.Create(&newUser) - if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.User{}, res.Error - } - - return r.reflect(newUser), nil -} -func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name string, password string, email string, +func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, department string, description string, organizationId string, roleId string) (domain.User, error) { newUser := domain.User{ ID: uuid, AccountId: accountId, - Password: password, Name: name, Email: email, Department: department, @@ -218,13 +200,12 @@ func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser domain.User, err return r.reflect(user), nil } -func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, password string, roleId string, +func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, email string, department string, description string) (domain.User, error) { var user domain.User res := r.db.Model(&domain.User{}).Where("id = ?", uuid).Updates(domain.User{ AccountId: accountId, Name: name, - Password: password, Email: email, Department: department, Description: description, @@ -243,17 +224,15 @@ func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name s } return r.reflect(user), nil } -func (r *UserRepository) UpdatePassword(userId uuid.UUID, organizationId string, password string, isTemporary bool) error { - var updateUser = domain.User{ - Password: password, - } +func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error { + var updateUser = domain.User{} if isTemporary { updateUser.PasswordUpdatedAt = time.Time{} } else { updateUser.PasswordUpdatedAt = time.Now() } res := r.db.Model(&domain.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). - Select("password", "password_updated_at").Updates(updateUser) + Select("password_updated_at").Updates(updateUser) if res.RowsAffected == 0 || res.Error != nil { return httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") @@ -303,27 +282,27 @@ func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { return r.reflectRole(role), nil } -func (r *UserRepository) FetchRoles() (*[]domain.Role, error) { - var roles []domain.Role - res := r.db.Find(&roles) - - if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return nil, res.Error - } - - if res.RowsAffected == 0 { - return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") - } - - var out []domain.Role - for _, role := range roles { - outRole := r.reflectRole(role) - out = append(out, outRole) - } - - return &out, nil -} +//func (r *UserRepository) FetchRoles() (*[]domain.Role, error) { +// var roles []domain.Role +// res := r.db.Find(&roles) +// +// if res.Error != nil { +// log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) +// return nil, res.Error +// } +// +// if res.RowsAffected == 0 { +// return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") +// } +// +// var out []domain.Role +// for _, role := range roles { +// outRole := r.reflectRole(role) +// out = append(out, outRole) +// } +// +// return &out, nil +//} // private members func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (domain.User, error) { diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 564601a1..4fe4fd15 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -36,7 +36,6 @@ type IAuthUsecase interface { FindId(code string, email string, userName string, organizationId string) (string, error) FindPassword(code string, accountId string, email string, userName string, organizationId string) error VerifyIdentity(accountId string, email string, userName string, organizationId string) error - FetchRoles() (out []domain.Role, err error) SingleSignIn(organizationId, accountId, password string) ([]*http.Cookie, error) SingleSignOut(organizationId string) (string, []*http.Cookie, error) VerifyToken(token string) (bool, error) @@ -231,10 +230,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, return httpErrors.NewInternalServerError(err, "", "") } - if user.Password, err = helper.HashPassword(randomPassword); err != nil { - return httpErrors.NewInternalServerError(err, "", "") - } - if err = u.userRepository.UpdatePassword(user.ID, organizationId, user.Password, true); err != nil { + if err = u.userRepository.UpdatePasswordAt(user.ID, organizationId, true); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -307,14 +303,6 @@ func (u *AuthUsecase) VerifyIdentity(accountId string, email string, userName st return nil } -func (u *AuthUsecase) FetchRoles() (out []domain.Role, err error) { - roles, err := u.userRepository.FetchRoles() - if err != nil { - return nil, err - } - return *roles, nil -} - func (u *AuthUsecase) SingleSignIn(organizationId, accountId, password string) ([]*http.Cookie, error) { cookies, err := makingCookie(organizationId, accountId, password) if err != nil { diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 1c1ce670..e07d2cbb 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -47,6 +47,7 @@ type IUserUsecase interface { type UserUsecase struct { userRepository repository.IUserRepository + roleRepository repository.IRoleRepository organizationRepository repository.IOrganizationRepository kc keycloak.IKeycloak } @@ -60,7 +61,7 @@ func (u *UserUsecase) RenewalPasswordExpiredTime(ctx context.Context, userId uui return httpErrors.NewInternalServerError(err, "", "") } - err = u.userRepository.UpdatePassword(userId, user.Organization.ID, user.Password, false) + err = u.userRepository.UpdatePasswordAt(userId, user.Organization.ID, false) if err != nil { log.ErrorfWithContext(ctx, "failed to update password expired time: %v", err) return httpErrors.NewInternalServerError(err, "", "") @@ -107,10 +108,7 @@ func (u *UserUsecase) ResetPassword(userId uuid.UUID) error { return httpErrors.NewInternalServerError(err, "", "") } - if user.Password, err = helper.HashPassword(randomPassword); err != nil { - return httpErrors.NewInternalServerError(err, "", "") - } - if err = u.userRepository.UpdatePassword(userId, user.Organization.ID, user.Password, true); err != nil { + if err = u.userRepository.UpdatePasswordAt(userId, user.Organization.ID, true); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -194,6 +192,7 @@ func (u *UserUsecase) DeleteAdmin(organizationId string) error { } func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*domain.User, error) { + // Generate Admin user object randomPassword := helper.GenerateRandomString(passwordLength) user := domain.User{ AccountId: "admin", @@ -208,79 +207,27 @@ func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*domain. Name: "admin", } - // Create user in keycloak - groups := []string{fmt.Sprintf("%s@%s", user.Role.Name, orgainzationId)} - err := u.kc.CreateUser(orgainzationId, &gocloak.User{ - Username: gocloak.StringP(user.AccountId), - Email: gocloak.StringP(user.Email), - Credentials: &[]gocloak.CredentialRepresentation{ - { - Type: gocloak.StringP("password"), - Value: gocloak.StringP(user.Password), - Temporary: gocloak.BoolP(false), - }, - }, - Groups: &groups, - FirstName: gocloak.StringP(user.Name), - }) - if err != nil { - return nil, errors.Wrap(err, "creating user in keycloak failed") - } - keycloakUser, err := u.kc.GetUser(user.Organization.ID, user.AccountId) - if err != nil { - return nil, errors.Wrap(err, "getting user from keycloak failed") - } - - userUuid, err := uuid.Parse(*keycloakUser.ID) - if err != nil { - return nil, err - } - - hashedPassword, err := helper.HashPassword(user.Password) - if err != nil { - return nil, err - } - - roles, err := u.userRepository.FetchRoles() - if err != nil { - return nil, err - } - for _, role := range *roles { - if role.Name == user.Role.Name { - user.Role.ID = role.ID - } - } - roleUuid := user.Role.ID - if err != nil { - return nil, err - } - resUser, err := u.userRepository.CreateWithUuid(userUuid, user.AccountId, user.Name, hashedPassword, user.Email, - user.Department, user.Description, user.Organization.ID, roleUuid) - if err != nil { - return nil, err - } - err = u.userRepository.UpdatePassword(userUuid, user.Organization.ID, hashedPassword, true) + // Create Admin user in keycloak & DB + resUser, err := u.Create(context.Background(), &user) if err != nil { return nil, err } + // Send mail of temporary password organizationInfo, err := u.organizationRepository.Get(orgainzationId) if err != nil { return nil, err } - message, err := mail.MakeGeneratingOrganizationMessage(orgainzationId, organizationInfo.Name, user.Email, user.AccountId, randomPassword) if err != nil { return nil, httpErrors.NewInternalServerError(err, "", "") } - mailer := mail.New(message) - if err := mailer.SendMail(); err != nil { return nil, httpErrors.NewInternalServerError(err, "", "") } - return &resUser, nil + return resUser, nil } func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId string, originPassword string, newPassword string, @@ -308,18 +255,13 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s return errors.Wrap(err, "updating user in keycloak failed") } - // update password in DB - + // update password UpdateAt in DB user, err := u.userRepository.Get(accountId, organizationId) if err != nil { return errors.Wrap(err, "getting user from repository failed") } - hashedPassword, err := helper.HashPassword(newPassword) - if err != nil { - return errors.Wrap(err, "hashing password failed") - } - err = u.userRepository.UpdatePassword(user.ID, organizationId, hashedPassword, false) + err = u.userRepository.UpdatePasswordAt(user.ID, organizationId, false) if err != nil { return errors.Wrap(err, "updating user in repository failed") } @@ -402,6 +344,7 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u if err != nil { return nil, err } + if (originUser.Email == nil || *originUser.Email != user.Email) || (originUser.FirstName == nil || *originUser.FirstName != user.Name) { originUser.Email = gocloak.StringP(user.Email) originUser.FirstName = gocloak.StringP(user.Name) @@ -425,14 +368,12 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u return nil, fmt.Errorf("multiple users found") } - originPassword := (*users)[0].Password - roleUuid := (*users)[0].Role.ID if err != nil { return nil, err } - *user, err = u.userRepository.UpdateWithUuid((*users)[0].ID, user.AccountId, user.Name, originPassword, roleUuid, user.Email, + *user, err = u.userRepository.UpdateWithUuid((*users)[0].ID, user.AccountId, user.Name, roleUuid, user.Email, user.Department, user.Description) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") @@ -483,7 +424,7 @@ func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, o func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.User, error) { // Create user in keycloak groups := []string{fmt.Sprintf("%s@%s", user.Role.Name, user.Organization.ID)} - err := u.kc.CreateUser(user.Organization.ID, &gocloak.User{ + userUuidStr, err := u.kc.CreateUser(user.Organization.ID, &gocloak.User{ Username: gocloak.StringP(user.AccountId), Credentials: &[]gocloak.CredentialRepresentation{ { @@ -496,43 +437,36 @@ func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.Us Groups: &groups, FirstName: gocloak.StringP(user.Name), }) - if err != nil { - if _, err := u.kc.GetUser(user.Organization.ID, user.AccountId); err == nil { - return nil, httpErrors.NewConflictError(errors.New("user already exists"), "", "") - } - - return nil, errors.Wrap(err, "creating user in keycloak failed") - } - keycloakUser, err := u.kc.GetUser(user.Organization.ID, user.AccountId) - if err != nil { - return nil, errors.Wrap(err, "getting user from keycloak failed") - } - - userUuid, err := uuid.Parse(*keycloakUser.ID) if err != nil { return nil, err } - hashedPassword, err := helper.HashPassword(user.Password) + // Get user role + var roleUuid string + tksRoles, err := u.roleRepository.ListTksRoles(user.Organization.ID, nil) if err != nil { return nil, err } - - roles, err := u.userRepository.FetchRoles() - if err != nil { - return nil, err + if len(tksRoles) == 0 { + return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") } - for _, role := range *roles { - if role.Name == user.Role.Name { - user.Role.ID = role.ID + for _, role := range tksRoles { + if role.Role.Name == user.Role.Name { + roleUuid = role.RoleID } } - roleUuid := user.Role.ID + if roleUuid == "" { + return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") + } + + // Generate user uuid + userUuid, err := uuid.Parse(userUuidStr) if err != nil { return nil, err } - resUser, err := u.userRepository.CreateWithUuid(userUuid, user.AccountId, user.Name, hashedPassword, user.Email, + // Create user in DB + resUser, err := u.userRepository.CreateWithUuid(userUuid, user.AccountId, user.Name, user.Email, user.Department, user.Description, user.Organization.ID, roleUuid) if err != nil { return nil, err @@ -541,68 +475,49 @@ func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.Us return &resUser, nil } -func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) { - userInfo, ok := request.UserFrom(ctx) - if !ok { - return nil, fmt.Errorf("user in the context is empty") - } - - originUser, err := u.kc.GetUser(userInfo.GetOrganizationId(), accountId) +func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *domain.User) (*domain.User, error) { + user, err := u.UpdateByAccountId(ctx, accountId, newUser) if err != nil { return nil, err } - if (originUser.Email == nil || *originUser.Email != user.Email) || (originUser.FirstName == nil || *originUser.FirstName != user.Name) { - originUser.Email = gocloak.StringP(user.Email) - originUser.FirstName = gocloak.StringP(user.Name) - err = u.kc.UpdateUser(userInfo.GetOrganizationId(), originUser) - if err != nil { - return nil, err - } - } - users, err := u.userRepository.List(u.userRepository.OrganizationFilter(userInfo.GetOrganizationId()), - u.userRepository.AccountIdFilter(accountId)) - if err != nil { - if _, code := httpErrors.ErrorResponse(err); code == http.StatusNotFound { - return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") - } - return nil, errors.Wrap(err, "getting users from repository failed") - } - if len(*users) == 0 { - return nil, fmt.Errorf("user not found") - } else if len(*users) > 1 { - return nil, fmt.Errorf("multiple users found") + userInfo, ok := request.UserFrom(ctx) + if !ok { + return nil, fmt.Errorf("user in the context is empty") } - if user.Role.Name != (*users)[0].Role.Name { - originGroupName := fmt.Sprintf("%s@%s", (*users)[0].Role.Name, userInfo.GetOrganizationId()) + + if newUser.Role.Name != user.Role.Name { + originGroupName := fmt.Sprintf("%s@%s", user.Role.Name, userInfo.GetOrganizationId()) newGroupName := fmt.Sprintf("%s@%s", user.Role.Name, userInfo.GetOrganizationId()) - if err := u.kc.LeaveGroup(userInfo.GetOrganizationId(), (*users)[0].ID.String(), originGroupName); err != nil { + if err := u.kc.LeaveGroup(userInfo.GetOrganizationId(), user.ID.String(), originGroupName); err != nil { log.ErrorfWithContext(ctx, "leave group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } - if err := u.kc.JoinGroup(userInfo.GetOrganizationId(), (*users)[0].ID.String(), newGroupName); err != nil { + if err := u.kc.JoinGroup(userInfo.GetOrganizationId(), user.ID.String(), newGroupName); err != nil { log.ErrorfWithContext(ctx, "join group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } } - originPassword := (*users)[0].Password - - roles, err := u.userRepository.FetchRoles() + // Get user role + var roleUuid string + tksRoles, err := u.roleRepository.ListTksRoles(user.Organization.ID, nil) if err != nil { return nil, err } - for _, role := range *roles { - if role.Name == user.Role.Name { - user.Role.ID = role.ID + if len(tksRoles) == 0 { + return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") + } + for _, role := range tksRoles { + if role.Role.Name == user.Role.Name { + roleUuid = role.RoleID } } - roleUuid := user.Role.ID - if err != nil { - return nil, err + if roleUuid == "" { + return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") } - *user, err = u.userRepository.UpdateWithUuid((*users)[0].ID, user.AccountId, user.Name, originPassword, roleUuid, user.Email, + *user, err = u.userRepository.UpdateWithUuid(user.ID, user.AccountId, user.Name, roleUuid, user.Email, user.Department, user.Description) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") @@ -614,6 +529,7 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st func NewUserUsecase(r repository.Repository, kc keycloak.IKeycloak) IUserUsecase { return &UserUsecase{ userRepository: r.User, + roleRepository: r.Role, kc: kc, organizationRepository: r.Organization, } diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 77c9092b..d63b4605 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -9,7 +9,7 @@ import ( type User struct { ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` - Password string `json:"password"` + Password string `gorm:"-:all" json:"password"` Name string `json:"name"` Token string `json:"token"` RoleId string From bef7a4c67cd63244f1587dfc397a9f3185229a6a Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 15 Feb 2024 18:41:26 +0900 Subject: [PATCH 069/502] ignore rbac due to refactoring --- internal/middleware/auth/authorizer/authorizer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/middleware/auth/authorizer/authorizer.go b/internal/middleware/auth/authorizer/authorizer.go index 9983dbd5..ff4af222 100644 --- a/internal/middleware/auth/authorizer/authorizer.go +++ b/internal/middleware/auth/authorizer/authorizer.go @@ -19,8 +19,8 @@ func NewDefaultAuthorization(repo repository.Repository) *defaultAuthorization { repo: repo, } d.addFilters(PasswordFilter) - d.addFilters(RBACFilter) - d.addFilters(RBACFilterWithEndpoint) + //d.addFilters(RBACFilter) + //d.addFilters(RBACFilterWithEndpoint) return d } From 13304b4f1a1bf12e77e29130fed248106691955d Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 16 Feb 2024 16:10:46 +0900 Subject: [PATCH 070/502] remove tks role struct and project role in role domain --- internal/delivery/http/role.go | 300 +++------------------------------ internal/repository/role.go | 205 ++++------------------ internal/usecase/role.go | 81 ++------- pkg/domain/role.go | 5 - 4 files changed, 68 insertions(+), 523 deletions(-) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 605005e9..601440a9 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -13,19 +13,10 @@ import ( type IRoleHandler interface { CreateTksRole(w http.ResponseWriter, r *http.Request) - CreateProjectRole(w http.ResponseWriter, r *http.Request) - ListTksRoles(w http.ResponseWriter, r *http.Request) - ListProjectRoles(w http.ResponseWriter, r *http.Request) - GetTksRole(w http.ResponseWriter, r *http.Request) - GetProjectRole(w http.ResponseWriter, r *http.Request) - DeleteTksRole(w http.ResponseWriter, r *http.Request) - DeleteProjectRole(w http.ResponseWriter, r *http.Request) - UpdateTksRole(w http.ResponseWriter, r *http.Request) - UpdateProjectRole(w http.ResponseWriter, r *http.Request) } type RoleHandler struct { @@ -70,13 +61,11 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - dto := domain.TksRole{ - Role: domain.Role{ - OrganizationID: organizationId, - Name: input.Name, - Description: input.Description, - Type: string(domain.RoleTypeTks), - }, + dto := domain.Role{ + OrganizationID: organizationId, + Name: input.Name, + Description: input.Description, + Type: string(domain.RoleTypeTks), } if err := h.roleUsecase.CreateTksRole(&dto); err != nil { @@ -86,60 +75,6 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } -// CreateTksRole godoc -// @Tags Role -// @Summary Create Project Role -// @Description Create Project Role -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param body body domain.CreateProjectRoleRequest true "Create Project Role Request" -// @Success 200 {object} domain.CreateProjectRoleResponse -// @Router /organizations/{organizationId}/projects/{projectId}/roles [post] - -func (h RoleHandler) CreateProjectRole(w http.ResponseWriter, r *http.Request) { - // path parameter - var organizationId, projectId string - - vars := mux.Vars(r) - if v, ok := vars["organizationId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - organizationId = v - } - if v, ok := vars["projectId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - projectId = v - } - - // request body - input := domain.CreateProjectRoleRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - ErrorJSON(w, r, err) - return - } - - // input to dto - dto := domain.ProjectRole{ - Role: domain.Role{ - OrganizationID: organizationId, - Name: input.Name, - Description: input.Description, - Type: string(domain.RoleTypeProject), - }, - ProjectID: projectId, - } - - if err := h.roleUsecase.CreateProjectRole(&dto); err != nil { - ErrorJSON(w, r, err) - return - } -} - // ListTksRoles godoc // @Tags Role // @Summary List Tks Roles @@ -179,73 +114,13 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { out.Roles = make([]domain.GetTksRoleResponse, len(roles)) for i, role := range roles { out.Roles[i] = domain.GetTksRoleResponse{ - ID: role.Role.ID, - Name: role.Role.Name, - OrganizationID: role.Role.OrganizationID, - Description: role.Role.Description, - Creator: role.Role.Creator.String(), - CreatedAt: role.Role.CreatedAt, - UpdatedAt: role.Role.UpdatedAt, - } - } - - if err := serializer.Map(*pg, &out.Pagination); err != nil { - log.InfoWithContext(r.Context(), err) - } - - // response - ResponseJSON(w, r, http.StatusOK, out) -} - -// ListProjectRoles godoc -// @Tags Role -// @Summary List Project Roles -// @Description List Project Roles -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Success 200 {object} domain.ListProjectRoleResponse -// @Router /organizations/{organizationId}/projects/{projectId}/roles [get] - -func (h RoleHandler) ListProjectRoles(w http.ResponseWriter, r *http.Request) { - // path parameter - var projectId string - - vars := mux.Vars(r) - if v, ok := vars["projectId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - projectId = v - } - - // query parameter - urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - // list roles - roles, err := h.roleUsecase.ListProjectRoles(projectId, pg) - if err != nil { - ErrorJSON(w, r, err) - return - } - - var out domain.ListProjectRoleResponse - out.Roles = make([]domain.GetProjectRoleResponse, len(roles)) - for i, role := range roles { - out.Roles[i] = domain.GetProjectRoleResponse{ - ID: role.RoleID, - Name: role.Role.Name, - OrganizationID: role.Role.OrganizationID, - ProjectID: role.ProjectID, - Description: role.Role.Description, - Creator: role.Role.Creator.String(), - CreatedAt: role.Role.CreatedAt, - UpdatedAt: role.Role.UpdatedAt, + ID: role.ID, + Name: role.Name, + OrganizationID: role.OrganizationID, + Description: role.Description, + Creator: role.Creator.String(), + CreatedAt: role.CreatedAt, + UpdatedAt: role.UpdatedAt, } } @@ -286,57 +161,13 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // response out := domain.GetTksRoleResponse{ - ID: role.Role.ID, - Name: role.Role.Name, - OrganizationID: role.Role.OrganizationID, - Description: role.Role.Description, - Creator: role.Role.Creator.String(), - CreatedAt: role.Role.CreatedAt, - UpdatedAt: role.Role.UpdatedAt, - } - - ResponseJSON(w, r, http.StatusOK, out) -} - -// GetProjectRole godoc -// @Tags Role -// @Summary Get Project Role -// @Description Get Project Role -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param roleId path string true "Role ID" -// @Success 200 {object} domain.GetProjectRoleResponse -// @Router /organizations/{organizationId}/projects/{projectId}/roles/{roleId} [get] - -func (h RoleHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { - // path parameter - vars := mux.Vars(r) - var roleId string - if v, ok := vars["roleId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - roleId = v - } - - // get role - role, err := h.roleUsecase.GetProjectRole(roleId) - if err != nil { - ErrorJSON(w, r, err) - return - } - - // response - out := domain.GetProjectRoleResponse{ - ID: role.RoleID, - Name: role.Role.Name, - OrganizationID: role.Role.OrganizationID, - ProjectID: role.ProjectID, - Description: role.Role.Description, - Creator: role.Role.Creator.String(), - CreatedAt: role.Role.CreatedAt, - UpdatedAt: role.Role.UpdatedAt, + ID: role.ID, + Name: role.Name, + OrganizationID: role.OrganizationID, + Description: role.Description, + Creator: role.Creator.String(), + CreatedAt: role.CreatedAt, + UpdatedAt: role.UpdatedAt, } ResponseJSON(w, r, http.StatusOK, out) @@ -373,38 +204,6 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, nil) } -// DeleteProjectRole godoc -// @Tags Role -// @Summary Delete Project Role -// @Description Delete Project Role -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param roleId path string true "Role ID" -// @Success 200 -// @Router /organizations/{organizationId}/projects/{projectId}/roles/{roleId} [delete] - -func (h RoleHandler) DeleteProjectRole(w http.ResponseWriter, r *http.Request) { - // path parameter - vars := mux.Vars(r) - var roleId string - if v, ok := vars["roleId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - roleId = v - } - - // delete role - if err := h.roleUsecase.DeleteProjectRole(roleId); err != nil { - ErrorJSON(w, r, err) - return - } - - // response - ResponseJSON(w, r, http.StatusOK, nil) -} - // UpdateTksRole godoc // @Tags Role // @Summary Update Tks Role @@ -437,12 +236,10 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - dto := domain.TksRole{ - Role: domain.Role{ - ID: roleId, - Name: input.Name, - Description: input.Description, - }, + dto := domain.Role{ + ID: roleId, + Name: input.Name, + Description: input.Description, } // update role @@ -454,54 +251,3 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // response ResponseJSON(w, r, http.StatusOK, nil) } - -// UpdateProjectRole godoc -// @Tags Role -// @Summary Update Project Role -// @Description Update Project Role -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param roleId path string true "Role ID" -// @Param body body domain.UpdateProjectRoleRequest true "Update Project Role Request" -// @Success 200 -// @Router /organizations/{organizationId}/projects/{projectId}/roles/{roleId} [put] - -func (h RoleHandler) UpdateProjectRole(w http.ResponseWriter, r *http.Request) { - // path parameter - vars := mux.Vars(r) - var roleId string - if v, ok := vars["roleId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - roleId = v - } - - // request body - input := domain.UpdateProjectRoleRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - ErrorJSON(w, r, err) - return - } - - // input to dto - dto := domain.ProjectRole{ - Role: domain.Role{ - ID: roleId, - Name: input.Name, - Description: input.Description, - }, - } - - // update role - if err := h.roleUsecase.UpdateProjectRole(&dto); err != nil { - ErrorJSON(w, r, err) - return - } - - // response - ResponseJSON(w, r, http.StatusOK, nil) -} diff --git a/internal/repository/role.go b/internal/repository/role.go index 9f63ba2a..dedbb876 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -9,83 +9,36 @@ import ( "math" ) -// -//type Role struct { -// gorm.Model -// -// ID string `gorm:"primarykey;"` -// Name string -// OrganizationID string -// Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;"` -// Type string -// Creator uuid.UUID -// Description string -//} -// -//func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { -// r.ID = uuid.New().String() -// return nil -//} -// -//type TksRole struct { -// RoleID string `gorm:"primarykey;"` -// Role Role `gorm:"foreignKey:RoleID;references:ID;"` -//} - -//type ProjectRole struct { -// RoleID string `gorm:"primarykey;"` -// Role Role `gorm:"foreignKey:RoleID;references:ID;"` -// ProjectID string -// Project domain.Project `gorm:"foreignKey:ProjectID;references:ID;"` -//} - type IRoleRepository interface { - Create(roleObj interface{}) error + Create(roleObj *domain.Role) error List(pg *pagination.Pagination) ([]*domain.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) - ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) - Get(id uuid.UUID) (*domain.Role, error) - GetTksRole(id uuid.UUID) (*domain.TksRole, error) - GetTksRoleByRoleName(roleName string) (*domain.TksRole, error) - GetProjectRole(id uuid.UUID) (*domain.ProjectRole, error) - DeleteCascade(id uuid.UUID) error - Update(roleObj interface{}) error + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) + Get(id string) (*domain.Role, error) + GetTksRole(id string) (*domain.Role, error) + GetTksRoleByRoleName(roleName string) (*domain.Role, error) + Delete(id string) error + Update(roleObj *domain.Role) error } type RoleRepository struct { db *gorm.DB } -func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.TksRole, error) { - var role domain.TksRole +func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.Role, error) { + var role domain.Role if err := r.db.Preload("Role").First(&role, "Role.name = ?", roleName).Error; err != nil { return nil, err } - return ConvertRepoToDomainTksRole(&role), nil + return &role, nil } -func (r RoleRepository) Create(roleObj interface{}) error { +func (r RoleRepository) Create(roleObj *domain.Role) error { if roleObj == nil { return fmt.Errorf("roleObj is nil") } - switch roleObj.(type) { - case *domain.TksRole: - inputRole := roleObj.(*domain.TksRole) - role := ConvertDomainToRepoTksRole(inputRole) - if err := r.db.Create(role).Error; err != nil { - return err - } - - case *domain.ProjectRole: - inputRole := roleObj.(*domain.ProjectRole) - //role := ConvertDomainToRepoProjectRole(inputRole) - //if err := r.db.Create(role).Error; err != nil { - // return err - //} - if err := r.db.Create(inputRole).Error; err != nil { - return err - } + if err := r.db.Create(roleObj).Error; err != nil { + return err } return nil @@ -93,7 +46,6 @@ func (r RoleRepository) Create(roleObj interface{}) error { func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) { var roles []*domain.Role - var objs []*domain.Role if pg == nil { pg = pagination.NewDefaultPagination() @@ -105,29 +57,23 @@ func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - //res := db.Joins("JOIN roles as r on r.id = tks_roles.role_id"). - // Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&roles) if res.Error != nil { return nil, res.Error } - for _, role := range objs { - roles = append(roles, ConvertRepoToDomainRole(role)) - } return roles, nil } -func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) { - var roles []*domain.TksRole - var objs []*domain.TksRole +func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) { + var roles []*domain.Role if pg == nil { pg = pagination.NewDefaultPagination() } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.TksRole{})) + db := filterFunc(r.db.Model(&domain.Role{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -138,14 +84,11 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin Offset(pg.GetOffset()). Limit(pg.GetLimit()). Order(orderQuery). - Find(&objs) + Find(&roles) //res := db.Preload("Role").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) if res.Error != nil { return nil, res.Error } - for _, role := range objs { - roles = append(roles, ConvertRepoToDomainTksRole(role)) - } return roles, nil } @@ -178,22 +121,22 @@ func (r RoleRepository) ListProjectRoles(projectId string, pg *pagination.Pagina return roles, nil } -func (r RoleRepository) Get(id uuid.UUID) (*domain.Role, error) { +func (r RoleRepository) Get(id string) (*domain.Role, error) { var role domain.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } - return ConvertRepoToDomainRole(&role), nil + return &role, nil } -func (r RoleRepository) GetTksRole(id uuid.UUID) (*domain.TksRole, error) { - var role domain.TksRole +func (r RoleRepository) GetTksRole(id string) (*domain.Role, error) { + var role domain.Role if err := r.db.Preload("Role").First(&role, "role_id = ?", id).Error; err != nil { return nil, err } - return ConvertRepoToDomainTksRole(&role), nil + return &role, nil } func (r RoleRepository) GetProjectRole(id uuid.UUID) (*domain.ProjectRole, error) { @@ -205,44 +148,26 @@ func (r RoleRepository) GetProjectRole(id uuid.UUID) (*domain.ProjectRole, error return &role, nil } -func (r RoleRepository) DeleteCascade(id uuid.UUID) error { - // manual cascade delete - if err := r.db.Delete(&domain.TksRole{}, "role_id = ?", id).Error; err != nil { - return err - } - if err := r.db.Delete(&domain.ProjectRole{}, "role_id = ?", id).Error; err != nil { - return err +func (r RoleRepository) Update(roleObj *domain.Role) error { + if roleObj == nil { + return fmt.Errorf("roleObj is nil") } - if err := r.db.Delete(&domain.Role{}, "id = ?", id).Error; err != nil { + err := r.db.Model(&domain.Role{}).Where("id = ?", roleObj.ID).Updates(domain.Role{ + Name: roleObj.Name, + Description: roleObj.Description, + }).Error + + if err != nil { return err } return nil } -func (r RoleRepository) Update(roleObj interface{}) error { - switch roleObj.(type) { - case *domain.TksRole: - inputRole := roleObj.(*domain.TksRole) - role := ConvertRepoToDomainTksRole(inputRole) - if err := r.db.Model(&domain.TksRole{}).Where("id = ?", role.RoleID).Updates(domain.Role{ - Name: role.Role.Name, - Description: role.Role.Description, - }).Error; err != nil { - return err - } - - case *domain.ProjectRole: - inputRole := roleObj.(*domain.ProjectRole) - //projectRole := ConvertRepoToDomainProjectRole(inputRole) - // update role - if err := r.db.Model(&domain.ProjectRole{}).Where("role_id = ?", inputRole.RoleID).Updates(domain.Role{ - Name: inputRole.Role.Name, - Description: inputRole.Role.Description, - }).Error; err != nil { - return err - } +func (r RoleRepository) Delete(id string) error { + if err := r.db.Delete(&domain.Role{}, "id = ?", id).Error; err != nil { + return err } return nil @@ -253,63 +178,3 @@ func NewRoleRepository(db *gorm.DB) IRoleRepository { db: db, } } - -// domain.Role to repository.Role -func ConverDomainToRepoRole(domainRole *domain.Role) *domain.Role { - return &domain.Role{ - ID: domainRole.ID, - Name: domainRole.Name, - OrganizationID: domainRole.OrganizationID, - Type: domainRole.Type, - Creator: domainRole.Creator, - Description: domainRole.Description, - } -} - -// repository.Role to domain.Role -func ConvertRepoToDomainRole(repoRole *domain.Role) *domain.Role { - return &domain.Role{ - ID: repoRole.ID, - Name: repoRole.Name, - OrganizationID: repoRole.OrganizationID, - Type: repoRole.Type, - Creator: repoRole.Creator, - Description: repoRole.Description, - } -} - -// domain.TksRole to repository.TksRole -func ConvertDomainToRepoTksRole(domainRole *domain.TksRole) *domain.TksRole { - return &domain.TksRole{ - RoleID: domainRole.Role.ID, - Role: *ConverDomainToRepoRole(&domainRole.Role), - } -} - -// repository.TksRole to domain.TksRole -func ConvertRepoToDomainTksRole(repoRole *domain.TksRole) *domain.TksRole { - return &domain.TksRole{ - RoleID: repoRole.RoleID, - Role: *ConvertRepoToDomainRole(&repoRole.Role), - } -} - -//// domain.ProjectRole to repository.ProjectRole -//func ConvertDomainToRepoProjectRole(domainRole *domain.ProjectRole) *ProjectRole { -// return &ProjectRole{ -// RoleID: domainRole.RoleID, -// ProjectID: domainRole.ProjectID, -// Role: *ConverDomainToRepoRole(&domainRole.Role), -// Project: domainRole.Project, -// } -//} -// -//// repository.ProjectRole to domain.ProjectRole -//func ConvertRepoToDomainProjectRole(repoRole *ProjectRole) *domain.ProjectRole { -// return &domain.ProjectRole{ -// RoleID: repoRole.RoleID, -// ProjectID: repoRole.ProjectID, -// Role: *ConvertRepoToDomainRole(&repoRole.Role), -// Project: repoRole.Project, -// } -//} diff --git a/internal/usecase/role.go b/internal/usecase/role.go index fb6dbc56..31d28b0e 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -1,24 +1,18 @@ package usecase import ( - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" ) type IRoleUsecase interface { - CreateTksRole(role *domain.TksRole) error - CreateProjectRole(role *domain.ProjectRole) error + CreateTksRole(role *domain.Role) error ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) - ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) - GetTksRole(id string) (*domain.TksRole, error) - GetProjectRole(id string) (*domain.ProjectRole, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) + GetTksRole(id string) (*domain.Role, error) DeleteTksRole(id string) error - DeleteProjectRole(id string) error - UpdateTksRole(role *domain.TksRole) error - UpdateProjectRole(role *domain.ProjectRole) error + UpdateTksRole(role *domain.Role) error } type RoleUsecase struct { @@ -31,15 +25,11 @@ func NewRoleUsecase(repo repository.Repository) *RoleUsecase { } } -func (r RoleUsecase) CreateTksRole(role *domain.TksRole) error { +func (r RoleUsecase) CreateTksRole(role *domain.Role) error { return r.repo.Create(role) } -func (r RoleUsecase) CreateProjectRole(role *domain.ProjectRole) error { - return r.repo.Create(role) -} - -func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.TksRole, error) { +func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) { roles, err := r.repo.ListTksRoles(organizationId, pg) if err != nil { return nil, err @@ -48,40 +38,12 @@ func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Paginati return roles, nil } -func (r RoleUsecase) ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) { - roles, err := r.repo.ListProjectRoles(projectId, pg) - if err != nil { - return nil, err - } - - return roles, nil -} - func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) { return r.repo.List(nil) } -func (r RoleUsecase) GetTksRole(id string) (*domain.TksRole, error) { - roldId, err := uuid.Parse(id) - if err != nil { - return nil, err - } - - role, err := r.repo.GetTksRole(roldId) - if err != nil { - return nil, err - } - - return role, nil -} - -func (r RoleUsecase) GetProjectRole(id string) (*domain.ProjectRole, error) { - roleId, err := uuid.Parse(id) - if err != nil { - return nil, err - } - - role, err := r.repo.GetProjectRole(roleId) +func (r RoleUsecase) GetTksRole(id string) (*domain.Role, error) { + role, err := r.repo.GetTksRole(id) if err != nil { return nil, err } @@ -90,33 +52,10 @@ func (r RoleUsecase) GetProjectRole(id string) (*domain.ProjectRole, error) { } func (r RoleUsecase) DeleteTksRole(id string) error { - roleId, err := uuid.Parse(id) - if err != nil { - return err - } - - return r.repo.DeleteCascade(roleId) -} - -func (r RoleUsecase) DeleteProjectRole(id string) error { - roleId, err := uuid.Parse(id) - if err != nil { - return err - } - - return r.repo.DeleteCascade(roleId) -} - -func (r RoleUsecase) UpdateTksRole(role *domain.TksRole) error { - err := r.repo.Update(role) - if err != nil { - return err - } - - return nil + return r.repo.Delete(id) } -func (r RoleUsecase) UpdateProjectRole(role *domain.ProjectRole) error { +func (r RoleUsecase) UpdateTksRole(role *domain.Role) error { err := r.repo.Update(role) if err != nil { return err diff --git a/pkg/domain/role.go b/pkg/domain/role.go index a733e9a5..ae1d5cc3 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -33,11 +33,6 @@ type Role struct { UpdatedAt time.Time `json:"updatedAt"` } -type TksRole struct { - RoleID string `gorm:"primarykey;" json:"roleId"` - Role Role `gorm:"foreignKey:RoleID;references:ID;"` -} - type ProjectRole struct { RoleID string `gorm:"primaryKey" json:"roleId"` Role Role `gorm:"foreignKey:RoleID;references:ID;" json:"role"` From faf21f4bd041e441353dee009c82442d20c362ef Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 16 Feb 2024 16:16:32 +0900 Subject: [PATCH 071/502] remove tks role struct and project role in role domain --- internal/repository/role.go | 38 ---------------------------- pkg/domain/project.go | 9 +++++++ pkg/domain/role.go | 49 ------------------------------------- 3 files changed, 9 insertions(+), 87 deletions(-) diff --git a/internal/repository/role.go b/internal/repository/role.go index dedbb876..67607666 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -2,7 +2,6 @@ package repository import ( "fmt" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" @@ -93,34 +92,6 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin return roles, nil } -func (r RoleRepository) ListProjectRoles(projectId string, pg *pagination.Pagination) ([]*domain.ProjectRole, error) { - var roles []*domain.ProjectRole - var objs []*domain.ProjectRole - - if pg == nil { - pg = pagination.NewDefaultPagination() - } - filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.ProjectRole{})) - - db.Count(&pg.TotalRows) - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Joins("JOIN roles as r on r.id = project_roles.role_id"). - Where("project_roles.project_id = ?", projectId). - Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) - //res := db.Preload("Role").Preload("Project").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) - if res.Error != nil { - return nil, res.Error - } - for _, role := range objs { - roles = append(roles, role) - } - - return roles, nil -} - func (r RoleRepository) Get(id string) (*domain.Role, error) { var role domain.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { @@ -139,15 +110,6 @@ func (r RoleRepository) GetTksRole(id string) (*domain.Role, error) { return &role, nil } -func (r RoleRepository) GetProjectRole(id uuid.UUID) (*domain.ProjectRole, error) { - var role domain.ProjectRole - if err := r.db.Preload("Role").Preload("Project").First(&role, "role_id = ?", id).Error; err != nil { - return nil, err - } - - return &role, nil -} - func (r RoleRepository) Update(roleObj *domain.Role) error { if roleObj == nil { return fmt.Errorf("roleObj is nil") diff --git a/pkg/domain/project.go b/pkg/domain/project.go index c55d0a3d..386d68ed 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -78,6 +78,15 @@ type GetProjectResponse struct { Project *ProjectDetailResponse `json:"project"` } +type ProjectRole struct { + ID string `gorm:"primarykey" json:"id"` + Name string `json:"name"` // project-leader, project-member, project-viewer + Description string `json:"description,omitempty"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + type ProjectUser struct { ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` diff --git a/pkg/domain/role.go b/pkg/domain/role.go index ae1d5cc3..204baa5d 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -33,25 +33,6 @@ type Role struct { UpdatedAt time.Time `json:"updatedAt"` } -type ProjectRole struct { - RoleID string `gorm:"primaryKey" json:"roleId"` - Role Role `gorm:"foreignKey:RoleID;references:ID;" json:"role"` - ProjectID string `json:"projectID"` - Project Project `gorm:"foreignKey:ProjectID;references:ID;" json:"project"` -} - -//type Role = struct { -// ID uuid.UUID `json:"id"` -// Name string `json:"name"` -// OrganizationID string `json:"organizationId"` -// Organization Organization `json:"organization"` -// Type string `json:"type"` -// Description string `json:"description"` -// Creator uuid.UUID `json:"creator"` -// CreatedAt time.Time `json:"createdAt"` -// UpdatedAt time.Time `json:"updatedAt"` -//} - type CreateTksRoleRequest struct { Name string `json:"name" validate:"required"` Description string `json:"description" validate:"omitempty,min=0,max=100"` @@ -80,33 +61,3 @@ type UpdateTksRoleRequest struct { Name string `json:"name" validate:"required"` Description string `json:"description" validate:"omitempty,min=0,max=100"` } - -type CreateProjectRoleRequest struct { - Name string `json:"name" validate:"required"` - Description string `json:"description" validate:"omitempty,min=0,max=100"` -} - -type CreateProjectRoleResponse struct { - ID string `json:"id"` -} - -type GetProjectRoleResponse struct { - ID string `json:"id"` - Name string `json:"name"` - OrganizationID string `json:"organizationId"` - ProjectID string `json:"projectId"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - -type ListProjectRoleResponse struct { - Roles []GetProjectRoleResponse `json:"roles"` - Pagination PaginationResponse `json:"pagination"` -} - -type UpdateProjectRoleRequest struct { - Name string `json:"name" validate:"required"` - Description string `json:"description" validate:"omitempty,min=0,max=100"` -} From d02514f752140a1f5ab499b57618e313da9038ab Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 16 Feb 2024 16:23:04 +0900 Subject: [PATCH 072/502] rollback to original project --- internal/repository/project.go | 50 +++++++++++++++++++++++++++++++++- pkg/domain/project.go | 14 ++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/internal/repository/project.go b/internal/repository/project.go index 67f57e95..c042cdc2 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -20,6 +20,9 @@ type IProjectRepository interface { GetProjectByIdAndLeader(organizationId string, projectId string) (*domain.Project, error) GetProjectByName(organizationId string, projectName string) (*domain.Project, error) UpdateProject(p *domain.Project) error + GetAllProjectRoles() ([]domain.ProjectRole, error) + GetProjectRoleByName(name string) (*domain.ProjectRole, error) + GetProjectRoleById(id string) (*domain.ProjectRole, error) AddProjectMember(*domain.ProjectMember) (string, error) GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) ([]domain.ProjectMember, error) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) ([]domain.ProjectMember, error) @@ -203,7 +206,6 @@ func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, proje res := r.db.Limit(1). Preload("ProjectMembers", "is_project_leader = ?", true). Preload("ProjectMembers.ProjectRole"). - Preload("ProjectMembers.ProjectRole.Role"). Preload("ProjectMembers.ProjectUser"). First(&p, "organization_id = ? and id = ?", organizationId, projectId) @@ -246,6 +248,52 @@ func (r *ProjectRepository) UpdateProject(p *domain.Project) error { return nil } +func (r *ProjectRepository) GetProjectRoleById(id string) (*domain.ProjectRole, error) { + var pr = &domain.ProjectRole{ID: id} + res := r.db.First(pr) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project role") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pr, nil +} + +func (r *ProjectRepository) GetAllProjectRoles() (prs []domain.ProjectRole, err error) { + res := r.db.Find(&prs) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project roles") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return prs, nil +} + +func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *domain.ProjectRole, err error) { + res := r.db.Where("name = ?", name).First(&pr) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project roles") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pr, nil +} + func (r *ProjectRepository) AddProjectMember(pm *domain.ProjectMember) (string, error) { res := r.db.Create(&pm) if res.Error != nil { diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 386d68ed..23882b28 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -1,9 +1,10 @@ package domain import ( + "time" + "github.com/google/uuid" "gorm.io/gorm" - "time" ) func (a *Project) BeforeCreate(*gorm.DB) (err error) { @@ -11,6 +12,11 @@ func (a *Project) BeforeCreate(*gorm.DB) (err error) { return nil } +func (t *ProjectRole) BeforeCreate(*gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} + func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { t.ID = uuid.New().String() return nil @@ -108,7 +114,7 @@ type ProjectMember struct { ProjectUserId uuid.UUID `json:"projectUserId"` ProjectUser *ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectUser"` ProjectRoleId string `json:"projectRoleId"` - ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:RoleID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` + ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` IsProjectLeader bool `gorm:"default:false" json:"projectLeader"` CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` @@ -151,6 +157,10 @@ type UpdateProjectRequest struct { CreateProjectRequest } +type GetProjectRoleResponse struct { + ProjectRole ProjectRole `json:"projectRole"` +} + type GetProjectRolesResponse struct { ProjectRoles []ProjectRole `json:"projectRoles"` } From 0a1ca86408837426d968ca97b75e499336aea738 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 16 Feb 2024 16:28:09 +0900 Subject: [PATCH 073/502] rollback to original project --- internal/delivery/api/endpoint.go | 54 ++++++++----------------------- internal/route/route.go | 5 --- 2 files changed, 14 insertions(+), 45 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2a20f6ed..e15c06a2 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -130,6 +130,8 @@ const ( // Project CreateProject + GetProjectRoles + GetProjectRole GetProjects GetProject UpdateProject @@ -545,6 +547,14 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CreateProject", Group: "Project", }, + GetProjectRoles: { + Name: "GetProjectRoles", + Group: "Project", + }, + GetProjectRole: { + Name: "GetProjectRole", + Group: "Project", + }, GetProjects: { Name: "GetProjects", Group: "Project", @@ -641,42 +651,22 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CreateTksRole", Group: "Role", }, - CreateProjectRole: { - Name: "CreateProjectRole", - Group: "Role", - }, ListTksRoles: { Name: "ListTksRoles", Group: "Role", }, - ListProjectRoles: { - Name: "ListProjectRoles", - Group: "Role", - }, GetTksRole: { Name: "GetTksRole", Group: "Role", }, - GetProjectRole: { - Name: "GetProjectRole", - Group: "Role", - }, DeleteTksRole: { Name: "DeleteTksRole", Group: "Role", }, - DeleteProjectRole: { - Name: "DeleteProjectRole", - Group: "Role", - }, UpdateTksRole: { Name: "UpdateTksRole", Group: "Role", }, - UpdateProjectRole: { - Name: "UpdateProjectRole", - Group: "Role", - }, } func (e Endpoint) String() string { @@ -871,6 +861,10 @@ func (e Endpoint) String() string { return "InstallStack" case CreateProject: return "CreateProject" + case GetProjectRoles: + return "GetProjectRoles" + case GetProjectRole: + return "GetProjectRole" case GetProjects: return "GetProjects" case GetProject: @@ -919,24 +913,14 @@ func (e Endpoint) String() string { return "DeleteAudit" case CreateTksRole: return "CreateTksRole" - case CreateProjectRole: - return "CreateProjectRole" case ListTksRoles: return "ListTksRoles" - case ListProjectRoles: - return "ListProjectRoles" case GetTksRole: return "GetTksRole" - case GetProjectRole: - return "GetProjectRole" case DeleteTksRole: return "DeleteTksRole" - case DeleteProjectRole: - return "DeleteProjectRole" case UpdateTksRole: return "UpdateTksRole" - case UpdateProjectRole: - return "UpdateProjectRole" default: return "" } @@ -1185,24 +1169,14 @@ func GetEndpoint(name string) Endpoint { return DeleteAudit case "CreateTksRole": return CreateTksRole - case "CreateProjectRole": - return CreateProjectRole case "ListTksRoles": return ListTksRoles - case "ListProjectRoles": - return ListProjectRoles case "GetTksRole": return GetTksRole - case "GetProjectRole": - return GetProjectRole case "DeleteTksRole": return DeleteTksRole - case "DeleteProjectRole": - return DeleteProjectRole case "UpdateTksRole": return UpdateTksRole - case "UpdateProjectRole": - return UpdateProjectRole default: return -1 } diff --git a/internal/route/route.go b/internal/route/route.go index ede3ff36..432aede0 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -238,11 +238,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.GetTksRole, http.HandlerFunc(roleHandler.GetTksRole))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.DeleteTksRole, http.HandlerFunc(roleHandler.DeleteTksRole))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateTksRole, http.HandlerFunc(roleHandler.UpdateTksRole))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles", customMiddleware.Handle(internalApi.CreateProjectRole, http.HandlerFunc(roleHandler.CreateProjectRole))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles", customMiddleware.Handle(internalApi.ListProjectRoles, http.HandlerFunc(roleHandler.ListProjectRoles))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles/{roleId}", customMiddleware.Handle(internalApi.GetProjectRole, http.HandlerFunc(roleHandler.GetProjectRole))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles/{roleId}", customMiddleware.Handle(internalApi.DeleteProjectRole, http.HandlerFunc(roleHandler.DeleteProjectRole))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateProjectRole, http.HandlerFunc(roleHandler.UpdateProjectRole))).Methods(http.MethodPut) r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets From 26a0981de349e9b3c759f4d0583b340da9ec0911 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 16 Feb 2024 17:49:46 +0900 Subject: [PATCH 074/502] Automatically import endpoints on initializing server --- cmd/server/main.go | 3 ++ internal/database/database.go | 59 +++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index a194abf8..b33b705e 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -117,6 +117,9 @@ func main() { log.Fatal("cannot connect gormDB") } + // Ensure default rows in database + err = database.EnsureDefaultRows(db) + // Initialize external client var argoClient argowf.ArgoClient if viper.GetString("argo-address") == "" || viper.GetInt("argo-port") == 0 { diff --git a/internal/database/database.go b/internal/database/database.go index 6e27de84..40d6046e 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -2,6 +2,7 @@ package database import ( "fmt" + "github.com/openinfradev/tks-api/internal/delivery/api" "os" "strings" @@ -118,9 +119,6 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&domain.Permission{}); err != nil { return err } - if err := db.AutoMigrate(&domain.ProjectRole{}); err != nil { - return err - } if err := db.AutoMigrate(&domain.Endpoint{}); err != nil { return err } @@ -135,6 +133,61 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&domain.ProjectNamespace{}); err != nil { return err } + if err := db.AutoMigrate(&domain.ProjectRole{}); err != nil { + return err + } + + return nil +} + +func EnsureDefaultRows(db *gorm.DB) error { + // Create default rows + repoFactory := repository.Repository{ + Auth: repository.NewAuthRepository(db), + User: repository.NewUserRepository(db), + Cluster: repository.NewClusterRepository(db), + Organization: repository.NewOrganizationRepository(db), + AppGroup: repository.NewAppGroupRepository(db), + AppServeApp: repository.NewAppServeAppRepository(db), + CloudAccount: repository.NewCloudAccountRepository(db), + StackTemplate: repository.NewStackTemplateRepository(db), + Alert: repository.NewAlertRepository(db), + Role: repository.NewRoleRepository(db), + Permission: repository.NewPermissionRepository(db), + Endpoint: repository.NewEndpointRepository(db), + Project: repository.NewProjectRepository(db), + } + + // + eps, err := repoFactory.Endpoint.List(nil) + if err != nil { + return err + } + if len(eps) == 0 { + for _, ep := range api.ApiMap { + if err := repoFactory.Endpoint.Create(&domain.Endpoint{ + Name: ep.Name, + Group: ep.Group, + }); err != nil { + return err + } + } + } else { + var storedEps = make(map[string]struct{}) + for _, ep := range eps { + storedEps[ep.Name] = struct{}{} + } + for _, ep := range api.ApiMap { + if _, ok := storedEps[ep.Name]; !ok { + if err := repoFactory.Endpoint.Create(&domain.Endpoint{ + Name: ep.Name, + Group: ep.Group, + }); err != nil { + return err + } + } + } + } // Audit if err := db.AutoMigrate(&repository.Audit{}); err != nil { From 58b5679369dd16b99a6469e320da8a7cfa568306 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 21 Feb 2024 18:50:12 +0900 Subject: [PATCH 075/502] merge up-to-date --- internal/database/database.go | 24 +- internal/delivery/api/endpoint.go | 74 +++-- internal/rbac/permission.go | 504 ++++++++++++++++++++++++++++++ internal/repository/endpoint.go | 74 +---- internal/repository/permission.go | 280 ++++++----------- internal/repository/repository.go | 2 + internal/repository/role.go | 10 +- internal/usecase/organization.go | 30 +- internal/usecase/role.go | 4 +- internal/usecase/user.go | 20 +- pkg/domain/endpoint.go | 17 +- pkg/domain/mapper_test.go | 3 +- pkg/domain/permmision.go | 2 +- 13 files changed, 681 insertions(+), 363 deletions(-) create mode 100644 internal/rbac/permission.go diff --git a/internal/database/database.go b/internal/database/database.go index 40d6046e..cb3f0aee 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -163,8 +163,13 @@ func EnsureDefaultRows(db *gorm.DB) error { if err != nil { return err } - if len(eps) == 0 { - for _, ep := range api.ApiMap { + + var storedEps = make(map[string]struct{}) + for _, ep := range eps { + storedEps[ep.Name] = struct{}{} + } + for _, ep := range api.ApiMap { + if _, ok := storedEps[ep.Name]; !ok { if err := repoFactory.Endpoint.Create(&domain.Endpoint{ Name: ep.Name, Group: ep.Group, @@ -172,21 +177,6 @@ func EnsureDefaultRows(db *gorm.DB) error { return err } } - } else { - var storedEps = make(map[string]struct{}) - for _, ep := range eps { - storedEps[ep.Name] = struct{}{} - } - for _, ep := range api.ApiMap { - if _, ok := storedEps[ep.Name]; !ok { - if err := repoFactory.Endpoint.Create(&domain.Endpoint{ - Name: ep.Name, - Group: ep.Group, - }); err != nil { - return err - } - } - } } // Audit diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index e15c06a2..137cb4b6 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -82,6 +82,18 @@ const ( UpdateAppServeAppStatus UpdateAppServeAppEndpoint RollbackAppServeApp + CreateAppServeApp // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 + GetAppServeApps // 프로젝트 관리/앱 서빙/조회 + GetNumOfAppsOnStack // 프로젝트 관리/앱 서빙/조회 + GetAppServeApp // 프로젝트 관리/앱 서빙/조회 + GetAppServeAppLatestTask // 프로젝트 관리/앱 서빙/조회 + IsAppServeAppExist // 프로젝트 관리/앱 서빙/조회 // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 + IsAppServeAppNameExist // 프로젝트 관리/앱 서빙/조회 // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 + DeleteAppServeApp // 프로젝트 관리/앱 서빙/삭제 + UpdateAppServeApp // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 + UpdateAppServeAppStatus // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 + UpdateAppServeAppEndpoint // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 + RollbackAppServeApp // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 // CloudAccount GetCloudAccounts @@ -102,10 +114,10 @@ const ( DeleteStackTemplate // Dashboard - GetChartsDashboard - GetChartDashboard - GetStacksDashboard - GetResourcesDashboard + GetChartsDashboard // 대시보드/대시보드/조회 + GetChartDashboard // 대시보드/대시보드/조회 + GetStacksDashboard // 대시보드/대시보드/조회 + GetResourcesDashboard // 대시보드/대시보드/조회 // Alert CreateAlert @@ -116,36 +128,36 @@ const ( CreateAlertAction // Stack - GetStacks - CreateStack - CheckStackName - GetStack - UpdateStack - DeleteStack - GetStackKubeConfig - GetStackStatus - SetFavoriteStack - DeleteFavoriteStack - InstallStack + GetStacks // 스택관리/조회 + CreateStack // // 스택관리/생성 + CheckStackName // 스택관리/조회 + GetStack // 스택관리/조회 + UpdateStack // 스택관리/수정 + DeleteStack // 스택관리/삭제 + GetStackKubeConfig // 스택관리/조회 + GetStackStatus // 스택관리/조회 + SetFavoriteStack // 스택관리/조회 + DeleteFavoriteStack // 스택관리/조회 + InstallStack // 스택관리 / 조회 // Project - CreateProject - GetProjectRoles - GetProjectRole - GetProjects - GetProject - UpdateProject - DeleteProject - AddProjectMember - GetProjectMember - GetProjectMembers - RemoveProjectMember - UpdateProjectMemberRole - CreateProjectNamespace - GetProjectNamespaces - GetProjectNamespace + CreateProject // 프로젝트 관리/프로젝트/생성 + GetProjectRoles // 프로젝트 관리/설정-일반/조회 // 프로젝트 관리/설정-멤버/조회 + GetProjectRole // 프로젝트 관리/설정-일반/조회 // 프로젝트 관리/설정-멤버/조회 + GetProjects // 프로젝트 관리/프로젝트/조회 // 프로젝트 관리/설정-일반/조회 + GetProject // 프로젝트 관리/프로젝트/조회 // 프로젝트 관리/설정-일반/조회 + UpdateProject // 프로젝트 관리/설정-일반/수정 + DeleteProject // 프로젝트 관리/설정-일반/삭제 + AddProjectMember // 프로젝트 관리/설정-멤버/생성 + GetProjectMember // 프로젝트 관리/설정-멤버/조회 + GetProjectMembers // 프로젝트 관리/설정-멤버/조회 + RemoveProjectMember // 프로젝트 관리/설정-멤버/삭제 + UpdateProjectMemberRole // 프로젝트 관리/설정-멤버/수정 + CreateProjectNamespace // 프로젝트 관리/설정-네임스페이스/생성 + GetProjectNamespaces // 프로젝트 관리/설정-네임스페이스/조회 + GetProjectNamespace // 프로젝트 관리/설정-네임스페이스/조회 UpdateProjectNamespace - DeleteProjectNamespace + DeleteProjectNamespace // 프로젝트 관리/설정-네임스페이스/삭제 SetFavoriteProject SetFavoriteProjectNamespace UnSetFavoriteProject diff --git a/internal/rbac/permission.go b/internal/rbac/permission.go new file mode 100644 index 00000000..4b0ea9ed --- /dev/null +++ b/internal/rbac/permission.go @@ -0,0 +1,504 @@ +package rbac + +import ( + "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/pkg/domain" +) + +type PermissionSet struct { + Dashboard *domain.Permission + Stack *domain.Permission + SecurityPolicy *domain.Permission + ProjectManagement *domain.Permission + Notification *domain.Permission + Configuration *domain.Permission +} + +func NewDefaultPermission() *PermissionSet { + return &PermissionSet{ + Dashboard: newDashboard(), + Stack: newStack(), + SecurityPolicy: newSecurityPolicy(), + ProjectManagement: newProjectManagement(), + Notification: newNotification(), + Configuration: newConfiguration(), + } +} + +func endpointObjects(eps ...api.Endpoint) []*domain.Endpoint { + var result []*domain.Endpoint + for _, ep := range eps { + result = append(result, &domain.Endpoint{ + Name: api.ApiMap[ep].Name, + Group: api.ApiMap[ep].Group, + }) + } + return result +} + +func newDashboard() *domain.Permission { + dashboard := &domain.Permission{ + Name: "대시보드", + Children: []*domain.Permission{ + { + Name: "대시보드", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetChartsDashboard, + api.GetChartDashboard, + api.GetStacksDashboard, + api.GetResourcesDashboard, + ), + }, + }, + }, + { + Name: "대시보드 설정", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return dashboard +} + +func newStack() *domain.Permission { + stack := &domain.Permission{ + Name: "스택 관리", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetStacks, + api.GetStack, + api.CheckStackName, + api.GetStackStatus, + api.GetStackKubeConfig, + + api.SetFavoriteStack, + api.DeleteFavoriteStack, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateStack, + api.InstallStack, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateStack, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteStack, + ), + }, + }, + } + + return stack +} + +func newSecurityPolicy() *domain.Permission { + security_policy := &domain.Permission{ + Name: "보안/정책 관리", + Children: []*domain.Permission{ + { + Name: "보안/정책", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return security_policy +} + +func newProjectManagement() *domain.Permission { + projectManagement := &domain.Permission{ + Name: "프로젝트 관리", + Children: []*domain.Permission{ + { + Name: "프로젝트", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProject, + ), + }, + }, + }, + { + Name: "앱 서빙", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetAppServeApps, + api.GetAppServeApp, + api.GetNumOfAppsOnStack, + api.GetAppServeAppLatestTask, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + ), + }, + { + Name: "빌드", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + Name: "배포", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteAppServeApp, + ), + }, + }, + }, + { + Name: "설정-일반", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + + api.GetProjectRoles, + api.GetProjectRole, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProject, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProject, + ), + }, + }, + }, + { + Name: "설정-멤버", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectMembers, + api.GetProjectMember, + api.GetProjectRoles, + api.GetProjectRole, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.AddProjectMember, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProjectMemberRole, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.RemoveProjectMember, + ), + }, + }, + }, + { + Name: "설정-네임스페이스", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectNamespaces, + api.GetProjectNamespace, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProjectNamespace, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects(), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProjectNamespace, + ), + }, + }, + }, + }, + } + + return projectManagement +} + +func newNotification() *domain.Permission { + notification := &domain.Permission{ + Name: "알림", + Children: []*domain.Permission{ + { + Name: "시스템 경고", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "보안/정책 감사로그", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return notification +} + +func newConfiguration() *domain.Permission { + configuration := &domain.Permission{ + Name: "설정", + Children: []*domain.Permission{ + { + Name: "일반", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "클라우드 계정", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "스택 템플릿", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "프로젝트 관리", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자 권한 관리", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "알림 설정", + Children: []*domain.Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return configuration +} diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go index 1bd4d4cc..c90589ac 100644 --- a/internal/repository/endpoint.go +++ b/internal/repository/endpoint.go @@ -2,7 +2,6 @@ package repository import ( "fmt" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" @@ -12,9 +11,7 @@ import ( type IEndpointRepository interface { Create(endpoint *domain.Endpoint) error List(pg *pagination.Pagination) ([]*domain.Endpoint, error) - Get(id uuid.UUID) (*domain.Endpoint, error) - Update(endpoint *domain.Endpoint) error - Delete(id uuid.UUID) error + Get(id uint) (*domain.Endpoint, error) } type EndpointRepository struct { @@ -27,22 +24,10 @@ func NewEndpointRepository(db *gorm.DB) *EndpointRepository { } } -//type Endpoint struct { -// gorm.Model -// -// ID uuid.UUID `gorm:"type:uuid;primary_key;"` -// -// Name string `gorm:"type:text;not null;unique"` -// Group string `gorm:"type:text;"` -// PermissionID uuid.UUID `gorm:"type:uuid;"` -// Permission Permission `gorm:"foreignKey:PermissionID;"` -//} - func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { obj := &domain.Endpoint{ - Name: endpoint.Name, - Group: endpoint.Group, - PermissionID: endpoint.PermissionID, + Name: endpoint.Name, + Group: endpoint.Group, } if err := e.db.Create(obj).Error; err != nil { @@ -54,7 +39,6 @@ func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint, error) { var endpoints []*domain.Endpoint - var objs []*domain.Endpoint if pg == nil { pg = pagination.NewDefaultPagination() @@ -66,24 +50,15 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Preload("Permissions").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&endpoints) if res.Error != nil { return nil, res.Error } - for _, obj := range objs { - endpoints = append(endpoints, &domain.Endpoint{ - ID: obj.ID, - Name: obj.Name, - Group: obj.Group, - PermissionID: obj.PermissionID, - Permission: obj.Permission, - }) - } return endpoints, nil } -func (e *EndpointRepository) Get(id uuid.UUID) (*domain.Endpoint, error) { +func (e *EndpointRepository) Get(id uint) (*domain.Endpoint, error) { var obj domain.Endpoint if err := e.db.Preload("Permission").First(&obj, "id = ?", id).Error; err != nil { @@ -91,46 +66,7 @@ func (e *EndpointRepository) Get(id uuid.UUID) (*domain.Endpoint, error) { } return &domain.Endpoint{ - ID: obj.ID, Name: obj.Name, Group: obj.Group, }, nil } - -func (e *EndpointRepository) Update(endpoint *domain.Endpoint) error { - obj := &domain.Endpoint{ - ID: endpoint.ID, - Name: endpoint.Name, - Group: endpoint.Group, - PermissionID: endpoint.PermissionID, - } - - if err := e.db.Save(obj).Error; err != nil { - return err - } - - return nil -} - -// -//// domain.Endpoint to repository.Endpoint -//func ConvertDomainToRepoEndpoint(endpoint *domain.Endpoint) *Endpoint { -// return &Endpoint{ -// ID: endpoint.ID, -// Name: endpoint.Name, -// Group: endpoint.Group, -// PermissionID: endpoint.PermissionID, -// Permission: *ConvertDomainToRepoPermission(&endpoint.Permission), -// } -//} -// -//// repository.Endpoint to domain.Endpoint -//func ConvertRepoToDomainEndpoint(endpoint *Endpoint) *domain.Endpoint { -// return &domain.Endpoint{ -// ID: endpoint.ID, -// Name: endpoint.Name, -// Group: endpoint.Group, -// PermissionID: endpoint.PermissionID, -// Permission: *ConvertRepoToDomainPermission(&endpoint.Permission), -// } -//} diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 5a28a708..09c50939 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -24,197 +24,91 @@ func NewPermissionRepository(db *gorm.DB) *PermissionRepository { } } -// -//type Permission struct { -// gorm.Model -// -// ID uuid.UUID `gorm:"primarykey;type:uuid;"` -// Name string -// -// IsAllowed *bool `gorm:"type:boolean;"` -// RoleID string -// Role *Role `gorm:"foreignKey:RoleID;references:ID;"` -// Endpoints []*Endpoint `gorm:"one2many:endpoints;"` -// -// ParentID *uuid.UUID -// Parent *Permission `gorm:"foreignKey:ParentID;references:ID;"` -// Children []*Permission `gorm:"foreignKey:ParentID;references:ID;"` -//} -// -//func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { -// if p.ID == uuid.Nil { -// p.ID = uuid.New() -// } -// return nil -//} -// -//func (r PermissionRepository) Create(p *domain.Permission) error { -// //var parent *Permission -// //var children []*Permission -// // -// //if p.Parent != nil { -// // parent = &Permission{} -// // result := r.db.First(&parent, "id = ?", p.Parent.ID) -// // if result.Error != nil { -// // return result.Error -// // } -// //} -// //if p.Children != nil { -// // for _, child := range p.Children { -// // newChild := &Permission{} -// // result := r.db.First(&newChild, "id = ?", child.ID) -// // if result.Error != nil { -// // return result.Error -// // } -// // children = append(children, newChild) -// // } -// //} -// -// permission := ConvertDomainToRepoPermission(p) -// -// return r.db.Create(permission).Error -//} -// -//func (r PermissionRepository) List() ([]*domain.Permission, error) { -// var permissions []*domain.Permission -// var outs []*domain.Permission -// -// err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL").Find(&permissions).Error -// if err != nil { -// return nil, err -// } -// -// for _, permission := range permissions { -// outs = append(outs, ConvertRepoToDomainPermission(permission)) -// } -// return outs, nil -//} -// -//func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { -// permission := &domain.Permission{} -// result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) -// if result.Error != nil { -// return nil, result.Error -// } -// -// return ConvertRepoToDomainPermission(permission), nil -//} -// -//func (r PermissionRepository) Delete(id uuid.UUID) error { -// return r.db.Delete(&Permission{}, id).Error -//} +func (r PermissionRepository) Create(p *domain.Permission) error { + //var parent *Permission + //var children []*Permission + // + //if p.Parent != nil { + // parent = &Permission{} + // result := r.db.First(&parent, "id = ?", p.Parent.ID) + // if result.Error != nil { + // return result.Error + // } + //} + //if p.Children != nil { + // for _, child := range p.Children { + // newChild := &Permission{} + // result := r.db.First(&newChild, "id = ?", child.ID) + // if result.Error != nil { + // return result.Error + // } + // children = append(children, newChild) + // } + //} -//func (r PermissionRepository) Update(p *domain.Permission) error { -// permission := ConvertDomainToRepoPermission(p) -// -// return r.db.Updates(permission).Error -// -// //var parent *Permission -// //var children []*Permission -// // -// //if p.Parent != nil { -// // parent = &Permission{} -// // result := r.db.First(&parent, "id = ?", p.Parent.ID) -// // if result.Error != nil { -// // return result.Error -// // } -// //} -// //if p.Children != nil { -// // for _, child := range p.Children { -// // newChild := &Permission{} -// // result := r.db.First(&newChild, "id = ?", child.ID) -// // if result.Error != nil { -// // return result.Error -// // } -// // children = append(children, newChild) -// // } -// //} -// // -// //permission := &Permission{} -// // -// //result := r.db.First(&permission, "id = ?", p.ID) -// //if result.Error != nil { -// // return result.Error -// //} -// // -// //permission.Name = p.Name -// //permission.Parent = parent -// //permission.Children = children -// //permission.IsAllowed = p.IsAllowed -// // -// //return r.db.Save(permission).Error -//} -// -//// repository.Permission to domain.Permission -//func ConvertRepoToDomainPermission(repoPerm *domain.Permission) *domain.Permission { -// if repoPerm == nil { -// return nil -// } -// -// if repoPerm.Endpoints == nil { -// repoPerm.Endpoints = []*Endpoint{} -// } -// var domainEndpoints []*domain.Endpoint -// for _, endpoint := range repoPerm.Endpoints { -// domainEndpoints = append(domainEndpoints, ConvertRepoToDomainEndpoint(endpoint)) -// } -// -// // Domain Permission 객체 생성 -// domainPerm := &domain.Permission{ -// ID: repoPerm.ID, -// Name: repoPerm.Name, -// ParentID: repoPerm.ParentID, -// IsAllowed: repoPerm.IsAllowed, -// Endpoints: domainEndpoints, -// } -// -// // 자식 권한들 변환 -// for _, child := range repoPerm.Children { -// domainChild := ConvertRepoToDomainPermission(child) -// domainPerm.Children = append(domainPerm.Children, domainChild) -// } -// -// // 부모 권한 변환 (부모 권한이 있을 경우만) -// if repoPerm.Parent != nil { -// domainPerm.Parent = ConvertRepoToDomainPermission(repoPerm.Parent) -// } -// -// return domainPerm -//} -// -//// domain.Permission to repository.Permission -//func ConvertDomainToRepoPermission(domainPerm *domain.Permission) *Permission { -// if domainPerm == nil { -// return nil -// } -// -// if domainPerm.Endpoints == nil { -// domainPerm.Endpoints = []*domain.Endpoint{} -// } -// var repoEndpoints []*Endpoint -// for _, endpoint := range domainPerm.Endpoints { -// repoEndpoints = append(repoEndpoints, ConvertDomainToRepoEndpoint(endpoint)) -// } -// -// // Domain Permission 객체 생성 -// repoPerm := &Permission{ -// ID: domainPerm.ID, -// Name: domainPerm.Name, -// ParentID: domainPerm.ParentID, -// IsAllowed: domainPerm.IsAllowed, -// Endpoints: repoEndpoints, -// } -// -// // 자식 권한들 변환 -// for _, child := range domainPerm.Children { -// repoChild := ConvertDomainToRepoPermission(child) -// repoPerm.Children = append(repoPerm.Children, repoChild) -// } -// -// // 부모 권한 변환 (부모 권한이 있을 경우만) -// if domainPerm.Parent != nil { -// repoPerm.Parent = ConvertDomainToRepoPermission(domainPerm.Parent) -// } -// -// return repoPerm -//} + return r.db.Create(p).Error +} + +func (r PermissionRepository) List() ([]*domain.Permission, error) { + var permissions []*domain.Permission + + err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL").Find(&permissions).Error + if err != nil { + return nil, err + } + + return permissions, nil +} + +func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { + permission := &domain.Permission{} + result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) + if result.Error != nil { + return nil, result.Error + } + + return permission, nil +} + +func (r PermissionRepository) Delete(id uuid.UUID) error { + return r.db.Delete(&domain.Permission{}, "id = ?", id).Error +} + +func (r PermissionRepository) Update(p *domain.Permission) error { + return r.db.Save(p).Error + + //var parent *Permission + //var children []*Permission + // + //if p.Parent != nil { + // parent = &Permission{} + // result := r.db.First(&parent, "id = ?", p.Parent.ID) + // if result.Error != nil { + // return result.Error + // } + //} + //if p.Children != nil { + // for _, child := range p.Children { + // newChild := &Permission{} + // result := r.db.First(&newChild, "id = ?", child.ID) + // if result.Error != nil { + // return result.Error + // } + // children = append(children, newChild) + // } + //} + // + //permission := &Permission{} + // + //result := r.db.First(&permission, "id = ?", p.ID) + //if result.Error != nil { + // return result.Error + //} + // + //permission.Name = p.Name + //permission.Parent = parent + //permission.Children = children + //permission.IsAllowed = p.IsAllowed + // + //return r.db.Save(permission).Error +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index e176a7c8..46138c9d 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -22,6 +22,8 @@ type Repository struct { StackTemplate IStackTemplateRepository Alert IAlertRepository Role IRoleRepository + Permission IPermissionRepository + Endpoint IEndpointRepository Project IProjectRepository Audit IAuditRepository } diff --git a/internal/repository/role.go b/internal/repository/role.go index 67607666..dbae6ed9 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -9,7 +9,7 @@ import ( ) type IRoleRepository interface { - Create(roleObj *domain.Role) error + Create(roleObj *domain.Role) (string, error) List(pg *pagination.Pagination) ([]*domain.Role, error) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) Get(id string) (*domain.Role, error) @@ -32,15 +32,15 @@ func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.Role, err return &role, nil } -func (r RoleRepository) Create(roleObj *domain.Role) error { +func (r RoleRepository) Create(roleObj *domain.Role) (string, error) { if roleObj == nil { - return fmt.Errorf("roleObj is nil") + return "", fmt.Errorf("roleObj is nil") } if err := r.db.Create(roleObj).Error; err != nil { - return err + return "", err } - return nil + return roleObj.ID, nil } func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) { diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index ad074123..9246d018 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -64,25 +64,21 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *domain.Organizatio } // Create admin roles in DB - if err := u.roleRepo.Create(domain.TksRole{ - Role: domain.Role{ - OrganizationID: organizationId, - Name: "admin", - Description: "admin", - Type: string(domain.RoleTypeTks), - }, + if _, err := u.roleRepo.Create(&domain.Role{ + OrganizationID: organizationId, + Name: "admin", + Description: "admin", + Type: string(domain.RoleTypeTks), }); err != nil { return "", err } // Create user roles in DB - if err := u.roleRepo.Create(domain.TksRole{ - Role: domain.Role{ - OrganizationID: organizationId, - Name: "user", - Description: "user", - Type: string(domain.RoleTypeTks), - }, + if _, err := u.roleRepo.Create(&domain.Role{ + OrganizationID: organizationId, + Name: "user", + Description: "user", + Type: string(domain.RoleTypeTks), }); err != nil { return "", err } @@ -140,11 +136,7 @@ func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) return err } for _, role := range roles { - uuid, err := uuid.Parse(role.RoleID) - if err != nil { - return err - } - if err := u.roleRepo.DeleteCascade(uuid); err != nil { + if err := u.roleRepo.Delete(role.ID); err != nil { return err } } diff --git a/internal/usecase/role.go b/internal/usecase/role.go index 31d28b0e..70d51081 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -7,7 +7,7 @@ import ( ) type IRoleUsecase interface { - CreateTksRole(role *domain.Role) error + CreateTksRole(role *domain.Role) (string, error) ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) GetTksRole(id string) (*domain.Role, error) @@ -25,7 +25,7 @@ func NewRoleUsecase(repo repository.Repository) *RoleUsecase { } } -func (r RoleUsecase) CreateTksRole(role *domain.Role) error { +func (r RoleUsecase) CreateTksRole(role *domain.Role) (string, error) { return r.repo.Create(role) } diff --git a/internal/usecase/user.go b/internal/usecase/user.go index e07d2cbb..3be12a0a 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -443,16 +443,16 @@ func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.Us // Get user role var roleUuid string - tksRoles, err := u.roleRepository.ListTksRoles(user.Organization.ID, nil) + roles, err := u.roleRepository.ListTksRoles(user.Organization.ID, nil) if err != nil { return nil, err } - if len(tksRoles) == 0 { + if len(roles) == 0 { return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") } - for _, role := range tksRoles { - if role.Role.Name == user.Role.Name { - roleUuid = role.RoleID + for _, role := range roles { + if role.Name == user.Role.Name { + roleUuid = role.ID } } if roleUuid == "" { @@ -501,16 +501,16 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st // Get user role var roleUuid string - tksRoles, err := u.roleRepository.ListTksRoles(user.Organization.ID, nil) + roles, err := u.roleRepository.ListTksRoles(user.Organization.ID, nil) if err != nil { return nil, err } - if len(tksRoles) == 0 { + if len(roles) == 0 { return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") } - for _, role := range tksRoles { - if role.Role.Name == user.Role.Name { - roleUuid = role.RoleID + for _, role := range roles { + if role.Name == user.Role.Name { + roleUuid = role.ID } } if roleUuid == "" { diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index 6926dbe5..95e0292a 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -1,19 +1,6 @@ package domain -import ( - "github.com/google/uuid" - "gorm.io/gorm" -) - type Endpoint struct { - ID uuid.UUID `gorm:"type:uuid;primaryKey;" json:"id"` - Name string `gorm:"type:text;not null;unique" json:"name"` - Group string `gorm:"type:text;" json:"group"` - PermissionID uuid.UUID `gorm:"type:uuid;" json:"permissionId"` - Permission *Permission `gorm:"foreignKey:PermissionID;" json:"permission"` -} - -func (e *Endpoint) BeforeCreate(tx *gorm.DB) error { - e.ID = uuid.New() - return nil + Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` + Group string `gorm:"type:text;" json:"group"` } diff --git a/pkg/domain/mapper_test.go b/pkg/domain/mapper_test.go index f1d57270..c235e360 100644 --- a/pkg/domain/mapper_test.go +++ b/pkg/domain/mapper_test.go @@ -2,6 +2,7 @@ package domain import ( "fmt" + "github.com/google/uuid" "testing" "time" ) @@ -84,7 +85,7 @@ func TestConvert(t *testing.T) { name: "test case User->GetUserResponse", args: args{ src: User{ - ID: "", + ID: uuid.New(), AccountId: "testAccount", Password: "testPassword", Name: "testName", diff --git a/pkg/domain/permmision.go b/pkg/domain/permmision.go index c3cf0d84..4bea6726 100644 --- a/pkg/domain/permmision.go +++ b/pkg/domain/permmision.go @@ -14,7 +14,7 @@ type Permission struct { IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` RoleID *string `json:"role_id,omitempty"` Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` - Endpoints []*Endpoint `gorm:"one2many:endpoints;" json:"endpoints,omitempty"` + Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` // omit empty ParentID *uuid.UUID `json:"parent_id,omitempty"` From e42120f823038f625e9db6b1df8cf55c89039b19 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 4 Mar 2024 14:55:56 +0900 Subject: [PATCH 076/502] permission add --- internal/delivery/api/endpoint.go | 19 +- internal/delivery/http/organization.go | 58 ++++- internal/delivery/http/permission.go | 141 ++++++++++++ internal/delivery/http/role.go | 24 +- internal/helper/util.go | 4 + internal/repository/permission.go | 44 +--- internal/repository/role.go | 7 +- internal/route/route.go | 11 +- internal/usecase/organization.go | 20 -- internal/usecase/permission.go | 94 +++++++- internal/usecase/usecase.go | 2 + pkg/domain/endpoint.go | 9 +- {internal/rbac => pkg/domain}/permission.go | 229 +++++++++++++++----- pkg/domain/permmision.go | 30 --- pkg/domain/role.go | 1 - 15 files changed, 511 insertions(+), 182 deletions(-) create mode 100644 internal/delivery/http/permission.go rename {internal/rbac => pkg/domain}/permission.go (57%) delete mode 100644 pkg/domain/permmision.go diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 137cb4b6..4d457214 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -68,20 +68,8 @@ const ( CreateApplication // AppServeApp - CreateAppServeApp - GetAppServeApps - GetNumOfAppsOnStack - GetAppServeApp GetAppServeAppTasksByAppId GetAppServeAppTaskDetail - GetAppServeAppLatestTask - IsAppServeAppExist - IsAppServeAppNameExist - DeleteAppServeApp - UpdateAppServeApp - UpdateAppServeAppStatus - UpdateAppServeAppEndpoint - RollbackAppServeApp CreateAppServeApp // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 GetAppServeApps // 프로젝트 관리/앱 서빙/조회 GetNumOfAppsOnStack // 프로젝트 관리/앱 서빙/조회 @@ -157,7 +145,7 @@ const ( GetProjectNamespaces // 프로젝트 관리/설정-네임스페이스/조회 GetProjectNamespace // 프로젝트 관리/설정-네임스페이스/조회 UpdateProjectNamespace - DeleteProjectNamespace // 프로젝트 관리/설정-네임스페이스/삭제 + DeleteProjectNamespace // 프로젝트 관리/설정-네임스페이스/삭제 SetFavoriteProject SetFavoriteProjectNamespace UnSetFavoriteProject @@ -176,6 +164,11 @@ const ( GetTksRole DeleteTksRole UpdateTksRole + + // Permission + GetPermissionTemplates + GetPermissionsByRoleId + UpdatePermissionsByRoleId ) var ApiMap = map[Endpoint]EndpointInfo{ diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 569d5145..8a3b7868 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -15,14 +15,18 @@ import ( ) type OrganizationHandler struct { - usecase usecase.IOrganizationUsecase - userUsecase usecase.IUserUsecase + usecase usecase.IOrganizationUsecase + userUsecase usecase.IUserUsecase + roleUsecase usecase.IRoleUsecase + permissionUsecase usecase.IPermissionUsecase } func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { return &OrganizationHandler{ - usecase: u.Organization, - userUsecase: u.User, + usecase: u.Organization, + userUsecase: u.User, + roleUsecase: u.Role, + permissionUsecase: u.Permission, } } @@ -59,6 +63,52 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. return } organization.ID = organizationId + + // Role 생성 + adminRole := domain.Role{ + OrganizationID: organizationId, + Name: "admin", + Description: "admin", + Type: string(domain.RoleTypeTks), + } + adminRoleId, err := h.roleUsecase.CreateTksRole(&adminRole) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + userRole := domain.Role{ + OrganizationID: organizationId, + Name: "user", + Description: "user", + Type: string(domain.RoleTypeTks), + } + userRoleId, err := h.roleUsecase.CreateTksRole(&userRole) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + // Permission 생성 + adminPermissionSet := h.permissionUsecase.GetAllowedPermissionSet() + h.permissionUsecase.SetRoleIdToPermissionSet(adminRoleId, adminPermissionSet) + err = h.permissionUsecase.CreatePermissionSet(adminPermissionSet) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + userPermissionSet := h.permissionUsecase.GetUserPermissionSet() + h.permissionUsecase.SetRoleIdToPermissionSet(userRoleId, userPermissionSet) + err = h.permissionUsecase.CreatePermissionSet(userPermissionSet) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + // Admin user 생성 _, err = h.userUsecase.CreateAdmin(organizationId, input.Email) if err != nil { diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go new file mode 100644 index 00000000..b67a6b8e --- /dev/null +++ b/internal/delivery/http/permission.go @@ -0,0 +1,141 @@ +package http + +import ( + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "net/http" +) + +type IPermissionHandler interface { + GetPermissionTemplates(w http.ResponseWriter, r *http.Request) + GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) + UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) +} + +type PermissionHandler struct { + permissionUsecase usecase.IPermissionUsecase +} + +func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { + return &PermissionHandler{ + permissionUsecase: usecase.Permission, + } +} + +// GetPermissionTemplates godoc +// @Tags Permission +// @Summary Get Permission Templates +// @Description Get Permission Templates +// @Accept json +// @Produce json +// @Success 200 {object} domain.PermissionSet +// @Router /permissions/templates [get] +func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { + permissionSet := domain.NewDefaultPermissionSet() + + var out domain.GetPermissionTemplatesResponse + out.Permissions = append(out.Permissions, permissionSet.Dashboard) + out.Permissions = append(out.Permissions, permissionSet.Stack) + out.Permissions = append(out.Permissions, permissionSet.SecurityPolicy) + out.Permissions = append(out.Permissions, permissionSet.ProjectManagement) + out.Permissions = append(out.Permissions, permissionSet.Notification) + out.Permissions = append(out.Permissions, permissionSet.Configuration) + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetPermissionsByRoleId godoc +// @Tags Permission +// @Summary Get Permissions By Role ID +// @Description Get Permissions By Role ID +// @Accept json +// @Produce json +// @Success 200 {object} domain.PermissionSet +// @Router /roles/{roleId}/permissions [get] +func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { + // path parameter + var roleId string + + vars := mux.Vars(r) + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(roleId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + var out domain.GetPermissionsByRoleIdResponse + out.Permissions = append(out.Permissions, permissionSet.Dashboard) + out.Permissions = append(out.Permissions, permissionSet.Stack) + out.Permissions = append(out.Permissions, permissionSet.SecurityPolicy) + out.Permissions = append(out.Permissions, permissionSet.ProjectManagement) + out.Permissions = append(out.Permissions, permissionSet.Notification) + out.Permissions = append(out.Permissions, permissionSet.Configuration) + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdatePermissionsByRoleId godoc +// @Tags Permission +// @Summary Update Permissions By Role ID +// @Description Update Permissions By Role ID +// @Accept json +// @Produce json +// @Param roleId path string true "Role ID" +// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" +// @Success 200 +// @Router /roles/{roleId}/permissions [put] +func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { + // path parameter + log.Debug("UpdatePermissionsByRoleId Called") + var roleId string + _ = roleId + vars := mux.Vars(r) + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + // request + input := domain.UpdatePermissionsByRoleIdRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + log.Debugf("input: %+v", input) + + for _, permission := range input.Permissions { + log.Debugf("permission: %+v", permission) + if err := h.permissionUsecase.UpdatePermission(permission); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + + //var edgePermissions []*domain.Permission + //for _, permission := range input.Permissions { + // domain.GetEdgePermission(permission, edgePermissions, nil) + //} + //log.Debugf("edgePermissions: %+v", edgePermissions) + //for _, permission := range edgePermissions { + // err := h.permissionUsecase.UpdatePermission(permission) + // if err != nil { + // ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + // return + // } + //} + + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 601440a9..8f357117 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -20,12 +20,14 @@ type IRoleHandler interface { } type RoleHandler struct { - roleUsecase usecase.IRoleUsecase + roleUsecase usecase.IRoleUsecase + permissionUsecase usecase.IPermissionUsecase } -func NewRoleHandler(roleUsecase usecase.IRoleUsecase) *RoleHandler { +func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { return &RoleHandler{ - roleUsecase: roleUsecase, + roleUsecase: usecase.Role, + permissionUsecase: usecase.Permission, } } @@ -68,11 +70,24 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { Type: string(domain.RoleTypeTks), } - if err := h.roleUsecase.CreateTksRole(&dto); err != nil { + // create role + var roleId string + if roleId, err = h.roleUsecase.CreateTksRole(&dto); err != nil { ErrorJSON(w, r, err) return } + // create permission + defaultPermissionSet := domain.NewDefaultPermissionSet() + h.permissionUsecase.SetRoleIdToPermissionSet(roleId, defaultPermissionSet) + err = h.permissionUsecase.CreatePermissionSet(defaultPermissionSet) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // response + ResponseJSON(w, r, http.StatusOK, domain.CreateTksRoleResponse{ID: roleId}) } // ListTksRoles godoc @@ -238,7 +253,6 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // input to dto dto := domain.Role{ ID: roleId, - Name: input.Name, Description: input.Description, } diff --git a/internal/helper/util.go b/internal/helper/util.go index 5919d7b7..5a7cae86 100644 --- a/internal/helper/util.go +++ b/internal/helper/util.go @@ -96,6 +96,10 @@ func BoolP(value bool) *bool { return &value } +func StringP(value string) *string { + return &value +} + func UUIDP(value uuid.UUID) *uuid.UUID { return &value } diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 09c50939..db097922 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -8,7 +8,7 @@ import ( type IPermissionRepository interface { Create(permission *domain.Permission) error - List() ([]*domain.Permission, error) + List(roleId string) ([]*domain.Permission, error) Get(id uuid.UUID) (*domain.Permission, error) Delete(id uuid.UUID) error Update(permission *domain.Permission) error @@ -49,10 +49,10 @@ func (r PermissionRepository) Create(p *domain.Permission) error { return r.db.Create(p).Error } -func (r PermissionRepository) List() ([]*domain.Permission, error) { +func (r PermissionRepository) List(roleId string) ([]*domain.Permission, error) { var permissions []*domain.Permission - err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL").Find(&permissions).Error + err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL AND role_id = ?", roleId).Find(&permissions).Error if err != nil { return nil, err } @@ -75,40 +75,6 @@ func (r PermissionRepository) Delete(id uuid.UUID) error { } func (r PermissionRepository) Update(p *domain.Permission) error { - return r.db.Save(p).Error - - //var parent *Permission - //var children []*Permission - // - //if p.Parent != nil { - // parent = &Permission{} - // result := r.db.First(&parent, "id = ?", p.Parent.ID) - // if result.Error != nil { - // return result.Error - // } - //} - //if p.Children != nil { - // for _, child := range p.Children { - // newChild := &Permission{} - // result := r.db.First(&newChild, "id = ?", child.ID) - // if result.Error != nil { - // return result.Error - // } - // children = append(children, newChild) - // } - //} - // - //permission := &Permission{} - // - //result := r.db.First(&permission, "id = ?", p.ID) - //if result.Error != nil { - // return result.Error - //} - // - //permission.Name = p.Name - //permission.Parent = parent - //permission.Children = children - //permission.IsAllowed = p.IsAllowed - // - //return r.db.Save(permission).Error + // update on is_allowed + return r.db.Model(&domain.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error } diff --git a/internal/repository/role.go b/internal/repository/role.go index dbae6ed9..176dad48 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -78,12 +78,11 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Joins("JOIN roles as r on r.id = tks_roles.role_id"). - Where("r.organization_id = ?", organizationId). + res := db. Offset(pg.GetOffset()). Limit(pg.GetLimit()). Order(orderQuery). - Find(&roles) + Find(&roles, "organization_id = ?", organizationId) //res := db.Preload("Role").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) if res.Error != nil { return nil, res.Error @@ -103,7 +102,7 @@ func (r RoleRepository) Get(id string) (*domain.Role, error) { func (r RoleRepository) GetTksRole(id string) (*domain.Role, error) { var role domain.Role - if err := r.db.Preload("Role").First(&role, "role_id = ?", id).Error; err != nil { + if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } diff --git a/internal/route/route.go b/internal/route/route.go index 432aede0..82e765fd 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -52,6 +52,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Alert: repository.NewAlertRepository(db), Role: repository.NewRoleRepository(db), Project: repository.NewProjectRepository(db), + Permission: repository.NewPermissionRepository(db), + Endpoint: repository.NewEndpointRepository(db), Audit: repository.NewAuditRepository(db), } @@ -69,6 +71,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), Audit: usecase.NewAuditUsecase(repoFactory), + Role: usecase.NewRoleUsecase(repoFactory), + Permission: usecase.NewPermissionUsecase(repoFactory), } customMiddleware := internalMiddleware.NewMiddleware( @@ -232,13 +236,18 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) - roleHandler := delivery.NewRoleHandler(usecase.NewRoleUsecase(repoFactory)) + roleHandler := delivery.NewRoleHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.CreateTksRole, http.HandlerFunc(roleHandler.CreateTksRole))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.ListTksRoles, http.HandlerFunc(roleHandler.ListTksRoles))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.GetTksRole, http.HandlerFunc(roleHandler.GetTksRole))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.DeleteTksRole, http.HandlerFunc(roleHandler.DeleteTksRole))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateTksRole, http.HandlerFunc(roleHandler.UpdateTksRole))).Methods(http.MethodPut) + permissionHandler := delivery.NewPermissionHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(permissionHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) + r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 9246d018..832430a1 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -63,26 +63,6 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *domain.Organizatio return "", err } - // Create admin roles in DB - if _, err := u.roleRepo.Create(&domain.Role{ - OrganizationID: organizationId, - Name: "admin", - Description: "admin", - Type: string(domain.RoleTypeTks), - }); err != nil { - return "", err - } - - // Create user roles in DB - if _, err := u.roleRepo.Create(&domain.Role{ - OrganizationID: organizationId, - Name: "user", - Description: "user", - Type: string(domain.RoleTypeTks), - }); err != nil { - return "", err - } - workflowId, err := u.argo.SumbitWorkflowFromWftpl( "tks-create-contract-repo", argowf.SubmitOptions{ diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index df3c8072..4d38cca3 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -7,10 +7,15 @@ import ( ) type IPermissionUsecase interface { - CreatePermission(permission *domain.Permission) error - ListPermissions() ([]*domain.Permission, error) - GetPermission(id uuid.UUID) (*domain.Permission, error) - DeletePermission(id uuid.UUID) error + CreatePermissionSet(permissionSet *domain.PermissionSet) error + GetPermissionSetByRoleId(roleId string) (*domain.PermissionSet, error) + ListPermissions(roleId string) ([]*domain.Permission, error) + //GetPermission(id uuid.UUID) (*domain.Permission, error) + //DeletePermission(id uuid.UUID) error + //UpdatePermission(permission *domain.Permission) error + SetRoleIdToPermissionSet(roleId string, permissionSet *domain.PermissionSet) + GetAllowedPermissionSet() *domain.PermissionSet + GetUserPermissionSet() *domain.PermissionSet UpdatePermission(permission *domain.Permission) error } @@ -18,18 +23,71 @@ type PermissionUsecase struct { repo repository.IPermissionRepository } -func NewPermissionUsecase(repo repository.IPermissionRepository) *PermissionUsecase { +func NewPermissionUsecase(repo repository.Repository) *PermissionUsecase { return &PermissionUsecase{ - repo: repo, + repo: repo.Permission, } } -func (p PermissionUsecase) CreatePermission(permission *domain.Permission) error { - return p.repo.Create(permission) +func (p PermissionUsecase) CreatePermissionSet(permissionSet *domain.PermissionSet) error { + var err error + if err = p.repo.Create(permissionSet.Dashboard); err != nil { + return err + } + if err = p.repo.Create(permissionSet.Stack); err != nil { + return err + } + if err = p.repo.Create(permissionSet.SecurityPolicy); err != nil { + return err + } + if err = p.repo.Create(permissionSet.ProjectManagement); err != nil { + return err + } + if err = p.repo.Create(permissionSet.Notification); err != nil { + return err + } + if err = p.repo.Create(permissionSet.Configuration); err != nil { + return err + } + + return nil } +func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*domain.PermissionSet, error) { + permissionSet := &domain.PermissionSet{ + Dashboard: nil, + Stack: nil, + SecurityPolicy: nil, + ProjectManagement: nil, + Notification: nil, + Configuration: nil, + } -func (p PermissionUsecase) ListPermissions() ([]*domain.Permission, error) { - return p.repo.List() + permissionList, err := p.repo.List(roleId) + if err != nil { + return nil, err + } + for _, permission := range permissionList { + switch permission.Name { + case string(domain.DashBoardPermission): + permissionSet.Dashboard = permission + case string(domain.StackPermission): + permissionSet.Stack = permission + case string(domain.SecurityPolicyPermission): + permissionSet.SecurityPolicy = permission + case string(domain.ProjectManagementPermission): + permissionSet.ProjectManagement = permission + case string(domain.NotificationPermission): + permissionSet.Notification = permission + case string(domain.ConfigurationPermission): + permissionSet.Configuration = permission + } + } + + return permissionSet, nil +} + +func (p PermissionUsecase) ListPermissions(roleId string) ([]*domain.Permission, error) { + return p.repo.List(roleId) } func (p PermissionUsecase) GetPermission(id uuid.UUID) (*domain.Permission, error) { @@ -43,3 +101,19 @@ func (p PermissionUsecase) DeletePermission(id uuid.UUID) error { func (p PermissionUsecase) UpdatePermission(permission *domain.Permission) error { return p.repo.Update(permission) } + +func (p PermissionUsecase) SetRoleIdToPermissionSet(roleId string, permissionSet *domain.PermissionSet) { + permissionSet.SetRoleId(roleId) +} + +func (p PermissionUsecase) GetAllowedPermissionSet() *domain.PermissionSet { + permissionSet := domain.NewDefaultPermissionSet() + permissionSet.SetAllowedPermissionSet() + return permissionSet +} + +func (p PermissionUsecase) GetUserPermissionSet() *domain.PermissionSet { + permissionSet := domain.NewDefaultPermissionSet() + permissionSet.SetUserPermissionSet() + return permissionSet +} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index 66111e99..4e7da85b 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -13,5 +13,7 @@ type Usecase struct { Alert IAlertUsecase Stack IStackUsecase Project IProjectUsecase + Role IRoleUsecase + Permission IPermissionUsecase Audit IAuditUsecase } diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index 95e0292a..c34a45ae 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -1,6 +1,11 @@ package domain +import ( + "time" +) + type Endpoint struct { - Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` - Group string `gorm:"type:text;" json:"group"` + Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` + Group string `gorm:"type:text;" json:"group"` + CreatedAt time.Time } diff --git a/internal/rbac/permission.go b/pkg/domain/permission.go similarity index 57% rename from internal/rbac/permission.go rename to pkg/domain/permission.go index 4b0ea9ed..ad95656e 100644 --- a/internal/rbac/permission.go +++ b/pkg/domain/permission.go @@ -1,21 +1,57 @@ -package rbac +package domain import ( + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" ) +type PermissionKind string + +const ( + DashBoardPermission PermissionKind = "대시보드" + StackPermission PermissionKind = "스택 관리" + SecurityPolicyPermission PermissionKind = "보안/정책 관리" + ProjectManagementPermission PermissionKind = "프로젝트 관리" + NotificationPermission PermissionKind = "알림" + ConfigurationPermission PermissionKind = "설정" +) + +type Permission struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` + Name string `json:"name"` + + IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` + RoleID *string `json:"role_id,omitempty"` + Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` + Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` + // omit empty + + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` + Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` +} + +func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { + if p.ID == uuid.Nil { + p.ID = uuid.New() + } + return nil +} + type PermissionSet struct { - Dashboard *domain.Permission - Stack *domain.Permission - SecurityPolicy *domain.Permission - ProjectManagement *domain.Permission - Notification *domain.Permission - Configuration *domain.Permission + Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` + Stack *Permission `gorm:"-:all" json:"stack,omitempty"` + SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` + ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` + Notification *Permission `gorm:"-:all" json:"notification,omitempty"` + Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` } -func NewDefaultPermission() *PermissionSet { +func NewDefaultPermissionSet() *PermissionSet { return &PermissionSet{ Dashboard: newDashboard(), Stack: newStack(), @@ -26,10 +62,41 @@ func NewDefaultPermission() *PermissionSet { } } -func endpointObjects(eps ...api.Endpoint) []*domain.Endpoint { - var result []*domain.Endpoint +type GetPermissionTemplatesResponse struct { + Permissions []*Permission `json:"permissions"` +} + +type GetPermissionsByRoleIdResponse struct { + Permissions []*Permission `json:"permissions"` +} + +type UpdatePermissionsByRoleIdRequest struct { + Permissions []*Permission `json:"permissions"` +} + +func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { + if root.Children == nil { + return append(edgePermissions, root) + } + + for _, child := range root.Children { + if f != nil && !(*f)(*child) { + continue + } + edgePermissions = GetEdgePermission(child, edgePermissions, f) + } + + return edgePermissions +} + +func SetRoleIDToPermission(roleID string, permission *Permission) { + permission.RoleID = helper.StringP(roleID) +} + +func endpointObjects(eps ...api.Endpoint) []*Endpoint { + var result []*Endpoint for _, ep := range eps { - result = append(result, &domain.Endpoint{ + result = append(result, &Endpoint{ Name: api.ApiMap[ep].Name, Group: api.ApiMap[ep].Group, }) @@ -37,13 +104,13 @@ func endpointObjects(eps ...api.Endpoint) []*domain.Endpoint { return result } -func newDashboard() *domain.Permission { - dashboard := &domain.Permission{ - Name: "대시보드", - Children: []*domain.Permission{ +func newDashboard() *Permission { + dashboard := &Permission{ + Name: string(DashBoardPermission), + Children: []*Permission{ { Name: "대시보드", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -58,7 +125,7 @@ func newDashboard() *domain.Permission { }, { Name: "대시보드 설정", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -83,10 +150,10 @@ func newDashboard() *domain.Permission { return dashboard } -func newStack() *domain.Permission { - stack := &domain.Permission{ - Name: "스택 관리", - Children: []*domain.Permission{ +func newStack() *Permission { + stack := &Permission{ + Name: string(StackPermission), + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -129,13 +196,13 @@ func newStack() *domain.Permission { return stack } -func newSecurityPolicy() *domain.Permission { - security_policy := &domain.Permission{ - Name: "보안/정책 관리", - Children: []*domain.Permission{ +func newSecurityPolicy() *Permission { + security_policy := &Permission{ + Name: string(SecurityPolicyPermission), + Children: []*Permission{ { Name: "보안/정책", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -160,13 +227,13 @@ func newSecurityPolicy() *domain.Permission { return security_policy } -func newProjectManagement() *domain.Permission { - projectManagement := &domain.Permission{ - Name: "프로젝트 관리", - Children: []*domain.Permission{ +func newProjectManagement() *Permission { + projectManagement := &Permission{ + Name: string(ProjectManagementPermission), + Children: []*Permission{ { Name: "프로젝트", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -186,7 +253,7 @@ func newProjectManagement() *domain.Permission { }, { Name: "앱 서빙", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -236,7 +303,7 @@ func newProjectManagement() *domain.Permission { }, { Name: "설정-일반", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -266,7 +333,7 @@ func newProjectManagement() *domain.Permission { }, { Name: "설정-멤버", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -302,7 +369,7 @@ func newProjectManagement() *domain.Permission { }, { Name: "설정-네임스페이스", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -338,13 +405,13 @@ func newProjectManagement() *domain.Permission { return projectManagement } -func newNotification() *domain.Permission { - notification := &domain.Permission{ - Name: "알림", - Children: []*domain.Permission{ +func newNotification() *Permission { + notification := &Permission{ + Name: string(NotificationPermission), + Children: []*Permission{ { Name: "시스템 경고", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -353,7 +420,7 @@ func newNotification() *domain.Permission { }, { Name: "보안/정책 감사로그", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -366,13 +433,13 @@ func newNotification() *domain.Permission { return notification } -func newConfiguration() *domain.Permission { - configuration := &domain.Permission{ - Name: "설정", - Children: []*domain.Permission{ +func newConfiguration() *Permission { + configuration := &Permission{ + Name: string(ConfigurationPermission), + Children: []*Permission{ { Name: "일반", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -385,7 +452,7 @@ func newConfiguration() *domain.Permission { }, { Name: "클라우드 계정", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -406,7 +473,7 @@ func newConfiguration() *domain.Permission { }, { Name: "스택 템플릿", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -415,7 +482,7 @@ func newConfiguration() *domain.Permission { }, { Name: "프로젝트 관리", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -436,7 +503,7 @@ func newConfiguration() *domain.Permission { }, { Name: "사용자", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -457,7 +524,7 @@ func newConfiguration() *domain.Permission { }, { Name: "사용자 권한 관리", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -478,7 +545,7 @@ func newConfiguration() *domain.Permission { }, { Name: "알림 설정", - Children: []*domain.Permission{ + Children: []*Permission{ { Name: "조회", IsAllowed: helper.BoolP(false), @@ -502,3 +569,59 @@ func newConfiguration() *domain.Permission { return configuration } + +func (p *PermissionSet) SetAllowedPermissionSet() { + edgePermissions := make([]*Permission, 0) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) + + for _, permission := range edgePermissions { + permission.IsAllowed = helper.BoolP(true) + } + + return +} + +func (p *PermissionSet) SetUserPermissionSet() { + f := func(permission Permission) bool { + return permission.Name == "조회" + } + edgePermissions := make([]*Permission, 0) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) + //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) + + for _, permission := range edgePermissions { + permission.IsAllowed = helper.BoolP(true) + } + + return +} + +func (p *PermissionSet) SetRoleId(roleId string) { + setRoleIdToPermission(p.Dashboard, roleId) + setRoleIdToPermission(p.Stack, roleId) + setRoleIdToPermission(p.SecurityPolicy, roleId) + setRoleIdToPermission(p.ProjectManagement, roleId) + setRoleIdToPermission(p.Notification, roleId) + setRoleIdToPermission(p.Configuration, roleId) +} + +func setRoleIdToPermission(root *Permission, roleId string) { + root.RoleID = helper.StringP(roleId) + + if root.Children == nil { + return + } + + for _, child := range root.Children { + setRoleIdToPermission(child, roleId) + } +} diff --git a/pkg/domain/permmision.go b/pkg/domain/permmision.go deleted file mode 100644 index 4bea6726..00000000 --- a/pkg/domain/permmision.go +++ /dev/null @@ -1,30 +0,0 @@ -package domain - -import ( - "github.com/google/uuid" - "gorm.io/gorm" -) - -type Permission struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"id"` - Name string `json:"name"` - - IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` - RoleID *string `json:"role_id,omitempty"` - Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` - Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` - // omit empty - - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` - Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` -} - -func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { - if p.ID == uuid.Nil { - p.ID = uuid.New() - } - return nil -} diff --git a/pkg/domain/role.go b/pkg/domain/role.go index 204baa5d..4e19e39d 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -58,6 +58,5 @@ type ListTksRoleResponse struct { } type UpdateTksRoleRequest struct { - Name string `json:"name" validate:"required"` Description string `json:"description" validate:"omitempty,min=0,max=100"` } From 599f58d129f7aa775164e741690ed2477d06b7e0 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 4 Mar 2024 15:57:12 +0900 Subject: [PATCH 077/502] solve merge confict --- internal/repository/organization.go | 7 ------- internal/repository/user.go | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 2c23b54b..a7839166 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -77,13 +77,6 @@ func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (*[]domain.Org pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("organizations", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.Organization{})) - db.Count(&pg.TotalRows) - - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&organizations) _, res := pg.Fetch(r.db, &organizations) if res.Error != nil { return nil, res.Error diff --git a/internal/repository/user.go b/internal/repository/user.go index 9de16cd2..baf14464 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -164,7 +164,7 @@ func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizat pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&User{}).Where("organization_id = ?", organizationId), &users) + _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&domain.User{}).Where("organization_id = ?", organizationId), &users) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error From 2d2880ec43a986af5ac7aac528ca099494df7016 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 4 Mar 2024 16:05:49 +0900 Subject: [PATCH 078/502] bug fix: build error fix --- internal/delivery/http/auth.go | 4 +--- internal/delivery/http/role.go | 6 +----- internal/repository/audit.go | 6 +++--- internal/repository/endpoint.go | 2 +- internal/repository/role.go | 4 ++-- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index a7566312..d101be63 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -4,7 +4,6 @@ import ( "fmt" "net/http" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/request" @@ -73,14 +72,13 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } else { - userId, _ := uuid.Parse(user.ID) _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ OrganizationId: input.OrganizationId, Group: "Auth", Message: fmt.Sprintf("[%s]님이 로그인 하였습니다.", input.AccountId), Description: "", ClientIP: audit.GetClientIpAddress(w, r), - UserId: &userId, + UserId: &user.ID, }) } diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 8f357117..473150af 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -112,11 +112,7 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { // query parameter urlParams := r.URL.Query() - pg, err := pagination.NewPagination(&urlParams) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } + pg := pagination.NewPagination(&urlParams) // list roles roles, err := h.roleUsecase.ListTksRoles(organizationId, pg) diff --git a/internal/repository/audit.go b/internal/repository/audit.go index 5e2d684c..bbee184c 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -37,13 +37,13 @@ type Audit struct { ID uuid.UUID `gorm:"primarykey"` OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` Group string Message string Description string ClientIP string - UserId *uuid.UUID `gorm:"type:uuid"` - User User `gorm:"foreignKey:UserId"` + UserId *uuid.UUID `gorm:"type:uuid"` + User domain.User `gorm:"foreignKey:UserId"` } func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go index c90589ac..707d8d58 100644 --- a/internal/repository/endpoint.go +++ b/internal/repository/endpoint.go @@ -41,7 +41,7 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint var endpoints []*domain.Endpoint if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("endpoints", pg.GetFilters(), pg.CombinedFilter) db := filterFunc(e.db.Model(&domain.Endpoint{})) diff --git a/internal/repository/role.go b/internal/repository/role.go index 176dad48..d7bdb198 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -47,7 +47,7 @@ func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) var roles []*domain.Role if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) db := filterFunc(r.db.Model(&domain.Role{})) @@ -69,7 +69,7 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin var roles []*domain.Role if pg == nil { - pg = pagination.NewDefaultPagination() + pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) db := filterFunc(r.db.Model(&domain.Role{})) From 06a55c2009aeffce44824ee54ff058a32ee5b19d Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 4 Mar 2024 16:19:04 +0900 Subject: [PATCH 079/502] fix. build error --- Dockerfile | 2 +- Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9c401c07..331de531 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ RUN wget https://github.com/swaggo/swag/releases/download/v1.16.3/swag_1.16.3_Li WORKDIR /app/backend COPY ./ . -RUN swag init -g ./cmd/server/main.go -o ./api/swagger +RUN swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger RUN go mod tidy RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/server ./cmd/server/main.go diff --git a/Makefile b/Makefile index 390be8d4..8bae219d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: docs docs: - swag init -g ./cmd/server/main.go -o ./api/swagger + swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger .PHONY: build build: @@ -17,6 +17,6 @@ test: .PHONY: dev_run dev_run: - swag init -g ./cmd/server/main.go -o ./api/swagger + swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger go build ./cmd/server/main.go ./main From 8dcb1252194b3a3487a05cc5ddb569a9331027b7 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 4 Mar 2024 16:30:20 +0900 Subject: [PATCH 080/502] fix. build error --- Dockerfile | 3 +-- go.mod | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 331de531..3de05bf6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,9 +6,8 @@ RUN wget https://github.com/swaggo/swag/releases/download/v1.16.3/swag_1.16.3_Li WORKDIR /app/backend COPY ./ . -RUN swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger - RUN go mod tidy +RUN swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/server ./cmd/server/main.go ENV TZ=Asia/Seoul diff --git a/go.mod b/go.mod index d92bc9f9..0674b4e6 100644 --- a/go.mod +++ b/go.mod @@ -43,6 +43,7 @@ require ( gorm.io/driver/postgres v1.5.6 gorm.io/gorm v1.25.7 goyave.dev/goyave/v4 v4.4.11 + k8s.io/api v0.26.1 k8s.io/apimachinery v0.26.4 k8s.io/client-go v0.26.1 k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 @@ -132,7 +133,6 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.5.0 // indirect - k8s.io/api v0.26.1 // indirect k8s.io/apiextensions-apiserver v0.26.1 // indirect k8s.io/component-base v0.26.1 // indirect k8s.io/klog/v2 v2.80.1 // indirect From d5355f44cc529618a8649bccad36227b97904a8a Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 4 Mar 2024 18:01:11 +0900 Subject: [PATCH 081/502] trivial. fix exception handle --- internal/pagination/pagination.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 956257e5..0b2295f0 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -186,8 +186,6 @@ func NewPagination(urlParams *url.Values) *Pagination { Columns: keys, Value: value, } - } else { - return nil } } case FILTER, FILTER_ARRAY, OR, OR_ARRAY: From c90917ac147044201acaa4cabb028617aa8220d7 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 5 Mar 2024 10:24:29 +0900 Subject: [PATCH 082/502] make auto-gen code to leave generated code seperated with endpoint.go --- hack/endpoint-codegen.go | 37 +- internal/delivery/api/endpoint.go | 1016 ---------------- .../delivery/api/generated_endpoints.go.go | 1042 +++++++++++++++++ 3 files changed, 1058 insertions(+), 1037 deletions(-) create mode 100644 internal/delivery/api/generated_endpoints.go.go diff --git a/hack/endpoint-codegen.go b/hack/endpoint-codegen.go index eba0b574..354082b3 100644 --- a/hack/endpoint-codegen.go +++ b/hack/endpoint-codegen.go @@ -20,16 +20,11 @@ type endpointDecl struct { Group string } -//const indexTemplateStr = ` // This is generated code. DO NOT EDIT. -// -//package api -// -//type Endpoint int -//type EndpointInfo struct { -// Name string -// Group string -//} -//` +const indexTemplateStr = ` // This is generated code. DO NOT EDIT. + +package api + +` //const endpointTemplateStr = `// Comment below is special purpose for code generation. //// Do not edit this comment. @@ -129,16 +124,16 @@ func main() { log.Printf("Endpoint: %s, Group: %s\n", ep.Name, ep.Group) } - //// contents for index - //indexTemplate := template.New("index") - //indexTemplate, err = indexTemplate.Parse(indexTemplateStr) - //if err != nil { - // log.Fatalf("failed to parse template: %v", err) - //} - //var indexCode bytes.Buffer - //if err := indexTemplate.Execute(&indexCode, endpoints); err != nil { - // log.Fatalf("failed to execute template: %v", err) - //} + // contents for index + indexTemplate := template.New("index") + indexTemplate, err = indexTemplate.Parse(indexTemplateStr) + if err != nil { + log.Fatalf("failed to parse template: %v", err) + } + var indexCode bytes.Buffer + if err := indexTemplate.Execute(&indexCode, endpoints); err != nil { + log.Fatalf("failed to execute template: %v", err) + } //// contents for endpoint //endpointTemplate := template.New("endpoint") @@ -186,7 +181,7 @@ func main() { // replace original file(endpointFilePath) with new contents //contents := indexCode.String() + endpointCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() - contents := apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() + contents := indexCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() newFilePath := strings.Replace(endpointFilePath, "endpoint", "generated_endpoints.go", 1) if err := ioutil.WriteFile(newFilePath, []byte(contents), 0644); err != nil { diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 4d457214..10597114 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -170,1019 +170,3 @@ const ( GetPermissionsByRoleId UpdatePermissionsByRoleId ) - -var ApiMap = map[Endpoint]EndpointInfo{ - Login: { - Name: "Login", - Group: "Auth", - }, - PingToken: { - Name: "PingToken", - Group: "Auth", - }, - Logout: { - Name: "Logout", - Group: "Auth", - }, - RefreshToken: { - Name: "RefreshToken", - Group: "Auth", - }, - FindId: { - Name: "FindId", - Group: "Auth", - }, - FindPassword: { - Name: "FindPassword", - Group: "Auth", - }, - VerifyIdentityForLostId: { - Name: "VerifyIdentityForLostId", - Group: "Auth", - }, - VerifyIdentityForLostPassword: { - Name: "VerifyIdentityForLostPassword", - Group: "Auth", - }, - VerifyToken: { - Name: "VerifyToken", - Group: "Auth", - }, - DeleteToken: { - Name: "DeleteToken", - Group: "Auth", - }, - CreateUser: { - Name: "CreateUser", - Group: "User", - }, - ListUser: { - Name: "ListUser", - Group: "User", - }, - GetUser: { - Name: "GetUser", - Group: "User", - }, - DeleteUser: { - Name: "DeleteUser", - Group: "User", - }, - UpdateUser: { - Name: "UpdateUser", - Group: "User", - }, - ResetPassword: { - Name: "ResetPassword", - Group: "User", - }, - CheckId: { - Name: "CheckId", - Group: "User", - }, - CheckEmail: { - Name: "CheckEmail", - Group: "User", - }, - GetMyProfile: { - Name: "GetMyProfile", - Group: "MyProfile", - }, - UpdateMyProfile: { - Name: "UpdateMyProfile", - Group: "MyProfile", - }, - UpdateMyPassword: { - Name: "UpdateMyPassword", - Group: "MyProfile", - }, - RenewPasswordExpiredDate: { - Name: "RenewPasswordExpiredDate", - Group: "MyProfile", - }, - DeleteMyProfile: { - Name: "DeleteMyProfile", - Group: "MyProfile", - }, - CreateOrganization: { - Name: "CreateOrganization", - Group: "Organization", - }, - GetOrganizations: { - Name: "GetOrganizations", - Group: "Organization", - }, - GetOrganization: { - Name: "GetOrganization", - Group: "Organization", - }, - DeleteOrganization: { - Name: "DeleteOrganization", - Group: "Organization", - }, - UpdateOrganization: { - Name: "UpdateOrganization", - Group: "Organization", - }, - UpdatePrimaryCluster: { - Name: "UpdatePrimaryCluster", - Group: "Organization", - }, - CreateCluster: { - Name: "CreateCluster", - Group: "Cluster", - }, - GetClusters: { - Name: "GetClusters", - Group: "Cluster", - }, - ImportCluster: { - Name: "ImportCluster", - Group: "Cluster", - }, - GetCluster: { - Name: "GetCluster", - Group: "Cluster", - }, - DeleteCluster: { - Name: "DeleteCluster", - Group: "Cluster", - }, - GetClusterSiteValues: { - Name: "GetClusterSiteValues", - Group: "Cluster", - }, - InstallCluster: { - Name: "InstallCluster", - Group: "Cluster", - }, - CreateBootstrapKubeconfig: { - Name: "CreateBootstrapKubeconfig", - Group: "Cluster", - }, - GetBootstrapKubeconfig: { - Name: "GetBootstrapKubeconfig", - Group: "Cluster", - }, - GetNodes: { - Name: "GetNodes", - Group: "Cluster", - }, - CreateAppgroup: { - Name: "CreateAppgroup", - Group: "Appgroup", - }, - GetAppgroups: { - Name: "GetAppgroups", - Group: "Appgroup", - }, - GetAppgroup: { - Name: "GetAppgroup", - Group: "Appgroup", - }, - DeleteAppgroup: { - Name: "DeleteAppgroup", - Group: "Appgroup", - }, - GetApplications: { - Name: "GetApplications", - Group: "Appgroup", - }, - CreateApplication: { - Name: "CreateApplication", - Group: "Appgroup", - }, - CreateAppServeApp: { - Name: "CreateAppServeApp", - Group: "AppServeApp", - }, - GetAppServeApps: { - Name: "GetAppServeApps", - Group: "AppServeApp", - }, - GetNumOfAppsOnStack: { - Name: "GetNumOfAppsOnStack", - Group: "AppServeApp", - }, - GetAppServeApp: { - Name: "GetAppServeApp", - Group: "AppServeApp", - }, - GetAppServeAppTasksByAppId: { - Name: "GetAppServeAppTasksByAppId", - Group: "AppServeApp", - }, - GetAppServeAppTaskDetail: { - Name: "GetAppServeAppTaskDetail", - Group: "AppServeApp", - }, - GetAppServeAppLatestTask: { - Name: "GetAppServeAppLatestTask", - Group: "AppServeApp", - }, - IsAppServeAppExist: { - Name: "IsAppServeAppExist", - Group: "AppServeApp", - }, - IsAppServeAppNameExist: { - Name: "IsAppServeAppNameExist", - Group: "AppServeApp", - }, - DeleteAppServeApp: { - Name: "DeleteAppServeApp", - Group: "AppServeApp", - }, - UpdateAppServeApp: { - Name: "UpdateAppServeApp", - Group: "AppServeApp", - }, - UpdateAppServeAppStatus: { - Name: "UpdateAppServeAppStatus", - Group: "AppServeApp", - }, - UpdateAppServeAppEndpoint: { - Name: "UpdateAppServeAppEndpoint", - Group: "AppServeApp", - }, - RollbackAppServeApp: { - Name: "RollbackAppServeApp", - Group: "AppServeApp", - }, - GetCloudAccounts: { - Name: "GetCloudAccounts", - Group: "CloudAccount", - }, - CreateCloudAccount: { - Name: "CreateCloudAccount", - Group: "CloudAccount", - }, - CheckCloudAccountName: { - Name: "CheckCloudAccountName", - Group: "CloudAccount", - }, - CheckAwsAccountId: { - Name: "CheckAwsAccountId", - Group: "CloudAccount", - }, - GetCloudAccount: { - Name: "GetCloudAccount", - Group: "CloudAccount", - }, - UpdateCloudAccount: { - Name: "UpdateCloudAccount", - Group: "CloudAccount", - }, - DeleteCloudAccount: { - Name: "DeleteCloudAccount", - Group: "CloudAccount", - }, - DeleteForceCloudAccount: { - Name: "DeleteForceCloudAccount", - Group: "CloudAccount", - }, - GetResourceQuota: { - Name: "GetResourceQuota", - Group: "CloudAccount", - }, - GetStackTemplates: { - Name: "GetStackTemplates", - Group: "StackTemplate", - }, - CreateStackTemplate: { - Name: "CreateStackTemplate", - Group: "StackTemplate", - }, - GetStackTemplate: { - Name: "GetStackTemplate", - Group: "StackTemplate", - }, - UpdateStackTemplate: { - Name: "UpdateStackTemplate", - Group: "StackTemplate", - }, - DeleteStackTemplate: { - Name: "DeleteStackTemplate", - Group: "StackTemplate", - }, - GetChartsDashboard: { - Name: "GetChartsDashboard", - Group: "Dashboard", - }, - GetChartDashboard: { - Name: "GetChartDashboard", - Group: "Dashboard", - }, - GetStacksDashboard: { - Name: "GetStacksDashboard", - Group: "Dashboard", - }, - GetResourcesDashboard: { - Name: "GetResourcesDashboard", - Group: "Dashboard", - }, - CreateAlert: { - Name: "CreateAlert", - Group: "Alert", - }, - GetAlerts: { - Name: "GetAlerts", - Group: "Alert", - }, - GetAlert: { - Name: "GetAlert", - Group: "Alert", - }, - DeleteAlert: { - Name: "DeleteAlert", - Group: "Alert", - }, - UpdateAlert: { - Name: "UpdateAlert", - Group: "Alert", - }, - CreateAlertAction: { - Name: "CreateAlertAction", - Group: "Alert", - }, - GetStacks: { - Name: "GetStacks", - Group: "Stack", - }, - CreateStack: { - Name: "CreateStack", - Group: "Stack", - }, - CheckStackName: { - Name: "CheckStackName", - Group: "Stack", - }, - GetStack: { - Name: "GetStack", - Group: "Stack", - }, - UpdateStack: { - Name: "UpdateStack", - Group: "Stack", - }, - DeleteStack: { - Name: "DeleteStack", - Group: "Stack", - }, - GetStackKubeConfig: { - Name: "GetStackKubeConfig", - Group: "Stack", - }, - GetStackStatus: { - Name: "GetStackStatus", - Group: "Stack", - }, - SetFavoriteStack: { - Name: "SetFavoriteStack", - Group: "Stack", - }, - DeleteFavoriteStack: { - Name: "DeleteFavoriteStack", - Group: "Stack", - }, - InstallStack: { - Name: "InstallStack", - Group: "Stack", - }, - CreateProject: { - Name: "CreateProject", - Group: "Project", - }, - GetProjectRoles: { - Name: "GetProjectRoles", - Group: "Project", - }, - GetProjectRole: { - Name: "GetProjectRole", - Group: "Project", - }, - GetProjects: { - Name: "GetProjects", - Group: "Project", - }, - GetProject: { - Name: "GetProject", - Group: "Project", - }, - UpdateProject: { - Name: "UpdateProject", - Group: "Project", - }, - DeleteProject: { - Name: "DeleteProject", - Group: "Project", - }, - AddProjectMember: { - Name: "AddProjectMember", - Group: "Project", - }, - GetProjectMember: { - Name: "GetProjectMember", - Group: "Project", - }, - GetProjectMembers: { - Name: "GetProjectMembers", - Group: "Project", - }, - RemoveProjectMember: { - Name: "RemoveProjectMember", - Group: "Project", - }, - UpdateProjectMemberRole: { - Name: "UpdateProjectMemberRole", - Group: "Project", - }, - CreateProjectNamespace: { - Name: "CreateProjectNamespace", - Group: "Project", - }, - GetProjectNamespaces: { - Name: "GetProjectNamespaces", - Group: "Project", - }, - GetProjectNamespace: { - Name: "GetProjectNamespace", - Group: "Project", - }, - UpdateProjectNamespace: { - Name: "UpdateProjectNamespace", - Group: "Project", - }, - DeleteProjectNamespace: { - Name: "DeleteProjectNamespace", - Group: "Project", - }, - SetFavoriteProject: { - Name: "SetFavoriteProject", - Group: "Project", - }, - SetFavoriteProjectNamespace: { - Name: "SetFavoriteProjectNamespace", - Group: "Project", - }, - UnSetFavoriteProject: { - Name: "UnSetFavoriteProject", - Group: "Project", - }, - UnSetFavoriteProjectNamespace: { - Name: "UnSetFavoriteProjectNamespace", - Group: "Project", - }, - GetProjectKubeconfig: { - Name: "GetProjectKubeconfig", - Group: "Project", - }, - GetProjectNamespaceK8sResources: { - Name: "GetProjectNamespaceK8sResources", - Group: "Project", - }, - GetAudits: { - Name: "GetAudits", - Group: "Audit", - }, - GetAudit: { - Name: "GetAudit", - Group: "Audit", - }, - DeleteAudit: { - Name: "DeleteAudit", - Group: "Audit", - }, - CreateTksRole: { - Name: "CreateTksRole", - Group: "Role", - }, - ListTksRoles: { - Name: "ListTksRoles", - Group: "Role", - }, - GetTksRole: { - Name: "GetTksRole", - Group: "Role", - }, - DeleteTksRole: { - Name: "DeleteTksRole", - Group: "Role", - }, - UpdateTksRole: { - Name: "UpdateTksRole", - Group: "Role", - }, -} - -func (e Endpoint) String() string { - switch e { - case Login: - return "Login" - case PingToken: - return "PingToken" - case Logout: - return "Logout" - case RefreshToken: - return "RefreshToken" - case FindId: - return "FindId" - case FindPassword: - return "FindPassword" - case VerifyIdentityForLostId: - return "VerifyIdentityForLostId" - case VerifyIdentityForLostPassword: - return "VerifyIdentityForLostPassword" - case VerifyToken: - return "VerifyToken" - case DeleteToken: - return "DeleteToken" - case CreateUser: - return "CreateUser" - case ListUser: - return "ListUser" - case GetUser: - return "GetUser" - case DeleteUser: - return "DeleteUser" - case UpdateUser: - return "UpdateUser" - case ResetPassword: - return "ResetPassword" - case CheckId: - return "CheckId" - case CheckEmail: - return "CheckEmail" - case GetMyProfile: - return "GetMyProfile" - case UpdateMyProfile: - return "UpdateMyProfile" - case UpdateMyPassword: - return "UpdateMyPassword" - case RenewPasswordExpiredDate: - return "RenewPasswordExpiredDate" - case DeleteMyProfile: - return "DeleteMyProfile" - case CreateOrganization: - return "CreateOrganization" - case GetOrganizations: - return "GetOrganizations" - case GetOrganization: - return "GetOrganization" - case DeleteOrganization: - return "DeleteOrganization" - case UpdateOrganization: - return "UpdateOrganization" - case UpdatePrimaryCluster: - return "UpdatePrimaryCluster" - case CreateCluster: - return "CreateCluster" - case GetClusters: - return "GetClusters" - case ImportCluster: - return "ImportCluster" - case GetCluster: - return "GetCluster" - case DeleteCluster: - return "DeleteCluster" - case GetClusterSiteValues: - return "GetClusterSiteValues" - case InstallCluster: - return "InstallCluster" - case CreateBootstrapKubeconfig: - return "CreateBootstrapKubeconfig" - case GetBootstrapKubeconfig: - return "GetBootstrapKubeconfig" - case GetNodes: - return "GetNodes" - case CreateAppgroup: - return "CreateAppgroup" - case GetAppgroups: - return "GetAppgroups" - case GetAppgroup: - return "GetAppgroup" - case DeleteAppgroup: - return "DeleteAppgroup" - case GetApplications: - return "GetApplications" - case CreateApplication: - return "CreateApplication" - case CreateAppServeApp: - return "CreateAppServeApp" - case GetAppServeApps: - return "GetAppServeApps" - case GetNumOfAppsOnStack: - return "GetNumOfAppsOnStack" - case GetAppServeApp: - return "GetAppServeApp" - case GetAppServeAppTasksByAppId: - return "GetAppServeAppTasksByAppId" - case GetAppServeAppTaskDetail: - return "GetAppServeAppTaskDetail" - case GetAppServeAppLatestTask: - return "GetAppServeAppLatestTask" - case IsAppServeAppExist: - return "IsAppServeAppExist" - case IsAppServeAppNameExist: - return "IsAppServeAppNameExist" - case DeleteAppServeApp: - return "DeleteAppServeApp" - case UpdateAppServeApp: - return "UpdateAppServeApp" - case UpdateAppServeAppStatus: - return "UpdateAppServeAppStatus" - case UpdateAppServeAppEndpoint: - return "UpdateAppServeAppEndpoint" - case RollbackAppServeApp: - return "RollbackAppServeApp" - case GetCloudAccounts: - return "GetCloudAccounts" - case CreateCloudAccount: - return "CreateCloudAccount" - case CheckCloudAccountName: - return "CheckCloudAccountName" - case CheckAwsAccountId: - return "CheckAwsAccountId" - case GetCloudAccount: - return "GetCloudAccount" - case UpdateCloudAccount: - return "UpdateCloudAccount" - case DeleteCloudAccount: - return "DeleteCloudAccount" - case DeleteForceCloudAccount: - return "DeleteForceCloudAccount" - case GetResourceQuota: - return "GetResourceQuota" - case GetStackTemplates: - return "GetStackTemplates" - case CreateStackTemplate: - return "CreateStackTemplate" - case GetStackTemplate: - return "GetStackTemplate" - case UpdateStackTemplate: - return "UpdateStackTemplate" - case DeleteStackTemplate: - return "DeleteStackTemplate" - case GetChartsDashboard: - return "GetChartsDashboard" - case GetChartDashboard: - return "GetChartDashboard" - case GetStacksDashboard: - return "GetStacksDashboard" - case GetResourcesDashboard: - return "GetResourcesDashboard" - case CreateAlert: - return "CreateAlert" - case GetAlerts: - return "GetAlerts" - case GetAlert: - return "GetAlert" - case DeleteAlert: - return "DeleteAlert" - case UpdateAlert: - return "UpdateAlert" - case CreateAlertAction: - return "CreateAlertAction" - case GetStacks: - return "GetStacks" - case CreateStack: - return "CreateStack" - case CheckStackName: - return "CheckStackName" - case GetStack: - return "GetStack" - case UpdateStack: - return "UpdateStack" - case DeleteStack: - return "DeleteStack" - case GetStackKubeConfig: - return "GetStackKubeConfig" - case GetStackStatus: - return "GetStackStatus" - case SetFavoriteStack: - return "SetFavoriteStack" - case DeleteFavoriteStack: - return "DeleteFavoriteStack" - case InstallStack: - return "InstallStack" - case CreateProject: - return "CreateProject" - case GetProjectRoles: - return "GetProjectRoles" - case GetProjectRole: - return "GetProjectRole" - case GetProjects: - return "GetProjects" - case GetProject: - return "GetProject" - case UpdateProject: - return "UpdateProject" - case DeleteProject: - return "DeleteProject" - case AddProjectMember: - return "AddProjectMember" - case GetProjectMember: - return "GetProjectMember" - case GetProjectMembers: - return "GetProjectMembers" - case RemoveProjectMember: - return "RemoveProjectMember" - case UpdateProjectMemberRole: - return "UpdateProjectMemberRole" - case CreateProjectNamespace: - return "CreateProjectNamespace" - case GetProjectNamespaces: - return "GetProjectNamespaces" - case GetProjectNamespace: - return "GetProjectNamespace" - case UpdateProjectNamespace: - return "UpdateProjectNamespace" - case DeleteProjectNamespace: - return "DeleteProjectNamespace" - case SetFavoriteProject: - return "SetFavoriteProject" - case SetFavoriteProjectNamespace: - return "SetFavoriteProjectNamespace" - case UnSetFavoriteProject: - return "UnSetFavoriteProject" - case UnSetFavoriteProjectNamespace: - return "UnSetFavoriteProjectNamespace" - case GetProjectKubeconfig: - return "GetProjectKubeconfig" - case GetProjectNamespaceK8sResources: - return "GetProjectNamespaceK8sResources" - case GetAudits: - return "GetAudits" - case GetAudit: - return "GetAudit" - case DeleteAudit: - return "DeleteAudit" - case CreateTksRole: - return "CreateTksRole" - case ListTksRoles: - return "ListTksRoles" - case GetTksRole: - return "GetTksRole" - case DeleteTksRole: - return "DeleteTksRole" - case UpdateTksRole: - return "UpdateTksRole" - default: - return "" - } -} -func GetEndpoint(name string) Endpoint { - switch name { - case "Login": - return Login - case "PingToken": - return PingToken - case "Logout": - return Logout - case "RefreshToken": - return RefreshToken - case "FindId": - return FindId - case "FindPassword": - return FindPassword - case "VerifyIdentityForLostId": - return VerifyIdentityForLostId - case "VerifyIdentityForLostPassword": - return VerifyIdentityForLostPassword - case "VerifyToken": - return VerifyToken - case "DeleteToken": - return DeleteToken - case "CreateUser": - return CreateUser - case "ListUser": - return ListUser - case "GetUser": - return GetUser - case "DeleteUser": - return DeleteUser - case "UpdateUser": - return UpdateUser - case "ResetPassword": - return ResetPassword - case "CheckId": - return CheckId - case "CheckEmail": - return CheckEmail - case "GetMyProfile": - return GetMyProfile - case "UpdateMyProfile": - return UpdateMyProfile - case "UpdateMyPassword": - return UpdateMyPassword - case "RenewPasswordExpiredDate": - return RenewPasswordExpiredDate - case "DeleteMyProfile": - return DeleteMyProfile - case "CreateOrganization": - return CreateOrganization - case "GetOrganizations": - return GetOrganizations - case "GetOrganization": - return GetOrganization - case "DeleteOrganization": - return DeleteOrganization - case "UpdateOrganization": - return UpdateOrganization - case "UpdatePrimaryCluster": - return UpdatePrimaryCluster - case "CreateCluster": - return CreateCluster - case "GetClusters": - return GetClusters - case "ImportCluster": - return ImportCluster - case "GetCluster": - return GetCluster - case "DeleteCluster": - return DeleteCluster - case "GetClusterSiteValues": - return GetClusterSiteValues - case "InstallCluster": - return InstallCluster - case "CreateBootstrapKubeconfig": - return CreateBootstrapKubeconfig - case "GetBootstrapKubeconfig": - return GetBootstrapKubeconfig - case "GetNodes": - return GetNodes - case "CreateAppgroup": - return CreateAppgroup - case "GetAppgroups": - return GetAppgroups - case "GetAppgroup": - return GetAppgroup - case "DeleteAppgroup": - return DeleteAppgroup - case "GetApplications": - return GetApplications - case "CreateApplication": - return CreateApplication - case "CreateAppServeApp": - return CreateAppServeApp - case "GetAppServeApps": - return GetAppServeApps - case "GetNumOfAppsOnStack": - return GetNumOfAppsOnStack - case "GetAppServeApp": - return GetAppServeApp - case "GetAppServeAppTasksByAppId": - return GetAppServeAppTasksByAppId - case "GetAppServeAppTaskDetail": - return GetAppServeAppTaskDetail - case "GetAppServeAppLatestTask": - return GetAppServeAppLatestTask - case "IsAppServeAppExist": - return IsAppServeAppExist - case "IsAppServeAppNameExist": - return IsAppServeAppNameExist - case "DeleteAppServeApp": - return DeleteAppServeApp - case "UpdateAppServeApp": - return UpdateAppServeApp - case "UpdateAppServeAppStatus": - return UpdateAppServeAppStatus - case "UpdateAppServeAppEndpoint": - return UpdateAppServeAppEndpoint - case "RollbackAppServeApp": - return RollbackAppServeApp - case "GetCloudAccounts": - return GetCloudAccounts - case "CreateCloudAccount": - return CreateCloudAccount - case "CheckCloudAccountName": - return CheckCloudAccountName - case "CheckAwsAccountId": - return CheckAwsAccountId - case "GetCloudAccount": - return GetCloudAccount - case "UpdateCloudAccount": - return UpdateCloudAccount - case "DeleteCloudAccount": - return DeleteCloudAccount - case "DeleteForceCloudAccount": - return DeleteForceCloudAccount - case "GetResourceQuota": - return GetResourceQuota - case "GetStackTemplates": - return GetStackTemplates - case "CreateStackTemplate": - return CreateStackTemplate - case "GetStackTemplate": - return GetStackTemplate - case "UpdateStackTemplate": - return UpdateStackTemplate - case "DeleteStackTemplate": - return DeleteStackTemplate - case "GetChartsDashboard": - return GetChartsDashboard - case "GetChartDashboard": - return GetChartDashboard - case "GetStacksDashboard": - return GetStacksDashboard - case "GetResourcesDashboard": - return GetResourcesDashboard - case "CreateAlert": - return CreateAlert - case "GetAlerts": - return GetAlerts - case "GetAlert": - return GetAlert - case "DeleteAlert": - return DeleteAlert - case "UpdateAlert": - return UpdateAlert - case "CreateAlertAction": - return CreateAlertAction - case "GetStacks": - return GetStacks - case "CreateStack": - return CreateStack - case "CheckStackName": - return CheckStackName - case "GetStack": - return GetStack - case "UpdateStack": - return UpdateStack - case "DeleteStack": - return DeleteStack - case "GetStackKubeConfig": - return GetStackKubeConfig - case "GetStackStatus": - return GetStackStatus - case "SetFavoriteStack": - return SetFavoriteStack - case "DeleteFavoriteStack": - return DeleteFavoriteStack - case "InstallStack": - return InstallStack - case "CreateProject": - return CreateProject - case "GetProjectRoles": - return GetProjectRoles - case "GetProjectRole": - return GetProjectRole - case "GetProjects": - return GetProjects - case "GetProject": - return GetProject - case "UpdateProject": - return UpdateProject - case "DeleteProject": - return DeleteProject - case "AddProjectMember": - return AddProjectMember - case "GetProjectMember": - return GetProjectMember - case "GetProjectMembers": - return GetProjectMembers - case "RemoveProjectMember": - return RemoveProjectMember - case "UpdateProjectMemberRole": - return UpdateProjectMemberRole - case "CreateProjectNamespace": - return CreateProjectNamespace - case "GetProjectNamespaces": - return GetProjectNamespaces - case "GetProjectNamespace": - return GetProjectNamespace - case "UpdateProjectNamespace": - return UpdateProjectNamespace - case "DeleteProjectNamespace": - return DeleteProjectNamespace - case "SetFavoriteProject": - return SetFavoriteProject - case "SetFavoriteProjectNamespace": - return SetFavoriteProjectNamespace - case "UnSetFavoriteProject": - return UnSetFavoriteProject - case "UnSetFavoriteProjectNamespace": - return UnSetFavoriteProjectNamespace - case "GetProjectKubeconfig": - return GetProjectKubeconfig - case "GetProjectNamespaceK8sResources": - return GetProjectNamespaceK8sResources - case "GetAudits": - return GetAudits - case "GetAudit": - return GetAudit - case "DeleteAudit": - return DeleteAudit - case "CreateTksRole": - return CreateTksRole - case "ListTksRoles": - return ListTksRoles - case "GetTksRole": - return GetTksRole - case "DeleteTksRole": - return DeleteTksRole - case "UpdateTksRole": - return UpdateTksRole - default: - return -1 - } -} diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go new file mode 100644 index 00000000..f781ef50 --- /dev/null +++ b/internal/delivery/api/generated_endpoints.go.go @@ -0,0 +1,1042 @@ + // This is generated code. DO NOT EDIT. + +package api + +var ApiMap = map[Endpoint]EndpointInfo{ + Login: { + Name: "Login", + Group: "Auth", + }, + PingToken: { + Name: "PingToken", + Group: "Auth", + }, + Logout: { + Name: "Logout", + Group: "Auth", + }, + RefreshToken: { + Name: "RefreshToken", + Group: "Auth", + }, + FindId: { + Name: "FindId", + Group: "Auth", + }, + FindPassword: { + Name: "FindPassword", + Group: "Auth", + }, + VerifyIdentityForLostId: { + Name: "VerifyIdentityForLostId", + Group: "Auth", + }, + VerifyIdentityForLostPassword: { + Name: "VerifyIdentityForLostPassword", + Group: "Auth", + }, + VerifyToken: { + Name: "VerifyToken", + Group: "Auth", + }, + DeleteToken: { + Name: "DeleteToken", + Group: "Auth", + }, + CreateUser: { + Name: "CreateUser", + Group: "User", + }, + ListUser: { + Name: "ListUser", + Group: "User", + }, + GetUser: { + Name: "GetUser", + Group: "User", + }, + DeleteUser: { + Name: "DeleteUser", + Group: "User", + }, + UpdateUser: { + Name: "UpdateUser", + Group: "User", + }, + ResetPassword: { + Name: "ResetPassword", + Group: "User", + }, + CheckId: { + Name: "CheckId", + Group: "User", + }, + CheckEmail: { + Name: "CheckEmail", + Group: "User", + }, + GetMyProfile: { + Name: "GetMyProfile", + Group: "MyProfile", + }, + UpdateMyProfile: { + Name: "UpdateMyProfile", + Group: "MyProfile", + }, + UpdateMyPassword: { + Name: "UpdateMyPassword", + Group: "MyProfile", + }, + RenewPasswordExpiredDate: { + Name: "RenewPasswordExpiredDate", + Group: "MyProfile", + }, + DeleteMyProfile: { + Name: "DeleteMyProfile", + Group: "MyProfile", + }, + CreateOrganization: { + Name: "CreateOrganization", + Group: "Organization", + }, + GetOrganizations: { + Name: "GetOrganizations", + Group: "Organization", + }, + GetOrganization: { + Name: "GetOrganization", + Group: "Organization", + }, + DeleteOrganization: { + Name: "DeleteOrganization", + Group: "Organization", + }, + UpdateOrganization: { + Name: "UpdateOrganization", + Group: "Organization", + }, + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", + Group: "Organization", + }, + CreateCluster: { + Name: "CreateCluster", + Group: "Cluster", + }, + GetClusters: { + Name: "GetClusters", + Group: "Cluster", + }, + ImportCluster: { + Name: "ImportCluster", + Group: "Cluster", + }, + GetCluster: { + Name: "GetCluster", + Group: "Cluster", + }, + DeleteCluster: { + Name: "DeleteCluster", + Group: "Cluster", + }, + GetClusterSiteValues: { + Name: "GetClusterSiteValues", + Group: "Cluster", + }, + InstallCluster: { + Name: "InstallCluster", + Group: "Cluster", + }, + CreateBootstrapKubeconfig: { + Name: "CreateBootstrapKubeconfig", + Group: "Cluster", + }, + GetBootstrapKubeconfig: { + Name: "GetBootstrapKubeconfig", + Group: "Cluster", + }, + GetNodes: { + Name: "GetNodes", + Group: "Cluster", + }, + CreateAppgroup: { + Name: "CreateAppgroup", + Group: "Appgroup", + }, + GetAppgroups: { + Name: "GetAppgroups", + Group: "Appgroup", + }, + GetAppgroup: { + Name: "GetAppgroup", + Group: "Appgroup", + }, + DeleteAppgroup: { + Name: "DeleteAppgroup", + Group: "Appgroup", + }, + GetApplications: { + Name: "GetApplications", + Group: "Appgroup", + }, + CreateApplication: { + Name: "CreateApplication", + Group: "Appgroup", + }, + GetAppServeAppTasksByAppId: { + Name: "GetAppServeAppTasksByAppId", + Group: "AppServeApp", + }, + GetAppServeAppTaskDetail: { + Name: "GetAppServeAppTaskDetail", + Group: "AppServeApp", + }, + CreateAppServeApp: { + Name: "CreateAppServeApp", + Group: "AppServeApp", + }, + GetAppServeApps: { + Name: "GetAppServeApps", + Group: "AppServeApp", + }, + GetNumOfAppsOnStack: { + Name: "GetNumOfAppsOnStack", + Group: "AppServeApp", + }, + GetAppServeApp: { + Name: "GetAppServeApp", + Group: "AppServeApp", + }, + GetAppServeAppLatestTask: { + Name: "GetAppServeAppLatestTask", + Group: "AppServeApp", + }, + IsAppServeAppExist: { + Name: "IsAppServeAppExist", + Group: "AppServeApp", + }, + IsAppServeAppNameExist: { + Name: "IsAppServeAppNameExist", + Group: "AppServeApp", + }, + DeleteAppServeApp: { + Name: "DeleteAppServeApp", + Group: "AppServeApp", + }, + UpdateAppServeApp: { + Name: "UpdateAppServeApp", + Group: "AppServeApp", + }, + UpdateAppServeAppStatus: { + Name: "UpdateAppServeAppStatus", + Group: "AppServeApp", + }, + UpdateAppServeAppEndpoint: { + Name: "UpdateAppServeAppEndpoint", + Group: "AppServeApp", + }, + RollbackAppServeApp: { + Name: "RollbackAppServeApp", + Group: "AppServeApp", + }, + GetCloudAccounts: { + Name: "GetCloudAccounts", + Group: "CloudAccount", + }, + CreateCloudAccount: { + Name: "CreateCloudAccount", + Group: "CloudAccount", + }, + CheckCloudAccountName: { + Name: "CheckCloudAccountName", + Group: "CloudAccount", + }, + CheckAwsAccountId: { + Name: "CheckAwsAccountId", + Group: "CloudAccount", + }, + GetCloudAccount: { + Name: "GetCloudAccount", + Group: "CloudAccount", + }, + UpdateCloudAccount: { + Name: "UpdateCloudAccount", + Group: "CloudAccount", + }, + DeleteCloudAccount: { + Name: "DeleteCloudAccount", + Group: "CloudAccount", + }, + DeleteForceCloudAccount: { + Name: "DeleteForceCloudAccount", + Group: "CloudAccount", + }, + GetResourceQuota: { + Name: "GetResourceQuota", + Group: "CloudAccount", + }, + GetStackTemplates: { + Name: "GetStackTemplates", + Group: "StackTemplate", + }, + CreateStackTemplate: { + Name: "CreateStackTemplate", + Group: "StackTemplate", + }, + GetStackTemplate: { + Name: "GetStackTemplate", + Group: "StackTemplate", + }, + UpdateStackTemplate: { + Name: "UpdateStackTemplate", + Group: "StackTemplate", + }, + DeleteStackTemplate: { + Name: "DeleteStackTemplate", + Group: "StackTemplate", + }, + GetChartsDashboard: { + Name: "GetChartsDashboard", + Group: "Dashboard", + }, + GetChartDashboard: { + Name: "GetChartDashboard", + Group: "Dashboard", + }, + GetStacksDashboard: { + Name: "GetStacksDashboard", + Group: "Dashboard", + }, + GetResourcesDashboard: { + Name: "GetResourcesDashboard", + Group: "Dashboard", + }, + CreateAlert: { + Name: "CreateAlert", + Group: "Alert", + }, + GetAlerts: { + Name: "GetAlerts", + Group: "Alert", + }, + GetAlert: { + Name: "GetAlert", + Group: "Alert", + }, + DeleteAlert: { + Name: "DeleteAlert", + Group: "Alert", + }, + UpdateAlert: { + Name: "UpdateAlert", + Group: "Alert", + }, + CreateAlertAction: { + Name: "CreateAlertAction", + Group: "Alert", + }, + GetStacks: { + Name: "GetStacks", + Group: "Stack", + }, + CreateStack: { + Name: "CreateStack", + Group: "Stack", + }, + CheckStackName: { + Name: "CheckStackName", + Group: "Stack", + }, + GetStack: { + Name: "GetStack", + Group: "Stack", + }, + UpdateStack: { + Name: "UpdateStack", + Group: "Stack", + }, + DeleteStack: { + Name: "DeleteStack", + Group: "Stack", + }, + GetStackKubeConfig: { + Name: "GetStackKubeConfig", + Group: "Stack", + }, + GetStackStatus: { + Name: "GetStackStatus", + Group: "Stack", + }, + SetFavoriteStack: { + Name: "SetFavoriteStack", + Group: "Stack", + }, + DeleteFavoriteStack: { + Name: "DeleteFavoriteStack", + Group: "Stack", + }, + InstallStack: { + Name: "InstallStack", + Group: "Stack", + }, + CreateProject: { + Name: "CreateProject", + Group: "Project", + }, + GetProjectRoles: { + Name: "GetProjectRoles", + Group: "Project", + }, + GetProjectRole: { + Name: "GetProjectRole", + Group: "Project", + }, + GetProjects: { + Name: "GetProjects", + Group: "Project", + }, + GetProject: { + Name: "GetProject", + Group: "Project", + }, + UpdateProject: { + Name: "UpdateProject", + Group: "Project", + }, + DeleteProject: { + Name: "DeleteProject", + Group: "Project", + }, + AddProjectMember: { + Name: "AddProjectMember", + Group: "Project", + }, + GetProjectMember: { + Name: "GetProjectMember", + Group: "Project", + }, + GetProjectMembers: { + Name: "GetProjectMembers", + Group: "Project", + }, + RemoveProjectMember: { + Name: "RemoveProjectMember", + Group: "Project", + }, + UpdateProjectMemberRole: { + Name: "UpdateProjectMemberRole", + Group: "Project", + }, + CreateProjectNamespace: { + Name: "CreateProjectNamespace", + Group: "Project", + }, + GetProjectNamespaces: { + Name: "GetProjectNamespaces", + Group: "Project", + }, + GetProjectNamespace: { + Name: "GetProjectNamespace", + Group: "Project", + }, + UpdateProjectNamespace: { + Name: "UpdateProjectNamespace", + Group: "Project", + }, + DeleteProjectNamespace: { + Name: "DeleteProjectNamespace", + Group: "Project", + }, + SetFavoriteProject: { + Name: "SetFavoriteProject", + Group: "Project", + }, + SetFavoriteProjectNamespace: { + Name: "SetFavoriteProjectNamespace", + Group: "Project", + }, + UnSetFavoriteProject: { + Name: "UnSetFavoriteProject", + Group: "Project", + }, + UnSetFavoriteProjectNamespace: { + Name: "UnSetFavoriteProjectNamespace", + Group: "Project", + }, + GetProjectKubeconfig: { + Name: "GetProjectKubeconfig", + Group: "Project", + }, + GetProjectNamespaceK8sResources: { + Name: "GetProjectNamespaceK8sResources", + Group: "Project", + }, + GetAudits: { + Name: "GetAudits", + Group: "Audit", + }, + GetAudit: { + Name: "GetAudit", + Group: "Audit", + }, + DeleteAudit: { + Name: "DeleteAudit", + Group: "Audit", + }, + CreateTksRole: { + Name: "CreateTksRole", + Group: "Role", + }, + ListTksRoles: { + Name: "ListTksRoles", + Group: "Role", + }, + GetTksRole: { + Name: "GetTksRole", + Group: "Role", + }, + DeleteTksRole: { + Name: "DeleteTksRole", + Group: "Role", + }, + UpdateTksRole: { + Name: "UpdateTksRole", + Group: "Role", + }, + GetPermissionTemplates: { + Name: "GetPermissionTemplates", + Group: "Permission", + }, + GetPermissionsByRoleId: { + Name: "GetPermissionsByRoleId", + Group: "Permission", + }, + UpdatePermissionsByRoleId: { + Name: "UpdatePermissionsByRoleId", + Group: "Permission", + }, +} +func (e Endpoint) String() string { + switch e { + case Login: + return "Login" + case PingToken: + return "PingToken" + case Logout: + return "Logout" + case RefreshToken: + return "RefreshToken" + case FindId: + return "FindId" + case FindPassword: + return "FindPassword" + case VerifyIdentityForLostId: + return "VerifyIdentityForLostId" + case VerifyIdentityForLostPassword: + return "VerifyIdentityForLostPassword" + case VerifyToken: + return "VerifyToken" + case DeleteToken: + return "DeleteToken" + case CreateUser: + return "CreateUser" + case ListUser: + return "ListUser" + case GetUser: + return "GetUser" + case DeleteUser: + return "DeleteUser" + case UpdateUser: + return "UpdateUser" + case ResetPassword: + return "ResetPassword" + case CheckId: + return "CheckId" + case CheckEmail: + return "CheckEmail" + case GetMyProfile: + return "GetMyProfile" + case UpdateMyProfile: + return "UpdateMyProfile" + case UpdateMyPassword: + return "UpdateMyPassword" + case RenewPasswordExpiredDate: + return "RenewPasswordExpiredDate" + case DeleteMyProfile: + return "DeleteMyProfile" + case CreateOrganization: + return "CreateOrganization" + case GetOrganizations: + return "GetOrganizations" + case GetOrganization: + return "GetOrganization" + case DeleteOrganization: + return "DeleteOrganization" + case UpdateOrganization: + return "UpdateOrganization" + case UpdatePrimaryCluster: + return "UpdatePrimaryCluster" + case CreateCluster: + return "CreateCluster" + case GetClusters: + return "GetClusters" + case ImportCluster: + return "ImportCluster" + case GetCluster: + return "GetCluster" + case DeleteCluster: + return "DeleteCluster" + case GetClusterSiteValues: + return "GetClusterSiteValues" + case InstallCluster: + return "InstallCluster" + case CreateBootstrapKubeconfig: + return "CreateBootstrapKubeconfig" + case GetBootstrapKubeconfig: + return "GetBootstrapKubeconfig" + case GetNodes: + return "GetNodes" + case CreateAppgroup: + return "CreateAppgroup" + case GetAppgroups: + return "GetAppgroups" + case GetAppgroup: + return "GetAppgroup" + case DeleteAppgroup: + return "DeleteAppgroup" + case GetApplications: + return "GetApplications" + case CreateApplication: + return "CreateApplication" + case GetAppServeAppTasksByAppId: + return "GetAppServeAppTasksByAppId" + case GetAppServeAppTaskDetail: + return "GetAppServeAppTaskDetail" + case CreateAppServeApp: + return "CreateAppServeApp" + case GetAppServeApps: + return "GetAppServeApps" + case GetNumOfAppsOnStack: + return "GetNumOfAppsOnStack" + case GetAppServeApp: + return "GetAppServeApp" + case GetAppServeAppLatestTask: + return "GetAppServeAppLatestTask" + case IsAppServeAppExist: + return "IsAppServeAppExist" + case IsAppServeAppNameExist: + return "IsAppServeAppNameExist" + case DeleteAppServeApp: + return "DeleteAppServeApp" + case UpdateAppServeApp: + return "UpdateAppServeApp" + case UpdateAppServeAppStatus: + return "UpdateAppServeAppStatus" + case UpdateAppServeAppEndpoint: + return "UpdateAppServeAppEndpoint" + case RollbackAppServeApp: + return "RollbackAppServeApp" + case GetCloudAccounts: + return "GetCloudAccounts" + case CreateCloudAccount: + return "CreateCloudAccount" + case CheckCloudAccountName: + return "CheckCloudAccountName" + case CheckAwsAccountId: + return "CheckAwsAccountId" + case GetCloudAccount: + return "GetCloudAccount" + case UpdateCloudAccount: + return "UpdateCloudAccount" + case DeleteCloudAccount: + return "DeleteCloudAccount" + case DeleteForceCloudAccount: + return "DeleteForceCloudAccount" + case GetResourceQuota: + return "GetResourceQuota" + case GetStackTemplates: + return "GetStackTemplates" + case CreateStackTemplate: + return "CreateStackTemplate" + case GetStackTemplate: + return "GetStackTemplate" + case UpdateStackTemplate: + return "UpdateStackTemplate" + case DeleteStackTemplate: + return "DeleteStackTemplate" + case GetChartsDashboard: + return "GetChartsDashboard" + case GetChartDashboard: + return "GetChartDashboard" + case GetStacksDashboard: + return "GetStacksDashboard" + case GetResourcesDashboard: + return "GetResourcesDashboard" + case CreateAlert: + return "CreateAlert" + case GetAlerts: + return "GetAlerts" + case GetAlert: + return "GetAlert" + case DeleteAlert: + return "DeleteAlert" + case UpdateAlert: + return "UpdateAlert" + case CreateAlertAction: + return "CreateAlertAction" + case GetStacks: + return "GetStacks" + case CreateStack: + return "CreateStack" + case CheckStackName: + return "CheckStackName" + case GetStack: + return "GetStack" + case UpdateStack: + return "UpdateStack" + case DeleteStack: + return "DeleteStack" + case GetStackKubeConfig: + return "GetStackKubeConfig" + case GetStackStatus: + return "GetStackStatus" + case SetFavoriteStack: + return "SetFavoriteStack" + case DeleteFavoriteStack: + return "DeleteFavoriteStack" + case InstallStack: + return "InstallStack" + case CreateProject: + return "CreateProject" + case GetProjectRoles: + return "GetProjectRoles" + case GetProjectRole: + return "GetProjectRole" + case GetProjects: + return "GetProjects" + case GetProject: + return "GetProject" + case UpdateProject: + return "UpdateProject" + case DeleteProject: + return "DeleteProject" + case AddProjectMember: + return "AddProjectMember" + case GetProjectMember: + return "GetProjectMember" + case GetProjectMembers: + return "GetProjectMembers" + case RemoveProjectMember: + return "RemoveProjectMember" + case UpdateProjectMemberRole: + return "UpdateProjectMemberRole" + case CreateProjectNamespace: + return "CreateProjectNamespace" + case GetProjectNamespaces: + return "GetProjectNamespaces" + case GetProjectNamespace: + return "GetProjectNamespace" + case UpdateProjectNamespace: + return "UpdateProjectNamespace" + case DeleteProjectNamespace: + return "DeleteProjectNamespace" + case SetFavoriteProject: + return "SetFavoriteProject" + case SetFavoriteProjectNamespace: + return "SetFavoriteProjectNamespace" + case UnSetFavoriteProject: + return "UnSetFavoriteProject" + case UnSetFavoriteProjectNamespace: + return "UnSetFavoriteProjectNamespace" + case GetProjectKubeconfig: + return "GetProjectKubeconfig" + case GetProjectNamespaceK8sResources: + return "GetProjectNamespaceK8sResources" + case GetAudits: + return "GetAudits" + case GetAudit: + return "GetAudit" + case DeleteAudit: + return "DeleteAudit" + case CreateTksRole: + return "CreateTksRole" + case ListTksRoles: + return "ListTksRoles" + case GetTksRole: + return "GetTksRole" + case DeleteTksRole: + return "DeleteTksRole" + case UpdateTksRole: + return "UpdateTksRole" + case GetPermissionTemplates: + return "GetPermissionTemplates" + case GetPermissionsByRoleId: + return "GetPermissionsByRoleId" + case UpdatePermissionsByRoleId: + return "UpdatePermissionsByRoleId" + default: + return "" + } +} +func GetEndpoint(name string) Endpoint { + switch name { + case "Login": + return Login + case "PingToken": + return PingToken + case "Logout": + return Logout + case "RefreshToken": + return RefreshToken + case "FindId": + return FindId + case "FindPassword": + return FindPassword + case "VerifyIdentityForLostId": + return VerifyIdentityForLostId + case "VerifyIdentityForLostPassword": + return VerifyIdentityForLostPassword + case "VerifyToken": + return VerifyToken + case "DeleteToken": + return DeleteToken + case "CreateUser": + return CreateUser + case "ListUser": + return ListUser + case "GetUser": + return GetUser + case "DeleteUser": + return DeleteUser + case "UpdateUser": + return UpdateUser + case "ResetPassword": + return ResetPassword + case "CheckId": + return CheckId + case "CheckEmail": + return CheckEmail + case "GetMyProfile": + return GetMyProfile + case "UpdateMyProfile": + return UpdateMyProfile + case "UpdateMyPassword": + return UpdateMyPassword + case "RenewPasswordExpiredDate": + return RenewPasswordExpiredDate + case "DeleteMyProfile": + return DeleteMyProfile + case "CreateOrganization": + return CreateOrganization + case "GetOrganizations": + return GetOrganizations + case "GetOrganization": + return GetOrganization + case "DeleteOrganization": + return DeleteOrganization + case "UpdateOrganization": + return UpdateOrganization + case "UpdatePrimaryCluster": + return UpdatePrimaryCluster + case "CreateCluster": + return CreateCluster + case "GetClusters": + return GetClusters + case "ImportCluster": + return ImportCluster + case "GetCluster": + return GetCluster + case "DeleteCluster": + return DeleteCluster + case "GetClusterSiteValues": + return GetClusterSiteValues + case "InstallCluster": + return InstallCluster + case "CreateBootstrapKubeconfig": + return CreateBootstrapKubeconfig + case "GetBootstrapKubeconfig": + return GetBootstrapKubeconfig + case "GetNodes": + return GetNodes + case "CreateAppgroup": + return CreateAppgroup + case "GetAppgroups": + return GetAppgroups + case "GetAppgroup": + return GetAppgroup + case "DeleteAppgroup": + return DeleteAppgroup + case "GetApplications": + return GetApplications + case "CreateApplication": + return CreateApplication + case "GetAppServeAppTasksByAppId": + return GetAppServeAppTasksByAppId + case "GetAppServeAppTaskDetail": + return GetAppServeAppTaskDetail + case "CreateAppServeApp": + return CreateAppServeApp + case "GetAppServeApps": + return GetAppServeApps + case "GetNumOfAppsOnStack": + return GetNumOfAppsOnStack + case "GetAppServeApp": + return GetAppServeApp + case "GetAppServeAppLatestTask": + return GetAppServeAppLatestTask + case "IsAppServeAppExist": + return IsAppServeAppExist + case "IsAppServeAppNameExist": + return IsAppServeAppNameExist + case "DeleteAppServeApp": + return DeleteAppServeApp + case "UpdateAppServeApp": + return UpdateAppServeApp + case "UpdateAppServeAppStatus": + return UpdateAppServeAppStatus + case "UpdateAppServeAppEndpoint": + return UpdateAppServeAppEndpoint + case "RollbackAppServeApp": + return RollbackAppServeApp + case "GetCloudAccounts": + return GetCloudAccounts + case "CreateCloudAccount": + return CreateCloudAccount + case "CheckCloudAccountName": + return CheckCloudAccountName + case "CheckAwsAccountId": + return CheckAwsAccountId + case "GetCloudAccount": + return GetCloudAccount + case "UpdateCloudAccount": + return UpdateCloudAccount + case "DeleteCloudAccount": + return DeleteCloudAccount + case "DeleteForceCloudAccount": + return DeleteForceCloudAccount + case "GetResourceQuota": + return GetResourceQuota + case "GetStackTemplates": + return GetStackTemplates + case "CreateStackTemplate": + return CreateStackTemplate + case "GetStackTemplate": + return GetStackTemplate + case "UpdateStackTemplate": + return UpdateStackTemplate + case "DeleteStackTemplate": + return DeleteStackTemplate + case "GetChartsDashboard": + return GetChartsDashboard + case "GetChartDashboard": + return GetChartDashboard + case "GetStacksDashboard": + return GetStacksDashboard + case "GetResourcesDashboard": + return GetResourcesDashboard + case "CreateAlert": + return CreateAlert + case "GetAlerts": + return GetAlerts + case "GetAlert": + return GetAlert + case "DeleteAlert": + return DeleteAlert + case "UpdateAlert": + return UpdateAlert + case "CreateAlertAction": + return CreateAlertAction + case "GetStacks": + return GetStacks + case "CreateStack": + return CreateStack + case "CheckStackName": + return CheckStackName + case "GetStack": + return GetStack + case "UpdateStack": + return UpdateStack + case "DeleteStack": + return DeleteStack + case "GetStackKubeConfig": + return GetStackKubeConfig + case "GetStackStatus": + return GetStackStatus + case "SetFavoriteStack": + return SetFavoriteStack + case "DeleteFavoriteStack": + return DeleteFavoriteStack + case "InstallStack": + return InstallStack + case "CreateProject": + return CreateProject + case "GetProjectRoles": + return GetProjectRoles + case "GetProjectRole": + return GetProjectRole + case "GetProjects": + return GetProjects + case "GetProject": + return GetProject + case "UpdateProject": + return UpdateProject + case "DeleteProject": + return DeleteProject + case "AddProjectMember": + return AddProjectMember + case "GetProjectMember": + return GetProjectMember + case "GetProjectMembers": + return GetProjectMembers + case "RemoveProjectMember": + return RemoveProjectMember + case "UpdateProjectMemberRole": + return UpdateProjectMemberRole + case "CreateProjectNamespace": + return CreateProjectNamespace + case "GetProjectNamespaces": + return GetProjectNamespaces + case "GetProjectNamespace": + return GetProjectNamespace + case "UpdateProjectNamespace": + return UpdateProjectNamespace + case "DeleteProjectNamespace": + return DeleteProjectNamespace + case "SetFavoriteProject": + return SetFavoriteProject + case "SetFavoriteProjectNamespace": + return SetFavoriteProjectNamespace + case "UnSetFavoriteProject": + return UnSetFavoriteProject + case "UnSetFavoriteProjectNamespace": + return UnSetFavoriteProjectNamespace + case "GetProjectKubeconfig": + return GetProjectKubeconfig + case "GetProjectNamespaceK8sResources": + return GetProjectNamespaceK8sResources + case "GetAudits": + return GetAudits + case "GetAudit": + return GetAudit + case "DeleteAudit": + return DeleteAudit + case "CreateTksRole": + return CreateTksRole + case "ListTksRoles": + return ListTksRoles + case "GetTksRole": + return GetTksRole + case "DeleteTksRole": + return DeleteTksRole + case "UpdateTksRole": + return UpdateTksRole + case "GetPermissionTemplates": + return GetPermissionTemplates + case "GetPermissionsByRoleId": + return GetPermissionsByRoleId + case "UpdatePermissionsByRoleId": + return UpdatePermissionsByRoleId + default: + return -1 + } +} From 3b68a1ff476481d4de2e614658420102aff842bf Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 5 Mar 2024 16:36:32 +0900 Subject: [PATCH 083/502] Api for admin to manage User resource --- internal/delivery/api/endpoint.go | 11 + .../delivery/api/generated_endpoints.go.go | 56 +++ internal/delivery/http/role.go | 100 +++++ internal/delivery/http/user.go | 376 +++++++++++++++++- .../auth/authenticator/keycloak/keycloak.go | 6 + .../middleware/auth/authorizer/authorizer.go | 1 + internal/middleware/auth/authorizer/rbac.go | 25 ++ internal/middleware/auth/user/user.go | 6 + internal/route/route.go | 11 + internal/usecase/user.go | 27 ++ pkg/domain/admin/user.go | 69 ++++ 11 files changed, 679 insertions(+), 9 deletions(-) create mode 100644 pkg/domain/admin/user.go diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 10597114..bba7a2cc 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -169,4 +169,15 @@ const ( GetPermissionTemplates GetPermissionsByRoleId UpdatePermissionsByRoleId + + // Admin_User + Admin_CreateUser + Admin_ListUser + Admin_GetUser + Admin_DeleteUser + Admin_UpdateUser + + // Admin Role + Admin_ListTksRoles + Admin_GetTksRole ) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index f781ef50..7bc7a17b 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -515,6 +515,34 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdatePermissionsByRoleId", Group: "Permission", }, + Admin_CreateUser: { + Name: "Admin_CreateUser", + Group: "Admin_User", + }, + Admin_ListUser: { + Name: "Admin_ListUser", + Group: "Admin_User", + }, + Admin_GetUser: { + Name: "Admin_GetUser", + Group: "Admin_User", + }, + Admin_DeleteUser: { + Name: "Admin_DeleteUser", + Group: "Admin_User", + }, + Admin_UpdateUser: { + Name: "Admin_UpdateUser", + Group: "Admin_User", + }, + Admin_ListTksRoles: { + Name: "Admin_ListTksRoles", + Group: "Admin Role", + }, + Admin_GetTksRole: { + Name: "Admin_GetTksRole", + Group: "Admin Role", + }, } func (e Endpoint) String() string { switch e { @@ -774,6 +802,20 @@ func (e Endpoint) String() string { return "GetPermissionsByRoleId" case UpdatePermissionsByRoleId: return "UpdatePermissionsByRoleId" + case Admin_CreateUser: + return "Admin_CreateUser" + case Admin_ListUser: + return "Admin_ListUser" + case Admin_GetUser: + return "Admin_GetUser" + case Admin_DeleteUser: + return "Admin_DeleteUser" + case Admin_UpdateUser: + return "Admin_UpdateUser" + case Admin_ListTksRoles: + return "Admin_ListTksRoles" + case Admin_GetTksRole: + return "Admin_GetTksRole" default: return "" } @@ -1036,6 +1078,20 @@ func GetEndpoint(name string) Endpoint { return GetPermissionsByRoleId case "UpdatePermissionsByRoleId": return UpdatePermissionsByRoleId + case "Admin_CreateUser": + return Admin_CreateUser + case "Admin_ListUser": + return Admin_ListUser + case "Admin_GetUser": + return Admin_GetUser + case "Admin_DeleteUser": + return Admin_DeleteUser + case "Admin_UpdateUser": + return Admin_UpdateUser + case "Admin_ListTksRoles": + return Admin_ListTksRoles + case "Admin_GetTksRole": + return Admin_GetTksRole default: return -1 } diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 473150af..dd5f3565 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -17,6 +17,9 @@ type IRoleHandler interface { GetTksRole(w http.ResponseWriter, r *http.Request) DeleteTksRole(w http.ResponseWriter, r *http.Request) UpdateTksRole(w http.ResponseWriter, r *http.Request) + + Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) + Admin_GetTksRole(w http.ResponseWriter, r *http.Request) } type RoleHandler struct { @@ -261,3 +264,100 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // response ResponseJSON(w, r, http.StatusOK, nil) } + +// Admin_ListTksRoles godoc +// @Tags Role +// @Summary Admin List Tks Roles +// @Description Admin List Tks Roles +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.ListTksRoleResponse +// @Router /admin/organizations/{organizationId}/roles [get] + +func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) { + // Same as ListTksRoles + + var organizationId string + + vars := mux.Vars(r) + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + // query parameter + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + + // list roles + roles, err := h.roleUsecase.ListTksRoles(organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ListTksRoleResponse + out.Roles = make([]domain.GetTksRoleResponse, len(roles)) + for i, role := range roles { + out.Roles[i] = domain.GetTksRoleResponse{ + ID: role.ID, + Name: role.Name, + OrganizationID: role.OrganizationID, + Description: role.Description, + Creator: role.Creator.String(), + CreatedAt: role.CreatedAt, + UpdatedAt: role.UpdatedAt, + } + } + + if err := serializer.Map(*pg, &out.Pagination); err != nil { + log.InfoWithContext(r.Context(), err) + } + + // response + ResponseJSON(w, r, http.StatusOK, out) +} + +// Admin_GetTksRole godoc +// @Tags Role +// @Summary Admin Get Tks Role +// @Description Admin Get Tks Role +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 {object} domain.GetTksRoleResponse +// @Router /admin/organizations/{organizationId}/roles/{roleId} [get] + +func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { + // Same as GetTksRole + + vars := mux.Vars(r) + var roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + } else { + roleId = v + } + + // get role + role, err := h.roleUsecase.GetTksRole(roleId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // response + out := domain.GetTksRoleResponse{ + ID: role.ID, + Name: role.Name, + OrganizationID: role.OrganizationID, + Description: role.Description, + Creator: role.Creator.String(), + CreatedAt: role.CreatedAt, + UpdatedAt: role.UpdatedAt, + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index f4463ab5..c733710c 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -2,6 +2,7 @@ package http import ( "fmt" + admin_domain "github.com/openinfradev/tks-api/pkg/domain/admin" "net/http" "strings" @@ -31,15 +32,26 @@ type IUserHandler interface { CheckId(w http.ResponseWriter, r *http.Request) CheckEmail(w http.ResponseWriter, r *http.Request) + + // Admin + Admin_Create(w http.ResponseWriter, r *http.Request) + Admin_List(w http.ResponseWriter, r *http.Request) + Admin_Get(w http.ResponseWriter, r *http.Request) + Admin_Delete(w http.ResponseWriter, r *http.Request) + Admin_Update(w http.ResponseWriter, r *http.Request) } type UserHandler struct { - usecase usecase.IUserUsecase + usecase usecase.IUserUsecase + authUsecase usecase.IAuthUsecase + roleUsecase usecase.IRoleUsecase } func NewUserHandler(h usecase.Usecase) IUserHandler { return &UserHandler{ - usecase: h.User, + usecase: h.User, + authUsecase: h.Auth, + roleUsecase: h.Role, } } @@ -71,12 +83,6 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { return } - //userInfo, ok := request.UserFrom(r.Context()) - //if !ok { - // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("user info not found in token"))) - // return - //} - ctx := r.Context() var user domain.User if err = serializer.Map(input, &user); err != nil { @@ -86,6 +92,19 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { ID: organizationId, } + roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + for _, role := range roles { + if role.Name == input.Role { + user.Role = *role + break + } + } + resUser, err := u.usecase.Create(ctx, &user) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -282,7 +301,19 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { ID: organizationId, } user.AccountId = accountId - user.Role.Name = input.Role + + roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + for _, role := range roles { + if role.Name == input.Role { + user.Role = *role + break + } + } resUser, err := u.usecase.UpdateByAccountIdByAdmin(ctx, accountId, &user) if err != nil { @@ -616,3 +647,330 @@ func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } + +// Admin_Create godoc +// @Tags Admin +// @Summary Create user by admin +// @Description Create user by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body admin.CreateUserRequest true "create user request" +// @Success 200 {object} admin.CreateUserResponse "create user response" +// @Router /api/1.0/admin/organizations/{organizationId}/users [post] +// @Security JWT + +func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := admin_domain.CreateUserRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + user := domain.User{ + Name: input.Name, + AccountId: input.AccountId, + Email: input.Email, + Department: input.Department, + Description: input.Description, + } + + roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + for _, role := range roles { + if role.Name == input.Role { + user.Role = *role + break + } + } + + user.Organization = domain.Organization{ + ID: organizationId, + } + + // check admin password + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) + return + } + _, err = u.authUsecase.Login(requestUserInfo.GetAccountId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + if err != nil { + ErrorJSON(w, r, err) + return + } + + user.Password = u.usecase.GenerateRandomPassword() + + resUser, err := u.usecase.Create(r.Context(), &user) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusConflict { + ErrorJSON(w, r, httpErrors.NewConflictError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + err = u.usecase.SendEmailForTemporaryPassword(r.Context(), user.AccountId, organizationId, user.Password) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + var out admin_domain.CreateUserResponse + + out.ID = resUser.ID.String() + ResponseJSON(w, r, http.StatusCreated, out) + +} + +// Admin_List godoc +// @Tags Admin +// @Summary Get user list by admin +// @Description Get user list by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} admin.ListUserResponse "user list response" +// @Router /api/1.0/admin/organizations/{organizationId}/users [get] +// @Security JWT + +func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "", "")) + return + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + users, err := u.usecase.ListWithPagination(r.Context(), organizationId, pg) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + var out admin_domain.ListUserResponse + out.Users = make([]domain.ListUserBody, len(*users)) + for i, user := range *users { + if err = serializer.Map(user, &out.Users[i]); err != nil { + log.ErrorWithContext(r.Context(), err) + } + } + + if out.Pagination, err = pg.Response(); err != nil { + log.InfoWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// Admin_Get godoc +// @Tags Admin +// @Summary Get user detail by admin +// @Description Get user detail by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} admin.GetUserResponse +// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [get] +func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + userId, ok := vars["accountId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("accountId not found in path"), "C_INVALID_ACCOUNT_ID", "")) + return + } + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + user, err := u.usecase.GetByAccountId(r.Context(), userId, organizationId) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + var out admin_domain.GetUserResponse + if err = serializer.Map(*user, &out.User); err != nil { + log.ErrorWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// Admin_Delete godoc +// @Tags Admin +// @Summary Delete user by admin +// @Description Delete user by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} domain.User +// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [delete] +// @Security JWT + +func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + userId, ok := vars["accountId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("accountId not found in path"), "C_INVALID_ACCOUNT_ID", "")) + return + } + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "", "")) + return + } + + input := admin_domain.DeleteUserRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + // check admin password + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) + return + } + _, err = u.authUsecase.Login(requestUserInfo.GetAccountId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + if err != nil { + ErrorJSON(w, r, err) + return + } + + err = u.usecase.DeleteByAccountId(r.Context(), userId, organizationId) + if err != nil { + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +// Admin_Update godoc +// @Tags Admin +// @Summary Update user by admin +// @Description Update user by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Param body body admin.UpdateUserRequest true "input" +// @Success 200 {object} admin.UpdateUserResponse +// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [put] +// @Security JWT +func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + accountId, ok := vars["accountId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("accountId not found in path"), "C_INVALID_ACCOUNT_ID", "")) + return + } + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "", "")) + return + } + + input := admin_domain.UpdateUserRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + ctx := r.Context() + var user domain.User + if err = serializer.Map(input, &user); err != nil { + ErrorJSON(w, r, err) + return + } + user.Organization = domain.Organization{ + ID: organizationId, + } + user.AccountId = accountId + + roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + for _, role := range roles { + if role.Name == input.Role { + user.Role = *role + break + } + } + + resUser, err := u.usecase.UpdateByAccountIdByAdmin(ctx, accountId, &user) + if err != nil { + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + var out admin_domain.UpdateUserResponse + if err = serializer.Map(*resUser, &out.User); err != nil { + log.ErrorWithContext(r.Context(), err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/middleware/auth/authenticator/keycloak/keycloak.go b/internal/middleware/auth/authenticator/keycloak/keycloak.go index b694bc36..49c337be 100644 --- a/internal/middleware/auth/authenticator/keycloak/keycloak.go +++ b/internal/middleware/auth/authenticator/keycloak/keycloak.go @@ -115,8 +115,14 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("session id is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } + userAccountId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["preferred_username"].(string) + if !ok { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("preferred_username is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + userInfo := &user.DefaultInfo{ UserId: userId, + AccountId: userAccountId, OrganizationId: organizationId, ProjectIds: projectIds, RoleOrganizationMapping: roleOrganizationMapping, diff --git a/internal/middleware/auth/authorizer/authorizer.go b/internal/middleware/auth/authorizer/authorizer.go index ff4af222..1ce71727 100644 --- a/internal/middleware/auth/authorizer/authorizer.go +++ b/internal/middleware/auth/authorizer/authorizer.go @@ -21,6 +21,7 @@ func NewDefaultAuthorization(repo repository.Repository) *defaultAuthorization { d.addFilters(PasswordFilter) //d.addFilters(RBACFilter) //d.addFilters(RBACFilterWithEndpoint) + d.addFilters(AdminApiFilter) return d } diff --git a/internal/middleware/auth/authorizer/rbac.go b/internal/middleware/auth/authorizer/rbac.go index 45903fcc..722ccd8f 100644 --- a/internal/middleware/auth/authorizer/rbac.go +++ b/internal/middleware/auth/authorizer/rbac.go @@ -92,6 +92,31 @@ func RBACFilterWithEndpoint(handler http.Handler, repo repository.Repository) ht }) } +func AdminApiFilter(handler http.Handler, repo repository.Repository) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + return + } + + endpointInfo, ok := request.EndpointFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) + return + } + + if strings.HasPrefix(endpointInfo.String(), "Admin") { + if requestUserInfo.GetOrganizationId() != "master" { + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return + } + } + + handler.ServeHTTP(w, r) + }) +} + //type pair struct { // regexp string // method string diff --git a/internal/middleware/auth/user/user.go b/internal/middleware/auth/user/user.go index 92a0a6bb..f7117f2a 100644 --- a/internal/middleware/auth/user/user.go +++ b/internal/middleware/auth/user/user.go @@ -7,6 +7,7 @@ import ( // Info describes a user that has been authenticated to the system. type Info interface { GetUserId() uuid.UUID + GetAccountId() string GetOrganizationId() string GetRoleOrganizationMapping() map[string]string GetRoleProjectMapping() map[string]string @@ -16,6 +17,7 @@ type Info interface { // for components that implement the UserInfo interface. type DefaultInfo struct { UserId uuid.UUID + AccountId string OrganizationId string ProjectIds []string RoleOrganizationMapping map[string]string @@ -26,6 +28,10 @@ func (i *DefaultInfo) GetUserId() uuid.UUID { return i.UserId } +func (i *DefaultInfo) GetAccountId() string { + return i.AccountId +} + func (i *DefaultInfo) GetOrganizationId() string { return i.OrganizationId } diff --git a/internal/route/route.go b/internal/route/route.go index 82e765fd..cfaaff21 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -115,6 +115,13 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/next-password-change", customMiddleware.Handle(internalApi.RenewPasswordExpiredDate, http.HandlerFunc(userHandler.RenewPasswordExpiredDate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.DeleteMyProfile, http.HandlerFunc(userHandler.DeleteMyProfile))).Methods(http.MethodDelete) + // Admin + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_CreateUser, http.HandlerFunc(userHandler.Admin_Create))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_ListUser, http.HandlerFunc(userHandler.Admin_List))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_GetUser, http.HandlerFunc(userHandler.Admin_Get))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_UpdateUser, http.HandlerFunc(userHandler.Admin_Update))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_DeleteUser, http.HandlerFunc(userHandler.Admin_Delete))).Methods(http.MethodDelete) + organizationHandler := delivery.NewOrganizationHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.CreateOrganization, http.HandlerFunc(organizationHandler.CreateOrganization))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.GetOrganizations, http.HandlerFunc(organizationHandler.GetOrganizations))).Methods(http.MethodGet) @@ -243,6 +250,10 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.DeleteTksRole, http.HandlerFunc(roleHandler.DeleteTksRole))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateTksRole, http.HandlerFunc(roleHandler.UpdateTksRole))).Methods(http.MethodPut) + // Admin + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.Admin_ListTksRoles, http.HandlerFunc(roleHandler.Admin_ListTksRoles))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.Admin_GetTksRole, http.HandlerFunc(roleHandler.Admin_GetTksRole))).Methods(http.MethodGet) + permissionHandler := delivery.NewPermissionHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(permissionHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 3be12a0a..6a544812 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -30,9 +30,11 @@ type IUserUsecase interface { Update(ctx context.Context, userId uuid.UUID, user *domain.User) (*domain.User, error) ResetPassword(userId uuid.UUID) error ResetPasswordByAccountId(accountId string, organizationId string) error + GenerateRandomPassword() string Delete(userId uuid.UUID, organizationId string) error GetByAccountId(ctx context.Context, accountId string, organizationId string) (*domain.User, error) GetByEmail(ctx context.Context, email string, organizationId string) (*domain.User, error) + SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error UpdateByAccountId(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) UpdatePasswordByAccountId(ctx context.Context, accountId string, originPassword string, newPassword string, organizationId string) error @@ -138,6 +140,10 @@ func (u *UserUsecase) ResetPasswordByAccountId(accountId string, organizationId return u.ResetPassword(user.ID) } +func (u *UserUsecase) GenerateRandomPassword() string { + return helper.GenerateRandomString(passwordLength) +} + func (u *UserUsecase) ValidateAccount(userId uuid.UUID, password string, organizationId string) error { user, err := u.userRepository.GetByUuid(userId) if err != nil { @@ -230,6 +236,27 @@ func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*domain. return resUser, nil } +func (u *UserUsecase) SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error { + user, err := u.userRepository.Get(accountId, organizationId) + if err != nil { + return err + } + + message, err := mail.MakeTemporaryPasswordMessage(user.Email, organizationId, accountId, password) + if err != nil { + return err + } + + mailer := mail.New(message) + + if err := mailer.SendMail(); err != nil { + return err + } + + return nil + +} + func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId string, originPassword string, newPassword string, organizationId string) error { if originPassword == newPassword { diff --git a/pkg/domain/admin/user.go b/pkg/domain/admin/user.go new file mode 100644 index 00000000..da3a218c --- /dev/null +++ b/pkg/domain/admin/user.go @@ -0,0 +1,69 @@ +package admin + +import ( + "github.com/openinfradev/tks-api/pkg/domain" + "time" +) + +type CreateUserRequest struct { + AccountId string `json:"accountId" validate:"required"` + Name string `json:"name" validate:"name"` + Email string `json:"email" validate:"required,email"` + Role string `json:"role" validate:"required"` + Department string `json:"department" validate:"min=0,max=50"` + Description string `json:"description" validate:"min=0,max=100"` + AdminPassword string `json:"adminPassword" validate:"required"` +} + +type CreateUserResponse struct { + ID string `json:"id"` +} + +type ListUserResponse struct { + Users []domain.ListUserBody `json:"users"` + Pagination domain.PaginationResponse `json:"pagination"` +} + +type GetUserResponse struct { + User struct { + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role domain.Role `json:"role"` + Organization domain.Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + } `json:"user"` +} + +type UpdateUserRequest struct { + Name string `json:"name" validate:"name"` + Email string `json:"email" validate:"required,email"` + Department string `json:"department" validate:"min=0,max=50"` + Role string `json:"role" validate:"required"` + Description string `json:"description" validate:"min=0,max=100"` + AdminPassword string `json:"adminPassword" validate:"required"` +} + +type UpdateUserResponse struct { + User struct { + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role domain.Role `json:"role"` + Organization domain.Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + } `json:"user"` +} + +type DeleteUserRequest struct { + AdminPassword string `json:"adminPassword" validate:"required"` +} From bcf2791a246911eb1a1514e5a99c1f66d4df4f50 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 5 Mar 2024 18:15:43 +0900 Subject: [PATCH 084/502] minor trimming --- internal/delivery/http/user.go | 33 +++++++++---- internal/repository/user.go | 86 +++------------------------------- internal/usecase/user.go | 58 +++++------------------ 3 files changed, 45 insertions(+), 132 deletions(-) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index c733710c..c6a6e03e 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -413,6 +413,12 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { // @Router /api/1.0/organizations/{organizationId}/my-profile [put] // @Security JWT func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) + return + } requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) @@ -442,10 +448,8 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } - user.Organization = domain.Organization{ - ID: requestUserInfo.GetOrganizationId(), - } + user.OrganizationId = organizationId resUser, err := u.usecase.Update(ctx, requestUserInfo.GetUserId(), &user) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -875,7 +879,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) return } - _, err = u.authUsecase.Login(requestUserInfo.GetAccountId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) if err != nil { ErrorJSON(w, r, err) return @@ -930,16 +934,29 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { return } - ctx := r.Context() - var user domain.User - if err = serializer.Map(input, &user); err != nil { + // check admin password + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) + return + } + err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + if err != nil { ErrorJSON(w, r, err) return } + + ctx := r.Context() + user := domain.User{ + AccountId: accountId, + Name: input.Name, + Email: input.Email, + Department: input.Department, + Description: input.Description, + } user.Organization = domain.Organization{ ID: organizationId, } - user.AccountId = accountId roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) if err != nil { diff --git a/internal/repository/user.go b/internal/repository/user.go index baf14464..12ed1a50 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -99,7 +99,7 @@ func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name s return domain.User{}, err } - return r.reflect(user), nil + return user, nil } func (r *UserRepository) AccountIdFilter(accountId string) FilterFunc { return func(user *gorm.DB) *gorm.DB { @@ -151,7 +151,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { var out []domain.User for _, user := range users { - out = append(out, r.reflect(user)) + out = append(out, user) } return &out, nil @@ -172,7 +172,7 @@ func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizat var out []domain.User for _, user := range users { - out = append(out, r.reflect(user)) + out = append(out, user) } return &out, nil @@ -184,7 +184,7 @@ func (r *UserRepository) Get(accountId string, organizationId string) (domain.Us return domain.User{}, err } - return r.reflect(user), nil + return user, nil } func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser domain.User, err error) { user := domain.User{} @@ -198,7 +198,7 @@ func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser domain.User, err return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } - return r.reflect(user), nil + return user, nil } func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, email string, department string, description string) (domain.User, error) { @@ -222,7 +222,7 @@ func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name s if res.Error != nil { return domain.User{}, res.Error } - return r.reflect(user), nil + return user, nil } func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error { var updateUser = domain.User{} @@ -279,7 +279,7 @@ func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { return domain.Role{}, err } - return r.reflectRole(role), nil + return role, nil } //func (r *UserRepository) FetchRoles() (*[]domain.Role, error) { @@ -337,75 +337,3 @@ func (r *UserRepository) getRoleByName(roleName string) (domain.Role, error) { return role, nil } - -func (r *UserRepository) reflect(user domain.User) domain.User { - role := domain.Role{ - ID: user.Role.ID, - Name: user.Role.Name, - Description: user.Role.Description, - Creator: user.Role.Creator, - CreatedAt: user.Role.CreatedAt, - UpdatedAt: user.Role.UpdatedAt, - } - //for _, role := range user.Roles { - // outRole := domain.Role{ - // ID: role.ID.String(), - // Name: role.Name, - // Description: role.Description, - // Creator: role.Creator.String(), - // CreatedAt: role.CreatedAt, - // UpdatedAt: role.UpdatedAt, - // } - // resRoles = append(resRoles, outRole) - //} - - organization := domain.Organization{ - ID: user.Organization.ID, - Name: user.Organization.Name, - Description: user.Organization.Description, - Phone: user.Organization.Phone, - Status: user.Organization.Status, - StatusDesc: user.Organization.StatusDesc, - Creator: user.Organization.Creator, - CreatedAt: user.Organization.CreatedAt, - UpdatedAt: user.Organization.UpdatedAt, - } - //for _, organization := range user.Organizations { - // outOrganization := domain.Organization{ - // ID: organization.ID, - // Name: organization.Name, - // Description: organization.Description, - // Creator: organization.Creator.String(), - // CreatedAt: organization.CreatedAt, - // UpdatedAt: organization.UpdatedAt, - // } - // resOrganizations = append(resOrganizations, outOrganization) - //} - - return domain.User{ - ID: user.ID, - AccountId: user.AccountId, - Password: user.Password, - Name: user.Name, - Role: role, - Organization: organization, - Creator: user.Creator, - CreatedAt: user.CreatedAt, - UpdatedAt: user.UpdatedAt, - Email: user.Email, - Department: user.Department, - Description: user.Description, - PasswordUpdatedAt: user.PasswordUpdatedAt, - } -} - -func (r *UserRepository) reflectRole(role domain.Role) domain.Role { - return domain.Role{ - ID: role.ID, - Name: role.Name, - Description: role.Description, - Creator: role.Creator, - CreatedAt: role.CreatedAt, - UpdatedAt: role.UpdatedAt, - } -} diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 6a544812..b851d2f5 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -10,7 +10,6 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/mail" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" @@ -357,17 +356,9 @@ func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *domain } func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) { - userInfo, ok := request.UserFrom(ctx) - if !ok { - return nil, fmt.Errorf("user in the context is empty") - } - - _, err := u.kc.Login(user.AccountId, user.Password, userInfo.GetOrganizationId()) - if err != nil { - return nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid password"), "", "") - } + var out domain.User - originUser, err := u.kc.GetUser(userInfo.GetOrganizationId(), accountId) + originUser, err := u.kc.GetUser(user.Organization.ID, accountId) if err != nil { return nil, err } @@ -375,13 +366,13 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u if (originUser.Email == nil || *originUser.Email != user.Email) || (originUser.FirstName == nil || *originUser.FirstName != user.Name) { originUser.Email = gocloak.StringP(user.Email) originUser.FirstName = gocloak.StringP(user.Name) - err = u.kc.UpdateUser(userInfo.GetOrganizationId(), originUser) + err = u.kc.UpdateUser(user.Organization.ID, originUser) if err != nil { return nil, err } } - users, err := u.userRepository.List(u.userRepository.OrganizationFilter(userInfo.GetOrganizationId()), + users, err := u.userRepository.List(u.userRepository.OrganizationFilter(user.Organization.ID), u.userRepository.AccountIdFilter(accountId)) if err != nil { if _, code := httpErrors.ErrorResponse(err); code == http.StatusNotFound { @@ -400,13 +391,12 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u return nil, err } - *user, err = u.userRepository.UpdateWithUuid((*users)[0].ID, user.AccountId, user.Name, roleUuid, user.Email, - user.Department, user.Description) + out, err = u.userRepository.UpdateWithUuid((*users)[0].ID, user.AccountId, user.Name, roleUuid, user.Email, user.Department, user.Description) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") } - return user, nil + return &out, nil } func (u *UserUsecase) Delete(userId uuid.UUID, organizationId string) error { @@ -503,48 +493,26 @@ func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.Us } func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *domain.User) (*domain.User, error) { - user, err := u.UpdateByAccountId(ctx, accountId, newUser) + deepCopyUser := *newUser + user, err := u.UpdateByAccountId(ctx, accountId, &deepCopyUser) if err != nil { return nil, err } - userInfo, ok := request.UserFrom(ctx) - if !ok { - return nil, fmt.Errorf("user in the context is empty") - } - if newUser.Role.Name != user.Role.Name { - originGroupName := fmt.Sprintf("%s@%s", user.Role.Name, userInfo.GetOrganizationId()) - newGroupName := fmt.Sprintf("%s@%s", user.Role.Name, userInfo.GetOrganizationId()) - if err := u.kc.LeaveGroup(userInfo.GetOrganizationId(), user.ID.String(), originGroupName); err != nil { + originGroupName := fmt.Sprintf("%s@%s", user.Role.Name, newUser.Organization.ID) + newGroupName := fmt.Sprintf("%s@%s", newUser.Role.Name, newUser.Organization.ID) + if err := u.kc.LeaveGroup(newUser.Organization.ID, user.ID.String(), originGroupName); err != nil { log.ErrorfWithContext(ctx, "leave group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } - if err := u.kc.JoinGroup(userInfo.GetOrganizationId(), user.ID.String(), newGroupName); err != nil { + if err := u.kc.JoinGroup(newUser.Organization.ID, user.ID.String(), newGroupName); err != nil { log.ErrorfWithContext(ctx, "join group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } } - // Get user role - var roleUuid string - roles, err := u.roleRepository.ListTksRoles(user.Organization.ID, nil) - if err != nil { - return nil, err - } - if len(roles) == 0 { - return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") - } - for _, role := range roles { - if role.Name == user.Role.Name { - roleUuid = role.ID - } - } - if roleUuid == "" { - return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") - } - - *user, err = u.userRepository.UpdateWithUuid(user.ID, user.AccountId, user.Name, roleUuid, user.Email, + *user, err = u.userRepository.UpdateWithUuid(user.ID, user.AccountId, user.Name, newUser.Role.ID, user.Email, user.Department, user.Description) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") From a933488229ba8b76a5033eb2e4762ada144f82b2 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 6 Mar 2024 10:51:05 +0900 Subject: [PATCH 085/502] trivial. resolve swagger error --- api/swagger/docs.go | 1293 ++++++++++++++++++++++---------- api/swagger/swagger.json | 1293 ++++++++++++++++++++++---------- api/swagger/swagger.yaml | 1127 ++++++++++++++++++---------- internal/delivery/http/user.go | 17 +- 4 files changed, 2513 insertions(+), 1217 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 798c0e73..0c5deb4e 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -22,6 +22,96 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/api/1.0/admin/organizations/{organizationId}/users/{accountId}": { + "get": { + "description": "Get user detail by admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin" + ], + "summary": "Get user detail by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user by admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin" + ], + "summary": "Update user by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse" + } + } + } + } + }, "/api/1.0/app-groups": { "get": { "security": [ @@ -86,7 +176,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppGroupsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppGroupsResponse" } } } @@ -115,7 +205,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateAppGroupRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupRequest" } } ], @@ -123,7 +213,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateAppGroupResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupResponse" } } } @@ -194,7 +284,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppGroupResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse" } } } @@ -238,7 +328,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetApplicationsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetApplicationsResponse" } } } @@ -267,7 +357,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateApplicationRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateApplicationRequest" } } ], @@ -298,7 +388,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostIdRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest" } } ], @@ -306,13 +396,13 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -338,7 +428,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.FindIdRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindIdRequest" } } ], @@ -346,13 +436,13 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.FindIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindIdResponse" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -378,7 +468,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest" } } ], @@ -386,13 +476,13 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -418,7 +508,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.FindPasswordRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindPasswordRequest" } } ], @@ -429,7 +519,7 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -455,7 +545,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.LoginRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.LoginRequest" } } ], @@ -463,7 +553,7 @@ const docTemplate = `{ "200": { "description": "user detail", "schema": { - "$ref": "#/definitions/domain.LoginResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.LoginResponse" } } } @@ -491,7 +581,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.LogoutResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.LogoutResponse" } } } @@ -517,7 +607,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.PingTokenRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest" } } ], @@ -592,7 +682,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetClustersResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse" } } } @@ -621,7 +711,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateClusterRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateClusterRequest" } } ], @@ -629,7 +719,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse" } } } @@ -660,7 +750,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.ImportClusterRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest" } } ], @@ -668,7 +758,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.ImportClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportClusterResponse" } } } @@ -705,7 +795,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.Cluster" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" } } } @@ -740,7 +830,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.Cluster" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" } } } @@ -768,7 +858,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetBootstrapKubeconfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetBootstrapKubeconfigResponse" } } } @@ -794,7 +884,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateBootstrapKubeconfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateBootstrapKubeconfigResponse" } } } @@ -865,7 +955,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetClusterNodesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterNodesResponse" } } } @@ -902,7 +992,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.ClusterSiteValuesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterSiteValuesResponse" } } } @@ -968,7 +1058,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/domain.ListOrganizationBody" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody" } } } @@ -998,7 +1088,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateOrganizationRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest" } } ], @@ -1043,7 +1133,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetOrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse" } } } @@ -1079,7 +1169,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateOrganizationRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest" } } ], @@ -1087,7 +1177,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.UpdateOrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse" } } } @@ -1122,7 +1212,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" } } } @@ -1193,7 +1283,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAlertsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse" } } } @@ -1237,7 +1327,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAlertResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse" } } } @@ -1273,7 +1363,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateAlertRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest" } } ], @@ -1425,7 +1515,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAuditsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" } } } @@ -1454,7 +1544,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateAuditRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" } } ], @@ -1462,7 +1552,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateAuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" } } } @@ -1499,7 +1589,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" } } } @@ -1602,7 +1692,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetCloudAccountsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" } } } @@ -1638,7 +1728,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateCloudAccountRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" } } ], @@ -1646,7 +1736,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" } } } @@ -1690,7 +1780,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckCloudAccountAwsAccountIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" } } } @@ -1734,7 +1824,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckCloudAccountNameResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountNameResponse" } } } @@ -1778,7 +1868,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResponse" } } } @@ -1814,7 +1904,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateCloudAccountRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateCloudAccountRequest" } } ], @@ -1855,7 +1945,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.DeleteCloudAccountRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteCloudAccountRequest" } }, { @@ -1952,7 +2042,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetCloudAccountResourceQuotaResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResourceQuotaResponse" } } } @@ -2009,7 +2099,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetDashboardChartsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse" } } } @@ -2067,7 +2157,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetDashboardChartResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse" } } } @@ -2104,7 +2194,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetDashboardResourcesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse" } } } @@ -2141,7 +2231,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetDashboardStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse" } } } @@ -2178,7 +2268,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetMyProfileResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse" } } } @@ -2214,7 +2304,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateMyProfileRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest" } } ], @@ -2222,7 +2312,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.UpdateMyProfileResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileResponse" } } } @@ -2297,7 +2387,7 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -2335,7 +2425,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdatePasswordRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest" } } ], @@ -2378,7 +2468,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdatePrimaryClusterRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest" } } ], @@ -2426,7 +2516,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse" } } } @@ -2462,7 +2552,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateProjectRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest" } } ], @@ -2470,7 +2560,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse" } } } @@ -2520,7 +2610,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } @@ -2563,7 +2653,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectRolesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse" } } } @@ -2607,7 +2697,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse" } } } @@ -2651,7 +2741,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse" } } } @@ -2694,7 +2784,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateProjectRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest" } } ], @@ -2702,7 +2792,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -2788,7 +2878,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" } } } @@ -2832,7 +2922,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateAppServeAppRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest" } } ], @@ -2993,7 +3083,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppServeAppResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse" } } } @@ -3043,7 +3133,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest" } } ], @@ -3152,7 +3242,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest" } } ], @@ -3255,7 +3345,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" } } } @@ -3307,7 +3397,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.RollbackAppServeAppRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest" } } ], @@ -3367,7 +3457,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest" } } ], @@ -3455,7 +3545,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" } } } @@ -3514,7 +3604,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" } } } @@ -3558,7 +3648,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectKubeconfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse" } } } @@ -3608,7 +3698,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectMembersResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse" } } } @@ -3651,7 +3741,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateProjectMembersRoleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest" } } ], @@ -3659,7 +3749,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -3702,7 +3792,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.AddProjectMemberRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest" } } ], @@ -3710,7 +3800,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -3753,7 +3843,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.RemoveProjectMemberRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest" } } ], @@ -3761,7 +3851,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -3805,7 +3895,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectMemberCountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse" } } } @@ -3856,7 +3946,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectMemberResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse" } } } @@ -3905,7 +3995,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -3957,7 +4047,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateProjectMemberRoleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest" } } ], @@ -3965,7 +4055,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -4009,7 +4099,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectNamespacesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse" } } } @@ -4052,7 +4142,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateProjectNamespaceRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest" } } ], @@ -4060,7 +4150,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -4118,7 +4208,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectNamespaceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse" } } } @@ -4175,7 +4265,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateProjectNamespaceRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest" } } ], @@ -4183,7 +4273,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -4239,7 +4329,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -4297,7 +4387,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } @@ -4355,7 +4445,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectNamespaceK8sResourcesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse" } } } @@ -4422,7 +4512,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" } } } @@ -4458,7 +4548,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateStackRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" } } ], @@ -4466,7 +4556,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" } } } @@ -4558,7 +4648,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" } } } @@ -4601,7 +4691,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateStackRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest" } } ], @@ -4769,7 +4859,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackKubeConfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse" } } } @@ -4813,7 +4903,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" } } } @@ -4886,7 +4976,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/domain.ListUserBody" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListUserBody" } } } @@ -4923,7 +5013,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateUserRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest" } } ], @@ -4931,7 +5021,7 @@ const docTemplate = `{ "200": { "description": "create user response", "schema": { - "$ref": "#/definitions/domain.CreateUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse" } } } @@ -4972,7 +5062,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } @@ -5013,7 +5103,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } @@ -5057,7 +5147,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUserResponse" } } } @@ -5100,7 +5190,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateUserRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest" } } ], @@ -5108,7 +5198,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.UpdateUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse" } } } @@ -5150,7 +5240,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" } } } @@ -5255,7 +5345,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" } } } @@ -5284,7 +5374,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateStackTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" } } ], @@ -5292,7 +5382,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" } } } @@ -5329,7 +5419,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" } } } @@ -5358,7 +5448,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateStackTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" } } ], @@ -5401,6 +5491,117 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/roles": { + "get": { + "description": "List Tks Roles", + "produces": [ + "application/json" + ], + "tags": [ + "Role" + ], + "summary": "List Tks Roles", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" + } + } + } + } + }, + "/permissions/templates": { + "get": { + "description": "Get Permission Templates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Get Permission Templates", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + } + } + } + } + }, + "/roles/{roleId}/permissions": { + "get": { + "description": "Get Permissions By Role ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Get Permissions By Role ID", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + } + } + } + }, + "put": { + "description": "Update Permissions By Role ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Update Permissions By Role ID", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Update Permissions By Role ID Request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/system-api/organizations/{organizationId}/alerts": { "post": { "security": [ @@ -5437,7 +5638,7 @@ const docTemplate = `{ } }, "definitions": { - "domain.ActionResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { "body": { @@ -5462,18 +5663,18 @@ const docTemplate = `{ } } }, - "domain.AddProjectMemberRequest": { + "github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest": { "type": "object", "properties": { "projectMembers": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectMemberRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest" } } } }, - "domain.AlertActionResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse": { "type": "object", "properties": { "alertId": { @@ -5492,27 +5693,27 @@ const docTemplate = `{ "type": "string" }, "taker": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "updatedAt": { "type": "string" } } }, - "domain.AlertResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AlertResponse": { "type": "object", "properties": { "alertActions": { "type": "array", "items": { - "$ref": "#/definitions/domain.AlertActionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse" } }, "closedAt": { "type": "string" }, "cluster": { - "$ref": "#/definitions/domain.SimpleClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" }, "code": { "type": "string" @@ -5536,7 +5737,7 @@ const docTemplate = `{ "type": "string" }, "lastTaker": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "message": { "type": "string" @@ -5570,11 +5771,11 @@ const docTemplate = `{ } } }, - "domain.AppGroupResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { "appGroupType": { - "$ref": "#/definitions/domain.AppGroupType" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupType" }, "clusterId": { "type": "string" @@ -5583,7 +5784,7 @@ const docTemplate = `{ "type": "string" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -5595,7 +5796,7 @@ const docTemplate = `{ "type": "string" }, "status": { - "$ref": "#/definitions/domain.AppGroupStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupStatus" }, "statusDesc": { "type": "string" @@ -5604,14 +5805,14 @@ const docTemplate = `{ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "workflowId": { "type": "string" } } }, - "domain.AppGroupStatus": { + "github_com_openinfradev_tks-api_pkg_domain.AppGroupStatus": { "type": "integer", "enum": [ 0, @@ -5632,7 +5833,7 @@ const docTemplate = `{ "AppGroupStatus_DELETE_ERROR" ] }, - "domain.AppGroupType": { + "github_com_openinfradev_tks-api_pkg_domain.AppGroupType": { "type": "integer", "enum": [ 0, @@ -5645,13 +5846,13 @@ const docTemplate = `{ "AppGroupType_SERVICE_MESH" ] }, - "domain.AppServeApp": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeApp": { "type": "object", "properties": { "appServeAppTasks": { "type": "array", "items": { - "$ref": "#/definitions/domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" } }, "appType": { @@ -5716,7 +5917,7 @@ const docTemplate = `{ } } }, - "domain.AppServeAppTask": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask": { "type": "object", "properties": { "appConfig": { @@ -5816,14 +6017,14 @@ const docTemplate = `{ } } }, - "domain.ApplicationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse": { "type": "object", "properties": { "appGroupId": { "type": "string" }, "applicationType": { - "$ref": "#/definitions/domain.ApplicationType" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ApplicationType" }, "createdAt": { "type": "string" @@ -5842,7 +6043,7 @@ const docTemplate = `{ } } }, - "domain.ApplicationType": { + "github_com_openinfradev_tks-api_pkg_domain.ApplicationType": { "type": "integer", "enum": [ 0, @@ -5871,7 +6072,7 @@ const docTemplate = `{ "ApplicationType_KUBERNETES_DASHBOARD" ] }, - "domain.AuditResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AuditResponse": { "type": "object", "properties": { "clientIP": { @@ -5893,7 +6094,7 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.SimpleOrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" }, "organizationId": { "type": "string" @@ -5902,14 +6103,14 @@ const docTemplate = `{ "type": "string" }, "user": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "userId": { "type": "string" } } }, - "domain.Axis": { + "github_com_openinfradev_tks-api_pkg_domain.Axis": { "type": "object", "properties": { "data": { @@ -5920,7 +6121,7 @@ const docTemplate = `{ } } }, - "domain.BootstrapKubeconfig": { + "github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig": { "type": "object", "properties": { "expiration": { @@ -5928,30 +6129,30 @@ const docTemplate = `{ } } }, - "domain.ChartData": { + "github_com_openinfradev_tks-api_pkg_domain.ChartData": { "type": "object", "properties": { "podCounts": { "type": "array", "items": { - "$ref": "#/definitions/domain.PodCount" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PodCount" } }, "series": { "type": "array", "items": { - "$ref": "#/definitions/domain.Unit" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Unit" } }, "xAxis": { - "$ref": "#/definitions/domain.Axis" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis" }, "yAxis": { - "$ref": "#/definitions/domain.Axis" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis" } } }, - "domain.CheckCloudAccountAwsAccountIdResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse": { "type": "object", "properties": { "existed": { @@ -5959,7 +6160,7 @@ const docTemplate = `{ } } }, - "domain.CheckCloudAccountNameResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountNameResponse": { "type": "object", "properties": { "existed": { @@ -5967,7 +6168,7 @@ const docTemplate = `{ } } }, - "domain.CheckExistedResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse": { "type": "object", "properties": { "existed": { @@ -5975,7 +6176,7 @@ const docTemplate = `{ } } }, - "domain.CloudAccount": { + "github_com_openinfradev_tks-api_pkg_domain.CloudAccount": { "type": "object", "properties": { "accessKeyId": { @@ -5997,7 +6198,7 @@ const docTemplate = `{ "type": "boolean" }, "creator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "creatorId": { "type": "string" @@ -6024,7 +6225,7 @@ const docTemplate = `{ "type": "string" }, "status": { - "$ref": "#/definitions/domain.CloudAccountStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus" }, "statusDesc": { "type": "string" @@ -6033,14 +6234,14 @@ const docTemplate = `{ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "updatorId": { "type": "string" } } }, - "domain.CloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { "awsAccountId": { @@ -6059,7 +6260,7 @@ const docTemplate = `{ "type": "boolean" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -6083,11 +6284,11 @@ const docTemplate = `{ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" } } }, - "domain.CloudAccountStatus": { + "github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus": { "type": "integer", "enum": [ 0, @@ -6108,7 +6309,7 @@ const docTemplate = `{ "CloudAccountStatus_DELETE_ERROR" ] }, - "domain.Cluster": { + "github_com_openinfradev_tks-api_pkg_domain.Cluster": { "type": "object", "properties": { "byoClusterEndpointHost": { @@ -6118,7 +6319,7 @@ const docTemplate = `{ "type": "integer" }, "cloudAccount": { - "$ref": "#/definitions/domain.CloudAccount" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount" }, "cloudAccountId": { "type": "string" @@ -6130,13 +6331,13 @@ const docTemplate = `{ "type": "integer" }, "conf": { - "$ref": "#/definitions/domain.ClusterConf" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf" }, "createdAt": { "type": "string" }, "creator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "creatorId": { "type": "string" @@ -6166,13 +6367,13 @@ const docTemplate = `{ "type": "string" }, "stackTemplate": { - "$ref": "#/definitions/domain.StackTemplate" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate" }, "stackTemplateId": { "type": "string" }, "status": { - "$ref": "#/definitions/domain.ClusterStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus" }, "statusDesc": { "type": "string" @@ -6181,14 +6382,14 @@ const docTemplate = `{ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "updatorId": { "type": "string" } } }, - "domain.ClusterConf": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterConf": { "type": "object", "properties": { "tksCpNode": { @@ -6220,7 +6421,7 @@ const docTemplate = `{ } } }, - "domain.ClusterConfResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse": { "type": "object", "properties": { "tksCpNode": { @@ -6252,7 +6453,7 @@ const docTemplate = `{ } } }, - "domain.ClusterHost": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterHost": { "type": "object", "properties": { "name": { @@ -6263,7 +6464,7 @@ const docTemplate = `{ } } }, - "domain.ClusterNode": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterNode": { "type": "object", "properties": { "command": { @@ -6272,7 +6473,7 @@ const docTemplate = `{ "hosts": { "type": "array", "items": { - "$ref": "#/definitions/domain.ClusterHost" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterHost" } }, "registered": { @@ -6295,7 +6496,7 @@ const docTemplate = `{ } } }, - "domain.ClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterResponse": { "type": "object", "properties": { "byoClusterEndpointHost": { @@ -6305,7 +6506,7 @@ const docTemplate = `{ "type": "integer" }, "cloudAccount": { - "$ref": "#/definitions/domain.SimpleCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse" }, "cloudService": { "type": "string" @@ -6314,13 +6515,13 @@ const docTemplate = `{ "type": "string" }, "conf": { - "$ref": "#/definitions/domain.ClusterConfResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse" }, "createdAt": { "type": "string" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -6338,7 +6539,7 @@ const docTemplate = `{ "type": "string" }, "stackTemplate": { - "$ref": "#/definitions/domain.SimpleStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse" }, "status": { "type": "string" @@ -6350,11 +6551,11 @@ const docTemplate = `{ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" } } }, - "domain.ClusterSiteValuesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterSiteValuesResponse": { "type": "object", "properties": { "byoClusterEndpointHost": { @@ -6401,7 +6602,7 @@ const docTemplate = `{ } } }, - "domain.ClusterStatus": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterStatus": { "type": "integer", "enum": [ 0, @@ -6428,7 +6629,7 @@ const docTemplate = `{ "ClusterStatus_BOOTSTRAP_ERROR" ] }, - "domain.CommonProjectResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { "result": { @@ -6436,7 +6637,7 @@ const docTemplate = `{ } } }, - "domain.CreateAppGroupRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupRequest": { "type": "object", "required": [ "clusterId", @@ -6461,7 +6662,7 @@ const docTemplate = `{ } } }, - "domain.CreateAppGroupResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupResponse": { "type": "object", "properties": { "id": { @@ -6469,7 +6670,7 @@ const docTemplate = `{ } } }, - "domain.CreateAppServeAppRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest": { "type": "object", "required": [ "name", @@ -6547,7 +6748,7 @@ const docTemplate = `{ } } }, - "domain.CreateApplicationRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateApplicationRequest": { "type": "object", "properties": { "applicationType": { @@ -6561,21 +6762,21 @@ const docTemplate = `{ } } }, - "domain.CreateAuditRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest": { "type": "object" }, - "domain.CreateAuditResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse": { "type": "object" }, - "domain.CreateBootstrapKubeconfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateBootstrapKubeconfigResponse": { "type": "object", "properties": { "kubeconfig": { - "$ref": "#/definitions/domain.BootstrapKubeconfig" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig" } } }, - "domain.CreateCloudAccountRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest": { "type": "object", "required": [ "accessKeyId", @@ -6619,7 +6820,7 @@ const docTemplate = `{ } } }, - "domain.CreateCloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse": { "type": "object", "properties": { "id": { @@ -6627,7 +6828,7 @@ const docTemplate = `{ } } }, - "domain.CreateClusterRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateClusterRequest": { "type": "object", "required": [ "cloudService", @@ -6699,7 +6900,7 @@ const docTemplate = `{ } } }, - "domain.CreateClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse": { "type": "object", "properties": { "id": { @@ -6707,7 +6908,7 @@ const docTemplate = `{ } } }, - "domain.CreateOrganizationRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { "type": "object", "required": [ "Email", @@ -6730,7 +6931,7 @@ const docTemplate = `{ } } }, - "domain.CreateProjectNamespaceRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest": { "type": "object", "properties": { "description": { @@ -6744,7 +6945,7 @@ const docTemplate = `{ } } }, - "domain.CreateProjectRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest": { "type": "object", "required": [ "name" @@ -6761,7 +6962,7 @@ const docTemplate = `{ } } }, - "domain.CreateProjectResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse": { "type": "object", "properties": { "projectId": { @@ -6769,7 +6970,7 @@ const docTemplate = `{ } } }, - "domain.CreateStackRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest": { "type": "object", "required": [ "cloudService", @@ -6831,7 +7032,7 @@ const docTemplate = `{ } } }, - "domain.CreateStackResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse": { "type": "object", "properties": { "id": { @@ -6839,7 +7040,7 @@ const docTemplate = `{ } } }, - "domain.CreateStackTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest": { "type": "object", "required": [ "name", @@ -6880,7 +7081,7 @@ const docTemplate = `{ } } }, - "domain.CreateStackTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse": { "type": "object", "properties": { "id": { @@ -6888,7 +7089,7 @@ const docTemplate = `{ } } }, - "domain.CreateUserRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest": { "type": "object", "required": [ "accountId", @@ -6928,7 +7129,7 @@ const docTemplate = `{ } } }, - "domain.CreateUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse": { "type": "object", "properties": { "user": { @@ -6953,20 +7154,20 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } } }, - "domain.DashboardChartResponse": { + "github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse": { "type": "object", "properties": { "chartData": { - "$ref": "#/definitions/domain.ChartData" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ChartData" }, "chartType": { "type": "string" @@ -6997,7 +7198,7 @@ const docTemplate = `{ } } }, - "domain.DashboardResource": { + "github_com_openinfradev_tks-api_pkg_domain.DashboardResource": { "type": "object", "properties": { "cpu": { @@ -7014,7 +7215,7 @@ const docTemplate = `{ } } }, - "domain.DashboardStackResponse": { + "github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse": { "type": "object", "properties": { "cpu": { @@ -7049,7 +7250,7 @@ const docTemplate = `{ } } }, - "domain.DeleteCloudAccountRequest": { + "github_com_openinfradev_tks-api_pkg_domain.DeleteCloudAccountRequest": { "type": "object", "required": [ "accessKeyId", @@ -7072,7 +7273,21 @@ const docTemplate = `{ } } }, - "domain.FilterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "group": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { "column": { @@ -7092,7 +7307,7 @@ const docTemplate = `{ } } }, - "domain.FindIdRequest": { + "github_com_openinfradev_tks-api_pkg_domain.FindIdRequest": { "type": "object", "required": [ "code", @@ -7115,7 +7330,7 @@ const docTemplate = `{ } } }, - "domain.FindIdResponse": { + "github_com_openinfradev_tks-api_pkg_domain.FindIdResponse": { "type": "object", "properties": { "accountId": { @@ -7123,7 +7338,7 @@ const docTemplate = `{ } } }, - "domain.FindPasswordRequest": { + "github_com_openinfradev_tks-api_pkg_domain.FindPasswordRequest": { "type": "object", "required": [ "accountId", @@ -7150,219 +7365,219 @@ const docTemplate = `{ } } }, - "domain.GetAlertResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse": { "type": "object", "properties": { "alert": { - "$ref": "#/definitions/domain.AlertResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse" } } }, - "domain.GetAlertsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse": { "type": "object", "properties": { "alerts": { "type": "array", "items": { - "$ref": "#/definitions/domain.AlertResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetAppGroupResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse": { "type": "object", "properties": { "appGroup": { - "$ref": "#/definitions/domain.AppGroupResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse" } } }, - "domain.GetAppGroupsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAppGroupsResponse": { "type": "object", "properties": { "appGroups": { "type": "array", "items": { - "$ref": "#/definitions/domain.AppGroupResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetAppServeAppResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse": { "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" }, "stages": { "type": "array", "items": { - "$ref": "#/definitions/domain.StageResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse" } } } }, - "domain.GetAppServeAppTaskResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse": { "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" }, "appServeAppTask": { - "$ref": "#/definitions/domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" }, "stages": { "type": "array", "items": { - "$ref": "#/definitions/domain.StageResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse" } } } }, - "domain.GetApplicationsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetApplicationsResponse": { "type": "object", "properties": { "applications": { "type": "array", "items": { - "$ref": "#/definitions/domain.ApplicationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse" } } } }, - "domain.GetAuditResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse": { "type": "object", "properties": { "audit": { - "$ref": "#/definitions/domain.AuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AuditResponse" } } }, - "domain.GetAuditsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse": { "type": "object", "properties": { "audits": { "type": "array", "items": { - "$ref": "#/definitions/domain.AuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AuditResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetBootstrapKubeconfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetBootstrapKubeconfigResponse": { "type": "object", "properties": { "kubeconfig": { - "$ref": "#/definitions/domain.BootstrapKubeconfig" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig" } } }, - "domain.GetCloudAccountResourceQuotaResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResourceQuotaResponse": { "type": "object", "properties": { "available": { "type": "boolean" }, "resourceQuota": { - "$ref": "#/definitions/domain.ResourceQuota" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ResourceQuota" } } }, - "domain.GetCloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResponse": { "type": "object", "properties": { "cloudAccount": { - "$ref": "#/definitions/domain.CloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse" } } }, - "domain.GetCloudAccountsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse": { "type": "object", "properties": { "cloudAccounts": { "type": "array", "items": { - "$ref": "#/definitions/domain.CloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetClusterNodesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetClusterNodesResponse": { "type": "object", "properties": { "nodes": { "type": "array", "items": { - "$ref": "#/definitions/domain.ClusterNode" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode" } } } }, - "domain.GetClustersResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse": { "type": "object", "properties": { "clusters": { "type": "array", "items": { - "$ref": "#/definitions/domain.ClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetDashboardChartResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse": { "type": "object", "properties": { "chart": { - "$ref": "#/definitions/domain.DashboardChartResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse" } } }, - "domain.GetDashboardChartsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse": { "type": "object", "properties": { "charts": { "type": "array", "items": { - "$ref": "#/definitions/domain.DashboardChartResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse" } } } }, - "domain.GetDashboardResourcesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { "resources": { - "$ref": "#/definitions/domain.DashboardResource" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardResource" } } }, - "domain.GetDashboardStacksResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse": { "type": "object", "properties": { "stacks": { "type": "array", "items": { - "$ref": "#/definitions/domain.DashboardStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse" } } } }, - "domain.GetMyProfileResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse": { "type": "object", "properties": { "user": { @@ -7384,16 +7599,16 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } } }, - "domain.GetOrganizationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse": { "type": "object", "properties": { "organization": { @@ -7433,7 +7648,7 @@ const docTemplate = `{ } } }, - "domain.GetProjectKubeconfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse": { "type": "object", "properties": { "kubeconfig": { @@ -7441,7 +7656,7 @@ const docTemplate = `{ } } }, - "domain.GetProjectMemberCountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse": { "type": "object", "properties": { "projectLeaderCount": { @@ -7458,97 +7673,97 @@ const docTemplate = `{ } } }, - "domain.GetProjectMemberResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse": { "type": "object", "properties": { "projectMember": { - "$ref": "#/definitions/domain.ProjectMemberResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse" } } }, - "domain.GetProjectMembersResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse": { "type": "object", "properties": { "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, "projectMembers": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectMemberResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse" } } } }, - "domain.GetProjectNamespaceK8sResourcesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse": { "type": "object", "properties": { "k8sResources": { - "$ref": "#/definitions/domain.ProjectNamespaceK8sResources" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources" } } }, - "domain.GetProjectNamespaceResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse": { "type": "object", "properties": { "projectNamespace": { - "$ref": "#/definitions/domain.ProjectNamespaceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse" } } }, - "domain.GetProjectNamespacesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse": { "type": "object", "properties": { "projectNamespaces": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectNamespaceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse" } } } }, - "domain.GetProjectResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse": { "type": "object", "properties": { "project": { - "$ref": "#/definitions/domain.ProjectDetailResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse" } } }, - "domain.GetProjectRoleResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse": { "type": "object", "properties": { "projectRole": { - "$ref": "#/definitions/domain.ProjectRole" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole" } } }, - "domain.GetProjectRolesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse": { "type": "object", "properties": { "projectRoles": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectRole" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole" } } } }, - "domain.GetProjectsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse": { "type": "object", "properties": { "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, "projects": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectResponse" } } } }, - "domain.GetStackKubeConfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse": { "type": "object", "properties": { "kubeConfig": { @@ -7556,15 +7771,15 @@ const docTemplate = `{ } } }, - "domain.GetStackResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackResponse": { "type": "object", "properties": { "stack": { - "$ref": "#/definitions/domain.StackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse" } } }, - "domain.GetStackStatusResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse": { "type": "object", "properties": { "stackStatus": { @@ -7573,48 +7788,74 @@ const docTemplate = `{ "stepStatus": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackStepStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackStepStatus" } } } }, - "domain.GetStackTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse": { "type": "object", "properties": { "stackTemplate": { - "$ref": "#/definitions/domain.StackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse" } } }, - "domain.GetStackTemplatesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse": { "type": "object", "properties": { "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, "stackTemplates": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse" } } } }, - "domain.GetStacksResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse": { "type": "object", "properties": { "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, "stacks": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse" } } } }, - "domain.GetUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetUserResponse": { "type": "object", "properties": { "user": { @@ -7645,10 +7886,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -7657,7 +7898,7 @@ const docTemplate = `{ } } }, - "domain.ImportClusterRequest": { + "github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest": { "type": "object", "required": [ "name", @@ -7691,7 +7932,7 @@ const docTemplate = `{ } } }, - "domain.ImportClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ImportClusterResponse": { "type": "object", "properties": { "id": { @@ -7699,7 +7940,7 @@ const docTemplate = `{ } } }, - "domain.ListOrganizationBody": { + "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody": { "type": "object", "properties": { "createdAt": { @@ -7728,7 +7969,21 @@ const docTemplate = `{ } } }, - "domain.ListUserBody": { + "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ListUserBody": { "type": "object", "properties": { "accountId": { @@ -7756,17 +8011,17 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" } } }, - "domain.LoginRequest": { + "github_com_openinfradev_tks-api_pkg_domain.LoginRequest": { "type": "object", "required": [ "accountId", @@ -7785,7 +8040,7 @@ const docTemplate = `{ } } }, - "domain.LoginResponse": { + "github_com_openinfradev_tks-api_pkg_domain.LoginResponse": { "type": "object", "properties": { "user": { @@ -7801,13 +8056,13 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "passwordExpired": { "type": "boolean" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "token": { "type": "string" @@ -7816,7 +8071,7 @@ const docTemplate = `{ } } }, - "domain.LogoutResponse": { + "github_com_openinfradev_tks-api_pkg_domain.LogoutResponse": { "type": "object", "properties": { "ssoUrls": { @@ -7830,7 +8085,7 @@ const docTemplate = `{ } } }, - "domain.Organization": { + "github_com_openinfradev_tks-api_pkg_domain.Organization": { "type": "object", "properties": { "createdAt": { @@ -7839,6 +8094,9 @@ const docTemplate = `{ "creator": { "type": "string" }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "description": { "type": "string" }, @@ -7855,7 +8113,7 @@ const docTemplate = `{ "type": "string" }, "status": { - "$ref": "#/definitions/domain.OrganizationStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus" }, "statusDesc": { "type": "string" @@ -7865,7 +8123,7 @@ const docTemplate = `{ } } }, - "domain.OrganizationStatus": { + "github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus": { "type": "integer", "enum": [ 0, @@ -7888,13 +8146,13 @@ const docTemplate = `{ "OrganizationStatus_ERROR" ] }, - "domain.PaginationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.PaginationResponse": { "type": "object", "properties": { "filters": { "type": "array", "items": { - "$ref": "#/definitions/domain.FilterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.FilterResponse" } }, "pageNumber": { @@ -7917,7 +8175,80 @@ const docTemplate = `{ } } }, - "domain.PingTokenRequest": { + "github_com_openinfradev_tks-api_pkg_domain.Permission": { + "type": "object", + "properties": { + "ID": { + "type": "string" + }, + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, + "endpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" + } + }, + "id": { + "type": "integer" + }, + "is_allowed": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "parent": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "parent_id": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "role_id": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { + "type": "object", + "properties": { + "configuration": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "dashboard": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "notification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "project_management": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "security_policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "stack": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { "type": "object", "required": [ "organizationId", @@ -7932,7 +8263,7 @@ const docTemplate = `{ } } }, - "domain.PodCount": { + "github_com_openinfradev_tks-api_pkg_domain.PodCount": { "type": "object", "properties": { "day": { @@ -7943,7 +8274,7 @@ const docTemplate = `{ } } }, - "domain.ProjectDetailResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse": { "type": "object", "properties": { "createdAt": { @@ -7985,7 +8316,7 @@ const docTemplate = `{ } } }, - "domain.ProjectMemberRequest": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest": { "type": "object", "required": [ "projectRoleId", @@ -8000,7 +8331,7 @@ const docTemplate = `{ } } }, - "domain.ProjectMemberResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse": { "type": "object", "properties": { "createdAt": { @@ -8038,7 +8369,7 @@ const docTemplate = `{ } } }, - "domain.ProjectNamespaceK8sResources": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources": { "type": "object", "properties": { "cronjobs": { @@ -8073,7 +8404,7 @@ const docTemplate = `{ } } }, - "domain.ProjectNamespaceResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse": { "type": "object", "properties": { "appCount": { @@ -8105,7 +8436,7 @@ const docTemplate = `{ } } }, - "domain.ProjectResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectResponse": { "type": "object", "properties": { "appCount": { @@ -8143,7 +8474,7 @@ const docTemplate = `{ } } }, - "domain.ProjectRole": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectRole": { "type": "object", "properties": { "createdAt": { @@ -8167,7 +8498,7 @@ const docTemplate = `{ } } }, - "domain.RemoveProjectMemberRequest": { + "github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest": { "type": "object", "properties": { "projectMembers": { @@ -8183,18 +8514,18 @@ const docTemplate = `{ } } }, - "domain.ResourceQuota": { + "github_com_openinfradev_tks-api_pkg_domain.ResourceQuota": { "type": "object", "properties": { "quotas": { "type": "array", "items": { - "$ref": "#/definitions/domain.ResourceQuotaAttr" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ResourceQuotaAttr" } } } }, - "domain.ResourceQuotaAttr": { + "github_com_openinfradev_tks-api_pkg_domain.ResourceQuotaAttr": { "type": "object", "properties": { "quota": { @@ -8211,7 +8542,7 @@ const docTemplate = `{ } } }, - "domain.Role": { + "github_com_openinfradev_tks-api_pkg_domain.Role": { "type": "object", "properties": { "createdAt": { @@ -8220,6 +8551,9 @@ const docTemplate = `{ "creator": { "type": "string" }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "description": { "type": "string" }, @@ -8229,12 +8563,21 @@ const docTemplate = `{ "name": { "type": "string" }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "organizationId": { + "type": "string" + }, + "type": { + "type": "string" + }, "updatedAt": { "type": "string" } } }, - "domain.RollbackAppServeAppRequest": { + "github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest": { "type": "object", "properties": { "taskId": { @@ -8242,7 +8585,7 @@ const docTemplate = `{ } } }, - "domain.SimpleCloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse": { "type": "object", "properties": { "awsAccountId": { @@ -8271,7 +8614,7 @@ const docTemplate = `{ } } }, - "domain.SimpleClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse": { "type": "object", "properties": { "id": { @@ -8285,7 +8628,7 @@ const docTemplate = `{ } } }, - "domain.SimpleOrganizationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse": { "type": "object", "properties": { "description": { @@ -8299,7 +8642,7 @@ const docTemplate = `{ } } }, - "domain.SimpleRoleResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { "type": "object", "properties": { "description": { @@ -8313,7 +8656,7 @@ const docTemplate = `{ } } }, - "domain.SimpleStackTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { "cloudService": { @@ -8337,7 +8680,7 @@ const docTemplate = `{ "services": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackTemplateServiceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" } }, "template": { @@ -8345,7 +8688,7 @@ const docTemplate = `{ } } }, - "domain.SimpleUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse": { "type": "object", "properties": { "accountId": { @@ -8358,11 +8701,11 @@ const docTemplate = `{ "type": "string" }, "role": { - "$ref": "#/definitions/domain.SimpleRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" } } }, - "domain.StackConfResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackConfResponse": { "type": "object", "required": [ "tksInfraNode", @@ -8402,20 +8745,20 @@ const docTemplate = `{ } } }, - "domain.StackResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackResponse": { "type": "object", "properties": { "cloudAccount": { - "$ref": "#/definitions/domain.SimpleCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse" }, "conf": { - "$ref": "#/definitions/domain.StackConfResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackConfResponse" }, "createdAt": { "type": "string" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -8439,10 +8782,10 @@ const docTemplate = `{ "type": "boolean" }, "resource": { - "$ref": "#/definitions/domain.DashboardStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse" }, "stackTemplate": { - "$ref": "#/definitions/domain.SimpleStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse" }, "status": { "type": "string" @@ -8454,14 +8797,14 @@ const docTemplate = `{ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "userClusterEndpoint": { "type": "string" } } }, - "domain.StackStepStatus": { + "github_com_openinfradev_tks-api_pkg_domain.StackStepStatus": { "type": "object", "properties": { "maxStep": { @@ -8478,7 +8821,7 @@ const docTemplate = `{ } } }, - "domain.StackTemplate": { + "github_com_openinfradev_tks-api_pkg_domain.StackTemplate": { "type": "object", "properties": { "cloudService": { @@ -8488,7 +8831,7 @@ const docTemplate = `{ "type": "string" }, "creator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "creatorId": { "type": "string" @@ -8530,7 +8873,7 @@ const docTemplate = `{ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "updatorId": { "type": "string" @@ -8540,7 +8883,7 @@ const docTemplate = `{ } } }, - "domain.StackTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse": { "type": "object", "properties": { "cloudService": { @@ -8550,7 +8893,7 @@ const docTemplate = `{ "type": "string" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -8573,7 +8916,7 @@ const docTemplate = `{ "services": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackTemplateServiceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" } }, "template": { @@ -8586,14 +8929,14 @@ const docTemplate = `{ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "version": { "type": "string" } } }, - "domain.StackTemplateServiceApplicationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceApplicationResponse": { "type": "object", "properties": { "description": { @@ -8607,13 +8950,13 @@ const docTemplate = `{ } } }, - "domain.StackTemplateServiceResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse": { "type": "object", "properties": { "applications": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackTemplateServiceApplicationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceApplicationResponse" } }, "type": { @@ -8621,13 +8964,13 @@ const docTemplate = `{ } } }, - "domain.StageResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StageResponse": { "type": "object", "properties": { "actions": { "type": "array", "items": { - "$ref": "#/definitions/domain.ActionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ActionResponse" } }, "name": { @@ -8642,7 +8985,7 @@ const docTemplate = `{ } } }, - "domain.Unit": { + "github_com_openinfradev_tks-api_pkg_domain.Unit": { "type": "object", "properties": { "data": { @@ -8656,7 +8999,7 @@ const docTemplate = `{ } } }, - "domain.UpdateAlertRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest": { "type": "object", "properties": { "description": { @@ -8664,7 +9007,7 @@ const docTemplate = `{ } } }, - "domain.UpdateAppServeAppEndpointRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest": { "type": "object", "required": [ "taskId" @@ -8684,7 +9027,7 @@ const docTemplate = `{ } } }, - "domain.UpdateAppServeAppRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest": { "type": "object", "properties": { "abort": { @@ -8727,7 +9070,7 @@ const docTemplate = `{ } } }, - "domain.UpdateAppServeAppStatusRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest": { "type": "object", "required": [ "status", @@ -8745,7 +9088,7 @@ const docTemplate = `{ } } }, - "domain.UpdateCloudAccountRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateCloudAccountRequest": { "type": "object", "properties": { "description": { @@ -8753,7 +9096,7 @@ const docTemplate = `{ } } }, - "domain.UpdateMyProfileRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest": { "type": "object", "required": [ "password" @@ -8777,7 +9120,7 @@ const docTemplate = `{ } } }, - "domain.UpdateMyProfileResponse": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileResponse": { "type": "object", "properties": { "user": { @@ -8799,16 +9142,16 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } } }, - "domain.UpdateOrganizationRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest": { "type": "object", "required": [ "name" @@ -8832,7 +9175,7 @@ const docTemplate = `{ } } }, - "domain.UpdateOrganizationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse": { "type": "object", "properties": { "description": { @@ -8849,7 +9192,7 @@ const docTemplate = `{ } } }, - "domain.UpdatePasswordRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest": { "type": "object", "required": [ "newPassword", @@ -8864,7 +9207,18 @@ const docTemplate = `{ } } }, - "domain.UpdatePrimaryClusterRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { "type": "object", "properties": { "primaryClusterId": { @@ -8872,7 +9226,7 @@ const docTemplate = `{ } } }, - "domain.UpdateProjectMemberRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest": { "type": "object", "properties": { "projectRoleId": { @@ -8880,7 +9234,7 @@ const docTemplate = `{ } } }, - "domain.UpdateProjectMembersRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest": { "type": "object", "properties": { "projectMembers": { @@ -8899,7 +9253,7 @@ const docTemplate = `{ } } }, - "domain.UpdateProjectNamespaceRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest": { "type": "object", "properties": { "description": { @@ -8907,7 +9261,7 @@ const docTemplate = `{ } } }, - "domain.UpdateProjectRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest": { "type": "object", "required": [ "name" @@ -8924,7 +9278,7 @@ const docTemplate = `{ } } }, - "domain.UpdateStackRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { "type": "object", "properties": { "description": { @@ -8932,7 +9286,7 @@ const docTemplate = `{ } } }, - "domain.UpdateStackTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { "type": "object", "properties": { "description": { @@ -8940,7 +9294,7 @@ const docTemplate = `{ } } }, - "domain.UpdateUserRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest": { "type": "object", "properties": { "department": { @@ -8970,7 +9324,7 @@ const docTemplate = `{ } } }, - "domain.UpdateUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse": { "type": "object", "properties": { "user": { @@ -8998,10 +9352,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -9010,7 +9364,7 @@ const docTemplate = `{ } } }, - "domain.User": { + "github_com_openinfradev_tks-api_pkg_domain.User": { "type": "object", "properties": { "accountId": { @@ -9038,7 +9392,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "organizationId": { + "type": "string" }, "password": { "type": "string" @@ -9050,7 +9407,10 @@ const docTemplate = `{ "type": "string" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "roleId": { + "type": "string" }, "token": { "type": "string" @@ -9060,7 +9420,7 @@ const docTemplate = `{ } } }, - "domain.VerifyIdentityForLostIdRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ "email", @@ -9079,7 +9439,7 @@ const docTemplate = `{ } } }, - "domain.VerifyIdentityForLostIdResponse": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse": { "type": "object", "properties": { "validityPeriod": { @@ -9087,7 +9447,7 @@ const docTemplate = `{ } } }, - "domain.VerifyIdentityForLostPasswordRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest": { "type": "object", "required": [ "accountId", @@ -9110,7 +9470,7 @@ const docTemplate = `{ } } }, - "domain.VerifyIdentityForLostPasswordResponse": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse": { "type": "object", "properties": { "validityPeriod": { @@ -9118,7 +9478,122 @@ const docTemplate = `{ } } }, - "httpErrors.RestError": { + "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest": { + "type": "object", + "required": [ + "adminPassword", + "email", + "role" + ], + "properties": { + "adminPassword": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "role": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_httpErrors.RestError": { "type": "object", "properties": { "code": { @@ -9134,6 +9609,18 @@ const docTemplate = `{ "type": "string" } } + }, + "gorm.DeletedAt": { + "type": "object", + "properties": { + "time": { + "type": "string" + }, + "valid": { + "description": "Valid is true if Time is not NULL", + "type": "boolean" + } + } } }, "securityDefinitions": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index b2f2b027..ef1e95c6 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -16,6 +16,96 @@ "host": "tks-api-dev.taco-cat.xyz", "basePath": "/", "paths": { + "/api/1.0/admin/organizations/{organizationId}/users/{accountId}": { + "get": { + "description": "Get user detail by admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin" + ], + "summary": "Get user detail by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user by admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin" + ], + "summary": "Update user by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse" + } + } + } + } + }, "/api/1.0/app-groups": { "get": { "security": [ @@ -80,7 +170,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppGroupsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppGroupsResponse" } } } @@ -109,7 +199,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateAppGroupRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupRequest" } } ], @@ -117,7 +207,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateAppGroupResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupResponse" } } } @@ -188,7 +278,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppGroupResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse" } } } @@ -232,7 +322,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetApplicationsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetApplicationsResponse" } } } @@ -261,7 +351,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateApplicationRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateApplicationRequest" } } ], @@ -292,7 +382,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostIdRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest" } } ], @@ -300,13 +390,13 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -332,7 +422,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.FindIdRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindIdRequest" } } ], @@ -340,13 +430,13 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.FindIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindIdResponse" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -372,7 +462,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest" } } ], @@ -380,13 +470,13 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.VerifyIdentityForLostPasswordResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse" } }, "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -412,7 +502,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.FindPasswordRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindPasswordRequest" } } ], @@ -423,7 +513,7 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -449,7 +539,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.LoginRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.LoginRequest" } } ], @@ -457,7 +547,7 @@ "200": { "description": "user detail", "schema": { - "$ref": "#/definitions/domain.LoginResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.LoginResponse" } } } @@ -485,7 +575,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.LogoutResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.LogoutResponse" } } } @@ -511,7 +601,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.PingTokenRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest" } } ], @@ -586,7 +676,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetClustersResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse" } } } @@ -615,7 +705,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateClusterRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateClusterRequest" } } ], @@ -623,7 +713,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse" } } } @@ -654,7 +744,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.ImportClusterRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest" } } ], @@ -662,7 +752,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.ImportClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportClusterResponse" } } } @@ -699,7 +789,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.Cluster" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" } } } @@ -734,7 +824,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.Cluster" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" } } } @@ -762,7 +852,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetBootstrapKubeconfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetBootstrapKubeconfigResponse" } } } @@ -788,7 +878,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateBootstrapKubeconfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateBootstrapKubeconfigResponse" } } } @@ -859,7 +949,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetClusterNodesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterNodesResponse" } } } @@ -896,7 +986,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.ClusterSiteValuesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterSiteValuesResponse" } } } @@ -962,7 +1052,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/domain.ListOrganizationBody" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody" } } } @@ -992,7 +1082,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateOrganizationRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest" } } ], @@ -1037,7 +1127,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetOrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse" } } } @@ -1073,7 +1163,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateOrganizationRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest" } } ], @@ -1081,7 +1171,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.UpdateOrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse" } } } @@ -1116,7 +1206,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" } } } @@ -1187,7 +1277,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAlertsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse" } } } @@ -1231,7 +1321,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAlertResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse" } } } @@ -1267,7 +1357,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateAlertRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest" } } ], @@ -1419,7 +1509,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAuditsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" } } } @@ -1448,7 +1538,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateAuditRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" } } ], @@ -1456,7 +1546,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateAuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" } } } @@ -1493,7 +1583,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" } } } @@ -1596,7 +1686,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetCloudAccountsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" } } } @@ -1632,7 +1722,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateCloudAccountRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" } } ], @@ -1640,7 +1730,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" } } } @@ -1684,7 +1774,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckCloudAccountAwsAccountIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" } } } @@ -1728,7 +1818,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckCloudAccountNameResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountNameResponse" } } } @@ -1772,7 +1862,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResponse" } } } @@ -1808,7 +1898,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateCloudAccountRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateCloudAccountRequest" } } ], @@ -1849,7 +1939,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.DeleteCloudAccountRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteCloudAccountRequest" } }, { @@ -1946,7 +2036,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetCloudAccountResourceQuotaResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResourceQuotaResponse" } } } @@ -2003,7 +2093,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetDashboardChartsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse" } } } @@ -2061,7 +2151,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetDashboardChartResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse" } } } @@ -2098,7 +2188,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetDashboardResourcesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse" } } } @@ -2135,7 +2225,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetDashboardStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse" } } } @@ -2172,7 +2262,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetMyProfileResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse" } } } @@ -2208,7 +2298,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateMyProfileRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest" } } ], @@ -2216,7 +2306,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.UpdateMyProfileResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileResponse" } } } @@ -2291,7 +2381,7 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/httpErrors.RestError" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" } } } @@ -2329,7 +2419,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdatePasswordRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest" } } ], @@ -2372,7 +2462,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdatePrimaryClusterRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest" } } ], @@ -2420,7 +2510,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse" } } } @@ -2456,7 +2546,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateProjectRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest" } } ], @@ -2464,7 +2554,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse" } } } @@ -2514,7 +2604,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } @@ -2557,7 +2647,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectRolesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse" } } } @@ -2601,7 +2691,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse" } } } @@ -2645,7 +2735,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse" } } } @@ -2688,7 +2778,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateProjectRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest" } } ], @@ -2696,7 +2786,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -2782,7 +2872,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" } } } @@ -2826,7 +2916,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateAppServeAppRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest" } } ], @@ -2987,7 +3077,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppServeAppResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse" } } } @@ -3037,7 +3127,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest" } } ], @@ -3146,7 +3236,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppEndpointRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest" } } ], @@ -3249,7 +3339,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" } } } @@ -3301,7 +3391,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.RollbackAppServeAppRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest" } } ], @@ -3361,7 +3451,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateAppServeAppStatusRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest" } } ], @@ -3449,7 +3539,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" } } } @@ -3508,7 +3598,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetAppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" } } } @@ -3552,7 +3642,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectKubeconfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse" } } } @@ -3602,7 +3692,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectMembersResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse" } } } @@ -3645,7 +3735,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateProjectMembersRoleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest" } } ], @@ -3653,7 +3743,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -3696,7 +3786,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.AddProjectMemberRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest" } } ], @@ -3704,7 +3794,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -3747,7 +3837,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.RemoveProjectMemberRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest" } } ], @@ -3755,7 +3845,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -3799,7 +3889,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectMemberCountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse" } } } @@ -3850,7 +3940,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectMemberResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse" } } } @@ -3899,7 +3989,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -3951,7 +4041,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateProjectMemberRoleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest" } } ], @@ -3959,7 +4049,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -4003,7 +4093,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectNamespacesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse" } } } @@ -4046,7 +4136,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateProjectNamespaceRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest" } } ], @@ -4054,7 +4144,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -4112,7 +4202,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectNamespaceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse" } } } @@ -4169,7 +4259,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateProjectNamespaceRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest" } } ], @@ -4177,7 +4267,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -4233,7 +4323,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } @@ -4291,7 +4381,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } @@ -4349,7 +4439,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetProjectNamespaceK8sResourcesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse" } } } @@ -4416,7 +4506,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" } } } @@ -4452,7 +4542,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateStackRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" } } ], @@ -4460,7 +4550,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" } } } @@ -4552,7 +4642,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" } } } @@ -4595,7 +4685,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateStackRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest" } } ], @@ -4763,7 +4853,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackKubeConfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse" } } } @@ -4807,7 +4897,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" } } } @@ -4880,7 +4970,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/domain.ListUserBody" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListUserBody" } } } @@ -4917,7 +5007,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateUserRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest" } } ], @@ -4925,7 +5015,7 @@ "200": { "description": "create user response", "schema": { - "$ref": "#/definitions/domain.CreateUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse" } } } @@ -4966,7 +5056,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } @@ -5007,7 +5097,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } @@ -5051,7 +5141,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUserResponse" } } } @@ -5094,7 +5184,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateUserRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest" } } ], @@ -5102,7 +5192,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.UpdateUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse" } } } @@ -5144,7 +5234,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" } } } @@ -5249,7 +5339,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" } } } @@ -5278,7 +5368,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.CreateStackTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" } } ], @@ -5286,7 +5376,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.CreateStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" } } } @@ -5323,7 +5413,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" } } } @@ -5352,7 +5442,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/domain.UpdateStackTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" } } ], @@ -5395,6 +5485,117 @@ } } }, + "/organizations/{organizationId}/roles": { + "get": { + "description": "List Tks Roles", + "produces": [ + "application/json" + ], + "tags": [ + "Role" + ], + "summary": "List Tks Roles", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" + } + } + } + } + }, + "/permissions/templates": { + "get": { + "description": "Get Permission Templates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Get Permission Templates", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + } + } + } + } + }, + "/roles/{roleId}/permissions": { + "get": { + "description": "Get Permissions By Role ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Get Permissions By Role ID", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + } + } + } + }, + "put": { + "description": "Update Permissions By Role ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Update Permissions By Role ID", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Update Permissions By Role ID Request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/system-api/organizations/{organizationId}/alerts": { "post": { "security": [ @@ -5431,7 +5632,7 @@ } }, "definitions": { - "domain.ActionResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { "body": { @@ -5456,18 +5657,18 @@ } } }, - "domain.AddProjectMemberRequest": { + "github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest": { "type": "object", "properties": { "projectMembers": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectMemberRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest" } } } }, - "domain.AlertActionResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse": { "type": "object", "properties": { "alertId": { @@ -5486,27 +5687,27 @@ "type": "string" }, "taker": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "updatedAt": { "type": "string" } } }, - "domain.AlertResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AlertResponse": { "type": "object", "properties": { "alertActions": { "type": "array", "items": { - "$ref": "#/definitions/domain.AlertActionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse" } }, "closedAt": { "type": "string" }, "cluster": { - "$ref": "#/definitions/domain.SimpleClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" }, "code": { "type": "string" @@ -5530,7 +5731,7 @@ "type": "string" }, "lastTaker": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "message": { "type": "string" @@ -5564,11 +5765,11 @@ } } }, - "domain.AppGroupResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { "appGroupType": { - "$ref": "#/definitions/domain.AppGroupType" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupType" }, "clusterId": { "type": "string" @@ -5577,7 +5778,7 @@ "type": "string" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -5589,7 +5790,7 @@ "type": "string" }, "status": { - "$ref": "#/definitions/domain.AppGroupStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupStatus" }, "statusDesc": { "type": "string" @@ -5598,14 +5799,14 @@ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "workflowId": { "type": "string" } } }, - "domain.AppGroupStatus": { + "github_com_openinfradev_tks-api_pkg_domain.AppGroupStatus": { "type": "integer", "enum": [ 0, @@ -5626,7 +5827,7 @@ "AppGroupStatus_DELETE_ERROR" ] }, - "domain.AppGroupType": { + "github_com_openinfradev_tks-api_pkg_domain.AppGroupType": { "type": "integer", "enum": [ 0, @@ -5639,13 +5840,13 @@ "AppGroupType_SERVICE_MESH" ] }, - "domain.AppServeApp": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeApp": { "type": "object", "properties": { "appServeAppTasks": { "type": "array", "items": { - "$ref": "#/definitions/domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" } }, "appType": { @@ -5710,7 +5911,7 @@ } } }, - "domain.AppServeAppTask": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask": { "type": "object", "properties": { "appConfig": { @@ -5810,14 +6011,14 @@ } } }, - "domain.ApplicationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse": { "type": "object", "properties": { "appGroupId": { "type": "string" }, "applicationType": { - "$ref": "#/definitions/domain.ApplicationType" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ApplicationType" }, "createdAt": { "type": "string" @@ -5836,7 +6037,7 @@ } } }, - "domain.ApplicationType": { + "github_com_openinfradev_tks-api_pkg_domain.ApplicationType": { "type": "integer", "enum": [ 0, @@ -5865,7 +6066,7 @@ "ApplicationType_KUBERNETES_DASHBOARD" ] }, - "domain.AuditResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AuditResponse": { "type": "object", "properties": { "clientIP": { @@ -5887,7 +6088,7 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.SimpleOrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" }, "organizationId": { "type": "string" @@ -5896,14 +6097,14 @@ "type": "string" }, "user": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "userId": { "type": "string" } } }, - "domain.Axis": { + "github_com_openinfradev_tks-api_pkg_domain.Axis": { "type": "object", "properties": { "data": { @@ -5914,7 +6115,7 @@ } } }, - "domain.BootstrapKubeconfig": { + "github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig": { "type": "object", "properties": { "expiration": { @@ -5922,30 +6123,30 @@ } } }, - "domain.ChartData": { + "github_com_openinfradev_tks-api_pkg_domain.ChartData": { "type": "object", "properties": { "podCounts": { "type": "array", "items": { - "$ref": "#/definitions/domain.PodCount" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PodCount" } }, "series": { "type": "array", "items": { - "$ref": "#/definitions/domain.Unit" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Unit" } }, "xAxis": { - "$ref": "#/definitions/domain.Axis" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis" }, "yAxis": { - "$ref": "#/definitions/domain.Axis" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis" } } }, - "domain.CheckCloudAccountAwsAccountIdResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse": { "type": "object", "properties": { "existed": { @@ -5953,7 +6154,7 @@ } } }, - "domain.CheckCloudAccountNameResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountNameResponse": { "type": "object", "properties": { "existed": { @@ -5961,7 +6162,7 @@ } } }, - "domain.CheckExistedResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse": { "type": "object", "properties": { "existed": { @@ -5969,7 +6170,7 @@ } } }, - "domain.CloudAccount": { + "github_com_openinfradev_tks-api_pkg_domain.CloudAccount": { "type": "object", "properties": { "accessKeyId": { @@ -5991,7 +6192,7 @@ "type": "boolean" }, "creator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "creatorId": { "type": "string" @@ -6018,7 +6219,7 @@ "type": "string" }, "status": { - "$ref": "#/definitions/domain.CloudAccountStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus" }, "statusDesc": { "type": "string" @@ -6027,14 +6228,14 @@ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "updatorId": { "type": "string" } } }, - "domain.CloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { "awsAccountId": { @@ -6053,7 +6254,7 @@ "type": "boolean" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -6077,11 +6278,11 @@ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" } } }, - "domain.CloudAccountStatus": { + "github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus": { "type": "integer", "enum": [ 0, @@ -6102,7 +6303,7 @@ "CloudAccountStatus_DELETE_ERROR" ] }, - "domain.Cluster": { + "github_com_openinfradev_tks-api_pkg_domain.Cluster": { "type": "object", "properties": { "byoClusterEndpointHost": { @@ -6112,7 +6313,7 @@ "type": "integer" }, "cloudAccount": { - "$ref": "#/definitions/domain.CloudAccount" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount" }, "cloudAccountId": { "type": "string" @@ -6124,13 +6325,13 @@ "type": "integer" }, "conf": { - "$ref": "#/definitions/domain.ClusterConf" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf" }, "createdAt": { "type": "string" }, "creator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "creatorId": { "type": "string" @@ -6160,13 +6361,13 @@ "type": "string" }, "stackTemplate": { - "$ref": "#/definitions/domain.StackTemplate" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate" }, "stackTemplateId": { "type": "string" }, "status": { - "$ref": "#/definitions/domain.ClusterStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus" }, "statusDesc": { "type": "string" @@ -6175,14 +6376,14 @@ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "updatorId": { "type": "string" } } }, - "domain.ClusterConf": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterConf": { "type": "object", "properties": { "tksCpNode": { @@ -6214,7 +6415,7 @@ } } }, - "domain.ClusterConfResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse": { "type": "object", "properties": { "tksCpNode": { @@ -6246,7 +6447,7 @@ } } }, - "domain.ClusterHost": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterHost": { "type": "object", "properties": { "name": { @@ -6257,7 +6458,7 @@ } } }, - "domain.ClusterNode": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterNode": { "type": "object", "properties": { "command": { @@ -6266,7 +6467,7 @@ "hosts": { "type": "array", "items": { - "$ref": "#/definitions/domain.ClusterHost" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterHost" } }, "registered": { @@ -6289,7 +6490,7 @@ } } }, - "domain.ClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterResponse": { "type": "object", "properties": { "byoClusterEndpointHost": { @@ -6299,7 +6500,7 @@ "type": "integer" }, "cloudAccount": { - "$ref": "#/definitions/domain.SimpleCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse" }, "cloudService": { "type": "string" @@ -6308,13 +6509,13 @@ "type": "string" }, "conf": { - "$ref": "#/definitions/domain.ClusterConfResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse" }, "createdAt": { "type": "string" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -6332,7 +6533,7 @@ "type": "string" }, "stackTemplate": { - "$ref": "#/definitions/domain.SimpleStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse" }, "status": { "type": "string" @@ -6344,11 +6545,11 @@ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" } } }, - "domain.ClusterSiteValuesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterSiteValuesResponse": { "type": "object", "properties": { "byoClusterEndpointHost": { @@ -6395,7 +6596,7 @@ } } }, - "domain.ClusterStatus": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterStatus": { "type": "integer", "enum": [ 0, @@ -6422,7 +6623,7 @@ "ClusterStatus_BOOTSTRAP_ERROR" ] }, - "domain.CommonProjectResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { "result": { @@ -6430,7 +6631,7 @@ } } }, - "domain.CreateAppGroupRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupRequest": { "type": "object", "required": [ "clusterId", @@ -6455,7 +6656,7 @@ } } }, - "domain.CreateAppGroupResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupResponse": { "type": "object", "properties": { "id": { @@ -6463,7 +6664,7 @@ } } }, - "domain.CreateAppServeAppRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest": { "type": "object", "required": [ "name", @@ -6541,7 +6742,7 @@ } } }, - "domain.CreateApplicationRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateApplicationRequest": { "type": "object", "properties": { "applicationType": { @@ -6555,21 +6756,21 @@ } } }, - "domain.CreateAuditRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest": { "type": "object" }, - "domain.CreateAuditResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse": { "type": "object" }, - "domain.CreateBootstrapKubeconfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateBootstrapKubeconfigResponse": { "type": "object", "properties": { "kubeconfig": { - "$ref": "#/definitions/domain.BootstrapKubeconfig" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig" } } }, - "domain.CreateCloudAccountRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest": { "type": "object", "required": [ "accessKeyId", @@ -6613,7 +6814,7 @@ } } }, - "domain.CreateCloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse": { "type": "object", "properties": { "id": { @@ -6621,7 +6822,7 @@ } } }, - "domain.CreateClusterRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateClusterRequest": { "type": "object", "required": [ "cloudService", @@ -6693,7 +6894,7 @@ } } }, - "domain.CreateClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse": { "type": "object", "properties": { "id": { @@ -6701,7 +6902,7 @@ } } }, - "domain.CreateOrganizationRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { "type": "object", "required": [ "Email", @@ -6724,7 +6925,7 @@ } } }, - "domain.CreateProjectNamespaceRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest": { "type": "object", "properties": { "description": { @@ -6738,7 +6939,7 @@ } } }, - "domain.CreateProjectRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest": { "type": "object", "required": [ "name" @@ -6755,7 +6956,7 @@ } } }, - "domain.CreateProjectResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse": { "type": "object", "properties": { "projectId": { @@ -6763,7 +6964,7 @@ } } }, - "domain.CreateStackRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest": { "type": "object", "required": [ "cloudService", @@ -6825,7 +7026,7 @@ } } }, - "domain.CreateStackResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse": { "type": "object", "properties": { "id": { @@ -6833,7 +7034,7 @@ } } }, - "domain.CreateStackTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest": { "type": "object", "required": [ "name", @@ -6874,7 +7075,7 @@ } } }, - "domain.CreateStackTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse": { "type": "object", "properties": { "id": { @@ -6882,7 +7083,7 @@ } } }, - "domain.CreateUserRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest": { "type": "object", "required": [ "accountId", @@ -6922,7 +7123,7 @@ } } }, - "domain.CreateUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse": { "type": "object", "properties": { "user": { @@ -6947,20 +7148,20 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } } }, - "domain.DashboardChartResponse": { + "github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse": { "type": "object", "properties": { "chartData": { - "$ref": "#/definitions/domain.ChartData" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ChartData" }, "chartType": { "type": "string" @@ -6991,7 +7192,7 @@ } } }, - "domain.DashboardResource": { + "github_com_openinfradev_tks-api_pkg_domain.DashboardResource": { "type": "object", "properties": { "cpu": { @@ -7008,7 +7209,7 @@ } } }, - "domain.DashboardStackResponse": { + "github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse": { "type": "object", "properties": { "cpu": { @@ -7043,7 +7244,7 @@ } } }, - "domain.DeleteCloudAccountRequest": { + "github_com_openinfradev_tks-api_pkg_domain.DeleteCloudAccountRequest": { "type": "object", "required": [ "accessKeyId", @@ -7066,7 +7267,21 @@ } } }, - "domain.FilterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "group": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { "column": { @@ -7086,7 +7301,7 @@ } } }, - "domain.FindIdRequest": { + "github_com_openinfradev_tks-api_pkg_domain.FindIdRequest": { "type": "object", "required": [ "code", @@ -7109,7 +7324,7 @@ } } }, - "domain.FindIdResponse": { + "github_com_openinfradev_tks-api_pkg_domain.FindIdResponse": { "type": "object", "properties": { "accountId": { @@ -7117,7 +7332,7 @@ } } }, - "domain.FindPasswordRequest": { + "github_com_openinfradev_tks-api_pkg_domain.FindPasswordRequest": { "type": "object", "required": [ "accountId", @@ -7144,219 +7359,219 @@ } } }, - "domain.GetAlertResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse": { "type": "object", "properties": { "alert": { - "$ref": "#/definitions/domain.AlertResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse" } } }, - "domain.GetAlertsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse": { "type": "object", "properties": { "alerts": { "type": "array", "items": { - "$ref": "#/definitions/domain.AlertResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetAppGroupResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse": { "type": "object", "properties": { "appGroup": { - "$ref": "#/definitions/domain.AppGroupResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse" } } }, - "domain.GetAppGroupsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAppGroupsResponse": { "type": "object", "properties": { "appGroups": { "type": "array", "items": { - "$ref": "#/definitions/domain.AppGroupResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetAppServeAppResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse": { "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" }, "stages": { "type": "array", "items": { - "$ref": "#/definitions/domain.StageResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse" } } } }, - "domain.GetAppServeAppTaskResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse": { "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" }, "appServeAppTask": { - "$ref": "#/definitions/domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" }, "stages": { "type": "array", "items": { - "$ref": "#/definitions/domain.StageResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse" } } } }, - "domain.GetApplicationsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetApplicationsResponse": { "type": "object", "properties": { "applications": { "type": "array", "items": { - "$ref": "#/definitions/domain.ApplicationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse" } } } }, - "domain.GetAuditResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse": { "type": "object", "properties": { "audit": { - "$ref": "#/definitions/domain.AuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AuditResponse" } } }, - "domain.GetAuditsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse": { "type": "object", "properties": { "audits": { "type": "array", "items": { - "$ref": "#/definitions/domain.AuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AuditResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetBootstrapKubeconfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetBootstrapKubeconfigResponse": { "type": "object", "properties": { "kubeconfig": { - "$ref": "#/definitions/domain.BootstrapKubeconfig" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig" } } }, - "domain.GetCloudAccountResourceQuotaResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResourceQuotaResponse": { "type": "object", "properties": { "available": { "type": "boolean" }, "resourceQuota": { - "$ref": "#/definitions/domain.ResourceQuota" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ResourceQuota" } } }, - "domain.GetCloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResponse": { "type": "object", "properties": { "cloudAccount": { - "$ref": "#/definitions/domain.CloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse" } } }, - "domain.GetCloudAccountsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse": { "type": "object", "properties": { "cloudAccounts": { "type": "array", "items": { - "$ref": "#/definitions/domain.CloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetClusterNodesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetClusterNodesResponse": { "type": "object", "properties": { "nodes": { "type": "array", "items": { - "$ref": "#/definitions/domain.ClusterNode" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode" } } } }, - "domain.GetClustersResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse": { "type": "object", "properties": { "clusters": { "type": "array", "items": { - "$ref": "#/definitions/domain.ClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse" } }, "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, - "domain.GetDashboardChartResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse": { "type": "object", "properties": { "chart": { - "$ref": "#/definitions/domain.DashboardChartResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse" } } }, - "domain.GetDashboardChartsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse": { "type": "object", "properties": { "charts": { "type": "array", "items": { - "$ref": "#/definitions/domain.DashboardChartResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse" } } } }, - "domain.GetDashboardResourcesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { "resources": { - "$ref": "#/definitions/domain.DashboardResource" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardResource" } } }, - "domain.GetDashboardStacksResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse": { "type": "object", "properties": { "stacks": { "type": "array", "items": { - "$ref": "#/definitions/domain.DashboardStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse" } } } }, - "domain.GetMyProfileResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse": { "type": "object", "properties": { "user": { @@ -7378,16 +7593,16 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } } }, - "domain.GetOrganizationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse": { "type": "object", "properties": { "organization": { @@ -7427,7 +7642,7 @@ } } }, - "domain.GetProjectKubeconfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse": { "type": "object", "properties": { "kubeconfig": { @@ -7435,7 +7650,7 @@ } } }, - "domain.GetProjectMemberCountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse": { "type": "object", "properties": { "projectLeaderCount": { @@ -7452,97 +7667,97 @@ } } }, - "domain.GetProjectMemberResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse": { "type": "object", "properties": { "projectMember": { - "$ref": "#/definitions/domain.ProjectMemberResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse" } } }, - "domain.GetProjectMembersResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse": { "type": "object", "properties": { "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, "projectMembers": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectMemberResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse" } } } }, - "domain.GetProjectNamespaceK8sResourcesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse": { "type": "object", "properties": { "k8sResources": { - "$ref": "#/definitions/domain.ProjectNamespaceK8sResources" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources" } } }, - "domain.GetProjectNamespaceResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse": { "type": "object", "properties": { "projectNamespace": { - "$ref": "#/definitions/domain.ProjectNamespaceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse" } } }, - "domain.GetProjectNamespacesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse": { "type": "object", "properties": { "projectNamespaces": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectNamespaceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse" } } } }, - "domain.GetProjectResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse": { "type": "object", "properties": { "project": { - "$ref": "#/definitions/domain.ProjectDetailResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse" } } }, - "domain.GetProjectRoleResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse": { "type": "object", "properties": { "projectRole": { - "$ref": "#/definitions/domain.ProjectRole" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole" } } }, - "domain.GetProjectRolesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse": { "type": "object", "properties": { "projectRoles": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectRole" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole" } } } }, - "domain.GetProjectsResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse": { "type": "object", "properties": { "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, "projects": { "type": "array", "items": { - "$ref": "#/definitions/domain.ProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectResponse" } } } }, - "domain.GetStackKubeConfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse": { "type": "object", "properties": { "kubeConfig": { @@ -7550,15 +7765,15 @@ } } }, - "domain.GetStackResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackResponse": { "type": "object", "properties": { "stack": { - "$ref": "#/definitions/domain.StackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse" } } }, - "domain.GetStackStatusResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse": { "type": "object", "properties": { "stackStatus": { @@ -7567,48 +7782,74 @@ "stepStatus": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackStepStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackStepStatus" } } } }, - "domain.GetStackTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse": { "type": "object", "properties": { "stackTemplate": { - "$ref": "#/definitions/domain.StackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse" } } }, - "domain.GetStackTemplatesResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse": { "type": "object", "properties": { "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, "stackTemplates": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse" } } } }, - "domain.GetStacksResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse": { "type": "object", "properties": { "pagination": { - "$ref": "#/definitions/domain.PaginationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, "stacks": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse" } } } }, - "domain.GetUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetUserResponse": { "type": "object", "properties": { "user": { @@ -7639,10 +7880,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -7651,7 +7892,7 @@ } } }, - "domain.ImportClusterRequest": { + "github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest": { "type": "object", "required": [ "name", @@ -7685,7 +7926,7 @@ } } }, - "domain.ImportClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ImportClusterResponse": { "type": "object", "properties": { "id": { @@ -7693,7 +7934,7 @@ } } }, - "domain.ListOrganizationBody": { + "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody": { "type": "object", "properties": { "createdAt": { @@ -7722,7 +7963,21 @@ } } }, - "domain.ListUserBody": { + "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ListUserBody": { "type": "object", "properties": { "accountId": { @@ -7750,17 +8005,17 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" } } }, - "domain.LoginRequest": { + "github_com_openinfradev_tks-api_pkg_domain.LoginRequest": { "type": "object", "required": [ "accountId", @@ -7779,7 +8034,7 @@ } } }, - "domain.LoginResponse": { + "github_com_openinfradev_tks-api_pkg_domain.LoginResponse": { "type": "object", "properties": { "user": { @@ -7795,13 +8050,13 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "passwordExpired": { "type": "boolean" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "token": { "type": "string" @@ -7810,7 +8065,7 @@ } } }, - "domain.LogoutResponse": { + "github_com_openinfradev_tks-api_pkg_domain.LogoutResponse": { "type": "object", "properties": { "ssoUrls": { @@ -7824,7 +8079,7 @@ } } }, - "domain.Organization": { + "github_com_openinfradev_tks-api_pkg_domain.Organization": { "type": "object", "properties": { "createdAt": { @@ -7833,6 +8088,9 @@ "creator": { "type": "string" }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "description": { "type": "string" }, @@ -7849,7 +8107,7 @@ "type": "string" }, "status": { - "$ref": "#/definitions/domain.OrganizationStatus" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus" }, "statusDesc": { "type": "string" @@ -7859,7 +8117,7 @@ } } }, - "domain.OrganizationStatus": { + "github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus": { "type": "integer", "enum": [ 0, @@ -7882,13 +8140,13 @@ "OrganizationStatus_ERROR" ] }, - "domain.PaginationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.PaginationResponse": { "type": "object", "properties": { "filters": { "type": "array", "items": { - "$ref": "#/definitions/domain.FilterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.FilterResponse" } }, "pageNumber": { @@ -7911,7 +8169,80 @@ } } }, - "domain.PingTokenRequest": { + "github_com_openinfradev_tks-api_pkg_domain.Permission": { + "type": "object", + "properties": { + "ID": { + "type": "string" + }, + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, + "endpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" + } + }, + "id": { + "type": "integer" + }, + "is_allowed": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "parent": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "parent_id": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "role_id": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { + "type": "object", + "properties": { + "configuration": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "dashboard": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "notification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "project_management": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "security_policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "stack": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { "type": "object", "required": [ "organizationId", @@ -7926,7 +8257,7 @@ } } }, - "domain.PodCount": { + "github_com_openinfradev_tks-api_pkg_domain.PodCount": { "type": "object", "properties": { "day": { @@ -7937,7 +8268,7 @@ } } }, - "domain.ProjectDetailResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse": { "type": "object", "properties": { "createdAt": { @@ -7979,7 +8310,7 @@ } } }, - "domain.ProjectMemberRequest": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest": { "type": "object", "required": [ "projectRoleId", @@ -7994,7 +8325,7 @@ } } }, - "domain.ProjectMemberResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse": { "type": "object", "properties": { "createdAt": { @@ -8032,7 +8363,7 @@ } } }, - "domain.ProjectNamespaceK8sResources": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources": { "type": "object", "properties": { "cronjobs": { @@ -8067,7 +8398,7 @@ } } }, - "domain.ProjectNamespaceResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse": { "type": "object", "properties": { "appCount": { @@ -8099,7 +8430,7 @@ } } }, - "domain.ProjectResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectResponse": { "type": "object", "properties": { "appCount": { @@ -8137,7 +8468,7 @@ } } }, - "domain.ProjectRole": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectRole": { "type": "object", "properties": { "createdAt": { @@ -8161,7 +8492,7 @@ } } }, - "domain.RemoveProjectMemberRequest": { + "github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest": { "type": "object", "properties": { "projectMembers": { @@ -8177,18 +8508,18 @@ } } }, - "domain.ResourceQuota": { + "github_com_openinfradev_tks-api_pkg_domain.ResourceQuota": { "type": "object", "properties": { "quotas": { "type": "array", "items": { - "$ref": "#/definitions/domain.ResourceQuotaAttr" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ResourceQuotaAttr" } } } }, - "domain.ResourceQuotaAttr": { + "github_com_openinfradev_tks-api_pkg_domain.ResourceQuotaAttr": { "type": "object", "properties": { "quota": { @@ -8205,7 +8536,7 @@ } } }, - "domain.Role": { + "github_com_openinfradev_tks-api_pkg_domain.Role": { "type": "object", "properties": { "createdAt": { @@ -8214,6 +8545,9 @@ "creator": { "type": "string" }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "description": { "type": "string" }, @@ -8223,12 +8557,21 @@ "name": { "type": "string" }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "organizationId": { + "type": "string" + }, + "type": { + "type": "string" + }, "updatedAt": { "type": "string" } } }, - "domain.RollbackAppServeAppRequest": { + "github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest": { "type": "object", "properties": { "taskId": { @@ -8236,7 +8579,7 @@ } } }, - "domain.SimpleCloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse": { "type": "object", "properties": { "awsAccountId": { @@ -8265,7 +8608,7 @@ } } }, - "domain.SimpleClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse": { "type": "object", "properties": { "id": { @@ -8279,7 +8622,7 @@ } } }, - "domain.SimpleOrganizationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse": { "type": "object", "properties": { "description": { @@ -8293,7 +8636,7 @@ } } }, - "domain.SimpleRoleResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { "type": "object", "properties": { "description": { @@ -8307,7 +8650,7 @@ } } }, - "domain.SimpleStackTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { "cloudService": { @@ -8331,7 +8674,7 @@ "services": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackTemplateServiceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" } }, "template": { @@ -8339,7 +8682,7 @@ } } }, - "domain.SimpleUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse": { "type": "object", "properties": { "accountId": { @@ -8352,11 +8695,11 @@ "type": "string" }, "role": { - "$ref": "#/definitions/domain.SimpleRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" } } }, - "domain.StackConfResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackConfResponse": { "type": "object", "required": [ "tksInfraNode", @@ -8396,20 +8739,20 @@ } } }, - "domain.StackResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackResponse": { "type": "object", "properties": { "cloudAccount": { - "$ref": "#/definitions/domain.SimpleCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse" }, "conf": { - "$ref": "#/definitions/domain.StackConfResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackConfResponse" }, "createdAt": { "type": "string" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -8433,10 +8776,10 @@ "type": "boolean" }, "resource": { - "$ref": "#/definitions/domain.DashboardStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse" }, "stackTemplate": { - "$ref": "#/definitions/domain.SimpleStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse" }, "status": { "type": "string" @@ -8448,14 +8791,14 @@ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "userClusterEndpoint": { "type": "string" } } }, - "domain.StackStepStatus": { + "github_com_openinfradev_tks-api_pkg_domain.StackStepStatus": { "type": "object", "properties": { "maxStep": { @@ -8472,7 +8815,7 @@ } } }, - "domain.StackTemplate": { + "github_com_openinfradev_tks-api_pkg_domain.StackTemplate": { "type": "object", "properties": { "cloudService": { @@ -8482,7 +8825,7 @@ "type": "string" }, "creator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "creatorId": { "type": "string" @@ -8524,7 +8867,7 @@ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.User" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" }, "updatorId": { "type": "string" @@ -8534,7 +8877,7 @@ } } }, - "domain.StackTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse": { "type": "object", "properties": { "cloudService": { @@ -8544,7 +8887,7 @@ "type": "string" }, "creator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -8567,7 +8910,7 @@ "services": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackTemplateServiceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" } }, "template": { @@ -8580,14 +8923,14 @@ "type": "string" }, "updator": { - "$ref": "#/definitions/domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "version": { "type": "string" } } }, - "domain.StackTemplateServiceApplicationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceApplicationResponse": { "type": "object", "properties": { "description": { @@ -8601,13 +8944,13 @@ } } }, - "domain.StackTemplateServiceResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse": { "type": "object", "properties": { "applications": { "type": "array", "items": { - "$ref": "#/definitions/domain.StackTemplateServiceApplicationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceApplicationResponse" } }, "type": { @@ -8615,13 +8958,13 @@ } } }, - "domain.StageResponse": { + "github_com_openinfradev_tks-api_pkg_domain.StageResponse": { "type": "object", "properties": { "actions": { "type": "array", "items": { - "$ref": "#/definitions/domain.ActionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ActionResponse" } }, "name": { @@ -8636,7 +8979,7 @@ } } }, - "domain.Unit": { + "github_com_openinfradev_tks-api_pkg_domain.Unit": { "type": "object", "properties": { "data": { @@ -8650,7 +8993,7 @@ } } }, - "domain.UpdateAlertRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest": { "type": "object", "properties": { "description": { @@ -8658,7 +9001,7 @@ } } }, - "domain.UpdateAppServeAppEndpointRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest": { "type": "object", "required": [ "taskId" @@ -8678,7 +9021,7 @@ } } }, - "domain.UpdateAppServeAppRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest": { "type": "object", "properties": { "abort": { @@ -8721,7 +9064,7 @@ } } }, - "domain.UpdateAppServeAppStatusRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest": { "type": "object", "required": [ "status", @@ -8739,7 +9082,7 @@ } } }, - "domain.UpdateCloudAccountRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateCloudAccountRequest": { "type": "object", "properties": { "description": { @@ -8747,7 +9090,7 @@ } } }, - "domain.UpdateMyProfileRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest": { "type": "object", "required": [ "password" @@ -8771,7 +9114,7 @@ } } }, - "domain.UpdateMyProfileResponse": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileResponse": { "type": "object", "properties": { "user": { @@ -8793,16 +9136,16 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } } }, - "domain.UpdateOrganizationRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest": { "type": "object", "required": [ "name" @@ -8826,7 +9169,7 @@ } } }, - "domain.UpdateOrganizationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse": { "type": "object", "properties": { "description": { @@ -8843,7 +9186,7 @@ } } }, - "domain.UpdatePasswordRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest": { "type": "object", "required": [ "newPassword", @@ -8858,7 +9201,18 @@ } } }, - "domain.UpdatePrimaryClusterRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { "type": "object", "properties": { "primaryClusterId": { @@ -8866,7 +9220,7 @@ } } }, - "domain.UpdateProjectMemberRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest": { "type": "object", "properties": { "projectRoleId": { @@ -8874,7 +9228,7 @@ } } }, - "domain.UpdateProjectMembersRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest": { "type": "object", "properties": { "projectMembers": { @@ -8893,7 +9247,7 @@ } } }, - "domain.UpdateProjectNamespaceRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest": { "type": "object", "properties": { "description": { @@ -8901,7 +9255,7 @@ } } }, - "domain.UpdateProjectRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest": { "type": "object", "required": [ "name" @@ -8918,7 +9272,7 @@ } } }, - "domain.UpdateStackRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { "type": "object", "properties": { "description": { @@ -8926,7 +9280,7 @@ } } }, - "domain.UpdateStackTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { "type": "object", "properties": { "description": { @@ -8934,7 +9288,7 @@ } } }, - "domain.UpdateUserRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest": { "type": "object", "properties": { "department": { @@ -8964,7 +9318,7 @@ } } }, - "domain.UpdateUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse": { "type": "object", "properties": { "user": { @@ -8992,10 +9346,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -9004,7 +9358,7 @@ } } }, - "domain.User": { + "github_com_openinfradev_tks-api_pkg_domain.User": { "type": "object", "properties": { "accountId": { @@ -9032,7 +9386,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "organizationId": { + "type": "string" }, "password": { "type": "string" @@ -9044,7 +9401,10 @@ "type": "string" }, "role": { - "$ref": "#/definitions/domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "roleId": { + "type": "string" }, "token": { "type": "string" @@ -9054,7 +9414,7 @@ } } }, - "domain.VerifyIdentityForLostIdRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ "email", @@ -9073,7 +9433,7 @@ } } }, - "domain.VerifyIdentityForLostIdResponse": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse": { "type": "object", "properties": { "validityPeriod": { @@ -9081,7 +9441,7 @@ } } }, - "domain.VerifyIdentityForLostPasswordRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest": { "type": "object", "required": [ "accountId", @@ -9104,7 +9464,7 @@ } } }, - "domain.VerifyIdentityForLostPasswordResponse": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse": { "type": "object", "properties": { "validityPeriod": { @@ -9112,7 +9472,122 @@ } } }, - "httpErrors.RestError": { + "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest": { + "type": "object", + "required": [ + "adminPassword", + "email", + "role" + ], + "properties": { + "adminPassword": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "role": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_httpErrors.RestError": { "type": "object", "properties": { "code": { @@ -9128,6 +9603,18 @@ "type": "string" } } + }, + "gorm.DeletedAt": { + "type": "object", + "properties": { + "time": { + "type": "string" + }, + "valid": { + "description": "Valid is true if Time is not NULL", + "type": "boolean" + } + } } }, "securityDefinitions": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index dddeedec..bfa0d127 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1,6 +1,6 @@ basePath: / definitions: - domain.ActionResponse: + github_com_openinfradev_tks-api_pkg_domain.ActionResponse: properties: body: additionalProperties: @@ -17,14 +17,14 @@ definitions: uri: type: string type: object - domain.AddProjectMemberRequest: + github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest: properties: projectMembers: items: - $ref: '#/definitions/domain.ProjectMemberRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest' type: array type: object - domain.AlertActionResponse: + github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse: properties: alertId: type: string @@ -37,20 +37,20 @@ definitions: status: type: string taker: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' updatedAt: type: string type: object - domain.AlertResponse: + github_com_openinfradev_tks-api_pkg_domain.AlertResponse: properties: alertActions: items: - $ref: '#/definitions/domain.AlertActionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse' type: array closedAt: type: string cluster: - $ref: '#/definitions/domain.SimpleClusterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse' code: type: string createdAt: @@ -66,7 +66,7 @@ definitions: id: type: string lastTaker: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' message: type: string name: @@ -88,16 +88,16 @@ definitions: updatedAt: type: string type: object - domain.AppGroupResponse: + github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse: properties: appGroupType: - $ref: '#/definitions/domain.AppGroupType' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupType' clusterId: type: string createdAt: type: string creator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string id: @@ -105,17 +105,17 @@ definitions: name: type: string status: - $ref: '#/definitions/domain.AppGroupStatus' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupStatus' statusDesc: type: string updatedAt: type: string updator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' workflowId: type: string type: object - domain.AppGroupStatus: + github_com_openinfradev_tks-api_pkg_domain.AppGroupStatus: enum: - 0 - 1 @@ -133,7 +133,7 @@ definitions: - AppGroupStatus_DELETED - AppGroupStatus_INSTALL_ERROR - AppGroupStatus_DELETE_ERROR - domain.AppGroupType: + github_com_openinfradev_tks-api_pkg_domain.AppGroupType: enum: - 0 - 1 @@ -143,11 +143,11 @@ definitions: - AppGroupType_UNSPECIFIED - AppGroupType_LMA - AppGroupType_SERVICE_MESH - domain.AppServeApp: + github_com_openinfradev_tks-api_pkg_domain.AppServeApp: properties: appServeAppTasks: items: - $ref: '#/definitions/domain.AppServeAppTask' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask' type: array appType: description: appType (spring/springboot) @@ -194,7 +194,7 @@ definitions: updatedAt: type: string type: object - domain.AppServeAppTask: + github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask: properties: appConfig: description: java app config @@ -266,12 +266,12 @@ definitions: description: application version type: string type: object - domain.ApplicationResponse: + github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse: properties: appGroupId: type: string applicationType: - $ref: '#/definitions/domain.ApplicationType' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ApplicationType' createdAt: type: string endpoint: @@ -283,7 +283,7 @@ definitions: updatedAt: type: string type: object - domain.ApplicationType: + github_com_openinfradev_tks-api_pkg_domain.ApplicationType: enum: - 0 - 1 @@ -309,7 +309,7 @@ definitions: - ApplicationType_HORIZON - ApplicationType_JAEGER - ApplicationType_KUBERNETES_DASHBOARD - domain.AuditResponse: + github_com_openinfradev_tks-api_pkg_domain.AuditResponse: properties: clientIP: type: string @@ -324,59 +324,59 @@ definitions: message: type: string organization: - $ref: '#/definitions/domain.SimpleOrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse' organizationId: type: string updatedAt: type: string user: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' userId: type: string type: object - domain.Axis: + github_com_openinfradev_tks-api_pkg_domain.Axis: properties: data: items: type: string type: array type: object - domain.BootstrapKubeconfig: + github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig: properties: expiration: type: integer type: object - domain.ChartData: + github_com_openinfradev_tks-api_pkg_domain.ChartData: properties: podCounts: items: - $ref: '#/definitions/domain.PodCount' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PodCount' type: array series: items: - $ref: '#/definitions/domain.Unit' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Unit' type: array xAxis: - $ref: '#/definitions/domain.Axis' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis' yAxis: - $ref: '#/definitions/domain.Axis' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis' type: object - domain.CheckCloudAccountAwsAccountIdResponse: + github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse: properties: existed: type: boolean type: object - domain.CheckCloudAccountNameResponse: + github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountNameResponse: properties: existed: type: boolean type: object - domain.CheckExistedResponse: + github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse: properties: existed: type: boolean type: object - domain.CloudAccount: + github_com_openinfradev_tks-api_pkg_domain.CloudAccount: properties: accessKeyId: type: string @@ -391,7 +391,7 @@ definitions: createdIAM: type: boolean creator: - $ref: '#/definitions/domain.User' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' creatorId: type: string description: @@ -409,17 +409,17 @@ definitions: sessionToken: type: string status: - $ref: '#/definitions/domain.CloudAccountStatus' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus' statusDesc: type: string updatedAt: type: string updator: - $ref: '#/definitions/domain.User' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' updatorId: type: string type: object - domain.CloudAccountResponse: + github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse: properties: awsAccountId: type: string @@ -432,7 +432,7 @@ definitions: createdIAM: type: boolean creator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string id: @@ -448,9 +448,9 @@ definitions: updatedAt: type: string updator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' type: object - domain.CloudAccountStatus: + github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus: enum: - 0 - 1 @@ -468,14 +468,14 @@ definitions: - CloudAccountStatus_DELETED - CloudAccountStatus_CREATE_ERROR - CloudAccountStatus_DELETE_ERROR - domain.Cluster: + github_com_openinfradev_tks-api_pkg_domain.Cluster: properties: byoClusterEndpointHost: type: string byoClusterEndpointPort: type: integer cloudAccount: - $ref: '#/definitions/domain.CloudAccount' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount' cloudAccountId: type: string cloudService: @@ -483,11 +483,11 @@ definitions: clusterType: type: integer conf: - $ref: '#/definitions/domain.ClusterConf' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf' createdAt: type: string creator: - $ref: '#/definitions/domain.User' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' creatorId: type: string description: @@ -507,21 +507,21 @@ definitions: organizationId: type: string stackTemplate: - $ref: '#/definitions/domain.StackTemplate' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate' stackTemplateId: type: string status: - $ref: '#/definitions/domain.ClusterStatus' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus' statusDesc: type: string updatedAt: type: string updator: - $ref: '#/definitions/domain.User' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' updatorId: type: string type: object - domain.ClusterConf: + github_com_openinfradev_tks-api_pkg_domain.ClusterConf: properties: tksCpNode: type: integer @@ -542,7 +542,7 @@ definitions: tksUserNodeType: type: string type: object - domain.ClusterConfResponse: + github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse: properties: tksCpNode: type: integer @@ -563,20 +563,20 @@ definitions: tksUserNodeType: type: string type: object - domain.ClusterHost: + github_com_openinfradev_tks-api_pkg_domain.ClusterHost: properties: name: type: string status: type: string type: object - domain.ClusterNode: + github_com_openinfradev_tks-api_pkg_domain.ClusterNode: properties: command: type: string hosts: items: - $ref: '#/definitions/domain.ClusterHost' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterHost' type: array registered: type: integer @@ -591,24 +591,24 @@ definitions: validity: type: integer type: object - domain.ClusterResponse: + github_com_openinfradev_tks-api_pkg_domain.ClusterResponse: properties: byoClusterEndpointHost: type: string byoClusterEndpointPort: type: integer cloudAccount: - $ref: '#/definitions/domain.SimpleCloudAccountResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse' cloudService: type: string clusterType: type: string conf: - $ref: '#/definitions/domain.ClusterConfResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse' createdAt: type: string creator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string id: @@ -620,7 +620,7 @@ definitions: organizationId: type: string stackTemplate: - $ref: '#/definitions/domain.SimpleStackTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse' status: type: string statusDesc: @@ -628,9 +628,9 @@ definitions: updatedAt: type: string updator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' type: object - domain.ClusterSiteValuesResponse: + github_com_openinfradev_tks-api_pkg_domain.ClusterSiteValuesResponse: properties: byoClusterEndpointHost: type: string @@ -661,7 +661,7 @@ definitions: tksUserNodeType: type: string type: object - domain.ClusterStatus: + github_com_openinfradev_tks-api_pkg_domain.ClusterStatus: enum: - 0 - 1 @@ -685,12 +685,12 @@ definitions: - ClusterStatus_BOOTSTRAPPING - ClusterStatus_BOOTSTRAPPED - ClusterStatus_BOOTSTRAP_ERROR - domain.CommonProjectResponse: + github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse: properties: result: type: string type: object - domain.CreateAppGroupRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupRequest: properties: appGroupType: enum: @@ -707,12 +707,12 @@ definitions: - clusterId - name type: object - domain.CreateAppGroupResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupResponse: properties: id: type: string type: object - domain.CreateAppServeAppRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest: properties: appConfig: type: string @@ -766,7 +766,7 @@ definitions: - name - targetClusterId type: object - domain.CreateApplicationRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateApplicationRequest: properties: applicationType: type: string @@ -775,16 +775,16 @@ definitions: metadata: type: string type: object - domain.CreateAuditRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest: type: object - domain.CreateAuditResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse: type: object - domain.CreateBootstrapKubeconfigResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateBootstrapKubeconfigResponse: properties: kubeconfig: - $ref: '#/definitions/domain.BootstrapKubeconfig' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig' type: object - domain.CreateCloudAccountRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest: properties: accessKeyId: maxLength: 128 @@ -817,12 +817,12 @@ definitions: - name - secretAccessKey type: object - domain.CreateCloudAccountResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse: properties: id: type: string type: object - domain.CreateClusterRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateClusterRequest: properties: byoClusterEndpointHost: type: string @@ -871,12 +871,12 @@ definitions: - organizationId - stackTemplateId type: object - domain.CreateClusterResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse: properties: id: type: string type: object - domain.CreateOrganizationRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest: properties: Email: type: string @@ -892,7 +892,7 @@ definitions: - Email - name type: object - domain.CreateProjectNamespaceRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest: properties: description: type: string @@ -901,7 +901,7 @@ definitions: stackId: type: string type: object - domain.CreateProjectRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest: properties: description: type: string @@ -912,12 +912,12 @@ definitions: required: - name type: object - domain.CreateProjectResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse: properties: projectId: type: string type: object - domain.CreateStackRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest: properties: cloudAccountId: type: string @@ -959,12 +959,12 @@ definitions: - name - stackTemplateId type: object - domain.CreateStackResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse: properties: id: type: string type: object - domain.CreateStackTemplateRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest: properties: cloudService: enum: @@ -993,12 +993,12 @@ definitions: - template - version type: object - domain.CreateStackTemplateResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse: properties: id: type: string type: object - domain.CreateUserRequest: + github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest: properties: accountId: type: string @@ -1027,7 +1027,7 @@ definitions: - password - role type: object - domain.CreateUserResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse: properties: user: properties: @@ -1044,15 +1044,15 @@ definitions: name: type: string organization: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' type: object type: object - domain.DashboardChartResponse: + github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse: properties: chartData: - $ref: '#/definitions/domain.ChartData' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ChartData' chartType: type: string description: @@ -1072,7 +1072,7 @@ definitions: year: type: string type: object - domain.DashboardResource: + github_com_openinfradev_tks-api_pkg_domain.DashboardResource: properties: cpu: type: string @@ -1083,7 +1083,7 @@ definitions: storage: type: string type: object - domain.DashboardStackResponse: + github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse: properties: cpu: type: string @@ -1106,7 +1106,7 @@ definitions: updatedAt: type: string type: object - domain.DeleteCloudAccountRequest: + github_com_openinfradev_tks-api_pkg_domain.DeleteCloudAccountRequest: properties: accessKeyId: maxLength: 128 @@ -1123,7 +1123,16 @@ definitions: - accessKeyId - secretAccessKey type: object - domain.FilterResponse: + github_com_openinfradev_tks-api_pkg_domain.Endpoint: + properties: + createdAt: + type: string + group: + type: string + name: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: column: type: string @@ -1136,7 +1145,7 @@ definitions: type: string type: array type: object - domain.FindIdRequest: + github_com_openinfradev_tks-api_pkg_domain.FindIdRequest: properties: code: type: string @@ -1152,12 +1161,12 @@ definitions: - organizationId - userName type: object - domain.FindIdResponse: + github_com_openinfradev_tks-api_pkg_domain.FindIdResponse: properties: accountId: type: string type: object - domain.FindPasswordRequest: + github_com_openinfradev_tks-api_pkg_domain.FindPasswordRequest: properties: accountId: type: string @@ -1176,142 +1185,142 @@ definitions: - organizationId - userName type: object - domain.GetAlertResponse: + github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse: properties: alert: - $ref: '#/definitions/domain.AlertResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse' type: object - domain.GetAlertsResponse: + github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse: properties: alerts: items: - $ref: '#/definitions/domain.AlertResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse' type: array pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object - domain.GetAppGroupResponse: + github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse: properties: appGroup: - $ref: '#/definitions/domain.AppGroupResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse' type: object - domain.GetAppGroupsResponse: + github_com_openinfradev_tks-api_pkg_domain.GetAppGroupsResponse: properties: appGroups: items: - $ref: '#/definitions/domain.AppGroupResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse' type: array pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object - domain.GetAppServeAppResponse: + github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse: properties: appServeApp: - $ref: '#/definitions/domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' stages: items: - $ref: '#/definitions/domain.StageResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' type: array type: object - domain.GetAppServeAppTaskResponse: + github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse: properties: appServeApp: - $ref: '#/definitions/domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' appServeAppTask: - $ref: '#/definitions/domain.AppServeAppTask' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask' stages: items: - $ref: '#/definitions/domain.StageResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' type: array type: object - domain.GetApplicationsResponse: + github_com_openinfradev_tks-api_pkg_domain.GetApplicationsResponse: properties: applications: items: - $ref: '#/definitions/domain.ApplicationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse' type: array type: object - domain.GetAuditResponse: + github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse: properties: audit: - $ref: '#/definitions/domain.AuditResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AuditResponse' type: object - domain.GetAuditsResponse: + github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse: properties: audits: items: - $ref: '#/definitions/domain.AuditResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AuditResponse' type: array pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object - domain.GetBootstrapKubeconfigResponse: + github_com_openinfradev_tks-api_pkg_domain.GetBootstrapKubeconfigResponse: properties: kubeconfig: - $ref: '#/definitions/domain.BootstrapKubeconfig' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig' type: object - domain.GetCloudAccountResourceQuotaResponse: + github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResourceQuotaResponse: properties: available: type: boolean resourceQuota: - $ref: '#/definitions/domain.ResourceQuota' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ResourceQuota' type: object - domain.GetCloudAccountResponse: + github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResponse: properties: cloudAccount: - $ref: '#/definitions/domain.CloudAccountResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse' type: object - domain.GetCloudAccountsResponse: + github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse: properties: cloudAccounts: items: - $ref: '#/definitions/domain.CloudAccountResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse' type: array pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object - domain.GetClusterNodesResponse: + github_com_openinfradev_tks-api_pkg_domain.GetClusterNodesResponse: properties: nodes: items: - $ref: '#/definitions/domain.ClusterNode' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode' type: array type: object - domain.GetClustersResponse: + github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse: properties: clusters: items: - $ref: '#/definitions/domain.ClusterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse' type: array pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object - domain.GetDashboardChartResponse: + github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse: properties: chart: - $ref: '#/definitions/domain.DashboardChartResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse' type: object - domain.GetDashboardChartsResponse: + github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse: properties: charts: items: - $ref: '#/definitions/domain.DashboardChartResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse' type: array type: object - domain.GetDashboardResourcesResponse: + github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse: properties: resources: - $ref: '#/definitions/domain.DashboardResource' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardResource' type: object - domain.GetDashboardStacksResponse: + github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse: properties: stacks: items: - $ref: '#/definitions/domain.DashboardStackResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse' type: array type: object - domain.GetMyProfileResponse: + github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse: properties: user: properties: @@ -1326,12 +1335,12 @@ definitions: name: type: string organization: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' type: object type: object - domain.GetOrganizationResponse: + github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse: properties: organization: properties: @@ -1357,12 +1366,12 @@ definitions: type: string type: object type: object - domain.GetProjectKubeconfigResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse: properties: kubeconfig: type: string type: object - domain.GetProjectMemberCountResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse: properties: projectLeaderCount: type: integer @@ -1373,106 +1382,123 @@ definitions: projectViewerCount: type: integer type: object - domain.GetProjectMemberResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse: properties: projectMember: - $ref: '#/definitions/domain.ProjectMemberResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse' type: object - domain.GetProjectMembersResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse: properties: pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' projectMembers: items: - $ref: '#/definitions/domain.ProjectMemberResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse' type: array type: object - domain.GetProjectNamespaceK8sResourcesResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse: properties: k8sResources: - $ref: '#/definitions/domain.ProjectNamespaceK8sResources' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources' type: object - domain.GetProjectNamespaceResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse: properties: projectNamespace: - $ref: '#/definitions/domain.ProjectNamespaceResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse' type: object - domain.GetProjectNamespacesResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse: properties: projectNamespaces: items: - $ref: '#/definitions/domain.ProjectNamespaceResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse' type: array type: object - domain.GetProjectResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse: properties: project: - $ref: '#/definitions/domain.ProjectDetailResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse' type: object - domain.GetProjectRoleResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse: properties: projectRole: - $ref: '#/definitions/domain.ProjectRole' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole' type: object - domain.GetProjectRolesResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse: properties: projectRoles: items: - $ref: '#/definitions/domain.ProjectRole' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole' type: array type: object - domain.GetProjectsResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse: properties: pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' projects: items: - $ref: '#/definitions/domain.ProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectResponse' type: array type: object - domain.GetStackKubeConfigResponse: + github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse: properties: kubeConfig: type: string type: object - domain.GetStackResponse: + github_com_openinfradev_tks-api_pkg_domain.GetStackResponse: properties: stack: - $ref: '#/definitions/domain.StackResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse' type: object - domain.GetStackStatusResponse: + github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse: properties: stackStatus: type: string stepStatus: items: - $ref: '#/definitions/domain.StackStepStatus' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackStepStatus' type: array type: object - domain.GetStackTemplateResponse: + github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse: properties: stackTemplate: - $ref: '#/definitions/domain.StackTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse' type: object - domain.GetStackTemplatesResponse: + github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse: properties: pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' stackTemplates: items: - $ref: '#/definitions/domain.StackTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse' type: array type: object - domain.GetStacksResponse: + github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse: properties: pagination: - $ref: '#/definitions/domain.PaginationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' stacks: items: - $ref: '#/definitions/domain.StackResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse' type: array type: object - domain.GetUserResponse: + github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse: + properties: + createdAt: + type: string + creator: + type: string + description: + type: string + id: + type: string + name: + type: string + organizationId: + type: string + updatedAt: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.GetUserResponse: properties: user: properties: @@ -1493,14 +1519,14 @@ definitions: name: type: string organization: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' updatedAt: type: string type: object type: object - domain.ImportClusterRequest: + github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest: properties: cloudService: type: string @@ -1523,12 +1549,12 @@ definitions: - organizationId - stackTemplateId type: object - domain.ImportClusterResponse: + github_com_openinfradev_tks-api_pkg_domain.ImportClusterResponse: properties: id: type: string type: object - domain.ListOrganizationBody: + github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody: properties: createdAt: type: string @@ -1547,7 +1573,16 @@ definitions: updatedAt: type: string type: object - domain.ListUserBody: + github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain.ListUserBody: properties: accountId: type: string @@ -1566,13 +1601,13 @@ definitions: name: type: string organization: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' updatedAt: type: string type: object - domain.LoginRequest: + github_com_openinfradev_tks-api_pkg_domain.LoginRequest: properties: accountId: type: string @@ -1585,7 +1620,7 @@ definitions: - organizationId - password type: object - domain.LoginResponse: + github_com_openinfradev_tks-api_pkg_domain.LoginResponse: properties: user: properties: @@ -1596,16 +1631,16 @@ definitions: name: type: string organization: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' passwordExpired: type: boolean role: - $ref: '#/definitions/domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' token: type: string type: object type: object - domain.LogoutResponse: + github_com_openinfradev_tks-api_pkg_domain.LogoutResponse: properties: ssoUrls: additionalProperties: @@ -1614,12 +1649,14 @@ definitions: type: array type: object type: object - domain.Organization: + github_com_openinfradev_tks-api_pkg_domain.Organization: properties: createdAt: type: string creator: type: string + deletedAt: + $ref: '#/definitions/gorm.DeletedAt' description: type: string id: @@ -1631,13 +1668,13 @@ definitions: primaryClusterId: type: string status: - $ref: '#/definitions/domain.OrganizationStatus' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus' statusDesc: type: string updatedAt: type: string type: object - domain.OrganizationStatus: + github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus: enum: - 0 - 1 @@ -1657,11 +1694,11 @@ definitions: - OrganizationStatus_DELETING - OrganizationStatus_DELETED - OrganizationStatus_ERROR - domain.PaginationResponse: + github_com_openinfradev_tks-api_pkg_domain.PaginationResponse: properties: filters: items: - $ref: '#/definitions/domain.FilterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.FilterResponse' type: array pageNumber: type: integer @@ -1676,7 +1713,55 @@ definitions: totalRows: type: integer type: object - domain.PingTokenRequest: + github_com_openinfradev_tks-api_pkg_domain.Permission: + properties: + ID: + type: string + children: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + type: array + createdAt: + type: string + deletedAt: + $ref: '#/definitions/gorm.DeletedAt' + endpoints: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint' + type: array + id: + type: integer + is_allowed: + type: boolean + name: + type: string + parent: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + parent_id: + type: string + role: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + role_id: + type: string + updatedAt: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.PermissionSet: + properties: + configuration: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + dashboard: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + notification: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + project_management: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + security_policy: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + stack: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + type: object + github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest: properties: organizationId: type: string @@ -1686,14 +1771,14 @@ definitions: - organizationId - token type: object - domain.PodCount: + github_com_openinfradev_tks-api_pkg_domain.PodCount: properties: day: type: integer value: type: integer type: object - domain.ProjectDetailResponse: + github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse: properties: createdAt: description: |- @@ -1724,7 +1809,7 @@ definitions: updatedAt: type: string type: object - domain.ProjectMemberRequest: + github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest: properties: projectRoleId: type: string @@ -1734,7 +1819,7 @@ definitions: - projectRoleId - projectUserId type: object - domain.ProjectMemberResponse: + github_com_openinfradev_tks-api_pkg_domain.ProjectMemberResponse: properties: createdAt: type: string @@ -1759,7 +1844,7 @@ definitions: updatedAt: type: string type: object - domain.ProjectNamespaceK8sResources: + github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources: properties: cronjobs: type: integer @@ -1782,7 +1867,7 @@ definitions: updatedAt: type: string type: object - domain.ProjectNamespaceResponse: + github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse: properties: appCount: type: integer @@ -1803,7 +1888,7 @@ definitions: updatedAt: type: string type: object - domain.ProjectResponse: + github_com_openinfradev_tks-api_pkg_domain.ProjectResponse: properties: appCount: type: integer @@ -1828,7 +1913,7 @@ definitions: projectRoleName: type: string type: object - domain.ProjectRole: + github_com_openinfradev_tks-api_pkg_domain.ProjectRole: properties: createdAt: type: string @@ -1844,7 +1929,7 @@ definitions: updatedAt: type: string type: object - domain.RemoveProjectMemberRequest: + github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest: properties: projectMembers: items: @@ -1854,14 +1939,14 @@ definitions: type: object type: array type: object - domain.ResourceQuota: + github_com_openinfradev_tks-api_pkg_domain.ResourceQuota: properties: quotas: items: - $ref: '#/definitions/domain.ResourceQuotaAttr' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ResourceQuotaAttr' type: array type: object - domain.ResourceQuotaAttr: + github_com_openinfradev_tks-api_pkg_domain.ResourceQuotaAttr: properties: quota: type: integer @@ -1872,27 +1957,35 @@ definitions: usage: type: integer type: object - domain.Role: + github_com_openinfradev_tks-api_pkg_domain.Role: properties: createdAt: type: string creator: type: string + deletedAt: + $ref: '#/definitions/gorm.DeletedAt' description: type: string id: type: string name: type: string + organization: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + organizationId: + type: string + type: + type: string updatedAt: type: string type: object - domain.RollbackAppServeAppRequest: + github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest: properties: taskId: type: string type: object - domain.SimpleCloudAccountResponse: + github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse: properties: awsAccountId: type: string @@ -1911,7 +2004,7 @@ definitions: organizationId: type: string type: object - domain.SimpleClusterResponse: + github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse: properties: id: type: string @@ -1920,7 +2013,7 @@ definitions: organizationId: type: string type: object - domain.SimpleOrganizationResponse: + github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse: properties: description: type: string @@ -1929,7 +2022,7 @@ definitions: name: type: string type: object - domain.SimpleRoleResponse: + github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse: properties: description: type: string @@ -1938,7 +2031,7 @@ definitions: name: type: string type: object - domain.SimpleStackTemplateResponse: + github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse: properties: cloudService: type: string @@ -1954,12 +2047,12 @@ definitions: type: string services: items: - $ref: '#/definitions/domain.StackTemplateServiceResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse' type: array template: type: string type: object - domain.SimpleUserResponse: + github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse: properties: accountId: type: string @@ -1968,9 +2061,9 @@ definitions: name: type: string role: - $ref: '#/definitions/domain.SimpleRoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' type: object - domain.StackConfResponse: + github_com_openinfradev_tks-api_pkg_domain.StackConfResponse: properties: tksCpNode: type: integer @@ -1998,16 +2091,16 @@ definitions: - tksInfraNode - tksUserNode type: object - domain.StackResponse: + github_com_openinfradev_tks-api_pkg_domain.StackResponse: properties: cloudAccount: - $ref: '#/definitions/domain.SimpleCloudAccountResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse' conf: - $ref: '#/definitions/domain.StackConfResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackConfResponse' createdAt: type: string creator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string favorited: @@ -2023,9 +2116,9 @@ definitions: primaryCluster: type: boolean resource: - $ref: '#/definitions/domain.DashboardStackResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse' stackTemplate: - $ref: '#/definitions/domain.SimpleStackTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse' status: type: string statusDesc: @@ -2033,11 +2126,11 @@ definitions: updatedAt: type: string updator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' userClusterEndpoint: type: string type: object - domain.StackStepStatus: + github_com_openinfradev_tks-api_pkg_domain.StackStepStatus: properties: maxStep: type: integer @@ -2048,14 +2141,14 @@ definitions: step: type: integer type: object - domain.StackTemplate: + github_com_openinfradev_tks-api_pkg_domain.StackTemplate: properties: cloudService: type: string createdAt: type: string creator: - $ref: '#/definitions/domain.User' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' creatorId: type: string description: @@ -2083,20 +2176,20 @@ definitions: updatedAt: type: string updator: - $ref: '#/definitions/domain.User' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' updatorId: type: string version: type: string type: object - domain.StackTemplateResponse: + github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse: properties: cloudService: type: string createdAt: type: string creator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string id: @@ -2111,7 +2204,7 @@ definitions: type: string services: items: - $ref: '#/definitions/domain.StackTemplateServiceResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse' type: array template: type: string @@ -2120,11 +2213,11 @@ definitions: updatedAt: type: string updator: - $ref: '#/definitions/domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' version: type: string type: object - domain.StackTemplateServiceApplicationResponse: + github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceApplicationResponse: properties: description: type: string @@ -2133,20 +2226,20 @@ definitions: version: type: string type: object - domain.StackTemplateServiceResponse: + github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse: properties: applications: items: - $ref: '#/definitions/domain.StackTemplateServiceApplicationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceApplicationResponse' type: array type: type: string type: object - domain.StageResponse: + github_com_openinfradev_tks-api_pkg_domain.StageResponse: properties: actions: items: - $ref: '#/definitions/domain.ActionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ActionResponse' type: array name: description: BUILD (빌드), DEPLOY (배포), PROMOTE (프로모트), ROLLBACK (롤백) @@ -2156,7 +2249,7 @@ definitions: status: type: string type: object - domain.Unit: + github_com_openinfradev_tks-api_pkg_domain.Unit: properties: data: items: @@ -2165,12 +2258,12 @@ definitions: name: type: string type: object - domain.UpdateAlertRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest: properties: description: type: string type: object - domain.UpdateAppServeAppEndpointRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest: properties: endpointUrl: type: string @@ -2183,7 +2276,7 @@ definitions: required: - taskId type: object - domain.UpdateAppServeAppRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest: properties: abort: type: boolean @@ -2212,7 +2305,7 @@ definitions: description: Task type: string type: object - domain.UpdateAppServeAppStatusRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest: properties: output: type: string @@ -2224,12 +2317,12 @@ definitions: - status - taskId type: object - domain.UpdateCloudAccountRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateCloudAccountRequest: properties: description: type: string type: object - domain.UpdateMyProfileRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest: properties: department: maxLength: 50 @@ -2246,7 +2339,7 @@ definitions: required: - password type: object - domain.UpdateMyProfileResponse: + github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileResponse: properties: user: properties: @@ -2261,12 +2354,12 @@ definitions: name: type: string organization: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' type: object type: object - domain.UpdateOrganizationRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest: properties: description: maxLength: 100 @@ -2283,7 +2376,7 @@ definitions: required: - name type: object - domain.UpdateOrganizationResponse: + github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse: properties: description: type: string @@ -2294,7 +2387,7 @@ definitions: phone: type: string type: object - domain.UpdatePasswordRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest: properties: newPassword: type: string @@ -2304,17 +2397,24 @@ definitions: - newPassword - originPassword type: object - domain.UpdatePrimaryClusterRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest: + properties: + permissions: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest: properties: primaryClusterId: type: string type: object - domain.UpdateProjectMemberRoleRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest: properties: projectRoleId: type: string type: object - domain.UpdateProjectMembersRoleRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest: properties: projectMembers: items: @@ -2326,12 +2426,12 @@ definitions: type: object type: array type: object - domain.UpdateProjectNamespaceRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest: properties: description: type: string type: object - domain.UpdateProjectRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest: properties: description: type: string @@ -2342,17 +2442,17 @@ definitions: required: - name type: object - domain.UpdateStackRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest: properties: description: type: string type: object - domain.UpdateStackTemplateRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest: properties: description: type: string type: object - domain.UpdateUserRequest: + github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest: properties: department: maxLength: 50 @@ -2374,7 +2474,7 @@ definitions: - user type: string type: object - domain.UpdateUserResponse: + github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse: properties: user: properties: @@ -2393,14 +2493,14 @@ definitions: name: type: string organization: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' updatedAt: type: string type: object type: object - domain.User: + github_com_openinfradev_tks-api_pkg_domain.User: properties: accountId: type: string @@ -2419,7 +2519,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + organizationId: + type: string password: type: string passwordExpired: @@ -2427,13 +2529,15 @@ definitions: passwordUpdatedAt: type: string role: - $ref: '#/definitions/domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + roleId: + type: string token: type: string updatedAt: type: string type: object - domain.VerifyIdentityForLostIdRequest: + github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest: properties: email: type: string @@ -2446,12 +2550,12 @@ definitions: - organizationId - userName type: object - domain.VerifyIdentityForLostIdResponse: + github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse: properties: validityPeriod: type: string type: object - domain.VerifyIdentityForLostPasswordRequest: + github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest: properties: accountId: type: string @@ -2467,12 +2571,89 @@ definitions: - organizationId - userName type: object - domain.VerifyIdentityForLostPasswordResponse: + github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse: properties: validityPeriod: type: string type: object - httpErrors.RestError: + github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse: + properties: + user: + properties: + accountId: + type: string + createdAt: + type: string + creator: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + role: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + updatedAt: + type: string + type: object + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest: + properties: + adminPassword: + type: string + department: + maxLength: 50 + minLength: 0 + type: string + description: + maxLength: 100 + minLength: 0 + type: string + email: + type: string + name: + type: string + role: + type: string + required: + - adminPassword + - email + - role + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse: + properties: + user: + properties: + accountId: + type: string + createdAt: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + role: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + updatedAt: + type: string + type: object + type: object + github_com_openinfradev_tks-api_pkg_httpErrors.RestError: properties: code: type: string @@ -2483,6 +2664,14 @@ definitions: text: type: string type: object + gorm.DeletedAt: + properties: + time: + type: string + valid: + description: Valid is true if Time is not NULL + type: boolean + type: object host: tks-api-dev.taco-cat.xyz info: contact: @@ -2495,6 +2684,65 @@ info: title: tks-api service version: "1.0" paths: + /api/1.0/admin/organizations/{organizationId}/users/{accountId}: + get: + consumes: + - application/json + description: Get user detail by admin + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse' + summary: Get user detail by admin + tags: + - Admin + put: + consumes: + - application/json + description: Update user by admin + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + - description: input + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse' + security: + - JWT: [] + summary: Update user by admin + tags: + - Admin /api/1.0/app-groups: delete: consumes: @@ -2555,7 +2803,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAppGroupsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppGroupsResponse' security: - JWT: [] summary: Get appGroup list @@ -2571,14 +2819,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.CreateAppGroupRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CreateAppGroupResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppGroupResponse' security: - JWT: [] summary: Install appGroup @@ -2601,7 +2849,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAppGroupResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse' security: - JWT: [] summary: Get appGroup detail @@ -2629,7 +2877,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetApplicationsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetApplicationsResponse' security: - JWT: [] summary: Get applications @@ -2645,7 +2893,7 @@ paths: name: object required: true schema: - $ref: '#/definitions/domain.CreateApplicationRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateApplicationRequest' produces: - application/json responses: @@ -2669,18 +2917,18 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.VerifyIdentityForLostIdRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.VerifyIdentityForLostIdResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse' "400": description: Bad Request schema: - $ref: '#/definitions/httpErrors.RestError' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError' summary: Request to verify identity for lost id tags: - Auth @@ -2697,18 +2945,18 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.FindIdRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindIdRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.FindIdResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindIdResponse' "400": description: Bad Request schema: - $ref: '#/definitions/httpErrors.RestError' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError' summary: Request to find forgotten ID tags: - Auth @@ -2725,18 +2973,18 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.VerifyIdentityForLostPasswordRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.VerifyIdentityForLostPasswordResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse' "400": description: Bad Request schema: - $ref: '#/definitions/httpErrors.RestError' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError' summary: Request to verify identity for lost password tags: - Auth @@ -2753,7 +3001,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.FindPasswordRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.FindPasswordRequest' produces: - application/json responses: @@ -2762,7 +3010,7 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/httpErrors.RestError' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError' summary: Request to find forgotten password tags: - Auth @@ -2777,14 +3025,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.LoginRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.LoginRequest' produces: - application/json responses: "200": description: user detail schema: - $ref: '#/definitions/domain.LoginResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.LoginResponse' summary: login tags: - Auth @@ -2799,7 +3047,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.LogoutResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.LogoutResponse' security: - JWT: [] summary: logout @@ -2816,7 +3064,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.PingTokenRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest' produces: - application/json responses: @@ -2864,7 +3112,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetClustersResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse' security: - JWT: [] summary: Get clusters @@ -2880,14 +3128,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.CreateClusterRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateClusterRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CreateClusterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse' security: - JWT: [] summary: Create cluster @@ -2910,7 +3158,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.Cluster' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster' security: - JWT: [] summary: Delete cluster @@ -2932,7 +3180,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.Cluster' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster' security: - JWT: [] summary: Get cluster @@ -2949,7 +3197,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetBootstrapKubeconfigResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetBootstrapKubeconfigResponse' security: - JWT: [] summary: Get bootstrap kubeconfig for BYOH @@ -2965,7 +3213,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CreateBootstrapKubeconfigResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateBootstrapKubeconfigResponse' security: - JWT: [] summary: Create bootstrap kubeconfig for BYOH @@ -3009,7 +3257,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetClusterNodesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterNodesResponse' security: - JWT: [] summary: Get nodes information for BYOH @@ -3032,7 +3280,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.ClusterSiteValuesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterSiteValuesResponse' security: - JWT: [] summary: Get cluster site values for creating @@ -3049,14 +3297,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.ImportClusterRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.ImportClusterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportClusterResponse' security: - JWT: [] summary: Import cluster @@ -3098,7 +3346,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/domain.ListOrganizationBody' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody' type: array security: - JWT: [] @@ -3115,7 +3363,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.CreateOrganizationRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest' produces: - application/json responses: @@ -3145,7 +3393,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' security: - JWT: [] summary: Delete organization @@ -3167,7 +3415,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetOrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse' security: - JWT: [] summary: Get organization detail @@ -3188,14 +3436,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateOrganizationRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.UpdateOrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse' security: - JWT: [] summary: Update organization detail @@ -3241,7 +3489,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAlertsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse' security: - JWT: [] summary: Get Alerts @@ -3294,7 +3542,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAlertResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse' security: - JWT: [] summary: Get Alert @@ -3315,7 +3563,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateAlertRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest' produces: - application/json responses: @@ -3389,7 +3637,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAuditsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse' security: - JWT: [] summary: Get Audits @@ -3405,14 +3653,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.CreateAuditRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CreateAuditResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse' security: - JWT: [] summary: Create Audit @@ -3455,7 +3703,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAuditResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse' security: - JWT: [] summary: Get Audit @@ -3501,7 +3749,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetCloudAccountsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse' security: - JWT: [] summary: Get CloudAccounts @@ -3522,14 +3770,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.CreateCloudAccountRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CreateCloudAccountResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse' security: - JWT: [] summary: Create CloudAccount @@ -3551,7 +3799,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.DeleteCloudAccountRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteCloudAccountRequest' - description: cloudAccountId in: path name: cloudAccountId @@ -3588,7 +3836,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetCloudAccountResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResponse' security: - JWT: [] summary: Get CloudAccount @@ -3609,7 +3857,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateCloudAccountRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateCloudAccountRequest' produces: - application/json responses: @@ -3668,7 +3916,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetCloudAccountResourceQuotaResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountResourceQuotaResponse' security: - JWT: [] summary: Get resource quota by cloudAccount @@ -3696,7 +3944,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CheckCloudAccountAwsAccountIdResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse' security: - JWT: [] summary: Check awsAccountId for cloudAccount @@ -3724,7 +3972,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CheckCloudAccountNameResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountNameResponse' security: - JWT: [] summary: Check name for cloudAccount @@ -3761,7 +4009,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetDashboardChartsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse' security: - JWT: [] summary: Get charts data @@ -3799,7 +4047,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetDashboardChartResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse' security: - JWT: [] summary: Get chart data @@ -3822,7 +4070,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetDashboardResourcesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse' security: - JWT: [] summary: Get resources @@ -3845,7 +4093,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetDashboardStacksResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse' security: - JWT: [] summary: Get stacks @@ -3890,7 +4138,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetMyProfileResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse' security: - JWT: [] summary: Get my profile detail @@ -3911,14 +4159,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateMyProfileRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.UpdateMyProfileResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileResponse' security: - JWT: [] summary: Update my profile detail @@ -3943,7 +4191,7 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/httpErrors.RestError' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError' security: - JWT: [] summary: Update user's password expired date to current date @@ -3965,7 +4213,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdatePasswordRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest' produces: - application/json responses: @@ -3992,7 +4240,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdatePrimaryClusterRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest' produces: - application/json responses: @@ -4024,7 +4272,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse' security: - JWT: [] summary: Get projects @@ -4045,14 +4293,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/domain.CreateProjectRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CreateProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse' security: - JWT: [] summary: Create new project @@ -4080,7 +4328,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse' security: - JWT: [] summary: Get projects @@ -4106,14 +4354,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/domain.UpdateProjectRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Update project @@ -4169,7 +4417,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' type: array security: - JWT: [] @@ -4196,7 +4444,7 @@ paths: name: object required: true schema: - $ref: '#/definitions/domain.CreateAppServeAppRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest' produces: - application/json responses: @@ -4268,7 +4516,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAppServeAppResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse' security: - JWT: [] summary: Get appServeApp @@ -4299,7 +4547,7 @@ paths: name: object required: true schema: - $ref: '#/definitions/domain.UpdateAppServeAppRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest' produces: - application/json responses: @@ -4338,7 +4586,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateAppServeAppEndpointRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest' produces: - application/json responses: @@ -4406,7 +4654,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAppServeAppTaskResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse' security: - JWT: [] summary: Get latest task from appServeApp @@ -4438,7 +4686,7 @@ paths: name: object required: true schema: - $ref: '#/definitions/domain.RollbackAppServeAppRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest' produces: - application/json responses: @@ -4477,7 +4725,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateAppServeAppStatusRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest' produces: - application/json responses: @@ -4536,7 +4784,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' type: array security: - JWT: [] @@ -4575,7 +4823,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetAppServeAppTaskResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse' security: - JWT: [] summary: Get task detail from appServeApp @@ -4669,7 +4917,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectKubeconfigResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse' security: - JWT: [] summary: Get project kubeconfig @@ -4696,14 +4944,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/domain.RemoveProjectMemberRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Remove project members to project @@ -4735,7 +4983,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectMembersResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse' security: - JWT: [] summary: Get project members @@ -4761,14 +5009,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/domain.AddProjectMemberRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Add project member to project @@ -4794,14 +5042,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/domain.UpdateProjectMembersRoleRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Update project member Role @@ -4834,7 +5082,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Remove project members to project @@ -4866,7 +5114,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectMemberResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse' security: - JWT: [] summary: Get project member @@ -4898,14 +5146,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/domain.UpdateProjectMemberRoleRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Update project member Role @@ -4933,7 +5181,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectMemberCountResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse' security: - JWT: [] summary: Get project member count group by project role @@ -4961,7 +5209,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectNamespacesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse' security: - JWT: [] summary: Get project namespaces @@ -4987,14 +5235,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/domain.CreateProjectNamespaceRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Create project namespace @@ -5032,7 +5280,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Delete project namespace @@ -5069,7 +5317,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectNamespaceResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse' security: - JWT: [] summary: Get project namespace @@ -5105,14 +5353,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/domain.UpdateProjectNamespaceRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CommonProjectResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse' security: - JWT: [] summary: Update project namespace @@ -5150,7 +5398,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CheckExistedResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' security: - JWT: [] summary: Check project namespace exist @@ -5188,7 +5436,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectNamespaceK8sResourcesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse' security: - JWT: [] summary: Get k8s resources for project namespace @@ -5220,7 +5468,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CheckExistedResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' security: - JWT: [] summary: Check project name exist @@ -5248,7 +5496,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectRolesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse' security: - JWT: [] summary: Get project roles @@ -5276,7 +5524,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetProjectRoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse' security: - JWT: [] summary: Get project role @@ -5319,7 +5567,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetStacksResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse' security: - JWT: [] summary: Get Stacks @@ -5340,14 +5588,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.CreateStackRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CreateStackResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse' security: - JWT: [] summary: Create Stack @@ -5400,7 +5648,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetStackResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse' security: - JWT: [] summary: Get Stack @@ -5426,7 +5674,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateStackRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest' produces: - application/json responses: @@ -5510,7 +5758,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetStackKubeConfigResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse' security: - JWT: [] summary: Get KubeConfig by stack @@ -5538,7 +5786,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetStackStatusResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse' security: - JWT: [] summary: Get Stack Status @@ -5616,7 +5864,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/domain.ListUserBody' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListUserBody' type: array security: - JWT: [] @@ -5638,14 +5886,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.CreateUserRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest' produces: - application/json responses: "200": description: create user response schema: - $ref: '#/definitions/domain.CreateUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse' security: - JWT: [] summary: Create user @@ -5673,7 +5921,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.User' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' security: - JWT: [] summary: Delete user @@ -5700,7 +5948,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUserResponse' security: - JWT: [] summary: Get user detail @@ -5726,14 +5974,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateUserRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.UpdateUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse' security: - JWT: [] summary: Update user @@ -5786,7 +6034,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CheckExistedResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' security: - JWT: [] summary: Get user id existence @@ -5812,7 +6060,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.CheckExistedResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' security: - JWT: [] summary: Get user email existence @@ -5853,7 +6101,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetStackTemplatesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' security: - JWT: [] summary: Get StackTemplates @@ -5869,14 +6117,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.CreateStackTemplateRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/domain.CreateStackTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse' security: - JWT: [] summary: Create StackTemplate 'NOT IMPLEMENTED' @@ -5919,7 +6167,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/domain.GetStackTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse' security: - JWT: [] summary: Get StackTemplate @@ -5935,7 +6183,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/domain.UpdateStackTemplateRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest' produces: - application/json responses: @@ -5946,6 +6194,79 @@ paths: summary: Update StackTemplate 'NOT IMPLEMENTED' tags: - StackTemplates + /organizations/{organizationId}/roles: + get: + description: List Tks Roles + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' + summary: List Tks Roles + tags: + - Role + /permissions/templates: + get: + consumes: + - application/json + description: Get Permission Templates + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' + summary: Get Permission Templates + tags: + - Permission + /roles/{roleId}/permissions: + get: + consumes: + - application/json + description: Get Permissions By Role ID + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' + summary: Get Permissions By Role ID + tags: + - Permission + put: + consumes: + - application/json + description: Update Permissions By Role ID + parameters: + - description: Role ID + in: path + name: roleId + required: true + type: string + - description: Update Permissions By Role ID Request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest' + produces: + - application/json + responses: + "200": + description: OK + summary: Update Permissions By Role ID + tags: + - Permission /system-api/organizations/{organizationId}/alerts: post: consumes: diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index c6a6e03e..d96dfce5 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -2,10 +2,11 @@ package http import ( "fmt" - admin_domain "github.com/openinfradev/tks-api/pkg/domain/admin" "net/http" "strings" + admin_domain "github.com/openinfradev/tks-api/pkg/domain/admin" + "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/pagination" @@ -659,8 +660,8 @@ func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Param body body admin.CreateUserRequest true "create user request" -// @Success 200 {object} admin.CreateUserResponse "create user response" +// @Param body body admin_domain.CreateUserRequest true "create user request" +// @Success 200 {object} admin_domain.CreateUserResponse "create user response" // @Router /api/1.0/admin/organizations/{organizationId}/users [post] // @Security JWT @@ -759,7 +760,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} admin.ListUserResponse "user list response" +// @Success 200 {object} admin_domain.ListUserResponse "user list response" // @Router /api/1.0/admin/organizations/{organizationId}/users [get] // @Security JWT @@ -803,7 +804,7 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Success 200 {object} admin.GetUserResponse +// @Success 200 {object} admin_domain.GetUserResponse // @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [get] func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -847,7 +848,7 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Success 200 {object} domain.User +// @Success 200 {object} admin_domain.User // @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [delete] // @Security JWT @@ -908,8 +909,8 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Param body body admin.UpdateUserRequest true "input" -// @Success 200 {object} admin.UpdateUserResponse +// @Param body body admin_domain.UpdateUserRequest true "input" +// @Success 200 {object} admin_domain.UpdateUserResponse // @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [put] // @Security JWT func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { From 351040d40bf5ed09d3e3e5ace63303f8a776d383 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 6 Mar 2024 09:55:31 +0900 Subject: [PATCH 086/502] Refactoring domain object --- api/swagger/docs.go | 6 +- api/swagger/swagger.json | 6 +- api/swagger/swagger.yaml | 6 +- cmd/server/main.go | 26 +- internal/database/database.go | 9 +- internal/delivery/http/alert.go | 124 ++--- internal/delivery/http/app-group.go | 120 ++--- internal/delivery/http/app-serve-app.go | 334 ++++++------ internal/delivery/http/audit.go | 82 +-- internal/delivery/http/auth.go | 132 ++--- internal/delivery/http/cloud-account.go | 190 +++---- internal/delivery/http/cluster.go | 266 +++++----- internal/delivery/http/dashboard.go | 84 +-- internal/delivery/http/organization.go | 120 ++--- internal/delivery/http/permission.go | 46 +- internal/delivery/http/project.go | 626 ++++++++++++----------- internal/delivery/http/role.go | 84 +-- internal/delivery/http/stack-template.go | 98 ++-- internal/delivery/http/stack.go | 212 ++++---- internal/delivery/http/user.go | 264 +++++----- internal/domain/domain.go | 103 ++++ internal/repository/project.go | 15 +- internal/usecase/project.go | 17 +- internal/usecase/role_test.go | 2 +- pkg/domain/project.go | 115 +---- 25 files changed, 1565 insertions(+), 1522 deletions(-) create mode 100644 internal/domain/domain.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0c5deb4e..8af1e674 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -7734,7 +7734,7 @@ const docTemplate = `{ "type": "object", "properties": { "projectRole": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse" } } }, @@ -7744,7 +7744,7 @@ const docTemplate = `{ "projectRoles": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse" } } } @@ -8474,7 +8474,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ProjectRole": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse": { "type": "object", "properties": { "createdAt": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index ef1e95c6..a4400e25 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -7728,7 +7728,7 @@ "type": "object", "properties": { "projectRole": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse" } } }, @@ -7738,7 +7738,7 @@ "projectRoles": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse" } } } @@ -8468,7 +8468,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ProjectRole": { + "github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse": { "type": "object", "properties": { "createdAt": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index bfa0d127..ed65980c 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1421,13 +1421,13 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse: properties: projectRole: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse' type: object github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse: properties: projectRoles: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRole' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse' type: array type: object github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse: @@ -1913,7 +1913,7 @@ definitions: projectRoleName: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.ProjectRole: + github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse: properties: createdAt: type: string diff --git a/cmd/server/main.go b/cmd/server/main.go index b33b705e..6ad93bfd 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -84,23 +84,23 @@ func init() { swagger.SwaggerInfo.Host = address } -// @title tks-api service -// @version 1.0 -// @description This is backend api service for tks platform +// @title tks-api service +// @version 1.0 +// @description This is backend api service for tks platform -// @contact.name taekyu.kang@sk.com -// @contact.url -// @contact.email taekyu.kang@sk.com +// @contact.name taekyu.kang@sk.com +// @contact.url +// @contact.email taekyu.kang@sk.com -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html +// @license.name Apache 2.0 +// @license.url http://www.apache.org/licenses/LICENSE-2.0.html -// @securitydefinitions.apikey JWT -// @in header -// @name Authorization +// @securitydefinitions.apikey JWT +// @in header +// @name Authorization -// @host tks-api-dev.taco-cat.xyz -// @BasePath / +// @host tks-api-dev.taco-cat.xyz +// @BasePath / func main() { log.Info("*** Arguments *** ") for i, s := range viper.AllSettings() { diff --git a/internal/database/database.go b/internal/database/database.go index cb3f0aee..fd260524 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -11,6 +11,7 @@ import ( "gorm.io/gorm" "gorm.io/gorm/logger" + indomain "github.com/openinfradev/tks-api/internal/domain" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" ) @@ -124,16 +125,16 @@ func migrateSchema(db *gorm.DB) error { } // Project - if err := db.AutoMigrate(&domain.Project{}); err != nil { + if err := db.AutoMigrate(&indomain.Project{}); err != nil { return err } - if err := db.AutoMigrate(&domain.ProjectMember{}); err != nil { + if err := db.AutoMigrate(&indomain.ProjectMember{}); err != nil { return err } - if err := db.AutoMigrate(&domain.ProjectNamespace{}); err != nil { + if err := db.AutoMigrate(&indomain.ProjectNamespace{}); err != nil { return err } - if err := db.AutoMigrate(&domain.ProjectRole{}); err != nil { + if err := db.AutoMigrate(&indomain.ProjectRole{}); err != nil { return err } diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index b88964fc..89b9882b 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -28,15 +28,15 @@ func NewAlertHandler(h usecase.Usecase) *AlertHandler { } // CreateAlert godoc -// @Tags Alerts -// @Summary Create alert. ADMIN ONLY -// @Description Create alert. ADMIN ONLY -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} nil -// @Router /system-api/organizations/{organizationId}/alerts [post] -// @Security JWT +// @Tags Alerts +// @Summary Create alert. ADMIN ONLY +// @Description Create alert. ADMIN ONLY +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} nil +// @Router /system-api/organizations/{organizationId}/alerts [post] +// @Security JWT func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { /* @@ -72,20 +72,20 @@ func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { } // GetAlert godoc -// @Tags Alerts -// @Summary Get Alerts -// @Description Get Alerts -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetAlertsResponse -// @Router /api/1.0/organizations/{organizationId}/alerts [get] -// @Security JWT +// @Tags Alerts +// @Summary Get Alerts +// @Description Get Alerts +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetAlertsResponse +// @Router /api/1.0/organizations/{organizationId}/alerts [get] +// @Security JWT func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -147,16 +147,16 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { } // GetAlert godoc -// @Tags Alerts -// @Summary Get Alert -// @Description Get Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param alertId path string true "alertId" -// @Success 200 {object} domain.GetAlertResponse -// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [get] -// @Security JWT +// @Tags Alerts +// @Summary Get Alert +// @Description Get Alert +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param alertId path string true "alertId" +// @Success 200 {object} domain.GetAlertResponse +// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [get] +// @Security JWT func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["alertId"] @@ -194,31 +194,31 @@ func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { } // UpdateAlert godoc -// @Tags Alerts -// @Summary Update Alert -// @Description Update Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateAlertRequest true "Update cloud setting request" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [put] -// @Security JWT +// @Tags Alerts +// @Summary Update Alert +// @Description Update Alert +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateAlertRequest true "Update cloud setting request" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [put] +// @Security JWT func (h *AlertHandler) UpdateAlert(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("Need implementation")) } // DeleteAlert godoc -// @Tags Alerts -// @Summary Delete Alert -// @Description Delete Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param alertId path string true "alertId" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [delete] -// @Security JWT +// @Tags Alerts +// @Summary Delete Alert +// @Description Delete Alert +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param alertId path string true "alertId" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [delete] +// @Security JWT func (h *AlertHandler) DeleteAlert(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("Need implementation")) } @@ -234,15 +234,15 @@ func (h *AlertHandler) AlertTest(w http.ResponseWriter, r *http.Request) { } // CreateAlertAction godoc -// @Tags Alerts -// @Summary Create alert action -// @Description Create alert action -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId}/actions [post] -// @Security JWT +// @Tags Alerts +// @Summary Create alert action +// @Description Create alert action +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId}/actions [post] +// @Security JWT func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["alertId"] diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 8d60c7bc..5bd8af55 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -25,15 +25,15 @@ func NewAppGroupHandler(h usecase.Usecase) *AppGroupHandler { } // CreateAppGroup godoc -// @Tags AppGroups -// @Summary Install appGroup -// @Description Install appGroup -// @Accept json -// @Produce json -// @Param body body domain.CreateAppGroupRequest true "create appgroup request" -// @Success 200 {object} domain.CreateAppGroupResponse -// @Router /api/1.0/app-groups [post] -// @Security JWT +// @Tags AppGroups +// @Summary Install appGroup +// @Description Install appGroup +// @Accept json +// @Produce json +// @Param body body domain.CreateAppGroupRequest true "create appgroup request" +// @Success 200 {object} domain.CreateAppGroupResponse +// @Router /api/1.0/app-groups [post] +// @Security JWT func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) { input := domain.CreateAppGroupRequest{} err := UnmarshalRequestInput(r, &input) @@ -60,20 +60,20 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) } // GetAppGroups godoc -// @Tags AppGroups -// @Summary Get appGroup list -// @Description Get appGroup list by giving params -// @Accept json -// @Produce json -// @Param clusterId query string false "clusterId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetAppGroupsResponse -// @Router /api/1.0/app-groups [get] -// @Security JWT +// @Tags AppGroups +// @Summary Get appGroup list +// @Description Get appGroup list by giving params +// @Accept json +// @Produce json +// @Param clusterId query string false "clusterId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetAppGroupsResponse +// @Router /api/1.0/app-groups [get] +// @Security JWT func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -107,15 +107,15 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { } // GetAppGroup godoc -// @Tags AppGroups -// @Summary Get appGroup detail -// @Description Get appGroup detail by appGroupId -// @Accept json -// @Produce json -// @Param appGroupId path string true "appGroupId" -// @Success 200 {object} domain.GetAppGroupResponse -// @Router /api/1.0/app-groups/{appGroupId} [get] -// @Security JWT +// @Tags AppGroups +// @Summary Get appGroup detail +// @Description Get appGroup detail by appGroupId +// @Accept json +// @Produce json +// @Param appGroupId path string true "appGroupId" +// @Success 200 {object} domain.GetAppGroupResponse +// @Router /api/1.0/app-groups/{appGroupId} [get] +// @Security JWT func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["appGroupId"] @@ -143,15 +143,15 @@ func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { } // DeleteAppGroup godoc -// @Tags AppGroups -// @Summary Uninstall appGroup -// @Description Uninstall appGroup -// @Accept json -// @Produce json -// @Param object body string true "body" -// @Success 200 {object} nil -// @Router /api/1.0/app-groups [delete] -// @Security JWT +// @Tags AppGroups +// @Summary Uninstall appGroup +// @Description Uninstall appGroup +// @Accept json +// @Produce json +// @Param object body string true "body" +// @Success 200 {object} nil +// @Router /api/1.0/app-groups [delete] +// @Security JWT func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["appGroupId"] @@ -177,16 +177,16 @@ func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) } // GetApplications godoc -// @Tags AppGroups -// @Summary Get applications -// @Description Get applications -// @Accept json -// @Produce json -// @Param appGroupId path string true "appGroupId" -// @Param applicationType query string true "applicationType" -// @Success 200 {object} domain.GetApplicationsResponse -// @Router /api/1.0/app-groups/{appGroupId}/applications [get] -// @Security JWT +// @Tags AppGroups +// @Summary Get applications +// @Description Get applications +// @Accept json +// @Produce json +// @Param appGroupId path string true "appGroupId" +// @Param applicationType query string true "applicationType" +// @Success 200 {object} domain.GetApplicationsResponse +// @Router /api/1.0/app-groups/{appGroupId}/applications [get] +// @Security JWT func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["appGroupId"] @@ -229,15 +229,15 @@ func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request } // CreateApplication godoc -// @Tags AppGroups -// @Summary Create application -// @Description Create application -// @Accept json -// @Produce json -// @Param object body domain.CreateApplicationRequest true "body" -// @Success 200 {object} nil -// @Router /api/1.0/app-groups/{appGroupId}/applications [post] -// @Security JWT +// @Tags AppGroups +// @Summary Create application +// @Description Create application +// @Accept json +// @Produce json +// @Param object body domain.CreateApplicationRequest true "body" +// @Success 200 {object} nil +// @Router /api/1.0/app-groups/{appGroupId}/applications [post] +// @Security JWT func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["appGroupId"] diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 3ab28a32..ed342f6a 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -78,17 +78,17 @@ func NewAppServeAppHandler(h usecase.Usecase) *AppServeAppHandler { } // CreateAppServeApp godoc -// @Tags AppServeApps -// @Summary Install appServeApp -// @Description Install appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param object body domain.CreateAppServeAppRequest true "Request body to create app" -// @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps [post] -// @Security JWT +// @Tags AppServeApps +// @Summary Install appServeApp +// @Description Install appServeApp +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param object body domain.CreateAppServeAppRequest true "Request body to create app" +// @Success 200 {object} string +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps [post] +// @Security JWT func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -215,22 +215,22 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re } // GetAppServeApps godoc -// @Tags AppServeApps -// @Summary Get appServeApp list -// @Description Get appServeApp list by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param showAll query boolean false "Show all apps including deleted apps" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} []domain.AppServeApp -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] -// @Security JWT +// @Tags AppServeApps +// @Summary Get appServeApp list +// @Description Get appServeApp list by giving params +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param showAll query boolean false "Show all apps including deleted apps" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} []domain.AppServeApp +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] +// @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -272,17 +272,17 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ } // GetAppServeApp godoc -// @Tags AppServeApps -// @Summary Get appServeApp -// @Description Get appServeApp by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "App ID" -// @Success 200 {object} domain.GetAppServeAppResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] -// @Security JWT +// @Tags AppServeApps +// @Summary Get appServeApp +// @Description Get appServeApp by giving params +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Success 200 {object} domain.GetAppServeAppResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] +// @Security JWT func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Request) { ////////////////////////////////////////////////////////////////////////////////////////// // TODO: this API will'be deprecated soon once the new task-related API's are verified. @@ -335,17 +335,17 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque } // GetAppServeAppLatestTask godoc -// @Tags AppServeApps -// @Summary Get latest task from appServeApp -// @Description Get latest task from appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "App ID" -// @Success 200 {object} domain.GetAppServeAppTaskResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task [get] -// @Security JWT +// @Tags AppServeApps +// @Summary Get latest task from appServeApp +// @Description Get latest task from appServeApp +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Success 200 {object} domain.GetAppServeAppTaskResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task [get] +// @Security JWT func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -379,17 +379,17 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * } // GetNumOfAppsOnStack godoc -// @Tags AppServeApps -// @Summary Get number of apps on given stack -// @Description Get number of apps on given stack -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param stackId query string true "Stack ID" -// @Success 200 {object} int64 -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count [get] -// @Security JWT +// @Tags AppServeApps +// @Summary Get number of apps on given stack +// @Description Get number of apps on given stack +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId query string true "Stack ID" +// @Success 200 {object} int64 +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count [get] +// @Security JWT func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -417,21 +417,21 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. } // GetAppServeAppTasksByAppId godoc -// @Tags AppServeApps -// @Summary Get appServeAppTask list -// @Description Get appServeAppTask list by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param sortColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} []domain.AppServeApp -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] -// @Security JWT +// @Tags AppServeApps +// @Summary Get appServeAppTask list +// @Description Get appServeAppTask list by giving params +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param sortColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} []domain.AppServeApp +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] +// @Security JWT func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -467,18 +467,18 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r } // GetAppServeAppTaskDetail godoc -// @Tags AppServeApps -// @Summary Get task detail from appServeApp -// @Description Get task detail from appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "App ID" -// @Param taskId path string true "Task ID" -// @Success 200 {object} domain.GetAppServeAppTaskResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId} [get] -// @Security JWT +// @Tags AppServeApps +// @Summary Get task detail from appServeApp +// @Description Get task detail from appServeApp +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Param taskId path string true "Task ID" +// @Success 200 {object} domain.GetAppServeAppTaskResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId} [get] +// @Security JWT func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -635,16 +635,16 @@ func makeStage(task *domain.AppServeAppTask, app *domain.AppServeApp, pl string) } // IsAppServeAppExist godoc -// @Tags AppServeApps -// @Summary Get appServeApp -// @Description Get appServeApp by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Success 200 {object} bool -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist [get] -// @Security JWT +// @Tags AppServeApps +// @Summary Get appServeApp +// @Description Get appServeApp by giving params +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} bool +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist [get] +// @Security JWT func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -676,17 +676,17 @@ func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.R } // IsAppServeAppNameExist godoc -// @Tags AppServeApps -// @Summary Check duplicate appServeAppName -// @Description Check duplicate appServeAppName by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param name path string true "name" -// @Success 200 {object} bool -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence [get] -// @Security JWT +// @Tags AppServeApps +// @Summary Check duplicate appServeAppName +// @Description Check duplicate appServeAppName by giving params +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param name path string true "name" +// @Success 200 {object} bool +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence [get] +// @Security JWT func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -716,18 +716,18 @@ func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *ht } // UpdateAppServeApp godoc -// @Tags AppServeApps -// @Summary Update appServeApp -// @Description Update appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "App ID" -// @Param object body domain.UpdateAppServeAppRequest true "Request body to update app" -// @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [put] -// @Security JWT +// @Tags AppServeApps +// @Summary Update appServeApp +// @Description Update appServeApp +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Param object body domain.UpdateAppServeAppRequest true "Request body to update app" +// @Success 200 {object} string +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [put] +// @Security JWT func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -826,18 +826,18 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re } // UpdateAppServeAppStatus godoc -// @Tags AppServeApps -// @Summary Update app status -// @Description Update app status -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "App ID" -// @Param body body domain.UpdateAppServeAppStatusRequest true "Request body to update app status" -// @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status [patch] -// @Security JWT +// @Tags AppServeApps +// @Summary Update app status +// @Description Update app status +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Param body body domain.UpdateAppServeAppStatusRequest true "Request body to update app status" +// @Success 200 {object} string +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status [patch] +// @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -870,18 +870,18 @@ func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *h } // UpdateAppServeAppEndpoint godoc -// @Tags AppServeApps -// @Summary Update app endpoint -// @Description Update app endpoint -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "appId" -// @Param body body domain.UpdateAppServeAppEndpointRequest true "Request body to update app endpoint" -// @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint [patch] -// @Security JWT +// @Tags AppServeApps +// @Summary Update app endpoint +// @Description Update app endpoint +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "appId" +// @Param body body domain.UpdateAppServeAppEndpointRequest true "Request body to update app endpoint" +// @Success 200 {object} string +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint [patch] +// @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -919,17 +919,17 @@ func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r } // DeleteAppServeApp godoc -// @Tags AppServeApps -// @Summary Uninstall appServeApp -// @Description Uninstall appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "App ID" -// @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [delete] -// @Security JWT +// @Tags AppServeApps +// @Summary Uninstall appServeApp +// @Description Uninstall appServeApp +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Success 200 {object} string +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [delete] +// @Security JWT func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -956,18 +956,18 @@ func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Re } // RollbackAppServeApp godoc -// @Tags AppServeApps -// @Summary Rollback appServeApp -// @Description Rollback appServeApp -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "App ID" -// @Param object body domain.RollbackAppServeAppRequest true "Request body to rollback app" -// @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback [post] -// @Security JWT +// @Tags AppServeApps +// @Summary Rollback appServeApp +// @Description Rollback appServeApp +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Param object body domain.RollbackAppServeAppRequest true "Request body to rollback app" +// @Success 200 {object} string +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback [post] +// @Security JWT func (h *AppServeAppHandler) RollbackAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 7871fe88..0596fa88 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -26,34 +26,34 @@ func NewAuditHandler(h usecase.Usecase) *AuditHandler { } // CreateAudit godoc -// @Tags Audits -// @Summary Create Audit -// @Description Create Audit -// @Accept json -// @Produce json -// @Param body body domain.CreateAuditRequest true "create audit request" -// @Success 200 {object} domain.CreateAuditResponse -// @Router /api/1.0/organizations/{organizationId}/audits [post] -// @Security JWT +// @Tags Audits +// @Summary Create Audit +// @Description Create Audit +// @Accept json +// @Produce json +// @Param body body domain.CreateAuditRequest true "create audit request" +// @Success 200 {object} domain.CreateAuditResponse +// @Router /api/1.0/organizations/{organizationId}/audits [post] +// @Security JWT func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) } // GetAudit godoc -// @Tags Audits -// @Summary Get Audits -// @Description Get Audits -// @Accept json -// @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filter query []string false "filters" -// @Param or query []string false "filters" -// @Success 200 {object} domain.GetAuditsResponse -// @Router /api/1.0/organizations/{organizationId}/audits [get] -// @Security JWT +// @Tags Audits +// @Summary Get Audits +// @Description Get Audits +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filter query []string false "filters" +// @Param or query []string false "filters" +// @Success 200 {object} domain.GetAuditsResponse +// @Router /api/1.0/organizations/{organizationId}/audits [get] +// @Security JWT func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -86,15 +86,15 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { } // GetAudit godoc -// @Tags Audits -// @Summary Get Audit -// @Description Get Audit -// @Accept json -// @Produce json -// @Param auditId path string true "auditId" -// @Success 200 {object} domain.GetAuditResponse -// @Router /api/1.0/organizations/{organizationId}/audits/{auditId} [get] -// @Security JWT +// @Tags Audits +// @Summary Get Audit +// @Description Get Audit +// @Accept json +// @Produce json +// @Param auditId path string true "auditId" +// @Success 200 {object} domain.GetAuditResponse +// @Router /api/1.0/organizations/{organizationId}/audits/{auditId} [get] +// @Security JWT func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["auditId"] @@ -126,15 +126,15 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { } // DeleteAudit godoc -// @Tags Audits -// @Summary Delete Audit 'NOT IMPLEMENTED' -// @Description Delete Audit -// @Accept json -// @Produce json -// @Param auditId path string true "auditId" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/audits/{auditId} [delete] -// @Security JWT +// @Tags Audits +// @Summary Delete Audit 'NOT IMPLEMENTED' +// @Description Delete Audit +// @Accept json +// @Produce json +// @Param auditId path string true "auditId" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/audits/{auditId} [delete] +// @Security JWT func (h *AuditHandler) DeleteAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) } diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index d101be63..e12c5108 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -41,14 +41,14 @@ func NewAuthHandler(h usecase.Usecase) IAuthHandler { } // Login godoc -// @Tags Auth -// @Summary login -// @Description login -// @Accept json -// @Produce json -// @Param body body domain.LoginRequest true "account info" -// @Success 200 {object} domain.LoginResponse "user detail" -// @Router /api/1.0/auth/login [post] +// @Tags Auth +// @Summary login +// @Description login +// @Accept json +// @Produce json +// @Param body body domain.LoginRequest true "account info" +// @Success 200 {object} domain.LoginResponse "user detail" +// @Router /api/1.0/auth/login [post] func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { input := domain.LoginRequest{} err := UnmarshalRequestInput(r, &input) @@ -104,14 +104,14 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { } // Logout godoc -// @Tags Auth -// @Summary logout -// @Description logout -// @Accept json -// @Produce json -// @Success 200 {object} domain.LogoutResponse -// @Router /api/1.0/auth/logout [post] -// @Security JWT +// @Tags Auth +// @Summary logout +// @Description logout +// @Accept json +// @Produce json +// @Success 200 {object} domain.LogoutResponse +// @Router /api/1.0/auth/logout [post] +// @Security JWT func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -163,15 +163,15 @@ func (h *AuthHandler) RefreshToken(w http.ResponseWriter, r *http.Request) { } // FindId godoc -// @Tags Auth -// @Summary Request to find forgotten ID -// @Description This API allows users to find their account ID by submitting required information -// @Accept json -// @Produce json -// @Param body body domain.FindIdRequest true "Request body for finding the account ID including {organization ID, email, username, 6 digit code}" -// @Success 200 {object} domain.FindIdResponse -// @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/auth/find-id/verification [post] +// @Tags Auth +// @Summary Request to find forgotten ID +// @Description This API allows users to find their account ID by submitting required information +// @Accept json +// @Produce json +// @Param body body domain.FindIdRequest true "Request body for finding the account ID including {organization ID, email, username, 6 digit code}" +// @Success 200 {object} domain.FindIdResponse +// @Failure 400 {object} httpErrors.RestError +// @Router /api/1.0/auth/find-id/verification [post] func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { input := domain.FindIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -194,15 +194,15 @@ func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { } // FindPassword godoc -// @Tags Auth -// @Summary Request to find forgotten password -// @Description This API allows users to reset their forgotten password by submitting required information -// @Accept json -// @Produce json -// @Param body body domain.FindPasswordRequest true "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}" -// @Success 200 -// @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/auth/find-password/verification [post] +// @Tags Auth +// @Summary Request to find forgotten password +// @Description This API allows users to reset their forgotten password by submitting required information +// @Accept json +// @Produce json +// @Param body body domain.FindPasswordRequest true "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}" +// @Success 200 +// @Failure 400 {object} httpErrors.RestError +// @Router /api/1.0/auth/find-password/verification [post] func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { input := domain.FindPasswordRequest{} err := UnmarshalRequestInput(r, &input) @@ -222,15 +222,15 @@ func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { } // VerifyIdentityForLostId godoc -// @Tags Auth -// @Summary Request to verify identity for lost id -// @Description This API allows users to verify their identity for lost id by submitting required information -// @Accept json -// @Produce json -// @Param body body domain.VerifyIdentityForLostIdRequest true "Request body for verifying identity for lost id including {organization ID, email, username}" -// @Success 200 {object} domain.VerifyIdentityForLostIdResponse -// @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/auth/find-id/code [post] +// @Tags Auth +// @Summary Request to verify identity for lost id +// @Description This API allows users to verify their identity for lost id by submitting required information +// @Accept json +// @Produce json +// @Param body body domain.VerifyIdentityForLostIdRequest true "Request body for verifying identity for lost id including {organization ID, email, username}" +// @Success 200 {object} domain.VerifyIdentityForLostIdResponse +// @Failure 400 {object} httpErrors.RestError +// @Router /api/1.0/auth/find-id/code [post] func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Request) { input := domain.VerifyIdentityForLostIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -252,15 +252,15 @@ func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Req } // VerifyIdentityForLostPassword godoc -// @Tags Auth -// @Summary Request to verify identity for lost password -// @Description This API allows users to verify their identity for lost password by submitting required information -// @Accept json -// @Produce json -// @Param body body domain.VerifyIdentityForLostPasswordRequest true "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}" -// @Success 200 {object} domain.VerifyIdentityForLostPasswordResponse -// @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/auth/find-password/code [post] +// @Tags Auth +// @Summary Request to verify identity for lost password +// @Description This API allows users to verify their identity for lost password by submitting required information +// @Accept json +// @Produce json +// @Param body body domain.VerifyIdentityForLostPasswordRequest true "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}" +// @Success 200 {object} domain.VerifyIdentityForLostPasswordResponse +// @Failure 400 {object} httpErrors.RestError +// @Router /api/1.0/auth/find-password/code [post] func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *http.Request) { input := domain.VerifyIdentityForLostPasswordRequest{} err := UnmarshalRequestInput(r, &input) @@ -282,14 +282,14 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht } // Login godoc -// @Tags Auth -// @Summary ping with token -// @Description ping with token -// @Accept json -// @Produce json -// @Param body body domain.PingTokenRequest true "token info" -// @Success 200 {object} nil -// @Router /api/1.0/auth/ping [post] +// @Tags Auth +// @Summary ping with token +// @Description ping with token +// @Accept json +// @Produce json +// @Param body body domain.PingTokenRequest true "token info" +// @Success 200 {object} nil +// @Router /api/1.0/auth/ping [post] func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { input := domain.PingTokenRequest{} err := UnmarshalRequestInput(r, &input) @@ -309,12 +309,12 @@ func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { } // VerifyToken godoc -// @Tags Auth -// @Summary verify token -// @Description verify token -// @Success 200 {object} nil -// @Failure 401 {object} nil -// @Router /api/1.0/auth/verify-token [get] +// @Tags Auth +// @Summary verify token +// @Description verify token +// @Success 200 {object} nil +// @Failure 401 {object} nil +// @Router /api/1.0/auth/verify-token [get] func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { token, ok := request.TokenFrom(r.Context()) diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index c9b6315d..c9ab051b 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -27,16 +27,16 @@ func NewCloudAccountHandler(h usecase.Usecase) *CloudAccountHandler { } // CreateCloudAccount godoc -// @Tags CloudAccounts -// @Summary Create CloudAccount -// @Description Create CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.CreateCloudAccountRequest true "create cloud setting request" -// @Success 200 {object} domain.CreateCloudAccountResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts [post] -// @Security JWT +// @Tags CloudAccounts +// @Summary Create CloudAccount +// @Description Create CloudAccount +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.CreateCloudAccountRequest true "create cloud setting request" +// @Success 200 {object} domain.CreateCloudAccountResponse +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts [post] +// @Security JWT func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -71,20 +71,20 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. } // GetCloudAccount godoc -// @Tags CloudAccounts -// @Summary Get CloudAccounts -// @Description Get CloudAccounts -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetCloudAccountsResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts [get] -// @Security JWT +// @Tags CloudAccounts +// @Summary Get CloudAccounts +// @Description Get CloudAccounts +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetCloudAccountsResponse +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts [get] +// @Security JWT func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -118,16 +118,16 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re } // GetCloudAccount godoc -// @Tags CloudAccounts -// @Summary Get CloudAccount -// @Description Get CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param cloudAccountId path string true "cloudAccountId" -// @Success 200 {object} domain.GetCloudAccountResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [get] -// @Security JWT +// @Tags CloudAccounts +// @Summary Get CloudAccount +// @Description Get CloudAccount +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param cloudAccountId path string true "cloudAccountId" +// @Success 200 {object} domain.GetCloudAccountResponse +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [get] +// @Security JWT func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["cloudAccountId"] @@ -157,16 +157,16 @@ func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Req } // UpdateCloudAccount godoc -// @Tags CloudAccounts -// @Summary Update CloudAccount -// @Description Update CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateCloudAccountRequest true "Update cloud setting request" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [put] -// @Security JWT +// @Tags CloudAccounts +// @Summary Update CloudAccount +// @Description Update CloudAccount +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateCloudAccountRequest true "Update cloud setting request" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [put] +// @Security JWT func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["cloudAccountId"] @@ -211,17 +211,17 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. } // DeleteCloudAccount godoc -// @Tags CloudAccounts -// @Summary Delete CloudAccount -// @Description Delete CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.DeleteCloudAccountRequest true "Delete cloud setting request" -// @Param cloudAccountId path string true "cloudAccountId" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [delete] -// @Security JWT +// @Tags CloudAccounts +// @Summary Delete CloudAccount +// @Description Delete CloudAccount +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.DeleteCloudAccountRequest true "Delete cloud setting request" +// @Param cloudAccountId path string true "cloudAccountId" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [delete] +// @Security JWT func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) cloudAccountId, ok := vars["cloudAccountId"] @@ -259,16 +259,16 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. } // DeleteForceCloudAccount godoc -// @Tags CloudAccounts -// @Summary Delete Force CloudAccount -// @Description Delete Force CloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param cloudAccountId path string true "cloudAccountId" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error [delete] -// @Security JWT +// @Tags CloudAccounts +// @Summary Delete Force CloudAccount +// @Description Delete Force CloudAccount +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param cloudAccountId path string true "cloudAccountId" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error [delete] +// @Security JWT func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) cloudAccountId, ok := vars["cloudAccountId"] @@ -293,16 +293,16 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * } // CheckCloudAccountName godoc -// @Tags CloudAccounts -// @Summary Check name for cloudAccount -// @Description Check name for cloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param name path string true "name" -// @Success 200 {object} domain.CheckCloudAccountNameResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence [GET] -// @Security JWT +// @Tags CloudAccounts +// @Summary Check name for cloudAccount +// @Description Check name for cloudAccount +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param name path string true "name" +// @Success 200 {object} domain.CheckCloudAccountNameResponse +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence [GET] +// @Security JWT func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *http.Request) { user, ok := request.UserFrom(r.Context()) if !ok { @@ -335,16 +335,16 @@ func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *ht } // CheckAwsAccountId godoc -// @Tags CloudAccounts -// @Summary Check awsAccountId for cloudAccount -// @Description Check awsAccountId for cloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param awsAccountId path string true "awsAccountId" -// @Success 200 {object} domain.CheckCloudAccountAwsAccountIdResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence [GET] -// @Security JWT +// @Tags CloudAccounts +// @Summary Check awsAccountId for cloudAccount +// @Description Check awsAccountId for cloudAccount +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param awsAccountId path string true "awsAccountId" +// @Success 200 {object} domain.CheckCloudAccountAwsAccountIdResponse +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence [GET] +// @Security JWT func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) awsAccountId, ok := vars["awsAccountId"] @@ -371,16 +371,16 @@ func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.R } // GetResourceQuota godoc -// @Tags CloudAccounts -// @Summary Get resource quota by cloudAccount -// @Description Get resource quota by cloudAccount -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param cloudAccountId path string true "cloudAccountId" -// @Success 200 {object} domain.GetCloudAccountResourceQuotaResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota [GET] -// @Security JWT +// @Tags CloudAccounts +// @Summary Get resource quota by cloudAccount +// @Description Get resource quota by cloudAccount +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param cloudAccountId path string true "cloudAccountId" +// @Success 200 {object} domain.GetCloudAccountResourceQuotaResponse +// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota [GET] +// @Security JWT func (h *CloudAccountHandler) GetResourceQuota(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["cloudAccountId"] diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 528dcefe..45a0f7f3 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -25,20 +25,20 @@ func NewClusterHandler(h usecase.Usecase) *ClusterHandler { } // GetClusters godoc -// @Tags Clusters -// @Summary Get clusters -// @Description Get cluster list -// @Accept json -// @Produce json -// @Param organizationId query string false "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetClustersResponse -// @Router /api/1.0/clusters [get] -// @Security JWT +// @Tags Clusters +// @Summary Get clusters +// @Description Get cluster list +// @Accept json +// @Produce json +// @Param organizationId query string false "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetClustersResponse +// @Router /api/1.0/clusters [get] +// @Security JWT func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -67,15 +67,15 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { } // GetCluster godoc -// @Tags Clusters -// @Summary Get cluster -// @Description Get cluster detail -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.Cluster -// @Router /api/1.0/clusters/{clusterId} [get] -// @Security JWT +// @Tags Clusters +// @Summary Get cluster +// @Description Get cluster detail +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} domain.Cluster +// @Router /api/1.0/clusters/{clusterId} [get] +// @Security JWT func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -99,15 +99,15 @@ func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { } // GetClusterSiteValues godoc -// @Tags Clusters -// @Summary Get cluster site values for creating -// @Description Get cluster site values for creating -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.ClusterSiteValuesResponse -// @Router /api/1.0/clusters/{clusterId}/site-values [get] -// @Security JWT +// @Tags Clusters +// @Summary Get cluster site values for creating +// @Description Get cluster site values for creating +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} domain.ClusterSiteValuesResponse +// @Router /api/1.0/clusters/{clusterId}/site-values [get] +// @Security JWT func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -129,15 +129,15 @@ func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Req } // CreateCluster godoc -// @Tags Clusters -// @Summary Create cluster -// @Description Create cluster -// @Accept json -// @Produce json -// @Param body body domain.CreateClusterRequest true "create cluster request" -// @Success 200 {object} domain.CreateClusterResponse -// @Router /api/1.0/clusters [post] -// @Security JWT +// @Tags Clusters +// @Summary Create cluster +// @Description Create cluster +// @Accept json +// @Produce json +// @Param body body domain.CreateClusterRequest true "create cluster request" +// @Success 200 {object} domain.CreateClusterResponse +// @Router /api/1.0/clusters [post] +// @Security JWT func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { input := domain.CreateClusterRequest{} err := UnmarshalRequestInput(r, &input) @@ -188,15 +188,15 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { } // ImportCluster godoc -// @Tags Clusters -// @Summary Import cluster -// @Description Import cluster -// @Accept json -// @Produce json -// @Param body body domain.ImportClusterRequest true "import cluster request" -// @Success 200 {object} domain.ImportClusterResponse -// @Router /api/1.0/clusters/import [post] -// @Security JWT +// @Tags Clusters +// @Summary Import cluster +// @Description Import cluster +// @Accept json +// @Produce json +// @Param body body domain.ImportClusterRequest true "import cluster request" +// @Success 200 {object} domain.ImportClusterResponse +// @Router /api/1.0/clusters/import [post] +// @Security JWT func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { input := domain.ImportClusterRequest{} err := UnmarshalRequestInput(r, &input) @@ -230,15 +230,15 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { } // InstallCluster godoc -// @Tags Clusters -// @Summary Install cluster on tks cluster -// @Description Install cluster on tks cluster -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} nil -// @Router /api/1.0/clusters/{clusterId}/install [post] -// @Security JWT +// @Tags Clusters +// @Summary Install cluster on tks cluster +// @Description Install cluster on tks cluster +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} nil +// @Router /api/1.0/clusters/{clusterId}/install [post] +// @Security JWT func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -257,15 +257,15 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) } // DeleteCluster godoc -// @Tags Clusters -// @Summary Delete cluster -// @Description Delete cluster -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.Cluster -// @Router /api/1.0/clusters/{clusterId} [delete] -// @Security JWT +// @Tags Clusters +// @Summary Delete cluster +// @Description Delete cluster +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} domain.Cluster +// @Router /api/1.0/clusters/{clusterId} [delete] +// @Security JWT func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -284,14 +284,14 @@ func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { } // CreateBootstrapKubeconfig godoc -// @Tags Clusters -// @Summary Create bootstrap kubeconfig for BYOH -// @Description Create bootstrap kubeconfig for BYOH -// @Accept json -// @Produce json -// @Success 200 {object} domain.CreateBootstrapKubeconfigResponse -// @Router /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig [post] -// @Security JWT +// @Tags Clusters +// @Summary Create bootstrap kubeconfig for BYOH +// @Description Create bootstrap kubeconfig for BYOH +// @Accept json +// @Produce json +// @Success 200 {object} domain.CreateBootstrapKubeconfigResponse +// @Router /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig [post] +// @Security JWT func (h *ClusterHandler) CreateBootstrapKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -312,14 +312,14 @@ func (h *ClusterHandler) CreateBootstrapKubeconfig(w http.ResponseWriter, r *htt } // GetBootstrapKubeconfig godoc -// @Tags Clusters -// @Summary Get bootstrap kubeconfig for BYOH -// @Description Get bootstrap kubeconfig for BYOH -// @Accept json -// @Produce json -// @Success 200 {object} domain.GetBootstrapKubeconfigResponse -// @Router /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig [get] -// @Security JWT +// @Tags Clusters +// @Summary Get bootstrap kubeconfig for BYOH +// @Description Get bootstrap kubeconfig for BYOH +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetBootstrapKubeconfigResponse +// @Router /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig [get] +// @Security JWT func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -341,15 +341,15 @@ func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.R } // GetNodes godoc -// @Tags Clusters -// @Summary Get nodes information for BYOH -// @Description Get nodes information for BYOH -// @Accept json -// @Produce json -// @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.GetClusterNodesResponse -// @Router /api/1.0/clusters/{clusterId}/nodes [get] -// @Security JWT +// @Tags Clusters +// @Summary Get nodes information for BYOH +// @Description Get nodes information for BYOH +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} domain.GetClusterNodesResponse +// @Router /api/1.0/clusters/{clusterId}/nodes [get] +// @Security JWT func (h *ClusterHandler) GetNodes(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["clusterId"] @@ -377,14 +377,14 @@ func (h *ClusterHandler) GetNodes(w http.ResponseWriter, r *http.Request) { func (h *ClusterHandler) GetKubernetesInfo(w http.ResponseWriter, r *http.Request) { // GetKubernetesInfo godoc - // @Tags Clusters - // @Summary Get kubernetes info - // @Description Get kubernetes info for cluster - // @Accept json - // @Produce json - // @Param clusterId path string true "clusterId" - // @Success 200 {object} ClusterKubeInfo - // @Router /clusters/{clusterId}/kubeInfo [get] + // @Tags Clusters + // @Summary Get kubernetes info + // @Description Get kubernetes info for cluster + // @Accept json + // @Produce json + // @Param clusterId path string true "clusterId" + // @Success 200 {object} ClusterKubeInfo + // @Router /clusters/{clusterId}/kubeInfo [get] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -447,14 +447,14 @@ func (h *ClusterHandler) GetKubernetesInfo(w http.ResponseWriter, r *http.Reques func (h *ClusterHandler) GetClusterApplications(w http.ResponseWriter, r *http.Request) { // GetClusterApplications godoc - // @Tags Clusters - // @Summary Get application list - // @Description Get application list by clusterId - // @Accept json - // @Produce json - // @Param clusterId path string false "clusterId" - // @Success 200 {object} []ApplicationJson - // @Router /clusters/{clusterId}/applications [get] + // @Tags Clusters + // @Summary Get application list + // @Description Get application list by clusterId + // @Accept json + // @Produce json + // @Param clusterId path string false "clusterId" + // @Success 200 {object} []ApplicationJson + // @Router /clusters/{clusterId}/applications [get] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -596,14 +596,14 @@ func (h *ClusterHandler) GetClusterApplicationsKubeInfo(w http.ResponseWriter, r func (h *ClusterHandler) GetClusterKubeConfig(w http.ResponseWriter, r *http.Request) { // GetClusterKubeConfig godoc - // @Tags Clusters - // @Summary Get kubernetes kubeconfig - // @Description Get kubernetes kubeconfig for cluster - // @Accept json - // @Produce json - // @Param clusterId path string true "clusterId" - // @Success 200 {object} object - // @Router /clusters/{clusterId}/kubeconfig [get] + // @Tags Clusters + // @Summary Get kubernetes kubeconfig + // @Description Get kubernetes kubeconfig for cluster + // @Accept json + // @Produce json + // @Param clusterId path string true "clusterId" + // @Success 200 {object} object + // @Router /clusters/{clusterId}/kubeconfig [get] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -635,14 +635,14 @@ func (h *ClusterHandler) GetClusterKubeConfig(w http.ResponseWriter, r *http.Req func (h *ClusterHandler) GetClusterKubeResources(w http.ResponseWriter, r *http.Request) { // GetClusterKubeResources godoc - // @Tags Clusters - // @Summary Get kubernetes resources - // @Description Get kubernetes resources - // @Accept json - // @Produce json - // @Param clusterId path string true "clusterId" - // @Success 200 {object} ClusterJson - // @Router /clusters/{clusterId}/kube-resources [get] + // @Tags Clusters + // @Summary Get kubernetes resources + // @Description Get kubernetes resources + // @Accept json + // @Produce json + // @Param clusterId path string true "clusterId" + // @Success 200 {object} ClusterJson + // @Router /clusters/{clusterId}/kube-resources [get] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] @@ -828,14 +828,14 @@ func (h *ClusterHandler) GetClusterKubeResources(w http.ResponseWriter, r *http. func (h *ClusterHandler) SetIstioLabel(w http.ResponseWriter, r *http.Request) { // SetIstioLabel godoc - // @Tags Clusters - // @Summary Set Istio label to namespace - // @Description Set istio label to namespace on kubernetes - // @Accept json - // @Produce json - // @Param clusterId path string true "clusterId" - // @Success 200 {object} object - // @Router /clusters/{clusterId}/kube-resources/{namespace}/istio-label [post] + // @Tags Clusters + // @Summary Set Istio label to namespace + // @Description Set istio label to namespace on kubernetes + // @Accept json + // @Produce json + // @Param clusterId path string true "clusterId" + // @Success 200 {object} object + // @Router /clusters/{clusterId}/kube-resources/{namespace}/istio-label [post] /* vars := mux.Vars(r) clusterId, ok := vars["clusterId"] diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index ef1ba0d7..f1d07433 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -24,18 +24,18 @@ func NewDashboardHandler(h usecase.Usecase) *DashboardHandler { } // GetCharts godoc -// @Tags Dashboards -// @Summary Get charts data -// @Description Get charts data -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param chartType query string false "chartType" -// @Param duration query string true "duration" -// @Param interval query string true "interval" -// @Success 200 {object} domain.GetDashboardChartsResponse -// @Router /api/1.0/organizations/{organizationId}/dashboard/charts [get] -// @Security JWT +// @Tags Dashboards +// @Summary Get charts data +// @Description Get charts data +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param chartType query string false "chartType" +// @Param duration query string true "duration" +// @Param interval query string true "interval" +// @Success 200 {object} domain.GetDashboardChartsResponse +// @Router /api/1.0/organizations/{organizationId}/dashboard/charts [get] +// @Security JWT func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -83,18 +83,18 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { } // GetCharts godoc -// @Tags Dashboards -// @Summary Get chart data -// @Description Get chart data -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param chartType path string true "chartType" -// @Param duration query string true "duration" -// @Param interval query string true "interval" -// @Success 200 {object} domain.GetDashboardChartResponse -// @Router /api/1.0/organizations/{organizationId}/dashboard/charts/{chartType} [get] -// @Security JWT +// @Tags Dashboards +// @Summary Get chart data +// @Description Get chart data +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param chartType path string true "chartType" +// @Param duration query string true "duration" +// @Param interval query string true "interval" +// @Success 200 {object} domain.GetDashboardChartResponse +// @Router /api/1.0/organizations/{organizationId}/dashboard/charts/{chartType} [get] +// @Security JWT func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -159,15 +159,15 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { } // GetStacks godoc -// @Tags Dashboards -// @Summary Get stacks -// @Description Get stacks -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.GetDashboardStacksResponse -// @Router /api/1.0/organizations/{organizationId}/dashboard/stacks [get] -// @Security JWT +// @Tags Dashboards +// @Summary Get stacks +// @Description Get stacks +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetDashboardStacksResponse +// @Router /api/1.0/organizations/{organizationId}/dashboard/stacks [get] +// @Security JWT func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -200,15 +200,15 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } // GetResources godoc -// @Tags Dashboards -// @Summary Get resources -// @Description Get resources -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.GetDashboardResourcesResponse -// @Router /api/1.0/organizations/{organizationId}/dashboard/resources [get] -// @Security JWT +// @Tags Dashboards +// @Summary Get resources +// @Description Get resources +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetDashboardResourcesResponse +// @Router /api/1.0/organizations/{organizationId}/dashboard/resources [get] +// @Security JWT func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 8a3b7868..d5a1f0f3 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -31,15 +31,15 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { } // CreateOrganization godoc -// @Tags Organizations -// @Summary Create organization -// @Description Create organization -// @Accept json -// @Produce json -// @Param body body domain.CreateOrganizationRequest true "create organization request" -// @Success 200 {object} object -// @Router /api/1.0/organizations [post] -// @Security JWT +// @Tags Organizations +// @Summary Create organization +// @Description Create organization +// @Accept json +// @Produce json +// @Param body body domain.CreateOrganizationRequest true "create organization request" +// @Success 200 {object} object +// @Router /api/1.0/organizations [post] +// @Security JWT func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http.Request) { input := domain.CreateOrganizationRequest{} @@ -126,19 +126,19 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } // GetOrganizations godoc -// @Tags Organizations -// @Summary Get organization list -// @Description Get organization list -// @Accept json -// @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} []domain.ListOrganizationBody -// @Router /api/1.0/organizations [get] -// @Security JWT +// @Tags Organizations +// @Summary Get organization list +// @Description Get organization list +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} []domain.ListOrganizationBody +// @Router /api/1.0/organizations [get] +// @Security JWT func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) @@ -169,15 +169,15 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re } // GetOrganization godoc -// @Tags Organizations -// @Summary Get organization detail -// @Description Get organization detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.GetOrganizationResponse -// @Router /api/1.0/organizations/{organizationId} [get] -// @Security JWT +// @Tags Organizations +// @Summary Get organization detail +// @Description Get organization detail +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetOrganizationResponse +// @Router /api/1.0/organizations/{organizationId} [get] +// @Security JWT func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -206,15 +206,15 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req } // DeleteOrganization godoc -// @Tags Organizations -// @Summary Delete organization -// @Description Delete organization -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.Organization -// @Router /api/1.0/organizations/{organizationId} [delete] -// @Security JWT +// @Tags Organizations +// @Summary Delete organization +// @Description Delete organization +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.Organization +// @Router /api/1.0/organizations/{organizationId} [delete] +// @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -253,16 +253,16 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. } // UpdateOrganization godoc -// @Tags Organizations -// @Summary Update organization detail -// @Description Update organization detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateOrganizationRequest true "update organization request" -// @Success 200 {object} domain.UpdateOrganizationResponse -// @Router /api/1.0/organizations/{organizationId} [put] -// @Security JWT +// @Tags Organizations +// @Summary Update organization detail +// @Description Update organization detail +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateOrganizationRequest true "update organization request" +// @Success 200 {object} domain.UpdateOrganizationResponse +// @Router /api/1.0/organizations/{organizationId} [put] +// @Security JWT func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -298,16 +298,16 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. } // UpdatePrimaryCluster godoc -// @Tags Organizations -// @Summary Update primary cluster -// @Description Update primary cluster -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdatePrimaryClusterRequest true "update primary cluster request" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/primary-cluster [patch] -// @Security JWT +// @Tags Organizations +// @Summary Update primary cluster +// @Description Update primary cluster +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdatePrimaryClusterRequest true "update primary cluster request" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/primary-cluster [patch] +// @Security JWT func (h *OrganizationHandler) UpdatePrimaryCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index b67a6b8e..0b473a32 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -26,13 +26,13 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { } // GetPermissionTemplates godoc -// @Tags Permission -// @Summary Get Permission Templates -// @Description Get Permission Templates -// @Accept json -// @Produce json -// @Success 200 {object} domain.PermissionSet -// @Router /permissions/templates [get] +// @Tags Permission +// @Summary Get Permission Templates +// @Description Get Permission Templates +// @Accept json +// @Produce json +// @Success 200 {object} domain.PermissionSet +// @Router /permissions/templates [get] func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { permissionSet := domain.NewDefaultPermissionSet() @@ -48,13 +48,13 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http } // GetPermissionsByRoleId godoc -// @Tags Permission -// @Summary Get Permissions By Role ID -// @Description Get Permissions By Role ID -// @Accept json -// @Produce json -// @Success 200 {object} domain.PermissionSet -// @Router /roles/{roleId}/permissions [get] +// @Tags Permission +// @Summary Get Permissions By Role ID +// @Description Get Permissions By Role ID +// @Accept json +// @Produce json +// @Success 200 {object} domain.PermissionSet +// @Router /roles/{roleId}/permissions [get] func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { // path parameter var roleId string @@ -85,15 +85,15 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http } // UpdatePermissionsByRoleId godoc -// @Tags Permission -// @Summary Update Permissions By Role ID -// @Description Update Permissions By Role ID -// @Accept json -// @Produce json -// @Param roleId path string true "Role ID" -// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" -// @Success 200 -// @Router /roles/{roleId}/permissions [put] +// @Tags Permission +// @Summary Update Permissions By Role ID +// @Description Update Permissions By Role ID +// @Accept json +// @Produce json +// @Param roleId path string true "Role ID" +// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" +// @Success 200 +// @Router /roles/{roleId}/permissions [put] func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { // path parameter log.Debug("UpdatePermissionsByRoleId Called") diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 5f724ce5..fb61f645 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -12,8 +12,9 @@ import ( "github.com/openinfradev/tks-api/internal/serializer" "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/domain" "github.com/openinfradev/tks-api/internal/usecase" - "github.com/openinfradev/tks-api/pkg/domain" + outdomain "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" ) @@ -65,16 +66,17 @@ func NewProjectHandler(u usecase.Usecase) IProjectHandler { } // CreateProject godoc -// @Tags Projects -// @Summary Create new project -// @Description Create new project -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param request body domain.CreateProjectRequest true "Request body to create project" -// @Success 200 {object} domain.CreateProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects [post] -// @Security JWT +// +// @Tags Projects +// @Summary Create new project +// @Description Create new project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param request body outdomain.CreateProjectRequest true "Request body to create project" +// @Success 200 {object} outdomain.CreateProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects [post] +// @Security JWT func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -84,7 +86,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { "C_INVALID_ORGANIZATION_ID", "")) return } - var projectReq domain.CreateProjectRequest + var projectReq outdomain.CreateProjectRequest if err := UnmarshalRequestInput(r, &projectReq); err != nil { ErrorJSON(w, r, err) return @@ -138,22 +140,23 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } - out := domain.CreateProjectResponse{ProjectId: projectId} + out := outdomain.CreateProjectResponse{ProjectId: projectId} ResponseJSON(w, r, http.StatusOK, out) } // GetProjects godoc -// @Tags Projects -// @Summary Get projects -// @Description Get projects -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param query query string false "(all | only)" -// @Success 200 {object} domain.GetProjectsResponse -// @Router /api/1.0/organizations/{organizationId}/projects [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get projects +// @Description Get projects +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param query query string false "(all | only)" +// @Success 200 {object} outdomain.GetProjectsResponse +// @Router /api/1.0/organizations/{organizationId}/projects [get] +// @Security JWT func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -182,30 +185,31 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { return } - var out domain.GetProjectsResponse + var out outdomain.GetProjectsResponse out.Projects = pr if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } if pr == nil { - ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectsResponse{}) + ResponseJSON(w, r, http.StatusNotFound, outdomain.GetProjectsResponse{}) } else { ResponseJSON(w, r, http.StatusOK, out) } } // GetProject godoc -// @Tags Projects -// @Summary Get projects -// @Description Get projects -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Success 200 {object} domain.GetProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId} [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get projects +// @Description Get projects +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} outdomain.GetProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId} [get] +// @Security JWT func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -235,7 +239,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { // return //} - var out domain.GetProjectResponse + var out outdomain.GetProjectResponse if project == nil { ResponseJSON(w, r, http.StatusNotFound, out) return @@ -252,7 +256,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { projectRoleName = pu.ProjectRole.Name } - var pdr domain.ProjectDetailResponse + var pdr outdomain.ProjectDetailResponse if err = serializer.Map(*project, &pdr); err != nil { log.Error(err) ErrorJSON(w, r, err) @@ -271,17 +275,18 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { } // IsProjectNameExist godoc -// @Tags Projects -// @Summary Check project name exist -// @Description Check project name exist -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param type query string false "type (name)" -// @Param value query string true "value (project name)" -// @Success 200 {object} domain.CheckExistedResponse -// @Router /api/1.0/organizations/{organizationId}/projects/existence [get] -// @Security JWT +// +// @Tags Projects +// @Summary Check project name exist +// @Description Check project name exist +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param type query string false "type (name)" +// @Param value query string true "value (project name)" +// @Success 200 {object} outdomain.CheckExistedResponse +// @Router /api/1.0/organizations/{organizationId}/projects/existence [get] +// @Security JWT func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -300,24 +305,25 @@ func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Reques return } - var out domain.CheckExistedResponse + var out outdomain.CheckExistedResponse out.Existed = exist ResponseJSON(w, r, http.StatusOK, out) } // UpdateProject godoc -// @Tags Projects -// @Summary Update project -// @Description Update project -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param request body domain.UpdateProjectRequest true "Request body to update project" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId} [put] -// @Security JWT +// +// @Tags Projects +// @Summary Update project +// @Description Update project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param request body outdomain.UpdateProjectRequest true "Request body to update project" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId} [put] +// @Security JWT func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -335,7 +341,7 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { return } - var projectReq domain.UpdateProjectRequest + var projectReq outdomain.UpdateProjectRequest if err := UnmarshalRequestInput(r, &projectReq); err != nil { ErrorJSON(w, r, err) return @@ -364,7 +370,7 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { return } - ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) } func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { @@ -374,16 +380,17 @@ func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { } // GetProjectRole godoc -// @Tags Projects -// @Summary Get project role -// @Description Get project role by id -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectRoleId path string true "Project Role ID" -// @Success 200 {object} domain.GetProjectRoleResponse -// @Router /api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get project role +// @Description Get project role by id +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectRoleId path string true "Project Role ID" +// @Success 200 {object} outdomain.GetProjectRoleResponse +// @Router /api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] +// @Security JWT func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -409,23 +416,24 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { return } - var out domain.GetProjectRoleResponse - out.ProjectRole = *pr + var out outdomain.GetProjectRoleResponse + out.ProjectRole = outdomain.ProjectRoleResponse(*pr) ResponseJSON(w, r, http.StatusOK, out) } // GetProjectRoles godoc -// @Tags Projects -// @Summary Get project roles -// @Description Get project roles by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" -// @Success 200 {object} domain.GetProjectRolesResponse -// @Router /api/1.0/organizations/{organizationId}/projects/project-roles [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get project roles +// @Description Get project roles by giving params +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" +// @Success 200 {object} outdomain.GetProjectRolesResponse +// @Router /api/1.0/organizations/{organizationId}/projects/project-roles [get] +// @Security JWT func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -453,24 +461,27 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) return } - var out domain.GetProjectRolesResponse - out.ProjectRoles = prs + var out outdomain.GetProjectRolesResponse + for _, pr := range prs { + out.ProjectRoles = append(out.ProjectRoles, outdomain.ProjectRoleResponse(pr)) + } ResponseJSON(w, r, http.StatusOK, out) } // AddProjectMember godoc -// @Tags Projects -// @Summary Add project member to project -// @Description Add project member to project -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param request body domain.AddProjectMemberRequest true "Request body to add project member" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [post] -// @Security JWT +// +// @Tags Projects +// @Summary Add project member to project +// @Description Add project member to project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param request body outdomain.AddProjectMemberRequest true "Request body to add project member" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [post] +// @Security JWT func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -487,7 +498,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } - var projectMemberReq domain.AddProjectMemberRequest + var projectMemberReq outdomain.AddProjectMemberRequest if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { ErrorJSON(w, r, err) return @@ -553,22 +564,23 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) } } - out := domain.CommonProjectResponse{Result: "OK"} + out := outdomain.CommonProjectResponse{Result: "OK"} ResponseJSON(w, r, http.StatusOK, out) } // GetProjectMember godoc -// @Tags Projects -// @Summary Get project member -// @Description Get project member -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param projectMemberId path string true "Project Member ID" -// @Success 200 {object} domain.GetProjectMemberResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get project member +// @Description Get project member +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectMemberId path string true "Project Member ID" +// @Success 200 {object} outdomain.GetProjectMemberResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] +// @Security JWT func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -602,7 +614,13 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) return } - pmr := &domain.ProjectMemberResponse{ + var out outdomain.GetProjectMemberResponse + if pm == nil { + ResponseJSON(w, r, http.StatusNotFound, out) + return + } + + pmr := &outdomain.ProjectMemberResponse{ ID: pm.ID, ProjectId: pm.ProjectId, ProjectUserId: pm.ProjectUser.ID.String(), @@ -616,26 +634,23 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) UpdatedAt: pm.UpdatedAt, } - out := domain.GetProjectMemberResponse{ProjectMember: pmr} - if pm == nil { - ResponseJSON(w, r, http.StatusNotFound, out) - return - } + out.ProjectMember = pmr ResponseJSON(w, r, http.StatusOK, out) } // GetProjectMembers godoc -// @Tags Projects -// @Summary Get project members -// @Description Get project members -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param query query string false "project member search by query (query=all), (query=leader), (query=member), (query=viewer)" -// @Success 200 {object} domain.GetProjectMembersResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get project members +// @Description Get project members +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param query query string false "project member search by query (query=all), (query=leader), (query=member), (query=viewer)" +// @Success 200 {object} outdomain.GetProjectMembersResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [get] +// @Security JWT func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -680,15 +695,15 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request return } - var out domain.GetProjectMembersResponse + var out outdomain.GetProjectMembersResponse if pms == nil { ResponseJSON(w, r, http.StatusNotFound, out) return } - pmrs := make([]domain.ProjectMemberResponse, 0) + pmrs := make([]outdomain.ProjectMemberResponse, 0) for _, pm := range pms { - pmr := domain.ProjectMemberResponse{ + pmr := outdomain.ProjectMemberResponse{ ID: pm.ID, ProjectId: pm.ProjectId, ProjectUserId: pm.ProjectUser.ID.String(), @@ -704,7 +719,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request pmrs = append(pmrs, pmr) } - out = domain.GetProjectMembersResponse{ProjectMembers: pmrs} + out = outdomain.GetProjectMembersResponse{ProjectMembers: pmrs} if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } @@ -713,16 +728,17 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request } // GetProjectMemberCount godoc -// @Tags Projects -// @Summary Get project member count group by project role -// @Description Get project member count group by project role -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Success 200 {object} domain.GetProjectMemberCountResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/count [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get project member count group by project role +// @Description Get project member count group by project role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} outdomain.GetProjectMemberCountResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/count [get] +// @Security JWT func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -748,24 +764,25 @@ func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Req } if pmcr == nil { - ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectMembersResponse{}) + ResponseJSON(w, r, http.StatusNotFound, outdomain.GetProjectMembersResponse{}) return } ResponseJSON(w, r, http.StatusOK, pmcr) } // RemoveProjectMember godoc -// @Tags Projects -// @Summary Remove project members to project -// @Description Remove project members to project -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param projectMemberId path string true "Project Member ID" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] -// @Security JWT +// +// @Tags Projects +// @Summary Remove project members to project +// @Description Remove project members to project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectMemberId path string true "Project Member ID" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] +// @Security JWT func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -816,21 +833,22 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque return } - ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) } // RemoveProjectMembers godoc -// @Tags Projects -// @Summary Remove project members to project -// @Description Remove project members to project -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param request body domain.RemoveProjectMemberRequest true "Request body to remove project member" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [delete] -// @Security JWT +// +// @Tags Projects +// @Summary Remove project members to project +// @Description Remove project members to project +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param request body outdomain.RemoveProjectMemberRequest true "Request body to remove project member" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [delete] +// @Security JWT func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -849,7 +867,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ return } - var projectMemberReq domain.RemoveProjectMemberRequest + var projectMemberReq outdomain.RemoveProjectMemberRequest if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { ErrorJSON(w, r, err) return @@ -883,22 +901,23 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ return } } - ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) } // UpdateProjectMemberRole godoc -// @Tags Projects -// @Summary Update project member Role -// @Description Update project member Role -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param projectMemberId path string true "Project Member ID" -// @Param request body domain.UpdateProjectMemberRoleRequest true "Request body to update project member role" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] -// @Security JWT +// +// @Tags Projects +// @Summary Update project member Role +// @Description Update project member Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectMemberId path string true "Project Member ID" +// @Param request body outdomain.UpdateProjectMemberRoleRequest true "Request body to update project member role" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] +// @Security JWT func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -924,7 +943,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R return } - var pmrReq domain.UpdateProjectMemberRoleRequest + var pmrReq outdomain.UpdateProjectMemberRoleRequest if err := UnmarshalRequestInput(r, &pmrReq); err != nil { ErrorJSON(w, r, err) return @@ -980,21 +999,22 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } } - ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) } // UpdateProjectMembersRole godoc -// @Tags Projects -// @Summary Update project member Role -// @Description Update project member Role -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param request body domain.UpdateProjectMembersRoleRequest true "Request body to update project member role" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [put] -// @Security JWT +// +// @Tags Projects +// @Summary Update project member Role +// @Description Update project member Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param request body outdomain.UpdateProjectMembersRoleRequest true "Request body to update project member role" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [put] +// @Security JWT func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -1014,7 +1034,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } now := time.Now() - var projectMemberReq domain.UpdateProjectMembersRoleRequest + var projectMemberReq outdomain.UpdateProjectMembersRoleRequest if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { ErrorJSON(w, r, err) return @@ -1071,21 +1091,22 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } } - ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) } // CreateProjectNamespace godoc -// @Tags Projects -// @Summary Create project namespace -// @Description Create project namespace -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param request body domain.CreateProjectNamespaceRequest true "Request body to create project namespace" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [post] -// @Security JWT +// +// @Tags Projects +// @Summary Create project namespace +// @Description Create project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param request body outdomain.CreateProjectNamespaceRequest true "Request body to create project namespace" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [post] +// @Security JWT func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -1101,7 +1122,7 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re return } - var projectNamespaceReq domain.CreateProjectNamespaceRequest + var projectNamespaceReq outdomain.CreateProjectNamespaceRequest if err := UnmarshalRequestInput(r, &projectNamespaceReq); err != nil { ErrorJSON(w, r, err) return @@ -1132,23 +1153,24 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - out := domain.CommonProjectResponse{Result: "OK"} + out := outdomain.CommonProjectResponse{Result: "OK"} ResponseJSON(w, r, http.StatusOK, out) } // IsProjectNamespaceExist godoc -// @Tags Projects -// @Summary Check project namespace exist -// @Description Check project namespace exist -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param stackId path string true "Project Stack ID" -// @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} domain.CheckExistedResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence [get] -// @Security JWT +// +// @Tags Projects +// @Summary Check project namespace exist +// @Description Check project namespace exist +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Project Stack ID" +// @Param projectNamespace path string true "Project Namespace" +// @Success 200 {object} outdomain.CheckExistedResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence [get] +// @Security JWT func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -1182,23 +1204,24 @@ func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.R return } - var out domain.CheckExistedResponse + var out outdomain.CheckExistedResponse out.Existed = exist ResponseJSON(w, r, http.StatusOK, out) } // GetProjectNamespaces godoc -// @Tags Projects -// @Summary Get project namespaces -// @Description Get project namespaces -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Success 200 {object} domain.GetProjectNamespacesResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get project namespaces +// @Description Get project namespaces +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} outdomain.GetProjectNamespacesResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [get] +// @Security JWT func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -1223,14 +1246,14 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ return } - var out domain.GetProjectNamespacesResponse + var out outdomain.GetProjectNamespacesResponse if pns == nil { ResponseJSON(w, r, http.StatusNotFound, out) return } - pnrs := make([]domain.ProjectNamespaceResponse, 0) + pnrs := make([]outdomain.ProjectNamespaceResponse, 0) for _, pn := range pns { - var pnr domain.ProjectNamespaceResponse + var pnr outdomain.ProjectNamespaceResponse if err = serializer.Map(pn, &pnr); err != nil { log.Error(err) ErrorJSON(w, r, err) @@ -1254,18 +1277,19 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ } // GetProjectNamespace godoc -// @Tags Projects -// @Summary Get project namespace -// @Description Get project namespace -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param projectNamespace path string true "Project Namespace" -// @Param stackId path string true "Project Stack ID" -// @Success 200 {object} domain.GetProjectNamespaceResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get project namespace +// @Description Get project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectNamespace path string true "Project Namespace" +// @Param stackId path string true "Project Stack ID" +// @Success 200 {object} outdomain.GetProjectNamespaceResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [get] +// @Security JWT func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -1307,13 +1331,13 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque return } - var out domain.GetProjectNamespaceResponse + var out outdomain.GetProjectNamespaceResponse if pn == nil { ResponseJSON(w, r, http.StatusNotFound, out) return } - var pnr domain.ProjectNamespaceResponse + var pnr outdomain.ProjectNamespaceResponse if err = serializer.Map(*pn, &pnr); err != nil { log.Error(err) ErrorJSON(w, r, err) @@ -1328,19 +1352,20 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque } // UpdateProjectNamespace godoc -// @Tags Projects -// @Summary Update project namespace -// @Description Update project namespace -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param projectNamespace path string true "Project Namespace" -// @Param stackId path string true "Project Stack ID" -// @Param request body domain.UpdateProjectNamespaceRequest true "Request body to update project namespace" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] -// @Security JWT +// +// @Tags Projects +// @Summary Update project namespace +// @Description Update project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectNamespace path string true "Project Namespace" +// @Param stackId path string true "Project Stack ID" +// @Param request body outdomain.UpdateProjectNamespaceRequest true "Request body to update project namespace" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] +// @Security JWT func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -1369,7 +1394,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re return } - var projectNamespaceReq domain.UpdateProjectNamespaceRequest + var projectNamespaceReq outdomain.UpdateProjectNamespaceRequest if err := UnmarshalRequestInput(r, &projectNamespaceReq); err != nil { ErrorJSON(w, r, err) return @@ -1391,22 +1416,23 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re return } - ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) } // DeleteProjectNamespace godoc -// @Tags Projects -// @Summary Delete project namespace -// @Description Delete project namespace -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param stackId path string true "Stack ID" -// @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} domain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] -// @Security JWT +// +// @Tags Projects +// @Summary Delete project namespace +// @Description Delete project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Stack ID" +// @Param projectNamespace path string true "Project Namespace" +// @Success 200 {object} outdomain.CommonProjectResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] +// @Security JWT func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { //ToDo: from donggyu. uncomment lines below after implementing usecase.DeleteProjectNamespace. @@ -1473,16 +1499,17 @@ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r * } // GetProjectKubeconfig godoc -// @Tags Projects -// @Summary Get project kubeconfig -// @Description Get project kubeconfig -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Success 200 {object} domain.GetProjectKubeconfigResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get project kubeconfig +// @Description Get project kubeconfig +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Success 200 {object} outdomain.GetProjectKubeconfigResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig [get] +// @Security JWT func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -1506,7 +1533,7 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ return } - out := domain.GetProjectKubeconfigResponse{ + out := outdomain.GetProjectKubeconfigResponse{ Kubeconfig: kubeconfig, } @@ -1514,18 +1541,19 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ } // GetProjectNamespaceK8sResources godoc -// @Tags Projects -// @Summary Get k8s resources for project namespace -// @Description Get k8s resources for project namespace -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param stackId path string true "Stack ID" -// @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} domain.GetProjectNamespaceK8sResourcesResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources [get] -// @Security JWT +// +// @Tags Projects +// @Summary Get k8s resources for project namespace +// @Description Get k8s resources for project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Stack ID" +// @Param projectNamespace path string true "Project Namespace" +// @Success 200 {object} outdomain.GetProjectNamespaceK8sResourcesResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources [get] +// @Security JWT func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -1551,14 +1579,14 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r return } - k8sResources, err := p.usecase.GetK8sResources(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) + k8sResources, err := p.usecase.GetK8sResources(r.Context(), organizationId, projectId, projectNamespace, outdomain.StackId(stackId)) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) ErrorJSON(w, r, err) return } - var out domain.GetProjectNamespaceK8sResourcesResponse + var out outdomain.GetProjectNamespaceK8sResourcesResponse if err = serializer.Map(k8sResources, &out.K8sResources); err != nil { log.Error(err) } diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index dd5f3565..cb563a66 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -35,15 +35,15 @@ func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { } // CreateTksRole godoc -// @Tags Role -// @Summary Create Tks Role -// @Description Create Tks Role -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param body body domain.CreateTksRoleRequest true "Create Tks Role Request" -// @Success 200 {object} domain.CreateTksRoleResponse -// @Router /organizations/{organizationId}/roles [post] +// @Tags Role +// @Summary Create Tks Role +// @Description Create Tks Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param body body domain.CreateTksRoleRequest true "Create Tks Role Request" +// @Success 200 {object} domain.CreateTksRoleResponse +// @Router /organizations/{organizationId}/roles [post] func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { // path parameter @@ -94,13 +94,13 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // ListTksRoles godoc -// @Tags Role -// @Summary List Tks Roles -// @Description List Tks Roles -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Success 200 {object} domain.ListTksRoleResponse -// @Router /organizations/{organizationId}/roles [get] +// @Tags Role +// @Summary List Tks Roles +// @Description List Tks Roles +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.ListTksRoleResponse +// @Router /organizations/{organizationId}/roles [get] func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { // path parameter var organizationId string @@ -147,14 +147,14 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { } // GetTksRole godoc -// @Tags Role -// @Summary Get Tks Role -// @Description Get Tks Role -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" -// @Success 200 {object} domain.GetTksRoleResponse -// @Router /organizations/{organizationId}/roles/{roleId} [get] +// @Tags Role +// @Summary Get Tks Role +// @Description Get Tks Role +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 {object} domain.GetTksRoleResponse +// @Router /organizations/{organizationId}/roles/{roleId} [get] func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // path parameter @@ -188,14 +188,14 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { } // DeleteTksRole godoc -// @Tags Role -// @Summary Delete Tks Role -// @Description Delete Tks Role -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" -// @Success 200 -// @Router /organizations/{organizationId}/roles/{roleId} [delete] +// @Tags Role +// @Summary Delete Tks Role +// @Description Delete Tks Role +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 +// @Router /organizations/{organizationId}/roles/{roleId} [delete] func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { // path parameter @@ -219,16 +219,16 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { } // UpdateTksRole godoc -// @Tags Role -// @Summary Update Tks Role -// @Description Update Tks Role -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" -// @Param body body domain.UpdateTksRoleRequest true "Update Tks Role Request" -// @Success 200 -// @Router /organizations/{organizationId}/roles/{roleId} [put] +// @Tags Role +// @Summary Update Tks Role +// @Description Update Tks Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Param body body domain.UpdateTksRoleRequest true "Update Tks Role Request" +// @Success 200 +// @Router /organizations/{organizationId}/roles/{roleId} [put] func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // path parameter diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 79952471..d6f63894 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -27,33 +27,33 @@ func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { } // CreateStackTemplate godoc -// @Tags StackTemplates -// @Summary Create StackTemplate 'NOT IMPLEMENTED' -// @Description Create StackTemplate -// @Accept json -// @Produce json -// @Param body body domain.CreateStackTemplateRequest true "create stack template request" -// @Success 200 {object} domain.CreateStackTemplateResponse -// @Router /api/1.0/stack-templates [post] -// @Security JWT +// @Tags StackTemplates +// @Summary Create StackTemplate 'NOT IMPLEMENTED' +// @Description Create StackTemplate +// @Accept json +// @Produce json +// @Param body body domain.CreateStackTemplateRequest true "create stack template request" +// @Success 200 {object} domain.CreateStackTemplateResponse +// @Router /api/1.0/stack-templates [post] +// @Security JWT func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) } // GetStackTemplate godoc -// @Tags StackTemplates -// @Summary Get StackTemplates -// @Description Get StackTemplates -// @Accept json -// @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetStackTemplatesResponse -// @Router /api/1.0/stack-templates [get] -// @Security JWT +// @Tags StackTemplates +// @Summary Get StackTemplates +// @Description Get StackTemplates +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetStackTemplatesResponse +// @Router /api/1.0/stack-templates [get] +// @Security JWT func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) @@ -84,15 +84,15 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. } // GetStackTemplate godoc -// @Tags StackTemplates -// @Summary Get StackTemplate -// @Description Get StackTemplate -// @Accept json -// @Produce json -// @Param stackTemplateId path string true "stackTemplateId" -// @Success 200 {object} domain.GetStackTemplateResponse -// @Router /api/1.0/stack-templates/{stackTemplateId} [get] -// @Security JWT +// @Tags StackTemplates +// @Summary Get StackTemplate +// @Description Get StackTemplate +// @Accept json +// @Produce json +// @Param stackTemplateId path string true "stackTemplateId" +// @Success 200 {object} domain.GetStackTemplateResponse +// @Router /api/1.0/stack-templates/{stackTemplateId} [get] +// @Security JWT func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackTemplateId"] @@ -127,15 +127,15 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R } // UpdateStackTemplate godoc -// @Tags StackTemplates -// @Summary Update StackTemplate 'NOT IMPLEMENTED' -// @Description Update StackTemplate -// @Accept json -// @Produce json -// @Param body body domain.UpdateStackTemplateRequest true "Update stack template request" -// @Success 200 {object} nil -// @Router /api/1.0/stack-templates/{stackTemplateId} [put] -// @Security JWT +// @Tags StackTemplates +// @Summary Update StackTemplate 'NOT IMPLEMENTED' +// @Description Update StackTemplate +// @Accept json +// @Produce json +// @Param body body domain.UpdateStackTemplateRequest true "Update stack template request" +// @Success 200 {object} nil +// @Router /api/1.0/stack-templates/{stackTemplateId} [put] +// @Security JWT func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *http.Request) { /* vars := mux.Vars(r) @@ -168,15 +168,15 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt } // DeleteStackTemplate godoc -// @Tags StackTemplates -// @Summary Delete StackTemplate 'NOT IMPLEMENTED' -// @Description Delete StackTemplate -// @Accept json -// @Produce json -// @Param stackTemplateId path string true "stackTemplateId" -// @Success 200 {object} nil -// @Router /api/1.0/stack-templates/{stackTemplateId} [delete] -// @Security JWT +// @Tags StackTemplates +// @Summary Delete StackTemplate 'NOT IMPLEMENTED' +// @Description Delete StackTemplate +// @Accept json +// @Produce json +// @Param stackTemplateId path string true "stackTemplateId" +// @Success 200 {object} nil +// @Router /api/1.0/stack-templates/{stackTemplateId} [delete] +// @Security JWT func (h *StackTemplateHandler) DeleteStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) _, ok := vars["stackTemplateId"] diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 480ae3bf..18aa5639 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -25,16 +25,16 @@ func NewStackHandler(h usecase.Usecase) *StackHandler { } // CreateStack godoc -// @Tags Stacks -// @Summary Create Stack -// @Description Create Stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.CreateStackRequest true "create cloud setting request" -// @Success 200 {object} domain.CreateStackResponse -// @Router /api/1.0/organizations/{organizationId}/stacks [post] -// @Security JWT +// @Tags Stacks +// @Summary Create Stack +// @Description Create Stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.CreateStackRequest true "create cloud setting request" +// @Success 200 {object} domain.CreateStackResponse +// @Router /api/1.0/organizations/{organizationId}/stacks [post] +// @Security JWT func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -89,20 +89,20 @@ func (h *StackHandler) InstallStack(w http.ResponseWriter, r *http.Request) { } // GetStack godoc -// @Tags Stacks -// @Summary Get Stacks -// @Description Get Stacks -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param combinedFilter query string false "combinedFilter" -// @Success 200 {object} domain.GetStacksResponse -// @Router /api/1.0/organizations/{organizationId}/stacks [get] -// @Security JWT +// @Tags Stacks +// @Summary Get Stacks +// @Description Get Stacks +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param combinedFilter query string false "combinedFilter" +// @Success 200 {object} domain.GetStacksResponse +// @Router /api/1.0/organizations/{organizationId}/stacks [get] +// @Security JWT func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -141,16 +141,16 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } // GetStack godoc -// @Tags Stacks -// @Summary Get Stack -// @Description Get Stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} domain.GetStackResponse -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [get] -// @Security JWT +// @Tags Stacks +// @Summary Get Stack +// @Description Get Stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} domain.GetStackResponse +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [get] +// @Security JWT func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackId"] @@ -179,16 +179,16 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { } // GetStackStatus godoc -// @Tags Stacks -// @Summary Get Stack Status -// @Description Get Stack Status -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} domain.GetStackStatusResponse -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/status [get] -// @Security JWT +// @Tags Stacks +// @Summary Get Stack Status +// @Description Get Stack Status +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} domain.GetStackStatusResponse +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/status [get] +// @Security JWT func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -217,17 +217,17 @@ func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { } // UpdateStack godoc -// @Tags Stacks -// @Summary Update Stack -// @Description Update Stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Param body body domain.UpdateStackRequest true "Update cloud setting request" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [put] -// @Security JWT +// @Tags Stacks +// @Summary Update Stack +// @Description Update Stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Param body body domain.UpdateStackRequest true "Update cloud setting request" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [put] +// @Security JWT func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackId"] @@ -272,16 +272,16 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { } // DeleteStack godoc -// @Tags Stacks -// @Summary Delete Stack -// @Description Delete Stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [delete] -// @Security JWT +// @Tags Stacks +// @Summary Delete Stack +// @Description Delete Stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [delete] +// @Security JWT func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -310,17 +310,17 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { } // CheckStackName godoc -// @Tags Stacks -// @Summary Check name for stack -// @Description Check name for stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Param name path string true "name" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/name/{name}/existence [GET] -// @Security JWT +// @Tags Stacks +// @Summary Check name for stack +// @Description Check name for stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Param name path string true "name" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/stacks/name/{name}/existence [GET] +// @Security JWT func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -353,16 +353,16 @@ func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { } // GetStackKubeConfig godoc -// @Tags Stacks -// @Summary Get KubeConfig by stack -// @Description Get KubeConfig by stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "organizationId" -// @Success 200 {object} domain.GetStackKubeConfigResponse -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config [get] -// @Security JWT +// @Tags Stacks +// @Summary Get KubeConfig by stack +// @Description Get KubeConfig by stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "organizationId" +// @Success 200 {object} domain.GetStackKubeConfigResponse +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config [get] +// @Security JWT func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) _, ok := vars["organizationId"] @@ -396,16 +396,16 @@ func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request } // SetFavorite godoc -// @Tags Stacks -// @Summary Set favorite stack -// @Description Set favorite stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite [post] -// @Security JWT +// @Tags Stacks +// @Summary Set favorite stack +// @Description Set favorite stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite [post] +// @Security JWT func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackId"] @@ -423,16 +423,16 @@ func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { } // DeleteFavorite godoc -// @Tags Stacks -// @Summary Delete favorite stack -// @Description Delete favorite stack -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param stackId path string true "stackId" -// @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite [delete] -// @Security JWT +// @Tags Stacks +// @Summary Delete favorite stack +// @Description Delete favorite stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} nil +// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite [delete] +// @Security JWT func (h *StackHandler) DeleteFavorite(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) strId, ok := vars["stackId"] diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index d96dfce5..0874db5d 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -57,16 +57,16 @@ func NewUserHandler(h usecase.Usecase) IUserHandler { } // Create godoc -// @Tags Users -// @Summary Create user -// @Description Create user -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.CreateUserRequest true "create user request" -// @Success 200 {object} domain.CreateUserResponse "create user response" -// @Router /api/1.0/organizations/{organizationId}/users [post] -// @Security JWT +// @Tags Users +// @Summary Create user +// @Description Create user +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.CreateUserRequest true "create user request" +// @Success 200 {object} domain.CreateUserResponse "create user response" +// @Router /api/1.0/organizations/{organizationId}/users [post] +// @Security JWT func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -128,16 +128,16 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { } // Get godoc -// @Tags Users -// @Summary Get user detail -// @Description Get user detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} domain.GetUserResponse -// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [get] -// @Security JWT +// @Tags Users +// @Summary Get user detail +// @Description Get user detail +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} domain.GetUserResponse +// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [get] +// @Security JWT func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) userId, ok := vars["accountId"] @@ -173,20 +173,20 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { } // List godoc -// @Tags Users -// @Summary Get user list -// @Description Get user list -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} []domain.ListUserBody -// @Router /api/1.0/organizations/{organizationId}/users [get] -// @Security JWT +// @Tags Users +// @Summary Get user list +// @Description Get user list +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} []domain.ListUserBody +// @Router /api/1.0/organizations/{organizationId}/users [get] +// @Security JWT func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -220,16 +220,16 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { } // Delete godoc -// @Tags Users -// @Summary Delete user -// @Description Delete user -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} domain.User -// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [delete] -// @Security JWT +// @Tags Users +// @Summary Delete user +// @Description Delete user +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} domain.User +// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [delete] +// @Security JWT func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) userId, ok := vars["accountId"] @@ -259,17 +259,17 @@ func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { } // Update godoc -// @Tags Users -// @Summary Update user -// @Description Update user -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Param body body domain.UpdateUserRequest true "input" -// @Success 200 {object} domain.UpdateUserResponse -// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [put] -// @Security JWT +// @Tags Users +// @Summary Update user +// @Description Update user +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Param body body domain.UpdateUserRequest true "input" +// @Success 200 {object} domain.UpdateUserResponse +// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [put] +// @Security JWT func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) accountId, ok := vars["accountId"] @@ -338,16 +338,16 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } // ResetPassword godoc -// @Tags Users -// @Summary Reset user's password as temporary password by admin -// @Description Reset user's password as temporary password by admin and send email to user -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 -// @Router /api/1.0/organizations/{organizationId}/users/{accountId}/reset-password [put] -// @Security JWT +// @Tags Users +// @Summary Reset user's password as temporary password by admin +// @Description Reset user's password as temporary password by admin and send email to user +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 +// @Router /api/1.0/organizations/{organizationId}/users/{accountId}/reset-password [put] +// @Security JWT func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) accountId, ok := vars["accountId"] @@ -371,15 +371,15 @@ func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { } // GetMyProfile godoc -// @Tags My-profile -// @Summary Get my profile detail -// @Description Get my profile detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.GetMyProfileResponse -// @Router /api/1.0/organizations/{organizationId}/my-profile [get] -// @Security JWT +// @Tags My-profile +// @Summary Get my profile detail +// @Description Get my profile detail +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetMyProfileResponse +// @Router /api/1.0/organizations/{organizationId}/my-profile [get] +// @Security JWT func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -403,16 +403,16 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { } // UpdateMyProfile godoc -// @Tags My-profile -// @Summary Update my profile detail -// @Description Update my profile detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateMyProfileRequest true "Required fields: password due to double-check" -// @Success 200 {object} domain.UpdateMyProfileResponse -// @Router /api/1.0/organizations/{organizationId}/my-profile [put] -// @Security JWT +// @Tags My-profile +// @Summary Update my profile detail +// @Description Update my profile detail +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateMyProfileRequest true "Required fields: password due to double-check" +// @Success 200 {object} domain.UpdateMyProfileResponse +// @Router /api/1.0/organizations/{organizationId}/my-profile [put] +// @Security JWT func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -472,16 +472,16 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { } // UpdateMyPassword godoc -// @Tags My-profile -// @Summary Update user password detail -// @Description Update user password detail -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdatePasswordRequest true "update user password request" -// @Success 200 -// @Router /api/1.0/organizations/{organizationId}/my-profile/password [put] -// @Security JWT +// @Tags My-profile +// @Summary Update user password detail +// @Description Update user password detail +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdatePasswordRequest true "update user password request" +// @Success 200 +// @Router /api/1.0/organizations/{organizationId}/my-profile/password [put] +// @Security JWT func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -522,16 +522,16 @@ func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { } // RenewPasswordExpiredDate godoc -// @Tags My-profile -// @Summary Update user's password expired date to current date -// @Description Update user's password expired date to current date -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 -// @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/organizations/{organizationId}/my-profile/next-password-change [put] -// @Security JWT +// @Tags My-profile +// @Summary Update user's password expired date to current date +// @Description Update user's password expired date to current date +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 +// @Failure 400 {object} httpErrors.RestError +// @Router /api/1.0/organizations/{organizationId}/my-profile/next-password-change [put] +// @Security JWT func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -549,16 +549,16 @@ func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Req } // DeleteMyProfile godoc -// @Tags My-profile -// @Summary Delete myProfile -// @Description Delete myProfile -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 -// @Failure 400 -// @Router /api/1.0/organizations/{organizationId}/my-profile [delete] -// @Security JWT +// @Tags My-profile +// @Summary Delete myProfile +// @Description Delete myProfile +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 +// @Failure 400 +// @Router /api/1.0/organizations/{organizationId}/my-profile [delete] +// @Security JWT func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { @@ -574,15 +574,15 @@ func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { } // CheckId godoc -// @Tags Users -// @Summary Get user id existence -// @Description return true when accountId exists -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} domain.CheckExistedResponse -// @Router /api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence [get] -// @Security JWT +// @Tags Users +// @Summary Get user id existence +// @Description return true when accountId exists +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} domain.CheckExistedResponse +// @Router /api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence [get] +// @Security JWT func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) accountId, ok := vars["accountId"] @@ -614,15 +614,15 @@ func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { } // CheckEmail godoc -// @Tags Users -// @Summary Get user email existence -// @Description return true when email exists -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "email" -// @Success 200 {object} domain.CheckExistedResponse -// @Router /api/1.0/organizations/{organizationId}/users/email/{email}/existence [get] -// @Security JWT +// @Tags Users +// @Summary Get user email existence +// @Description return true when email exists +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "email" +// @Success 200 {object} domain.CheckExistedResponse +// @Router /api/1.0/organizations/{organizationId}/users/email/{email}/existence [get] +// @Security JWT func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) email, ok := vars["email"] diff --git a/internal/domain/domain.go b/internal/domain/domain.go new file mode 100644 index 00000000..a35a3062 --- /dev/null +++ b/internal/domain/domain.go @@ -0,0 +1,103 @@ +package domain + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +func (a *Project) BeforeCreate(*gorm.DB) (err error) { + a.ID = uuid.New().String() + return nil +} + +func (t *ProjectRole) BeforeCreate(*gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} + +func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} + +//func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { +// t.ID = uuid.New().String() +// return nil +//} + +func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { + return nil +} + +type Project struct { + ID string `gorm:"primarykey" json:"id"` + OrganizationId string `json:"organizationId"` + Name string `gorm:"index" json:"name"` + Description string `json:"description,omitempty"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` + ProjectMembers []ProjectMember `gorm:"foreignKey:ProjectId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectMembers,omitempty"` + ProjectNamespaces []ProjectNamespace `gorm:"foreignKey:ProjectId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectNamespaces,omitempty"` +} + +type ProjectRole struct { + ID string `gorm:"primarykey" json:"id"` + Name string `json:"name"` // project-leader, project-member, project-viewer + Description string `json:"description,omitempty"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +type ProjectUser struct { + ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +func (ProjectUser) TableName() string { + return "users" +} + +type ProjectMember struct { + ID string `gorm:"primarykey" json:"id"` + ProjectId string `gorm:"not null" json:"projectId"` + ProjectUserId uuid.UUID `json:"projectUserId"` + ProjectUser *ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectUser"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` + IsProjectLeader bool `gorm:"default:false" json:"projectLeader"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +type ProjectStack struct { + ID string `gorm:"primarykey" json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` +} + +func (ProjectStack) TableName() string { + return "clusters" +} + +type ProjectNamespace struct { + StackId string `gorm:"primarykey" json:"stackId"` + Namespace string `gorm:"primarykey" json:"namespace"` + Stack *ProjectStack `gorm:"foreignKey:StackId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"stack"` + ProjectId string `gorm:"not null" json:"projectId"` + Description string `json:"description,omitempty"` + Status string `json:"status,omitempty"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} diff --git a/internal/repository/project.go b/internal/repository/project.go index c042cdc2..13fc1428 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -5,8 +5,9 @@ import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/domain" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/domain" + out_domain "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gorm.io/gorm" @@ -14,8 +15,8 @@ import ( type IProjectRepository interface { CreateProject(p *domain.Project) (string, error) - GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) - GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]out_domain.ProjectResponse, error) + GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]out_domain.ProjectResponse, error) GetProjectById(organizationId string, projectId string) (*domain.Project, error) GetProjectByIdAndLeader(organizationId string, projectId string) (*domain.Project, error) GetProjectByName(organizationId string, projectName string) (*domain.Project, error) @@ -26,7 +27,7 @@ type IProjectRepository interface { AddProjectMember(*domain.ProjectMember) (string, error) GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) ([]domain.ProjectMember, error) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) ([]domain.ProjectMember, error) - GetProjectMemberCountByProjectId(projectId string) (*domain.GetProjectMemberCountResponse, error) + GetProjectMemberCountByProjectId(projectId string) (*out_domain.GetProjectMemberCountResponse, error) GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) GetProjectMemberByUserId(projectId string, projectUserId string) (pm *domain.ProjectMember, err error) RemoveProjectMember(projectMemberId string) error @@ -60,7 +61,7 @@ func (r *ProjectRepository) CreateProject(p *domain.Project) (string, error) { return p.ID, nil } -func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []out_domain.ProjectResponse, err error) { if pg == nil { pg = pagination.NewPagination(nil) } @@ -138,7 +139,7 @@ func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, return pr, nil } -func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []out_domain.ProjectResponse, err error) { if pg == nil { pg = pagination.NewPagination(nil) } @@ -346,7 +347,7 @@ func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId st return pms, nil } -func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { +func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) (pmcr *out_domain.GetProjectMemberCountResponse, err error) { res := r.db.Raw(""+ "select (plc.count + pmc.count + pvc.count) as project_member_all_count,"+ " plc.count as project_leader_count,"+ diff --git a/internal/usecase/project.go b/internal/usecase/project.go index a955be00..79af2cf6 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -6,13 +6,14 @@ import ( "time" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/domain" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" argowf "github.com/openinfradev/tks-api/pkg/argo-client" - "github.com/openinfradev/tks-api/pkg/domain" + out_domain "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gopkg.in/yaml.v3" @@ -28,7 +29,7 @@ const ( type IProjectUsecase interface { CreateProject(ctx context.Context, p *domain.Project) (string, error) - GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) ([]out_domain.ProjectResponse, error) GetProject(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) IsProjectNameExist(ctx context.Context, organizationId string, projectName string) (bool, error) @@ -39,7 +40,7 @@ type IProjectUsecase interface { GetProjectUser(ctx context.Context, projectUserId string) (*domain.ProjectUser, error) GetProjectMember(ctx context.Context, projectMemberId string) (*domain.ProjectMember, error) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) ([]domain.ProjectMember, error) - GetProjectMemberCount(ctx context.Context, projectMemberId string) (*domain.GetProjectMemberCountResponse, error) + GetProjectMemberCount(ctx context.Context, projectMemberId string) (*out_domain.GetProjectMemberCountResponse, error) RemoveProjectMember(ctx context.Context, projectMemberId string) error UpdateProjectMemberRole(ctx context.Context, pm *domain.ProjectMember) error CreateProjectNamespace(ctx context.Context, organizationId string, pn *domain.ProjectNamespace) error @@ -54,7 +55,7 @@ type IProjectUsecase interface { CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error DeleteK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) - GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) + GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceK8sResources, err error) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error } @@ -93,7 +94,7 @@ func (u *ProjectUsecase) CreateProject(ctx context.Context, p *domain.Project) ( return projectId, nil } -func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []out_domain.ProjectResponse, err error) { userUuid, err := uuid.Parse(userId) if err != nil { log.ErrorWithContext(ctx, err) @@ -305,7 +306,7 @@ func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string return pms, nil } -func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMemberId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { +func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMemberId string) (pmcr *out_domain.GetProjectMemberCountResponse, err error) { pmcr, err = u.projectRepo.GetProjectMemberCountByProjectId(projectMemberId) if err != nil { log.ErrorWithContext(ctx, err) @@ -704,8 +705,8 @@ func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationI return kubernetes.MergeKubeconfigsWithSingleUser(kubeconfigs) } -func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) { - _, err = u.clusterRepository.Get(domain.ClusterId(stackId)) +func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceK8sResources, err error) { + _, err = u.clusterRepository.Get(out_domain.ClusterId(stackId)) if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } diff --git a/internal/usecase/role_test.go b/internal/usecase/role_test.go index 10e746c7..e4931993 100644 --- a/internal/usecase/role_test.go +++ b/internal/usecase/role_test.go @@ -3,9 +3,9 @@ package usecase_test import ( "fmt" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/domain" myRepository "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/usecase" - "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm_test/config" diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 23882b28..8ecbea8f 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -1,47 +1,6 @@ package domain -import ( - "time" - - "github.com/google/uuid" - "gorm.io/gorm" -) - -func (a *Project) BeforeCreate(*gorm.DB) (err error) { - a.ID = uuid.New().String() - return nil -} - -func (t *ProjectRole) BeforeCreate(*gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} - -func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} - -//func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { -// t.ID = uuid.New().String() -// return nil -//} - -func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { - return nil -} - -type Project struct { - ID string `gorm:"primarykey" json:"id"` - OrganizationId string `json:"organizationId"` - Name string `gorm:"index" json:"name"` - Description string `json:"description,omitempty"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` - ProjectMembers []ProjectMember `gorm:"foreignKey:ProjectId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectMembers,omitempty"` - ProjectNamespaces []ProjectNamespace `gorm:"foreignKey:ProjectId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectNamespaces,omitempty"` -} +import "time" type ProjectResponse struct { ID string `json:"id"` @@ -84,65 +43,6 @@ type GetProjectResponse struct { Project *ProjectDetailResponse `json:"project"` } -type ProjectRole struct { - ID string `gorm:"primarykey" json:"id"` - Name string `json:"name"` // project-leader, project-member, project-viewer - Description string `json:"description,omitempty"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` -} - -type ProjectUser struct { - ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - -func (ProjectUser) TableName() string { - return "users" -} - -type ProjectMember struct { - ID string `gorm:"primarykey" json:"id"` - ProjectId string `gorm:"not null" json:"projectId"` - ProjectUserId uuid.UUID `json:"projectUserId"` - ProjectUser *ProjectUser `gorm:"foreignKey:ProjectUserId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectUser"` - ProjectRoleId string `json:"projectRoleId"` - ProjectRole *ProjectRole `gorm:"foreignKey:ProjectRoleId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"projectRole"` - IsProjectLeader bool `gorm:"default:false" json:"projectLeader"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` -} - -type ProjectStack struct { - ID string `gorm:"primarykey" json:"id"` - OrganizationId string `json:"organizationId"` - Name string `json:"name"` -} - -func (ProjectStack) TableName() string { - return "clusters" -} - -type ProjectNamespace struct { - StackId string `gorm:"primarykey" json:"stackId"` - Namespace string `gorm:"primarykey" json:"namespace"` - Stack *ProjectStack `gorm:"foreignKey:StackId;references:ID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT" json:"stack"` - ProjectId string `gorm:"not null" json:"projectId"` - Description string `json:"description,omitempty"` - Status string `json:"status,omitempty"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` -} - type CreateProjectRequest struct { Name string `json:"name" validate:"required"` Description string `json:"description"` @@ -157,12 +57,21 @@ type UpdateProjectRequest struct { CreateProjectRequest } +type ProjectRoleResponse struct { + ID string `json:"id"` + Name string `json:"name"` // project-leader, project-member, project-viewer + Description string `json:"description,omitempty"` + CreatedAt time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + type GetProjectRoleResponse struct { - ProjectRole ProjectRole `json:"projectRole"` + ProjectRole ProjectRoleResponse `json:"projectRole"` } type GetProjectRolesResponse struct { - ProjectRoles []ProjectRole `json:"projectRoles"` + ProjectRoles []ProjectRoleResponse `json:"projectRoles"` } type ProjectMemberRequest struct { From 09a0d71a3d937b56223f9ba06dde0a494c7bc13a Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 6 Mar 2024 11:15:19 +0900 Subject: [PATCH 087/502] swag fmt --- internal/delivery/http/project.go | 12 ++-- internal/delivery/http/role.go | 30 ++++----- internal/delivery/http/user.go | 108 +++++++++++++++--------------- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index fb61f645..5d078c3a 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1101,8 +1101,8 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. // @Description Create project namespace // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param request body outdomain.CreateProjectNamespaceRequest true "Request body to create project namespace" // @Success 200 {object} outdomain.CommonProjectResponse // @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [post] @@ -1358,10 +1358,10 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque // @Description Update project namespace // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param projectNamespace path string true "Project Namespace" -// @Param stackId path string true "Project Stack ID" +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectNamespace path string true "Project Namespace" +// @Param stackId path string true "Project Stack ID" // @Param request body outdomain.UpdateProjectNamespaceRequest true "Request body to update project namespace" // @Success 200 {object} outdomain.CommonProjectResponse // @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index cb563a66..7408878d 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -266,13 +266,13 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { } // Admin_ListTksRoles godoc -// @Tags Role -// @Summary Admin List Tks Roles -// @Description Admin List Tks Roles -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Success 200 {object} domain.ListTksRoleResponse -// @Router /admin/organizations/{organizationId}/roles [get] +// @Tags Role +// @Summary Admin List Tks Roles +// @Description Admin List Tks Roles +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.ListTksRoleResponse +// @Router /admin/organizations/{organizationId}/roles [get] func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) { // Same as ListTksRoles @@ -321,14 +321,14 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) } // Admin_GetTksRole godoc -// @Tags Role -// @Summary Admin Get Tks Role -// @Description Admin Get Tks Role -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" -// @Success 200 {object} domain.GetTksRoleResponse -// @Router /admin/organizations/{organizationId}/roles/{roleId} [get] +// @Tags Role +// @Summary Admin Get Tks Role +// @Description Admin Get Tks Role +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 {object} domain.GetTksRoleResponse +// @Router /admin/organizations/{organizationId}/roles/{roleId} [get] func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { // Same as GetTksRole diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 0874db5d..0d6a1d22 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -654,16 +654,16 @@ func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { } // Admin_Create godoc -// @Tags Admin -// @Summary Create user by admin -// @Description Create user by admin -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body admin_domain.CreateUserRequest true "create user request" -// @Success 200 {object} admin_domain.CreateUserResponse "create user response" -// @Router /api/1.0/admin/organizations/{organizationId}/users [post] -// @Security JWT +// @Tags Admin +// @Summary Create user by admin +// @Description Create user by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body admin_domain.CreateUserRequest true "create user request" +// @Success 200 {object} admin_domain.CreateUserResponse "create user response" +// @Router /api/1.0/admin/organizations/{organizationId}/users [post] +// @Security JWT func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -749,20 +749,20 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } // Admin_List godoc -// @Tags Admin -// @Summary Get user list by admin -// @Description Get user list by admin -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} admin_domain.ListUserResponse "user list response" -// @Router /api/1.0/admin/organizations/{organizationId}/users [get] -// @Security JWT +// @Tags Admin +// @Summary Get user list by admin +// @Description Get user list by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} admin_domain.ListUserResponse "user list response" +// @Router /api/1.0/admin/organizations/{organizationId}/users [get] +// @Security JWT func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -797,15 +797,15 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { } // Admin_Get godoc -// @Tags Admin -// @Summary Get user detail by admin -// @Description Get user detail by admin -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} admin_domain.GetUserResponse -// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [get] +// @Tags Admin +// @Summary Get user detail by admin +// @Description Get user detail by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} admin_domain.GetUserResponse +// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [get] func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) userId, ok := vars["accountId"] @@ -841,16 +841,16 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { } // Admin_Delete godoc -// @Tags Admin -// @Summary Delete user by admin -// @Description Delete user by admin -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} admin_domain.User -// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [delete] -// @Security JWT +// @Tags Admin +// @Summary Delete user by admin +// @Description Delete user by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Success 200 {object} admin_domain.User +// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [delete] +// @Security JWT func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -902,17 +902,17 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { } // Admin_Update godoc -// @Tags Admin -// @Summary Update user by admin -// @Description Update user by admin -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Param body body admin_domain.UpdateUserRequest true "input" -// @Success 200 {object} admin_domain.UpdateUserResponse -// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [put] -// @Security JWT +// @Tags Admin +// @Summary Update user by admin +// @Description Update user by admin +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" +// @Param body body admin_domain.UpdateUserRequest true "input" +// @Success 200 {object} admin_domain.UpdateUserResponse +// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [put] +// @Security JWT func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) accountId, ok := vars["accountId"] From d98241a1c71b26ace157db19c3b88fef790fdba3 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 6 Mar 2024 11:30:17 +0900 Subject: [PATCH 088/502] feature. add api for project namespace resource --- Makefile | 2 ++ internal/delivery/http/project.go | 52 +++++++++++++++++++++++++++++++ internal/route/route.go | 1 + internal/usecase/project.go | 10 ++++++ pkg/domain/project.go | 10 ++++++ 5 files changed, 75 insertions(+) diff --git a/Makefile b/Makefile index 8bae219d..40fe7741 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ .PHONY: docs docs: swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger + swag fmt .PHONY: build build: @@ -18,5 +19,6 @@ test: .PHONY: dev_run dev_run: swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger + swag fmt go build ./cmd/server/main.go ./main diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 5d078c3a..802bf6da 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1592,3 +1592,55 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r } ResponseJSON(w, r, http.StatusOK, out) } + +// GetProjectNamespaceResourcesUsage godoc +// @Tags Projects +// @Summary Get resources usage for project namespace +// @Description Get resources usage for project namespace +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Stack ID" +// @Param projectNamespace path string true "Project Namespace" +// @Success 200 {object} domain.GetProjectNamespaceResourcesUsageResponse +// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage [get] +// @Security JWT +func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found in path"), "C_INVALID_PROJECT_ID", "")) + return + } + + projectNamespace, ok := vars["projectNamespace"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespace"), "C_INVALID_PROJECT_NAMESPACE", "")) + return + } + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), "C_INVALID_STACK_ID", "")) + return + } + + resourcesUsage, err := p.usecase.GetResourcesUsage(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectNamespaceResourcesUsageResponse + if err = serializer.Map(resourcesUsage, &out.ResourcesUsage); err != nil { + log.Error(err) + } + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/route/route.go b/internal/route/route.go index cfaaff21..2f1315ed 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -232,6 +232,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.CreateProjectNamespace, http.HandlerFunc(projectHandler.CreateProjectNamespace))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.IsProjectNamespaceExist))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources", customMiddleware.Handle(internalApi.GetProjectNamespaceK8sResources, http.HandlerFunc(projectHandler.GetProjectNamespaceK8sResources))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage", customMiddleware.Handle(internalApi.GetProjectNamespaceK8sResources, http.HandlerFunc(projectHandler.GetProjectNamespaceResourcesUsage))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces", customMiddleware.Handle(internalApi.GetProjectNamespaces, http.HandlerFunc(projectHandler.GetProjectNamespaces))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateProjectNamespace, http.HandlerFunc(projectHandler.UpdateProjectNamespace))).Methods(http.MethodPut) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 79af2cf6..85a4d8c6 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -56,6 +56,7 @@ type IProjectUsecase interface { DeleteK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceK8sResources, err error) + GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceResourcesUsage, err error) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error } @@ -776,3 +777,12 @@ func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId str return } + +func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) { + _, err = u.clusterRepository.Get(domain.ClusterId(stackId)) + if err != nil { + return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) + } + + return +} diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 8ecbea8f..fe8c43d5 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -183,3 +183,13 @@ type ProjectNamespaceK8sResources struct { type GetProjectNamespaceK8sResourcesResponse struct { K8sResources ProjectNamespaceK8sResources `json:"k8sResources"` } + +type ProjectNamespaceResourcesUsage struct { + CPU int `json:"cpu"` + Memory int `json:"memory"` + PV int `json:"pv"` +} + +type GetProjectNamespaceResourcesUsageResponse struct { + ResourcesUsage ProjectNamespaceResourcesUsage `json:"resourcesUsage"` +} From 45c1d1943705f552261566a345e56f62b78a4080 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 6 Mar 2024 13:24:53 +0900 Subject: [PATCH 089/502] feature. add API for project namespace resources --- api/swagger/docs.go | 80 +++++++++++++++++++++++++++++++ api/swagger/swagger.json | 80 +++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 52 ++++++++++++++++++++ internal/delivery/http/project.go | 8 ++-- internal/usecase/project.go | 8 +++- pkg/domain/project.go | 6 +-- 6 files changed, 226 insertions(+), 8 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 8af1e674..4a74d2f5 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -4451,6 +4451,64 @@ const docTemplate = `{ } } }, + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get resources usage for project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get resources usage for project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse" + } + } + } + } + }, "/api/1.0/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -7703,6 +7761,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse": { + "type": "object", + "properties": { + "resourcesUsage": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResourcesUsage" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse": { "type": "object", "properties": { @@ -8404,6 +8470,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResourcesUsage": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index a4400e25..bc6efc75 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -4445,6 +4445,64 @@ } } }, + "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get resources usage for project namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get resources usage for project namespace", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse" + } + } + } + } + }, "/api/1.0/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -7697,6 +7755,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse": { + "type": "object", + "properties": { + "resourcesUsage": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResourcesUsage" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse": { "type": "object", "properties": { @@ -8398,6 +8464,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResourcesUsage": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ed65980c..f70f328d 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1401,6 +1401,11 @@ definitions: k8sResources: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources' type: object + github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse: + properties: + resourcesUsage: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResourcesUsage' + type: object github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse: properties: projectNamespace: @@ -1867,6 +1872,15 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResourcesUsage: + properties: + cpu: + type: string + memory: + type: string + storage: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceResponse: properties: appCount: @@ -5442,6 +5456,44 @@ paths: summary: Get k8s resources for project namespace tags: - Projects + /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage: + get: + consumes: + - application/json + description: Get resources usage for project namespace + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Stack ID + in: path + name: stackId + required: true + type: string + - description: Project Namespace + in: path + name: projectNamespace + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse' + security: + - JWT: [] + summary: Get resources usage for project namespace + tags: + - Projects /api/1.0/organizations/{organizationId}/projects/existence: get: consumes: diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 802bf6da..eeaba849 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -52,6 +52,7 @@ type IProjectHandler interface { GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) GetProjectNamespaceK8sResources(w http.ResponseWriter, r *http.Request) + GetProjectNamespaceResourcesUsage(w http.ResponseWriter, r *http.Request) } type ProjectHandler struct { @@ -1594,6 +1595,7 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r } // GetProjectNamespaceResourcesUsage godoc +// // @Tags Projects // @Summary Get resources usage for project namespace // @Description Get resources usage for project namespace @@ -1603,7 +1605,7 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r // @Param projectId path string true "Project ID" // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} domain.GetProjectNamespaceResourcesUsageResponse +// @Success 200 {object} outdomain.GetProjectNamespaceResourcesUsageResponse // @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, r *http.Request) { @@ -1631,14 +1633,14 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, return } - resourcesUsage, err := p.usecase.GetResourcesUsage(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) + resourcesUsage, err := p.usecase.GetResourcesUsage(r.Context(), organizationId, projectId, projectNamespace, outdomain.StackId(stackId)) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) ErrorJSON(w, r, err) return } - var out domain.GetProjectNamespaceResourcesUsageResponse + var out outdomain.GetProjectNamespaceResourcesUsageResponse if err = serializer.Map(resourcesUsage, &out.ResourcesUsage); err != nil { log.Error(err) } diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 85a4d8c6..ac9785ab 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -778,11 +778,15 @@ func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId str return } -func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) { - _, err = u.clusterRepository.Get(domain.ClusterId(stackId)) +func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceResourcesUsage, err error) { + _, err = u.clusterRepository.Get(out_domain.ClusterId(stackId)) if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } + out.Cpu = "1.0 %" + out.Memory = "2.0 %" + out.Storage = "3.0 %" + return } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index fe8c43d5..1007dd27 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -185,9 +185,9 @@ type GetProjectNamespaceK8sResourcesResponse struct { } type ProjectNamespaceResourcesUsage struct { - CPU int `json:"cpu"` - Memory int `json:"memory"` - PV int `json:"pv"` + Cpu string `json:"cpu"` + Memory string `json:"memory"` + Storage string `json:"storage"` } type GetProjectNamespaceResourcesUsageResponse struct { From 2d4becd2ee0ca85de517c2d054990718ef73cd54 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 6 Mar 2024 14:18:51 +0900 Subject: [PATCH 090/502] feature. support filter array --- internal/pagination/pagination.go | 51 ++++++++++++++++--------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 0b2295f0..22e4ad47 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -192,34 +192,37 @@ func NewPagination(urlParams *url.Values) *Pagination { for _, filterValue := range value { arr := strings.Split(filterValue, "|") - column := arr[0] - releation := "" - arrColumns := strings.Split(column, ".") - if len(arrColumns) > 1 { - releation = arrColumns[0] - column = arrColumns[1] - } + columns := strings.Split(arr[0], ",") + for i, column := range columns { + releation := "" + arrColumns := strings.Split(column, ".") + if len(arrColumns) > 1 { + releation = arrColumns[0] + column = arrColumns[1] + } - trimmedStr := strings.Trim(arr[1], "[]") - values := strings.Split(trimmedStr, ",") + trimmedStr := strings.Trim(arr[1], "[]") + values := strings.Split(trimmedStr, ",") - op := "$cont" - if len(arr) == 3 { - op = arr[2] - } + op := "$cont" + if len(arr) == 3 { + op = arr[2] + } - or := false - if key == OR || key == OR_ARRAY { - or = true - } + or := false + if i > 0 || key == OR || key == OR_ARRAY { + or = true + } - pg.Filters = append(pg.Filters, Filter{ - Column: helper.ToSnakeCase(strings.Replace(column, "[]", "", -1)), - Relation: releation, - Operator: op, - Values: values, - Or: or, - }) + pg.Filters = append(pg.Filters, Filter{ + Column: helper.ToSnakeCase(strings.Replace(column, "[]", "", -1)), + Relation: releation, + Operator: op, + Values: values, + Or: or, + }) + + } } } } From 7bc3aeaf2a849d86802919ec109cb56438975bed Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 6 Mar 2024 10:46:08 +0900 Subject: [PATCH 091/502] feature. stack template intergration --- Makefile | 2 + api/swagger/docs.go | 367 ++++++++++++++--------- api/swagger/swagger.json | 367 ++++++++++++++--------- api/swagger/swagger.yaml | 231 ++++++++------ internal/constants.go | 60 ++++ internal/database/database.go | 3 +- internal/delivery/http/stack-template.go | 72 ++++- internal/repository/stack-template.go | 65 ++-- internal/route/route.go | 6 + internal/usecase/stack-template.go | 47 ++- pkg/domain/organization.go | 3 +- pkg/domain/role.go | 3 +- pkg/domain/stack-template.go | 88 +++--- 13 files changed, 871 insertions(+), 443 deletions(-) diff --git a/Makefile b/Makefile index 8bae219d..40fe7741 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ .PHONY: docs docs: swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger + swag fmt .PHONY: build build: @@ -18,5 +19,6 @@ test: .PHONY: dev_run dev_run: swag init -g ./cmd/server/main.go --parseDependency --parseInternal -o ./api/swagger + swag fmt go build ./cmd/server/main.go ./main diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 8af1e674..a111bb51 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -22,6 +22,176 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/admin/1.0/stack-templates": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "description": "create stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" + } + } + } + } + }, + "/admin/1.0/stack-templates/services": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get GetStackTemplateServices", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get GetStackTemplateServices", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse" + } + } + } + } + }, + "/admin/1.0/stack-templates/{stackTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplate", + "parameters": [ + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "description": "Update stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/1.0/admin/organizations/{organizationId}/users/{accountId}": { "get": { "description": "Get user detail by admin", @@ -5349,146 +5519,6 @@ const docTemplate = `{ } } } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "description": "create stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" - } - } - } - } - }, - "/api/1.0/stack-templates/{stackTemplateId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplate", - "parameters": [ - { - "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "description": "Update stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } } }, "/organizations/{organizationId}/roles": { @@ -7043,8 +7073,12 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest": { "type": "object", "required": [ + "kubeType", + "kubeVersion", "name", + "organizationIds", "platform", + "serviceIds", "template", "version" ], @@ -7060,12 +7094,30 @@ const docTemplate = `{ "description": { "type": "string" }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, "name": { "type": "string" }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, "platform": { "type": "string" }, + "serviceIds": { + "type": "array", + "items": { + "type": "string" + } + }, "template": { "type": "string" }, @@ -7801,6 +7853,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse": { + "type": "object", + "properties": { + "services": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse": { "type": "object", "properties": { @@ -8854,9 +8917,27 @@ const docTemplate = `{ "organizationId": { "type": "string" }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + } + }, "platform": { "type": "string" }, + "serviceIds": { + "type": "array", + "items": { + "type": "string" + } + }, "services": { "type": "array", "items": { @@ -8910,6 +8991,12 @@ const docTemplate = `{ "name": { "type": "string" }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" + } + }, "platform": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index a4400e25..78695f81 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -16,6 +16,176 @@ "host": "tks-api-dev.taco-cat.xyz", "basePath": "/", "paths": { + "/admin/1.0/stack-templates": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "description": "create stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" + } + } + } + } + }, + "/admin/1.0/stack-templates/services": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get GetStackTemplateServices", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get GetStackTemplateServices", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse" + } + } + } + } + }, + "/admin/1.0/stack-templates/{stackTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplate", + "parameters": [ + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "description": "Update stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/1.0/admin/organizations/{organizationId}/users/{accountId}": { "get": { "description": "Get user detail by admin", @@ -5343,146 +5513,6 @@ } } } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "description": "create stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" - } - } - } - } - }, - "/api/1.0/stack-templates/{stackTemplateId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplate", - "parameters": [ - { - "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "description": "Update stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete StackTemplate", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } } }, "/organizations/{organizationId}/roles": { @@ -7037,8 +7067,12 @@ "github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest": { "type": "object", "required": [ + "kubeType", + "kubeVersion", "name", + "organizationIds", "platform", + "serviceIds", "template", "version" ], @@ -7054,12 +7088,30 @@ "description": { "type": "string" }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, "name": { "type": "string" }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, "platform": { "type": "string" }, + "serviceIds": { + "type": "array", + "items": { + "type": "string" + } + }, "template": { "type": "string" }, @@ -7795,6 +7847,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse": { + "type": "object", + "properties": { + "services": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse": { "type": "object", "properties": { @@ -8848,9 +8911,27 @@ "organizationId": { "type": "string" }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + } + }, "platform": { "type": "string" }, + "serviceIds": { + "type": "array", + "items": { + "type": "string" + } + }, "services": { "type": "array", "items": { @@ -8904,6 +8985,12 @@ "name": { "type": "string" }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" + } + }, "platform": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ed65980c..70c24807 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -974,10 +974,22 @@ definitions: type: string description: type: string + kubeType: + type: string + kubeVersion: + type: string name: type: string + organizationIds: + items: + type: string + type: array platform: type: string + serviceIds: + items: + type: string + type: array template: type: string templateType: @@ -988,8 +1000,12 @@ definitions: version: type: string required: + - kubeType + - kubeVersion - name + - organizationIds - platform + - serviceIds - template - version type: object @@ -1463,6 +1479,13 @@ definitions: stackTemplate: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse: + properties: + services: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse: properties: pagination: @@ -2163,8 +2186,20 @@ definitions: type: string organizationId: type: string + organizationIds: + items: + type: string + type: array + organizations: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + type: array platform: type: string + serviceIds: + items: + type: string + type: array services: items: type: integer @@ -2200,6 +2235,10 @@ definitions: type: string name: type: string + organizations: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse' + type: array platform: type: string services: @@ -2684,6 +2723,111 @@ info: title: tks-api service version: "1.0" paths: + /admin/1.0/stack-templates: + post: + consumes: + - application/json + description: Create StackTemplate + parameters: + - description: create stack template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse' + security: + - JWT: [] + summary: Create StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + /admin/1.0/stack-templates/{stackTemplateId}: + delete: + consumes: + - application/json + description: Delete StackTemplate + parameters: + - description: stackTemplateId + in: path + name: stackTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + get: + consumes: + - application/json + description: Get StackTemplate + parameters: + - description: stackTemplateId + in: path + name: stackTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse' + security: + - JWT: [] + summary: Get StackTemplate + tags: + - StackTemplates + put: + consumes: + - application/json + description: Update StackTemplate + parameters: + - description: Update stack template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + /admin/1.0/stack-templates/services: + get: + consumes: + - application/json + description: Get GetStackTemplateServices + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse' + security: + - JWT: [] + summary: Get GetStackTemplateServices + tags: + - StackTemplates /api/1.0/admin/organizations/{organizationId}/users/{accountId}: get: consumes: @@ -6107,93 +6251,6 @@ paths: summary: Get StackTemplates tags: - StackTemplates - post: - consumes: - - application/json - description: Create StackTemplate - parameters: - - description: create stack template request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse' - security: - - JWT: [] - summary: Create StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates - /api/1.0/stack-templates/{stackTemplateId}: - delete: - consumes: - - application/json - description: Delete StackTemplate - parameters: - - description: stackTemplateId - in: path - name: stackTemplateId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates - get: - consumes: - - application/json - description: Get StackTemplate - parameters: - - description: stackTemplateId - in: path - name: stackTemplateId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse' - security: - - JWT: [] - summary: Get StackTemplate - tags: - - StackTemplates - put: - consumes: - - application/json - description: Update StackTemplate - parameters: - - description: Update stack template request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates /organizations/{organizationId}/roles: get: description: List Tks Roles diff --git a/internal/constants.go b/internal/constants.go index 21a57eba..7210560a 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -16,3 +16,63 @@ const ( SYSTEM_API_VERSION = "/1.0" SYSTEM_API_PREFIX = "/system-api" ) + +// 일단 DB 로 데이터를 관리하지 않고, 하드코딩 처리함. +const SERVICE_LMA = `{ + "name": "Logging,Monitoring,Alerting", + "type": "LMA", + "applications": [ + { + "name": "thanos", + "version": "0.30.2", + "description": "다중클러스터의 모니터링 데이터 통합 질의처리" + }, + { + "name": "prometheus-stack", + "version": "v0.66.0", + "description": "모니터링 데이터 수집/저장 및 질의처리" + }, + { + "name": "alertmanager", + "version": "v0.25.0", + "description": "알람 처리를 위한 노티피케이션 서비스" + }, + { + "name": "loki", + "version": "2.6.1", + "description": "로그데이터 저장 및 질의처리" + }, + { + "name": "grafana", + "version": "8.3.3", + "description": "모니터링/로그 통합대시보드" + } + ] + }` + +const SERVICE_SERVICE_MESH = ` { + "name": "MSA", + "type": "SERVICE_MESH", + "applications": [ + { + "name": "istio", + "version": "v1.17.2", + "description": "MSA 플랫폼" + }, + { + "name": "jagger", + "version": "1.35.0", + "description": "분산 서비스간 트랜잭션 추적을 위한 플랫폼" + }, + { + "name": "kiali", + "version": "v1.63.0", + "description": "MSA 구조 및 성능을 볼 수 있는 Dashboard" + }, + { + "name": "k8ssandra", + "version": "1.6.0", + "description": "분산 서비스간 호출 로그를 저장하는 스토리지" + } + ] +}` diff --git a/internal/database/database.go b/internal/database/database.go index fd260524..9bb20356 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -2,10 +2,11 @@ package database import ( "fmt" - "github.com/openinfradev/tks-api/internal/delivery/api" "os" "strings" + "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/spf13/viper" "gorm.io/driver/postgres" "gorm.io/gorm" diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index d6f63894..646ffe50 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -7,6 +7,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -27,6 +28,7 @@ func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { } // CreateStackTemplate godoc +// // @Tags StackTemplates // @Summary Create StackTemplate 'NOT IMPLEMENTED' // @Description Create StackTemplate @@ -34,13 +36,35 @@ func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { // @Produce json // @Param body body domain.CreateStackTemplateRequest true "create stack template request" // @Success 200 {object} domain.CreateStackTemplateResponse -// @Router /api/1.0/stack-templates [post] +// @Router /admin/1.0/stack-templates [post] // @Security JWT func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *http.Request) { - ErrorJSON(w, r, fmt.Errorf("need implementation")) + input := domain.CreateStackTemplateRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto domain.StackTemplate + if err = serializer.Map(input, &dto); err != nil { + log.InfoWithContext(r.Context(), err) + } + + id, err := h.usecase.Create(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + out := domain.CreateStackTemplateResponse{ + ID: id.String(), + } + ResponseJSON(w, r, http.StatusOK, out) } // GetStackTemplate godoc +// // @Tags StackTemplates // @Summary Get StackTemplates // @Description Get StackTemplates @@ -84,6 +108,7 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. } // GetStackTemplate godoc +// // @Tags StackTemplates // @Summary Get StackTemplate // @Description Get StackTemplate @@ -91,7 +116,7 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. // @Produce json // @Param stackTemplateId path string true "stackTemplateId" // @Success 200 {object} domain.GetStackTemplateResponse -// @Router /api/1.0/stack-templates/{stackTemplateId} [get] +// @Router /admin/1.0/stack-templates/{stackTemplateId} [get] // @Security JWT func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -118,6 +143,14 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R log.InfoWithContext(r.Context(), err) } + out.StackTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) + for i, organization := range stackTemplate.Organizations { + if err := serializer.Map(organization, &out.StackTemplate.Organizations[i]); err != nil { + log.InfoWithContext(r.Context(), err) + continue + } + } + err = json.Unmarshal(stackTemplate.Services, &out.StackTemplate.Services) if err != nil { log.ErrorWithContext(r.Context(), err) @@ -127,6 +160,7 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R } // UpdateStackTemplate godoc +// // @Tags StackTemplates // @Summary Update StackTemplate 'NOT IMPLEMENTED' // @Description Update StackTemplate @@ -134,7 +168,7 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R // @Produce json // @Param body body domain.UpdateStackTemplateRequest true "Update stack template request" // @Success 200 {object} nil -// @Router /api/1.0/stack-templates/{stackTemplateId} [put] +// @Router /admin/1.0/stack-templates/{stackTemplateId} [put] // @Security JWT func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *http.Request) { /* @@ -168,6 +202,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt } // DeleteStackTemplate godoc +// // @Tags StackTemplates // @Summary Delete StackTemplate 'NOT IMPLEMENTED' // @Description Delete StackTemplate @@ -175,7 +210,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt // @Produce json // @Param stackTemplateId path string true "stackTemplateId" // @Success 200 {object} nil -// @Router /api/1.0/stack-templates/{stackTemplateId} [delete] +// @Router /admin/1.0/stack-templates/{stackTemplateId} [delete] // @Security JWT func (h *StackTemplateHandler) DeleteStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -187,3 +222,30 @@ func (h *StackTemplateHandler) DeleteStackTemplate(w http.ResponseWriter, r *htt ErrorJSON(w, r, fmt.Errorf("need implementation")) } + +// GetStackTemplateServices godoc +// +// @Tags StackTemplates +// @Summary Get GetStackTemplateServices +// @Description Get GetStackTemplateServices +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetStackTemplateServicesResponse +// @Router /admin/1.0/stack-templates/services [get] +// @Security JWT +func (h *StackTemplateHandler) GetStackTemplateServices(w http.ResponseWriter, r *http.Request) { + + var out domain.GetStackTemplateServicesResponse + out.Services = make([]domain.StackTemplateServiceResponse, 2) + err := json.Unmarshal([]byte(internal.SERVICE_LMA), &out.Services[0]) + if err != nil { + log.ErrorWithContext(r.Context(), err) + } + + err = json.Unmarshal([]byte(internal.SERVICE_SERVICE_MESH), &out.Services[1]) + if err != nil { + log.ErrorWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index bb8b28ad..73c322d4 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -19,6 +19,7 @@ type IStackTemplateRepository interface { Create(dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) Update(dto domain.StackTemplate) (err error) Delete(dto domain.StackTemplate) (err error) + UpdateOrganizations(stackTemplateId uuid.UUID, organizationIds []domain.Organization) (err error) } type StackTemplateRepository struct { @@ -35,23 +36,22 @@ func NewStackTemplateRepository(db *gorm.DB) IStackTemplateRepository { type StackTemplate struct { gorm.Model - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Name string `gorm:"index"` - Description string `gorm:"index"` - Template string - TemplateType string - Version string - CloudService string - Platform string - KubeVersion string - KubeType string - Services datatypes.JSON - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index"` + Description string `gorm:"index"` + Template string + TemplateType string + Version string + CloudService string + Platform string + KubeVersion string + KubeType string + Organizations []domain.Organization `gorm:"many2many:stack_template_organizations"` + Services datatypes.JSON + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` } func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { @@ -92,15 +92,14 @@ func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain func (r *StackTemplateRepository) Create(dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) { stackTemplate := StackTemplate{ - OrganizationId: dto.OrganizationId, - Name: dto.Name, - Description: dto.Description, - CloudService: dto.CloudService, - Platform: dto.Platform, - Template: dto.Template, - TemplateType: dto.TemplateType, - CreatorId: &dto.CreatorId, - UpdatorId: nil} + Name: dto.Name, + Description: dto.Description, + CloudService: dto.CloudService, + Platform: dto.Platform, + Template: dto.Template, + TemplateType: dto.TemplateType, + CreatorId: &dto.CreatorId, + UpdatorId: &dto.CreatorId} res := r.db.Create(&stackTemplate) if res.Error != nil { return uuid.Nil, res.Error @@ -128,6 +127,20 @@ func (r *StackTemplateRepository) Delete(dto domain.StackTemplate) (err error) { return nil } +func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, organizations []domain.Organization) (err error) { + var stackTemplate = StackTemplate{} + res := r.db.Preload("Organizations").First(&stackTemplate, "id = ?", stackTemplateId) + if res.Error != nil { + return res.Error + } + err = r.db.Model(&stackTemplate).Association("Organizations").Replace(organizations) + if err != nil { + return err + } + + return nil +} + func reflectStackTemplate(stackTemplate StackTemplate) (out domain.StackTemplate) { if err := serializer.Map(stackTemplate.Model, &out); err != nil { log.Error(err) diff --git a/internal/route/route.go b/internal/route/route.go index cfaaff21..e1ec5bef 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -178,11 +178,17 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quotas", customMiddleware.Handle(internalApi.GetResourceQuota, http.HandlerFunc(cloudAccountHandler.GetResourceQuota))).Methods(http.MethodGet) stackTemplateHandler := delivery.NewStackTemplateHandler(usecaseFactory) + /* REMOVE START */ r.Handle(API_PREFIX+API_VERSION+"/stack-templates", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/stack-templates", customMiddleware.Handle(internalApi.CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetStackTemplate, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) + /* REMOVE END */ + + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 4e2731ac..4f9284c2 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -2,33 +2,66 @@ package usecase import ( "context" + "fmt" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" ) type IStackTemplateUsecase interface { - Get(ctx context.Context, stackTemplate uuid.UUID) (domain.StackTemplate, error) + Get(ctx context.Context, stackTemplateId uuid.UUID) (domain.StackTemplate, error) Fetch(ctx context.Context, pg *pagination.Pagination) ([]domain.StackTemplate, error) Create(ctx context.Context, dto domain.StackTemplate) (stackTemplate uuid.UUID, err error) Update(ctx context.Context, dto domain.StackTemplate) error Delete(ctx context.Context, dto domain.StackTemplate) error + UpdateOrganization(ctx context.Context, stackTemplateId uuid.UUID, organizationIds []string) error } type StackTemplateUsecase struct { - repo repository.IStackTemplateRepository + repo repository.IStackTemplateRepository + organizationRepo repository.IOrganizationRepository } func NewStackTemplateUsecase(r repository.Repository) IStackTemplateUsecase { return &StackTemplateUsecase{ - repo: r.StackTemplate, + repo: r.StackTemplate, + organizationRepo: r.Organization, } } -func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTemplate) (stackTemplate uuid.UUID, err error) { - return uuid.Nil, nil +func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) { + user, ok := request.UserFrom(ctx) + if !ok { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + } + + dto.CreatorId = user.GetUserId() + dto.UpdatorId = user.GetUserId() + stackTemplateId, err = u.repo.Create(dto) + if err != nil { + return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") + } + log.InfoWithContext(ctx, "newly created StackTemplate ID:", stackTemplateId) + + organizations := make([]domain.Organization, 0) + for _, organizationId := range dto.OrganizationIds { + organization, err := u.organizationRepo.Get(organizationId) + if err == nil { + organizations = append(organizations, organization) + } + } + + err = u.repo.UpdateOrganizations(stackTemplateId, organizations) + if err != nil { + return uuid.Nil, err + } + + return stackTemplateId, nil } func (u *StackTemplateUsecase) Update(ctx context.Context, dto domain.StackTemplate) error { @@ -54,3 +87,7 @@ func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Paginat func (u *StackTemplateUsecase) Delete(ctx context.Context, dto domain.StackTemplate) (err error) { return nil } + +func (u *StackTemplateUsecase) UpdateOrganization(ctx context.Context, stackTemplateId uuid.UUID, organizationIds []string) error { + return nil +} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 87f94611..7e764d94 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -1,8 +1,9 @@ package domain import ( - "gorm.io/gorm" "time" + + "gorm.io/gorm" ) // enum diff --git a/pkg/domain/role.go b/pkg/domain/role.go index 4e19e39d..e177a76a 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -1,9 +1,10 @@ package domain import ( + "time" + "github.com/google/uuid" "gorm.io/gorm" - "time" ) type RoleType string diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index 0d3e6911..97be560a 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -11,24 +11,27 @@ const STACK_TEMPLATE_TYPE_MSA = "MSA" // 내부 type StackTemplate struct { - ID uuid.UUID - OrganizationId string - Name string - Description string - Template string - TemplateType string - CloudService string - Version string - Platform string - KubeVersion string - KubeType string - Services []byte - CreatorId uuid.UUID - Creator User - UpdatorId uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time + ID uuid.UUID + OrganizationId string + Name string + Description string + Template string + TemplateType string + CloudService string + Version string + Platform string + KubeVersion string + KubeType string + OrganizationIds []string + Organizations []Organization + ServiceIds []string + Services []byte + CreatorId uuid.UUID + Creator User + UpdatorId uuid.UUID + Updator User + CreatedAt time.Time + UpdatedAt time.Time } type StackTemplateServiceApplicationResponse struct { @@ -43,21 +46,22 @@ type StackTemplateServiceResponse struct { } type StackTemplateResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Template string `json:"template"` - TemplateType string `json:"templateType"` - CloudService string `json:"cloudService"` - Version string `json:"version"` - Platform string `json:"platform"` - KubeVersion string `json:"kubeVersion"` - KubeType string `json:"kubeType"` - Services []StackTemplateServiceResponse `json:"services"` - Creator SimpleUserResponse `json:"creator"` - Updator SimpleUserResponse `json:"updator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Template string `json:"template"` + TemplateType string `json:"templateType"` + CloudService string `json:"cloudService"` + Version string `json:"version"` + Platform string `json:"platform"` + KubeVersion string `json:"kubeVersion"` + KubeType string `json:"kubeType"` + Organizations []SimpleOrganizationResponse `json:"organizations"` + Services []StackTemplateServiceResponse `json:"services"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type SimpleStackTemplateResponse struct { @@ -81,13 +85,19 @@ type GetStackTemplateResponse struct { } type CreateStackTemplateRequest struct { - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + Version string `json:"version" validate:"required"` + CloudService string `json:"cloudService" validate:"oneof=AWS AZZURE GCP"` - Version string `json:"version" validate:"required"` Platform string `json:"platform" validate:"required"` - Template string `json:"template" validate:"required"` TemplateType string `json:"templateType" validate:"oneof=STANDARD MSA"` + Template string `json:"template" validate:"required"` + KubeVersion string `json:"kubeVersion" validate:"required"` + KubeType string `json:"kubeType" validate:"required"` + + OrganizationIds []string `json:"organizationIds" validate:"required"` + ServiceIds []string `json:"serviceIds" validate:"required"` } type CreateStackTemplateResponse struct { @@ -97,3 +107,7 @@ type CreateStackTemplateResponse struct { type UpdateStackTemplateRequest struct { Description string `json:"description"` } + +type GetStackTemplateServicesResponse struct { + Services []StackTemplateServiceResponse `json:"services"` +} From b4f2fd0f91054438fad5f50f8bc9dc59f2f9c0e8 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 6 Mar 2024 14:43:55 +0900 Subject: [PATCH 092/502] feature. rollback swagger base path "/api/1.0/" --- api/swagger/docs.go | 524 +++++++++++------------ api/swagger/swagger.json | 524 +++++++++++------------ api/swagger/swagger.yaml | 396 ++++++++--------- cmd/server/main.go | 4 +- internal/delivery/http/alert.go | 16 +- internal/delivery/http/app-group.go | 18 +- internal/delivery/http/app-serve-app.go | 42 +- internal/delivery/http/audit.go | 12 +- internal/delivery/http/auth.go | 23 +- internal/delivery/http/cloud-account.go | 27 +- internal/delivery/http/cluster.go | 30 +- internal/delivery/http/dashboard.go | 12 +- internal/delivery/http/organization.go | 18 +- internal/delivery/http/project.go | 48 +-- internal/delivery/http/stack-template.go | 12 +- internal/delivery/http/stack.go | 30 +- internal/delivery/http/user.go | 51 ++- 17 files changed, 939 insertions(+), 848 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index ca4643a1..b003ac38 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -22,7 +22,97 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/admin/1.0/stack-templates": { + "/admin/organizations/{organizationId}/users/{accountId}": { + "get": { + "description": "Get user detail by admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin" + ], + "summary": "Get user detail by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user by admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin" + ], + "summary": "Update user by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse" + } + } + } + } + }, + "/admin/stack-templates": { "post": { "security": [ { @@ -61,7 +151,7 @@ const docTemplate = `{ } } }, - "/admin/1.0/stack-templates/services": { + "/admin/stack-templates/services": { "get": { "security": [ { @@ -89,7 +179,7 @@ const docTemplate = `{ } } }, - "/admin/1.0/stack-templates/{stackTemplateId}": { + "/admin/stack-templates/{stackTemplateId}": { "get": { "security": [ { @@ -192,97 +282,7 @@ const docTemplate = `{ } } }, - "/api/1.0/admin/organizations/{organizationId}/users/{accountId}": { - "get": { - "description": "Get user detail by admin", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Admin" - ], - "summary": "Get user detail by admin", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update user by admin", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Admin" - ], - "summary": "Update user by admin", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - }, - { - "description": "input", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse" - } - } - } - } - }, - "/api/1.0/app-groups": { + "/app-groups": { "get": { "security": [ { @@ -423,7 +423,7 @@ const docTemplate = `{ } } }, - "/api/1.0/app-groups/{appGroupId}": { + "/app-groups/{appGroupId}": { "get": { "security": [ { @@ -460,7 +460,7 @@ const docTemplate = `{ } } }, - "/api/1.0/app-groups/{appGroupId}/applications": { + "/app-groups/{appGroupId}/applications": { "get": { "security": [ { @@ -538,7 +538,7 @@ const docTemplate = `{ } } }, - "/api/1.0/auth/find-id/code": { + "/auth/find-id/code": { "post": { "description": "This API allows users to verify their identity for lost id by submitting required information", "consumes": [ @@ -578,7 +578,7 @@ const docTemplate = `{ } } }, - "/api/1.0/auth/find-id/verification": { + "/auth/find-id/verification": { "post": { "description": "This API allows users to find their account ID by submitting required information", "consumes": [ @@ -618,7 +618,7 @@ const docTemplate = `{ } } }, - "/api/1.0/auth/find-password/code": { + "/auth/find-password/code": { "post": { "description": "This API allows users to verify their identity for lost password by submitting required information", "consumes": [ @@ -658,7 +658,7 @@ const docTemplate = `{ } } }, - "/api/1.0/auth/find-password/verification": { + "/auth/find-password/verification": { "post": { "description": "This API allows users to reset their forgotten password by submitting required information", "consumes": [ @@ -695,7 +695,7 @@ const docTemplate = `{ } } }, - "/api/1.0/auth/login": { + "/auth/login": { "post": { "description": "login", "consumes": [ @@ -729,7 +729,7 @@ const docTemplate = `{ } } }, - "/api/1.0/auth/logout": { + "/auth/logout": { "post": { "security": [ { @@ -757,7 +757,7 @@ const docTemplate = `{ } } }, - "/api/1.0/auth/ping": { + "/auth/ping": { "post": { "description": "ping with token", "consumes": [ @@ -788,7 +788,7 @@ const docTemplate = `{ } } }, - "/api/1.0/clusters": { + "/clusters": { "get": { "security": [ { @@ -895,7 +895,7 @@ const docTemplate = `{ } } }, - "/api/1.0/clusters/import": { + "/clusters/import": { "post": { "security": [ { @@ -934,7 +934,7 @@ const docTemplate = `{ } } }, - "/api/1.0/clusters/{clusterId}": { + "/clusters/{clusterId}": { "get": { "security": [ { @@ -1006,7 +1006,7 @@ const docTemplate = `{ } } }, - "/api/1.0/clusters/{clusterId}/bootstrap-kubeconfig": { + "/clusters/{clusterId}/bootstrap-kubeconfig": { "get": { "security": [ { @@ -1060,7 +1060,7 @@ const docTemplate = `{ } } }, - "/api/1.0/clusters/{clusterId}/install": { + "/clusters/{clusterId}/install": { "post": { "security": [ { @@ -1094,7 +1094,7 @@ const docTemplate = `{ } } }, - "/api/1.0/clusters/{clusterId}/nodes": { + "/clusters/{clusterId}/nodes": { "get": { "security": [ { @@ -1131,7 +1131,7 @@ const docTemplate = `{ } } }, - "/api/1.0/clusters/{clusterId}/site-values": { + "/clusters/{clusterId}/site-values": { "get": { "security": [ { @@ -1168,7 +1168,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations": { + "/organizations": { "get": { "security": [ { @@ -1272,7 +1272,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}": { + "/organizations/{organizationId}": { "get": { "security": [ { @@ -1388,7 +1388,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/alerts": { + "/organizations/{organizationId}/alerts": { "get": { "security": [ { @@ -1459,7 +1459,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/alerts/{alertId}": { + "/organizations/{organizationId}/alerts/{alertId}": { "get": { "security": [ { @@ -1583,7 +1583,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/alerts/{alertId}/actions": { + "/organizations/{organizationId}/alerts/{alertId}/actions": { "post": { "security": [ { @@ -1617,7 +1617,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/audits": { + "/organizations/{organizationId}/audits": { "get": { "security": [ { @@ -1728,7 +1728,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/audits/{auditId}": { + "/organizations/{organizationId}/audits/{auditId}": { "get": { "security": [ { @@ -1797,7 +1797,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts": { + "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ { @@ -1912,7 +1912,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { "get": { "security": [ { @@ -1956,7 +1956,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { "get": { "security": [ { @@ -2000,7 +2000,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { "get": { "security": [ { @@ -2133,7 +2133,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { "delete": { "security": [ { @@ -2174,7 +2174,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { "get": { "security": [ { @@ -2218,7 +2218,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/dashboard/charts": { + "/organizations/{organizationId}/dashboard/charts": { "get": { "security": [ { @@ -2275,7 +2275,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/dashboard/charts/{chartType}": { + "/organizations/{organizationId}/dashboard/charts/{chartType}": { "get": { "security": [ { @@ -2333,7 +2333,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/dashboard/resources": { + "/organizations/{organizationId}/dashboard/resources": { "get": { "security": [ { @@ -2370,7 +2370,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/dashboard/stacks": { + "/organizations/{organizationId}/dashboard/stacks": { "get": { "security": [ { @@ -2407,7 +2407,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/my-profile": { + "/organizations/{organizationId}/my-profile": { "get": { "security": [ { @@ -2523,7 +2523,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/my-profile/next-password-change": { + "/organizations/{organizationId}/my-profile/next-password-change": { "put": { "security": [ { @@ -2563,7 +2563,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/my-profile/password": { + "/organizations/{organizationId}/my-profile/password": { "put": { "security": [ { @@ -2606,7 +2606,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/primary-cluster": { + "/organizations/{organizationId}/primary-cluster": { "patch": { "security": [ { @@ -2649,7 +2649,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects": { + "/organizations/{organizationId}/projects": { "get": { "security": [ { @@ -2736,7 +2736,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/existence": { + "/organizations/{organizationId}/projects/existence": { "get": { "security": [ { @@ -2786,7 +2786,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/project-roles": { + "/organizations/{organizationId}/projects/project-roles": { "get": { "security": [ { @@ -2829,7 +2829,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { "get": { "security": [ { @@ -2873,7 +2873,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}": { + "/organizations/{organizationId}/projects/{projectId}": { "get": { "security": [ { @@ -2968,7 +2968,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { "get": { "security": [ { @@ -3106,7 +3106,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { "get": { "security": [ { @@ -3157,7 +3157,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { "get": { "security": [ { @@ -3208,7 +3208,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { "get": { "security": [ { @@ -3366,7 +3366,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { "patch": { "security": [ { @@ -3426,7 +3426,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { "get": { "security": [ { @@ -3470,7 +3470,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { "get": { "security": [ { @@ -3521,7 +3521,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { "post": { "security": [ { @@ -3581,7 +3581,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { "patch": { "security": [ { @@ -3641,7 +3641,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { "get": { "security": [ { @@ -3722,7 +3722,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { "get": { "security": [ { @@ -3780,7 +3780,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { "get": { "security": [ { @@ -3824,7 +3824,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/members": { + "/organizations/{organizationId}/projects/{projectId}/members": { "get": { "security": [ { @@ -4027,7 +4027,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/count": { + "/organizations/{organizationId}/projects/{projectId}/members/count": { "get": { "security": [ { @@ -4071,7 +4071,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { "get": { "security": [ { @@ -4171,7 +4171,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { "put": { "security": [ { @@ -4231,7 +4231,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces": { + "/organizations/{organizationId}/projects/{projectId}/namespaces": { "get": { "security": [ { @@ -4326,7 +4326,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { "get": { "security": [ { @@ -4505,7 +4505,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { "get": { "security": [ { @@ -4563,7 +4563,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { "get": { "security": [ { @@ -4621,7 +4621,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { "get": { "security": [ { @@ -4679,7 +4679,36 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/roles": { + "get": { + "description": "List Tks Roles", + "produces": [ + "application/json" + ], + "tags": [ + "Role" + ], + "summary": "List Tks Roles", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks": { "get": { "security": [ { @@ -4790,7 +4819,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/stacks/name/{name}/existence": { + "/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ { @@ -4838,7 +4867,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/stacks/{stackId}": { + "/organizations/{organizationId}/stacks/{stackId}": { "get": { "security": [ { @@ -4969,7 +4998,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite": { + "/organizations/{organizationId}/stacks/{stackId}/favorite": { "post": { "security": [ { @@ -5049,7 +5078,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "/organizations/{organizationId}/stacks/{stackId}/kube-config": { "get": { "security": [ { @@ -5093,7 +5122,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/stacks/{stackId}/status": { + "/organizations/{organizationId}/stacks/{stackId}/status": { "get": { "security": [ { @@ -5137,7 +5166,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/users": { + "/organizations/{organizationId}/users": { "get": { "security": [ { @@ -5255,7 +5284,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "/organizations/{organizationId}/users/account-id/{accountId}/existence": { "get": { "security": [ { @@ -5296,7 +5325,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/users/email/{email}/existence": { + "/organizations/{organizationId}/users/email/{email}/existence": { "get": { "security": [ { @@ -5337,7 +5366,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/users/{accountId}": { + "/organizations/{organizationId}/users/{accountId}": { "get": { "security": [ { @@ -5474,7 +5503,7 @@ const docTemplate = `{ } } }, - "/api/1.0/organizations/{organizationId}/users/{accountId}/reset-password": { + "/organizations/{organizationId}/users/{accountId}/reset-password": { "put": { "security": [ { @@ -5515,99 +5544,6 @@ const docTemplate = `{ } } }, - "/api/1.0/stack-templates": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get StackTemplates", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplates", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" - } - } - } - } - }, - "/organizations/{organizationId}/roles": { - "get": { - "description": "List Tks Roles", - "produces": [ - "application/json" - ], - "tags": [ - "Role" - ], - "summary": "List Tks Roles", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" - } - } - } - } - }, "/permissions/templates": { "get": { "description": "Get Permission Templates", @@ -5690,6 +5626,70 @@ const docTemplate = `{ } } }, + "/stack-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + } + }, "/system-api/organizations/{organizationId}/alerts": { "post": { "security": [ @@ -9803,7 +9803,7 @@ const docTemplate = `{ var SwaggerInfo = &swag.Spec{ Version: "1.0", Host: "tks-api-dev.taco-cat.xyz", - BasePath: "/", + BasePath: "/api/1.0/", Schemes: []string{}, Title: "tks-api service", Description: "This is backend api service for tks platform", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 0cdfea8e..07d2d34d 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -14,9 +14,99 @@ "version": "1.0" }, "host": "tks-api-dev.taco-cat.xyz", - "basePath": "/", + "basePath": "/api/1.0/", "paths": { - "/admin/1.0/stack-templates": { + "/admin/organizations/{organizationId}/users/{accountId}": { + "get": { + "description": "Get user detail by admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin" + ], + "summary": "Get user detail by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user by admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin" + ], + "summary": "Update user by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse" + } + } + } + } + }, + "/admin/stack-templates": { "post": { "security": [ { @@ -55,7 +145,7 @@ } } }, - "/admin/1.0/stack-templates/services": { + "/admin/stack-templates/services": { "get": { "security": [ { @@ -83,7 +173,7 @@ } } }, - "/admin/1.0/stack-templates/{stackTemplateId}": { + "/admin/stack-templates/{stackTemplateId}": { "get": { "security": [ { @@ -186,97 +276,7 @@ } } }, - "/api/1.0/admin/organizations/{organizationId}/users/{accountId}": { - "get": { - "description": "Get user detail by admin", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Admin" - ], - "summary": "Get user detail by admin", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update user by admin", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Admin" - ], - "summary": "Update user by admin", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true - }, - { - "description": "input", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse" - } - } - } - } - }, - "/api/1.0/app-groups": { + "/app-groups": { "get": { "security": [ { @@ -417,7 +417,7 @@ } } }, - "/api/1.0/app-groups/{appGroupId}": { + "/app-groups/{appGroupId}": { "get": { "security": [ { @@ -454,7 +454,7 @@ } } }, - "/api/1.0/app-groups/{appGroupId}/applications": { + "/app-groups/{appGroupId}/applications": { "get": { "security": [ { @@ -532,7 +532,7 @@ } } }, - "/api/1.0/auth/find-id/code": { + "/auth/find-id/code": { "post": { "description": "This API allows users to verify their identity for lost id by submitting required information", "consumes": [ @@ -572,7 +572,7 @@ } } }, - "/api/1.0/auth/find-id/verification": { + "/auth/find-id/verification": { "post": { "description": "This API allows users to find their account ID by submitting required information", "consumes": [ @@ -612,7 +612,7 @@ } } }, - "/api/1.0/auth/find-password/code": { + "/auth/find-password/code": { "post": { "description": "This API allows users to verify their identity for lost password by submitting required information", "consumes": [ @@ -652,7 +652,7 @@ } } }, - "/api/1.0/auth/find-password/verification": { + "/auth/find-password/verification": { "post": { "description": "This API allows users to reset their forgotten password by submitting required information", "consumes": [ @@ -689,7 +689,7 @@ } } }, - "/api/1.0/auth/login": { + "/auth/login": { "post": { "description": "login", "consumes": [ @@ -723,7 +723,7 @@ } } }, - "/api/1.0/auth/logout": { + "/auth/logout": { "post": { "security": [ { @@ -751,7 +751,7 @@ } } }, - "/api/1.0/auth/ping": { + "/auth/ping": { "post": { "description": "ping with token", "consumes": [ @@ -782,7 +782,7 @@ } } }, - "/api/1.0/clusters": { + "/clusters": { "get": { "security": [ { @@ -889,7 +889,7 @@ } } }, - "/api/1.0/clusters/import": { + "/clusters/import": { "post": { "security": [ { @@ -928,7 +928,7 @@ } } }, - "/api/1.0/clusters/{clusterId}": { + "/clusters/{clusterId}": { "get": { "security": [ { @@ -1000,7 +1000,7 @@ } } }, - "/api/1.0/clusters/{clusterId}/bootstrap-kubeconfig": { + "/clusters/{clusterId}/bootstrap-kubeconfig": { "get": { "security": [ { @@ -1054,7 +1054,7 @@ } } }, - "/api/1.0/clusters/{clusterId}/install": { + "/clusters/{clusterId}/install": { "post": { "security": [ { @@ -1088,7 +1088,7 @@ } } }, - "/api/1.0/clusters/{clusterId}/nodes": { + "/clusters/{clusterId}/nodes": { "get": { "security": [ { @@ -1125,7 +1125,7 @@ } } }, - "/api/1.0/clusters/{clusterId}/site-values": { + "/clusters/{clusterId}/site-values": { "get": { "security": [ { @@ -1162,7 +1162,7 @@ } } }, - "/api/1.0/organizations": { + "/organizations": { "get": { "security": [ { @@ -1266,7 +1266,7 @@ } } }, - "/api/1.0/organizations/{organizationId}": { + "/organizations/{organizationId}": { "get": { "security": [ { @@ -1382,7 +1382,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/alerts": { + "/organizations/{organizationId}/alerts": { "get": { "security": [ { @@ -1453,7 +1453,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/alerts/{alertId}": { + "/organizations/{organizationId}/alerts/{alertId}": { "get": { "security": [ { @@ -1577,7 +1577,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/alerts/{alertId}/actions": { + "/organizations/{organizationId}/alerts/{alertId}/actions": { "post": { "security": [ { @@ -1611,7 +1611,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/audits": { + "/organizations/{organizationId}/audits": { "get": { "security": [ { @@ -1722,7 +1722,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/audits/{auditId}": { + "/organizations/{organizationId}/audits/{auditId}": { "get": { "security": [ { @@ -1791,7 +1791,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts": { + "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ { @@ -1906,7 +1906,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { "get": { "security": [ { @@ -1950,7 +1950,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { "get": { "security": [ { @@ -1994,7 +1994,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}": { "get": { "security": [ { @@ -2127,7 +2127,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error": { "delete": { "security": [ { @@ -2168,7 +2168,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { + "/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota": { "get": { "security": [ { @@ -2212,7 +2212,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/dashboard/charts": { + "/organizations/{organizationId}/dashboard/charts": { "get": { "security": [ { @@ -2269,7 +2269,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/dashboard/charts/{chartType}": { + "/organizations/{organizationId}/dashboard/charts/{chartType}": { "get": { "security": [ { @@ -2327,7 +2327,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/dashboard/resources": { + "/organizations/{organizationId}/dashboard/resources": { "get": { "security": [ { @@ -2364,7 +2364,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/dashboard/stacks": { + "/organizations/{organizationId}/dashboard/stacks": { "get": { "security": [ { @@ -2401,7 +2401,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/my-profile": { + "/organizations/{organizationId}/my-profile": { "get": { "security": [ { @@ -2517,7 +2517,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/my-profile/next-password-change": { + "/organizations/{organizationId}/my-profile/next-password-change": { "put": { "security": [ { @@ -2557,7 +2557,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/my-profile/password": { + "/organizations/{organizationId}/my-profile/password": { "put": { "security": [ { @@ -2600,7 +2600,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/primary-cluster": { + "/organizations/{organizationId}/primary-cluster": { "patch": { "security": [ { @@ -2643,7 +2643,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects": { + "/organizations/{organizationId}/projects": { "get": { "security": [ { @@ -2730,7 +2730,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/existence": { + "/organizations/{organizationId}/projects/existence": { "get": { "security": [ { @@ -2780,7 +2780,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/project-roles": { + "/organizations/{organizationId}/projects/project-roles": { "get": { "security": [ { @@ -2823,7 +2823,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { "get": { "security": [ { @@ -2867,7 +2867,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}": { + "/organizations/{organizationId}/projects/{projectId}": { "get": { "security": [ { @@ -2962,7 +2962,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { "get": { "security": [ { @@ -3100,7 +3100,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { "get": { "security": [ { @@ -3151,7 +3151,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { "get": { "security": [ { @@ -3202,7 +3202,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { "get": { "security": [ { @@ -3360,7 +3360,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { "patch": { "security": [ { @@ -3420,7 +3420,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { "get": { "security": [ { @@ -3464,7 +3464,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { "get": { "security": [ { @@ -3515,7 +3515,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { "post": { "security": [ { @@ -3575,7 +3575,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { "patch": { "security": [ { @@ -3635,7 +3635,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { "get": { "security": [ { @@ -3716,7 +3716,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { "get": { "security": [ { @@ -3774,7 +3774,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { "get": { "security": [ { @@ -3818,7 +3818,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/members": { + "/organizations/{organizationId}/projects/{projectId}/members": { "get": { "security": [ { @@ -4021,7 +4021,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/count": { + "/organizations/{organizationId}/projects/{projectId}/members/count": { "get": { "security": [ { @@ -4065,7 +4065,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { "get": { "security": [ { @@ -4165,7 +4165,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { "put": { "security": [ { @@ -4225,7 +4225,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces": { + "/organizations/{organizationId}/projects/{projectId}/namespaces": { "get": { "security": [ { @@ -4320,7 +4320,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { "get": { "security": [ { @@ -4499,7 +4499,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { "get": { "security": [ { @@ -4557,7 +4557,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { "get": { "security": [ { @@ -4615,7 +4615,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { "get": { "security": [ { @@ -4673,7 +4673,36 @@ } } }, - "/api/1.0/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/roles": { + "get": { + "description": "List Tks Roles", + "produces": [ + "application/json" + ], + "tags": [ + "Role" + ], + "summary": "List Tks Roles", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks": { "get": { "security": [ { @@ -4784,7 +4813,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/stacks/name/{name}/existence": { + "/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ { @@ -4832,7 +4861,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/stacks/{stackId}": { + "/organizations/{organizationId}/stacks/{stackId}": { "get": { "security": [ { @@ -4963,7 +4992,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite": { + "/organizations/{organizationId}/stacks/{stackId}/favorite": { "post": { "security": [ { @@ -5043,7 +5072,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "/organizations/{organizationId}/stacks/{stackId}/kube-config": { "get": { "security": [ { @@ -5087,7 +5116,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/stacks/{stackId}/status": { + "/organizations/{organizationId}/stacks/{stackId}/status": { "get": { "security": [ { @@ -5131,7 +5160,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/users": { + "/organizations/{organizationId}/users": { "get": { "security": [ { @@ -5249,7 +5278,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "/organizations/{organizationId}/users/account-id/{accountId}/existence": { "get": { "security": [ { @@ -5290,7 +5319,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/users/email/{email}/existence": { + "/organizations/{organizationId}/users/email/{email}/existence": { "get": { "security": [ { @@ -5331,7 +5360,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/users/{accountId}": { + "/organizations/{organizationId}/users/{accountId}": { "get": { "security": [ { @@ -5468,7 +5497,7 @@ } } }, - "/api/1.0/organizations/{organizationId}/users/{accountId}/reset-password": { + "/organizations/{organizationId}/users/{accountId}/reset-password": { "put": { "security": [ { @@ -5509,99 +5538,6 @@ } } }, - "/api/1.0/stack-templates": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get StackTemplates", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplates", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" - } - } - } - } - }, - "/organizations/{organizationId}/roles": { - "get": { - "description": "List Tks Roles", - "produces": [ - "application/json" - ], - "tags": [ - "Role" - ], - "summary": "List Tks Roles", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" - } - } - } - } - }, "/permissions/templates": { "get": { "description": "Get Permission Templates", @@ -5684,6 +5620,70 @@ } } }, + "/stack-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + } + }, "/system-api/organizations/{organizationId}/alerts": { "post": { "security": [ diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 8d1c82b3..2e678e2a 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1,4 +1,4 @@ -basePath: / +basePath: /api/1.0/ definitions: github_com_openinfradev_tks-api_pkg_domain.ActionResponse: properties: @@ -2737,7 +2737,66 @@ info: title: tks-api service version: "1.0" paths: - /admin/1.0/stack-templates: + /admin/organizations/{organizationId}/users/{accountId}: + get: + consumes: + - application/json + description: Get user detail by admin + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse' + summary: Get user detail by admin + tags: + - Admin + put: + consumes: + - application/json + description: Update user by admin + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: accountId + in: path + name: accountId + required: true + type: string + - description: input + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse' + security: + - JWT: [] + summary: Update user by admin + tags: + - Admin + /admin/stack-templates: post: consumes: - application/json @@ -2761,7 +2820,7 @@ paths: summary: Create StackTemplate 'NOT IMPLEMENTED' tags: - StackTemplates - /admin/1.0/stack-templates/{stackTemplateId}: + /admin/stack-templates/{stackTemplateId}: delete: consumes: - application/json @@ -2825,7 +2884,7 @@ paths: summary: Update StackTemplate 'NOT IMPLEMENTED' tags: - StackTemplates - /admin/1.0/stack-templates/services: + /admin/stack-templates/services: get: consumes: - application/json @@ -2842,66 +2901,7 @@ paths: summary: Get GetStackTemplateServices tags: - StackTemplates - /api/1.0/admin/organizations/{organizationId}/users/{accountId}: - get: - consumes: - - application/json - description: Get user detail by admin - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: accountId - in: path - name: accountId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse' - summary: Get user detail by admin - tags: - - Admin - put: - consumes: - - application/json - description: Update user by admin - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: accountId - in: path - name: accountId - required: true - type: string - - description: input - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse' - security: - - JWT: [] - summary: Update user by admin - tags: - - Admin - /api/1.0/app-groups: + /app-groups: delete: consumes: - application/json @@ -2990,7 +2990,7 @@ paths: summary: Install appGroup tags: - AppGroups - /api/1.0/app-groups/{appGroupId}: + /app-groups/{appGroupId}: get: consumes: - application/json @@ -3013,7 +3013,7 @@ paths: summary: Get appGroup detail tags: - AppGroups - /api/1.0/app-groups/{appGroupId}/applications: + /app-groups/{appGroupId}/applications: get: consumes: - application/json @@ -3062,7 +3062,7 @@ paths: summary: Create application tags: - AppGroups - /api/1.0/auth/find-id/code: + /auth/find-id/code: post: consumes: - application/json @@ -3090,7 +3090,7 @@ paths: summary: Request to verify identity for lost id tags: - Auth - /api/1.0/auth/find-id/verification: + /auth/find-id/verification: post: consumes: - application/json @@ -3118,7 +3118,7 @@ paths: summary: Request to find forgotten ID tags: - Auth - /api/1.0/auth/find-password/code: + /auth/find-password/code: post: consumes: - application/json @@ -3146,7 +3146,7 @@ paths: summary: Request to verify identity for lost password tags: - Auth - /api/1.0/auth/find-password/verification: + /auth/find-password/verification: post: consumes: - application/json @@ -3172,7 +3172,7 @@ paths: summary: Request to find forgotten password tags: - Auth - /api/1.0/auth/login: + /auth/login: post: consumes: - application/json @@ -3194,7 +3194,7 @@ paths: summary: login tags: - Auth - /api/1.0/auth/logout: + /auth/logout: post: consumes: - application/json @@ -3211,7 +3211,7 @@ paths: summary: logout tags: - Auth - /api/1.0/auth/ping: + /auth/ping: post: consumes: - application/json @@ -3231,7 +3231,7 @@ paths: summary: ping with token tags: - Auth - /api/1.0/clusters: + /clusters: get: consumes: - application/json @@ -3299,7 +3299,7 @@ paths: summary: Create cluster tags: - Clusters - /api/1.0/clusters/{clusterId}: + /clusters/{clusterId}: delete: consumes: - application/json @@ -3344,7 +3344,7 @@ paths: summary: Get cluster tags: - Clusters - /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig: + /clusters/{clusterId}/bootstrap-kubeconfig: get: consumes: - application/json @@ -3377,7 +3377,7 @@ paths: summary: Create bootstrap kubeconfig for BYOH tags: - Clusters - /api/1.0/clusters/{clusterId}/install: + /clusters/{clusterId}/install: post: consumes: - application/json @@ -3398,7 +3398,7 @@ paths: summary: Install cluster on tks cluster tags: - Clusters - /api/1.0/clusters/{clusterId}/nodes: + /clusters/{clusterId}/nodes: get: consumes: - application/json @@ -3421,7 +3421,7 @@ paths: summary: Get nodes information for BYOH tags: - Clusters - /api/1.0/clusters/{clusterId}/site-values: + /clusters/{clusterId}/site-values: get: consumes: - application/json @@ -3444,7 +3444,7 @@ paths: summary: Get cluster site values for creating tags: - Clusters - /api/1.0/clusters/import: + /clusters/import: post: consumes: - application/json @@ -3468,7 +3468,7 @@ paths: summary: Import cluster tags: - Clusters - /api/1.0/organizations: + /organizations: get: consumes: - application/json @@ -3534,7 +3534,7 @@ paths: summary: Create organization tags: - Organizations - /api/1.0/organizations/{organizationId}: + /organizations/{organizationId}: delete: consumes: - application/json @@ -3607,7 +3607,7 @@ paths: summary: Update organization detail tags: - Organizations - /api/1.0/organizations/{organizationId}/alerts: + /organizations/{organizationId}/alerts: get: consumes: - application/json @@ -3653,7 +3653,7 @@ paths: summary: Get Alerts tags: - Alerts - /api/1.0/organizations/{organizationId}/alerts/{alertId}: + /organizations/{organizationId}/alerts/{alertId}: delete: consumes: - application/json @@ -3732,7 +3732,7 @@ paths: summary: Update Alert tags: - Alerts - /api/1.0/organizations/{organizationId}/alerts/{alertId}/actions: + /organizations/{organizationId}/alerts/{alertId}/actions: post: consumes: - application/json @@ -3753,7 +3753,7 @@ paths: summary: Create alert action tags: - Alerts - /api/1.0/organizations/{organizationId}/audits: + /organizations/{organizationId}/audits: get: consumes: - application/json @@ -3824,7 +3824,7 @@ paths: summary: Create Audit tags: - Audits - /api/1.0/organizations/{organizationId}/audits/{auditId}: + /organizations/{organizationId}/audits/{auditId}: delete: consumes: - application/json @@ -3867,7 +3867,7 @@ paths: summary: Get Audit tags: - Audits - /api/1.0/organizations/{organizationId}/cloud-accounts: + /organizations/{organizationId}/cloud-accounts: get: consumes: - application/json @@ -3941,7 +3941,7 @@ paths: summary: Create CloudAccount tags: - CloudAccounts - /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}: + /organizations/{organizationId}/cloud-accounts/{cloudAccountId}: delete: consumes: - application/json @@ -4026,7 +4026,7 @@ paths: summary: Update CloudAccount tags: - CloudAccounts - /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error: + /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error: delete: consumes: - application/json @@ -4052,7 +4052,7 @@ paths: summary: Delete Force CloudAccount tags: - CloudAccounts - /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota: + /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota: get: consumes: - application/json @@ -4080,7 +4080,7 @@ paths: summary: Get resource quota by cloudAccount tags: - CloudAccounts - /api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence: + /organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence: get: consumes: - application/json @@ -4108,7 +4108,7 @@ paths: summary: Check awsAccountId for cloudAccount tags: - CloudAccounts - /api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence: + /organizations/{organizationId}/cloud-accounts/name/{name}/existence: get: consumes: - application/json @@ -4136,7 +4136,7 @@ paths: summary: Check name for cloudAccount tags: - CloudAccounts - /api/1.0/organizations/{organizationId}/dashboard/charts: + /organizations/{organizationId}/dashboard/charts: get: consumes: - application/json @@ -4173,7 +4173,7 @@ paths: summary: Get charts data tags: - Dashboards - /api/1.0/organizations/{organizationId}/dashboard/charts/{chartType}: + /organizations/{organizationId}/dashboard/charts/{chartType}: get: consumes: - application/json @@ -4211,7 +4211,7 @@ paths: summary: Get chart data tags: - Dashboards - /api/1.0/organizations/{organizationId}/dashboard/resources: + /organizations/{organizationId}/dashboard/resources: get: consumes: - application/json @@ -4234,7 +4234,7 @@ paths: summary: Get resources tags: - Dashboards - /api/1.0/organizations/{organizationId}/dashboard/stacks: + /organizations/{organizationId}/dashboard/stacks: get: consumes: - application/json @@ -4257,7 +4257,7 @@ paths: summary: Get stacks tags: - Dashboards - /api/1.0/organizations/{organizationId}/my-profile: + /organizations/{organizationId}/my-profile: delete: consumes: - application/json @@ -4330,7 +4330,7 @@ paths: summary: Update my profile detail tags: - My-profile - /api/1.0/organizations/{organizationId}/my-profile/next-password-change: + /organizations/{organizationId}/my-profile/next-password-change: put: consumes: - application/json @@ -4355,7 +4355,7 @@ paths: summary: Update user's password expired date to current date tags: - My-profile - /api/1.0/organizations/{organizationId}/my-profile/password: + /organizations/{organizationId}/my-profile/password: put: consumes: - application/json @@ -4382,7 +4382,7 @@ paths: summary: Update user password detail tags: - My-profile - /api/1.0/organizations/{organizationId}/primary-cluster: + /organizations/{organizationId}/primary-cluster: patch: consumes: - application/json @@ -4409,7 +4409,7 @@ paths: summary: Update primary cluster tags: - Organizations - /api/1.0/organizations/{organizationId}/projects: + /organizations/{organizationId}/projects: get: consumes: - application/json @@ -4464,7 +4464,7 @@ paths: summary: Create new project tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}: + /organizations/{organizationId}/projects/{projectId}: get: consumes: - application/json @@ -4525,7 +4525,7 @@ paths: summary: Update project tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps: get: consumes: - application/json @@ -4615,7 +4615,7 @@ paths: summary: Install appServeApp tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}: delete: consumes: - application/json @@ -4718,7 +4718,7 @@ paths: summary: Update appServeApp tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint: patch: consumes: - application/json @@ -4757,7 +4757,7 @@ paths: summary: Update app endpoint tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist: get: consumes: - application/json @@ -4785,7 +4785,7 @@ paths: summary: Get appServeApp tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task: get: consumes: - application/json @@ -4818,7 +4818,7 @@ paths: summary: Get latest task from appServeApp tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback: post: consumes: - application/json @@ -4857,7 +4857,7 @@ paths: summary: Rollback appServeApp tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status: patch: consumes: - application/json @@ -4896,7 +4896,7 @@ paths: summary: Update app status tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks: get: consumes: - application/json @@ -4949,7 +4949,7 @@ paths: summary: Get appServeAppTask list tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}: get: consumes: - application/json @@ -4987,7 +4987,7 @@ paths: summary: Get task detail from appServeApp tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/count: get: consumes: - application/json @@ -5020,7 +5020,7 @@ paths: summary: Get number of apps on given stack tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence: + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence: get: consumes: - application/json @@ -5053,7 +5053,7 @@ paths: summary: Check duplicate appServeAppName tags: - AppServeApps - /api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig: + /organizations/{organizationId}/projects/{projectId}/kubeconfig: get: consumes: - application/json @@ -5081,7 +5081,7 @@ paths: summary: Get project kubeconfig tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/members: + /organizations/{organizationId}/projects/{projectId}/members: delete: consumes: - application/json @@ -5213,7 +5213,7 @@ paths: summary: Update project member Role tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}: + /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}: delete: consumes: - application/json @@ -5278,7 +5278,7 @@ paths: summary: Get project member tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role: + /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role: put: consumes: - application/json @@ -5317,7 +5317,7 @@ paths: summary: Update project member Role tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/members/count: + /organizations/{organizationId}/projects/{projectId}/members/count: get: consumes: - application/json @@ -5345,7 +5345,7 @@ paths: summary: Get project member count group by project role tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces: + /organizations/{organizationId}/projects/{projectId}/namespaces: get: consumes: - application/json @@ -5406,7 +5406,7 @@ paths: summary: Create project namespace tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}: + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}: delete: consumes: - application/json @@ -5524,7 +5524,7 @@ paths: summary: Update project namespace tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence: + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence: get: consumes: - application/json @@ -5562,7 +5562,7 @@ paths: summary: Check project namespace exist tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources: + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources: get: consumes: - application/json @@ -5600,7 +5600,7 @@ paths: summary: Get k8s resources for project namespace tags: - Projects - /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage: + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage: get: consumes: - application/json @@ -5638,7 +5638,7 @@ paths: summary: Get resources usage for project namespace tags: - Projects - /api/1.0/organizations/{organizationId}/projects/existence: + /organizations/{organizationId}/projects/existence: get: consumes: - application/json @@ -5670,7 +5670,7 @@ paths: summary: Check project name exist tags: - Projects - /api/1.0/organizations/{organizationId}/projects/project-roles: + /organizations/{organizationId}/projects/project-roles: get: consumes: - application/json @@ -5698,7 +5698,7 @@ paths: summary: Get project roles tags: - Projects - /api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId}: + /organizations/{organizationId}/projects/project-roles/{projectRoleId}: get: consumes: - application/json @@ -5726,7 +5726,26 @@ paths: summary: Get project role tags: - Projects - /api/1.0/organizations/{organizationId}/stacks: + /organizations/{organizationId}/roles: + get: + description: List Tks Roles + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' + summary: List Tks Roles + tags: + - Role + /organizations/{organizationId}/stacks: get: consumes: - application/json @@ -5797,7 +5816,7 @@ paths: summary: Create Stack tags: - Stacks - /api/1.0/organizations/{organizationId}/stacks/{stackId}: + /organizations/{organizationId}/stacks/{stackId}: delete: consumes: - application/json @@ -5881,7 +5900,7 @@ paths: summary: Update Stack tags: - Stacks - /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite: + /organizations/{organizationId}/stacks/{stackId}/favorite: delete: consumes: - application/json @@ -5932,7 +5951,7 @@ paths: summary: Set favorite stack tags: - Stacks - /api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config: + /organizations/{organizationId}/stacks/{stackId}/kube-config: get: consumes: - application/json @@ -5960,7 +5979,7 @@ paths: summary: Get KubeConfig by stack tags: - Stacks - /api/1.0/organizations/{organizationId}/stacks/{stackId}/status: + /organizations/{organizationId}/stacks/{stackId}/status: get: consumes: - application/json @@ -5988,7 +6007,7 @@ paths: summary: Get Stack Status tags: - Stacks - /api/1.0/organizations/{organizationId}/stacks/name/{name}/existence: + /organizations/{organizationId}/stacks/name/{name}/existence: get: consumes: - application/json @@ -6019,7 +6038,7 @@ paths: summary: Check name for stack tags: - Stacks - /api/1.0/organizations/{organizationId}/users: + /organizations/{organizationId}/users: get: consumes: - application/json @@ -6095,7 +6114,7 @@ paths: summary: Create user tags: - Users - /api/1.0/organizations/{organizationId}/users/{accountId}: + /organizations/{organizationId}/users/{accountId}: delete: consumes: - application/json @@ -6183,7 +6202,7 @@ paths: summary: Update user tags: - Users - /api/1.0/organizations/{organizationId}/users/{accountId}/reset-password: + /organizations/{organizationId}/users/{accountId}/reset-password: put: consumes: - application/json @@ -6210,7 +6229,7 @@ paths: summary: Reset user's password as temporary password by admin tags: - Users - /api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence: + /organizations/{organizationId}/users/account-id/{accountId}/existence: get: description: return true when accountId exists parameters: @@ -6236,7 +6255,7 @@ paths: summary: Get user id existence tags: - Users - /api/1.0/organizations/{organizationId}/users/email/{email}/existence: + /organizations/{organizationId}/users/email/{email}/existence: get: description: return true when email exists parameters: @@ -6262,66 +6281,6 @@ paths: summary: Get user email existence tags: - Users - /api/1.0/stack-templates: - get: - consumes: - - application/json - description: Get StackTemplates - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' - security: - - JWT: [] - summary: Get StackTemplates - tags: - - StackTemplates - /organizations/{organizationId}/roles: - get: - description: List Tks Roles - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' - summary: List Tks Roles - tags: - - Role /permissions/templates: get: consumes: @@ -6376,6 +6335,47 @@ paths: summary: Update Permissions By Role ID tags: - Permission + /stack-templates: + get: + consumes: + - application/json + description: Get StackTemplates + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' + security: + - JWT: [] + summary: Get StackTemplates + tags: + - StackTemplates /system-api/organizations/{organizationId}/alerts: post: consumes: diff --git a/cmd/server/main.go b/cmd/server/main.go index 6ad93bfd..bf6926f7 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -99,8 +99,8 @@ func init() { // @in header // @name Authorization -// @host tks-api-dev.taco-cat.xyz -// @BasePath / +// @host tks-api-dev.taco-cat.xyz +// @BasePath /api/1.0/ func main() { log.Info("*** Arguments *** ") for i, s := range viper.AllSettings() { diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index 89b9882b..5b03746f 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -28,6 +28,7 @@ func NewAlertHandler(h usecase.Usecase) *AlertHandler { } // CreateAlert godoc +// // @Tags Alerts // @Summary Create alert. ADMIN ONLY // @Description Create alert. ADMIN ONLY @@ -72,6 +73,7 @@ func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { } // GetAlert godoc +// // @Tags Alerts // @Summary Get Alerts // @Description Get Alerts @@ -84,7 +86,7 @@ func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetAlertsResponse -// @Router /api/1.0/organizations/{organizationId}/alerts [get] +// @Router /organizations/{organizationId}/alerts [get] // @Security JWT func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -147,6 +149,7 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { } // GetAlert godoc +// // @Tags Alerts // @Summary Get Alert // @Description Get Alert @@ -155,7 +158,7 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param alertId path string true "alertId" // @Success 200 {object} domain.GetAlertResponse -// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [get] +// @Router /organizations/{organizationId}/alerts/{alertId} [get] // @Security JWT func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -194,6 +197,7 @@ func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { } // UpdateAlert godoc +// // @Tags Alerts // @Summary Update Alert // @Description Update Alert @@ -202,13 +206,14 @@ func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param body body domain.UpdateAlertRequest true "Update cloud setting request" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [put] +// @Router /organizations/{organizationId}/alerts/{alertId} [put] // @Security JWT func (h *AlertHandler) UpdateAlert(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("Need implementation")) } // DeleteAlert godoc +// // @Tags Alerts // @Summary Delete Alert // @Description Delete Alert @@ -217,7 +222,7 @@ func (h *AlertHandler) UpdateAlert(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param alertId path string true "alertId" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId} [delete] +// @Router /organizations/{organizationId}/alerts/{alertId} [delete] // @Security JWT func (h *AlertHandler) DeleteAlert(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("Need implementation")) @@ -234,6 +239,7 @@ func (h *AlertHandler) AlertTest(w http.ResponseWriter, r *http.Request) { } // CreateAlertAction godoc +// // @Tags Alerts // @Summary Create alert action // @Description Create alert action @@ -241,7 +247,7 @@ func (h *AlertHandler) AlertTest(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/alerts/{alertId}/actions [post] +// @Router /organizations/{organizationId}/alerts/{alertId}/actions [post] // @Security JWT func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 5bd8af55..26dbb840 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -25,6 +25,7 @@ func NewAppGroupHandler(h usecase.Usecase) *AppGroupHandler { } // CreateAppGroup godoc +// // @Tags AppGroups // @Summary Install appGroup // @Description Install appGroup @@ -32,7 +33,7 @@ func NewAppGroupHandler(h usecase.Usecase) *AppGroupHandler { // @Produce json // @Param body body domain.CreateAppGroupRequest true "create appgroup request" // @Success 200 {object} domain.CreateAppGroupResponse -// @Router /api/1.0/app-groups [post] +// @Router /app-groups [post] // @Security JWT func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) { input := domain.CreateAppGroupRequest{} @@ -60,6 +61,7 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) } // GetAppGroups godoc +// // @Tags AppGroups // @Summary Get appGroup list // @Description Get appGroup list by giving params @@ -72,7 +74,7 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetAppGroupsResponse -// @Router /api/1.0/app-groups [get] +// @Router /app-groups [get] // @Security JWT func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -107,6 +109,7 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { } // GetAppGroup godoc +// // @Tags AppGroups // @Summary Get appGroup detail // @Description Get appGroup detail by appGroupId @@ -114,7 +117,7 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param appGroupId path string true "appGroupId" // @Success 200 {object} domain.GetAppGroupResponse -// @Router /api/1.0/app-groups/{appGroupId} [get] +// @Router /app-groups/{appGroupId} [get] // @Security JWT func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -143,6 +146,7 @@ func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { } // DeleteAppGroup godoc +// // @Tags AppGroups // @Summary Uninstall appGroup // @Description Uninstall appGroup @@ -150,7 +154,7 @@ func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param object body string true "body" // @Success 200 {object} nil -// @Router /api/1.0/app-groups [delete] +// @Router /app-groups [delete] // @Security JWT func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -177,6 +181,7 @@ func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) } // GetApplications godoc +// // @Tags AppGroups // @Summary Get applications // @Description Get applications @@ -185,7 +190,7 @@ func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) // @Param appGroupId path string true "appGroupId" // @Param applicationType query string true "applicationType" // @Success 200 {object} domain.GetApplicationsResponse -// @Router /api/1.0/app-groups/{appGroupId}/applications [get] +// @Router /app-groups/{appGroupId}/applications [get] // @Security JWT func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -229,6 +234,7 @@ func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request } // CreateApplication godoc +// // @Tags AppGroups // @Summary Create application // @Description Create application @@ -236,7 +242,7 @@ func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request // @Produce json // @Param object body domain.CreateApplicationRequest true "body" // @Success 200 {object} nil -// @Router /api/1.0/app-groups/{appGroupId}/applications [post] +// @Router /app-groups/{appGroupId}/applications [post] // @Security JWT func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index ed342f6a..d738685f 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -78,6 +78,7 @@ func NewAppServeAppHandler(h usecase.Usecase) *AppServeAppHandler { } // CreateAppServeApp godoc +// // @Tags AppServeApps // @Summary Install appServeApp // @Description Install appServeApp @@ -87,7 +88,7 @@ func NewAppServeAppHandler(h usecase.Usecase) *AppServeAppHandler { // @Param projectId path string true "Project ID" // @Param object body domain.CreateAppServeAppRequest true "Request body to create app" // @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps [post] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [post] // @Security JWT func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -215,6 +216,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re } // GetAppServeApps godoc +// // @Tags AppServeApps // @Summary Get appServeApp list // @Description Get appServeApp list by giving params @@ -229,7 +231,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.AppServeApp -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -272,6 +274,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ } // GetAppServeApp godoc +// // @Tags AppServeApps // @Summary Get appServeApp // @Description Get appServeApp by giving params @@ -281,7 +284,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ // @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} domain.GetAppServeAppResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Request) { ////////////////////////////////////////////////////////////////////////////////////////// @@ -335,6 +338,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque } // GetAppServeAppLatestTask godoc +// // @Tags AppServeApps // @Summary Get latest task from appServeApp // @Description Get latest task from appServeApp @@ -344,7 +348,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque // @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} domain.GetAppServeAppTaskResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -379,6 +383,7 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * } // GetNumOfAppsOnStack godoc +// // @Tags AppServeApps // @Summary Get number of apps on given stack // @Description Get number of apps on given stack @@ -388,7 +393,7 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * // @Param projectId path string true "Project ID" // @Param stackId query string true "Stack ID" // @Success 200 {object} int64 -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/count [get] // @Security JWT func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -417,6 +422,7 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. } // GetAppServeAppTasksByAppId godoc +// // @Tags AppServeApps // @Summary Get appServeAppTask list // @Description Get appServeAppTask list by giving params @@ -430,7 +436,7 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.AppServeApp -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -467,6 +473,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r } // GetAppServeAppTaskDetail godoc +// // @Tags AppServeApps // @Summary Get task detail from appServeApp // @Description Get task detail from appServeApp @@ -477,7 +484,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r // @Param appId path string true "App ID" // @Param taskId path string true "Task ID" // @Success 200 {object} domain.GetAppServeAppTaskResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId} [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId} [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -635,6 +642,7 @@ func makeStage(task *domain.AppServeAppTask, app *domain.AppServeApp, pl string) } // IsAppServeAppExist godoc +// // @Tags AppServeApps // @Summary Get appServeApp // @Description Get appServeApp by giving params @@ -643,7 +651,7 @@ func makeStage(task *domain.AppServeAppTask, app *domain.AppServeApp, pl string) // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} bool -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist [get] // @Security JWT func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -676,6 +684,7 @@ func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.R } // IsAppServeAppNameExist godoc +// // @Tags AppServeApps // @Summary Check duplicate appServeAppName // @Description Check duplicate appServeAppName by giving params @@ -685,7 +694,7 @@ func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.R // @Param projectId path string true "Project ID" // @Param name path string true "name" // @Success 200 {object} bool -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence [get] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence [get] // @Security JWT func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -716,6 +725,7 @@ func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *ht } // UpdateAppServeApp godoc +// // @Tags AppServeApps // @Summary Update appServeApp // @Description Update appServeApp @@ -726,7 +736,7 @@ func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *ht // @Param appId path string true "App ID" // @Param object body domain.UpdateAppServeAppRequest true "Request body to update app" // @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [put] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [put] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -826,6 +836,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re } // UpdateAppServeAppStatus godoc +// // @Tags AppServeApps // @Summary Update app status // @Description Update app status @@ -836,7 +847,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re // @Param appId path string true "App ID" // @Param body body domain.UpdateAppServeAppStatusRequest true "Request body to update app status" // @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status [patch] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status [patch] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -870,6 +881,7 @@ func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *h } // UpdateAppServeAppEndpoint godoc +// // @Tags AppServeApps // @Summary Update app endpoint // @Description Update app endpoint @@ -880,7 +892,7 @@ func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *h // @Param appId path string true "appId" // @Param body body domain.UpdateAppServeAppEndpointRequest true "Request body to update app endpoint" // @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint [patch] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint [patch] // @Security JWT func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -919,6 +931,7 @@ func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r } // DeleteAppServeApp godoc +// // @Tags AppServeApps // @Summary Uninstall appServeApp // @Description Uninstall appServeApp @@ -928,7 +941,7 @@ func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r // @Param projectId path string true "Project ID" // @Param appId path string true "App ID" // @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [delete] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [delete] // @Security JWT func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -956,6 +969,7 @@ func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Re } // RollbackAppServeApp godoc +// // @Tags AppServeApps // @Summary Rollback appServeApp // @Description Rollback appServeApp @@ -966,7 +980,7 @@ func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Re // @Param appId path string true "App ID" // @Param object body domain.RollbackAppServeAppRequest true "Request body to rollback app" // @Success 200 {object} string -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback [post] +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback [post] // @Security JWT func (h *AppServeAppHandler) RollbackAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 0596fa88..395d9112 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -26,6 +26,7 @@ func NewAuditHandler(h usecase.Usecase) *AuditHandler { } // CreateAudit godoc +// // @Tags Audits // @Summary Create Audit // @Description Create Audit @@ -33,13 +34,14 @@ func NewAuditHandler(h usecase.Usecase) *AuditHandler { // @Produce json // @Param body body domain.CreateAuditRequest true "create audit request" // @Success 200 {object} domain.CreateAuditResponse -// @Router /api/1.0/organizations/{organizationId}/audits [post] +// @Router /organizations/{organizationId}/audits [post] // @Security JWT func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) } // GetAudit godoc +// // @Tags Audits // @Summary Get Audits // @Description Get Audits @@ -52,7 +54,7 @@ func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { // @Param filter query []string false "filters" // @Param or query []string false "filters" // @Success 200 {object} domain.GetAuditsResponse -// @Router /api/1.0/organizations/{organizationId}/audits [get] +// @Router /organizations/{organizationId}/audits [get] // @Security JWT func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -86,6 +88,7 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { } // GetAudit godoc +// // @Tags Audits // @Summary Get Audit // @Description Get Audit @@ -93,7 +96,7 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} domain.GetAuditResponse -// @Router /api/1.0/organizations/{organizationId}/audits/{auditId} [get] +// @Router /organizations/{organizationId}/audits/{auditId} [get] // @Security JWT func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -126,6 +129,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { } // DeleteAudit godoc +// // @Tags Audits // @Summary Delete Audit 'NOT IMPLEMENTED' // @Description Delete Audit @@ -133,7 +137,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/audits/{auditId} [delete] +// @Router /organizations/{organizationId}/audits/{auditId} [delete] // @Security JWT func (h *AuditHandler) DeleteAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index e12c5108..72a56812 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -41,6 +41,7 @@ func NewAuthHandler(h usecase.Usecase) IAuthHandler { } // Login godoc +// // @Tags Auth // @Summary login // @Description login @@ -48,7 +49,7 @@ func NewAuthHandler(h usecase.Usecase) IAuthHandler { // @Produce json // @Param body body domain.LoginRequest true "account info" // @Success 200 {object} domain.LoginResponse "user detail" -// @Router /api/1.0/auth/login [post] +// @Router /auth/login [post] func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { input := domain.LoginRequest{} err := UnmarshalRequestInput(r, &input) @@ -104,13 +105,14 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { } // Logout godoc +// // @Tags Auth // @Summary logout // @Description logout // @Accept json // @Produce json // @Success 200 {object} domain.LogoutResponse -// @Router /api/1.0/auth/logout [post] +// @Router /auth/logout [post] // @Security JWT func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -163,6 +165,7 @@ func (h *AuthHandler) RefreshToken(w http.ResponseWriter, r *http.Request) { } // FindId godoc +// // @Tags Auth // @Summary Request to find forgotten ID // @Description This API allows users to find their account ID by submitting required information @@ -171,7 +174,7 @@ func (h *AuthHandler) RefreshToken(w http.ResponseWriter, r *http.Request) { // @Param body body domain.FindIdRequest true "Request body for finding the account ID including {organization ID, email, username, 6 digit code}" // @Success 200 {object} domain.FindIdResponse // @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/auth/find-id/verification [post] +// @Router /auth/find-id/verification [post] func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { input := domain.FindIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -194,6 +197,7 @@ func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { } // FindPassword godoc +// // @Tags Auth // @Summary Request to find forgotten password // @Description This API allows users to reset their forgotten password by submitting required information @@ -202,7 +206,7 @@ func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { // @Param body body domain.FindPasswordRequest true "Request body for finding the password including {organization ID, email, username, Account ID, 6 digit code}" // @Success 200 // @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/auth/find-password/verification [post] +// @Router /auth/find-password/verification [post] func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { input := domain.FindPasswordRequest{} err := UnmarshalRequestInput(r, &input) @@ -222,6 +226,7 @@ func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { } // VerifyIdentityForLostId godoc +// // @Tags Auth // @Summary Request to verify identity for lost id // @Description This API allows users to verify their identity for lost id by submitting required information @@ -230,7 +235,7 @@ func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { // @Param body body domain.VerifyIdentityForLostIdRequest true "Request body for verifying identity for lost id including {organization ID, email, username}" // @Success 200 {object} domain.VerifyIdentityForLostIdResponse // @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/auth/find-id/code [post] +// @Router /auth/find-id/code [post] func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Request) { input := domain.VerifyIdentityForLostIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -252,6 +257,7 @@ func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Req } // VerifyIdentityForLostPassword godoc +// // @Tags Auth // @Summary Request to verify identity for lost password // @Description This API allows users to verify their identity for lost password by submitting required information @@ -260,7 +266,7 @@ func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Req // @Param body body domain.VerifyIdentityForLostPasswordRequest true "Request body for verifying identity for lost password including {organization ID, email, username, Account ID}" // @Success 200 {object} domain.VerifyIdentityForLostPasswordResponse // @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/auth/find-password/code [post] +// @Router /auth/find-password/code [post] func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *http.Request) { input := domain.VerifyIdentityForLostPasswordRequest{} err := UnmarshalRequestInput(r, &input) @@ -282,6 +288,7 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht } // Login godoc +// // @Tags Auth // @Summary ping with token // @Description ping with token @@ -289,7 +296,7 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht // @Produce json // @Param body body domain.PingTokenRequest true "token info" // @Success 200 {object} nil -// @Router /api/1.0/auth/ping [post] +// @Router /auth/ping [post] func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { input := domain.PingTokenRequest{} err := UnmarshalRequestInput(r, &input) @@ -314,7 +321,7 @@ func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { // @Description verify token // @Success 200 {object} nil // @Failure 401 {object} nil -// @Router /api/1.0/auth/verify-token [get] +// @Router /auth/verify-token [get] func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { token, ok := request.TokenFrom(r.Context()) diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index c9ab051b..15b4f6a1 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -27,6 +27,7 @@ func NewCloudAccountHandler(h usecase.Usecase) *CloudAccountHandler { } // CreateCloudAccount godoc +// // @Tags CloudAccounts // @Summary Create CloudAccount // @Description Create CloudAccount @@ -35,7 +36,7 @@ func NewCloudAccountHandler(h usecase.Usecase) *CloudAccountHandler { // @Param organizationId path string true "organizationId" // @Param body body domain.CreateCloudAccountRequest true "create cloud setting request" // @Success 200 {object} domain.CreateCloudAccountResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts [post] +// @Router /organizations/{organizationId}/cloud-accounts [post] // @Security JWT func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -71,6 +72,7 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. } // GetCloudAccount godoc +// // @Tags CloudAccounts // @Summary Get CloudAccounts // @Description Get CloudAccounts @@ -83,7 +85,7 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetCloudAccountsResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts [get] +// @Router /organizations/{organizationId}/cloud-accounts [get] // @Security JWT func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -118,6 +120,7 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re } // GetCloudAccount godoc +// // @Tags CloudAccounts // @Summary Get CloudAccount // @Description Get CloudAccount @@ -126,7 +129,7 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re // @Param organizationId path string true "organizationId" // @Param cloudAccountId path string true "cloudAccountId" // @Success 200 {object} domain.GetCloudAccountResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [get] +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [get] // @Security JWT func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -157,6 +160,7 @@ func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Req } // UpdateCloudAccount godoc +// // @Tags CloudAccounts // @Summary Update CloudAccount // @Description Update CloudAccount @@ -165,7 +169,7 @@ func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Req // @Param organizationId path string true "organizationId" // @Param body body domain.UpdateCloudAccountRequest true "Update cloud setting request" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [put] +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [put] // @Security JWT func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -211,6 +215,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. } // DeleteCloudAccount godoc +// // @Tags CloudAccounts // @Summary Delete CloudAccount // @Description Delete CloudAccount @@ -220,7 +225,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. // @Param body body domain.DeleteCloudAccountRequest true "Delete cloud setting request" // @Param cloudAccountId path string true "cloudAccountId" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId} [delete] +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId} [delete] // @Security JWT func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -259,6 +264,7 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. } // DeleteForceCloudAccount godoc +// // @Tags CloudAccounts // @Summary Delete Force CloudAccount // @Description Delete Force CloudAccount @@ -267,7 +273,7 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. // @Param organizationId path string true "organizationId" // @Param cloudAccountId path string true "cloudAccountId" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error [delete] +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/error [delete] // @Security JWT func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -293,6 +299,7 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * } // CheckCloudAccountName godoc +// // @Tags CloudAccounts // @Summary Check name for cloudAccount // @Description Check name for cloudAccount @@ -301,7 +308,7 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * // @Param organizationId path string true "organizationId" // @Param name path string true "name" // @Success 200 {object} domain.CheckCloudAccountNameResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/name/{name}/existence [GET] +// @Router /organizations/{organizationId}/cloud-accounts/name/{name}/existence [GET] // @Security JWT func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *http.Request) { user, ok := request.UserFrom(r.Context()) @@ -335,6 +342,7 @@ func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *ht } // CheckAwsAccountId godoc +// // @Tags CloudAccounts // @Summary Check awsAccountId for cloudAccount // @Description Check awsAccountId for cloudAccount @@ -343,7 +351,7 @@ func (h *CloudAccountHandler) CheckCloudAccountName(w http.ResponseWriter, r *ht // @Param organizationId path string true "organizationId" // @Param awsAccountId path string true "awsAccountId" // @Success 200 {object} domain.CheckCloudAccountAwsAccountIdResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence [GET] +// @Router /organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence [GET] // @Security JWT func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -371,6 +379,7 @@ func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.R } // GetResourceQuota godoc +// // @Tags CloudAccounts // @Summary Get resource quota by cloudAccount // @Description Get resource quota by cloudAccount @@ -379,7 +388,7 @@ func (h *CloudAccountHandler) CheckAwsAccountId(w http.ResponseWriter, r *http.R // @Param organizationId path string true "organizationId" // @Param cloudAccountId path string true "cloudAccountId" // @Success 200 {object} domain.GetCloudAccountResourceQuotaResponse -// @Router /api/1.0/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota [GET] +// @Router /organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quota [GET] // @Security JWT func (h *CloudAccountHandler) GetResourceQuota(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 45a0f7f3..1f8fb6a9 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -25,6 +25,7 @@ func NewClusterHandler(h usecase.Usecase) *ClusterHandler { } // GetClusters godoc +// // @Tags Clusters // @Summary Get clusters // @Description Get cluster list @@ -37,7 +38,7 @@ func NewClusterHandler(h usecase.Usecase) *ClusterHandler { // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetClustersResponse -// @Router /api/1.0/clusters [get] +// @Router /clusters [get] // @Security JWT func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -67,6 +68,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { } // GetCluster godoc +// // @Tags Clusters // @Summary Get cluster // @Description Get cluster detail @@ -74,7 +76,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} domain.Cluster -// @Router /api/1.0/clusters/{clusterId} [get] +// @Router /clusters/{clusterId} [get] // @Security JWT func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -99,6 +101,7 @@ func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { } // GetClusterSiteValues godoc +// // @Tags Clusters // @Summary Get cluster site values for creating // @Description Get cluster site values for creating @@ -106,7 +109,7 @@ func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} domain.ClusterSiteValuesResponse -// @Router /api/1.0/clusters/{clusterId}/site-values [get] +// @Router /clusters/{clusterId}/site-values [get] // @Security JWT func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -129,6 +132,7 @@ func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Req } // CreateCluster godoc +// // @Tags Clusters // @Summary Create cluster // @Description Create cluster @@ -136,7 +140,7 @@ func (h *ClusterHandler) GetClusterSiteValues(w http.ResponseWriter, r *http.Req // @Produce json // @Param body body domain.CreateClusterRequest true "create cluster request" // @Success 200 {object} domain.CreateClusterResponse -// @Router /api/1.0/clusters [post] +// @Router /clusters [post] // @Security JWT func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { input := domain.CreateClusterRequest{} @@ -188,6 +192,7 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { } // ImportCluster godoc +// // @Tags Clusters // @Summary Import cluster // @Description Import cluster @@ -195,7 +200,7 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param body body domain.ImportClusterRequest true "import cluster request" // @Success 200 {object} domain.ImportClusterResponse -// @Router /api/1.0/clusters/import [post] +// @Router /clusters/import [post] // @Security JWT func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { input := domain.ImportClusterRequest{} @@ -230,6 +235,7 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { } // InstallCluster godoc +// // @Tags Clusters // @Summary Install cluster on tks cluster // @Description Install cluster on tks cluster @@ -237,7 +243,7 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} nil -// @Router /api/1.0/clusters/{clusterId}/install [post] +// @Router /clusters/{clusterId}/install [post] // @Security JWT func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -257,6 +263,7 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) } // DeleteCluster godoc +// // @Tags Clusters // @Summary Delete cluster // @Description Delete cluster @@ -264,7 +271,7 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} domain.Cluster -// @Router /api/1.0/clusters/{clusterId} [delete] +// @Router /clusters/{clusterId} [delete] // @Security JWT func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -284,13 +291,14 @@ func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { } // CreateBootstrapKubeconfig godoc +// // @Tags Clusters // @Summary Create bootstrap kubeconfig for BYOH // @Description Create bootstrap kubeconfig for BYOH // @Accept json // @Produce json // @Success 200 {object} domain.CreateBootstrapKubeconfigResponse -// @Router /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig [post] +// @Router /clusters/{clusterId}/bootstrap-kubeconfig [post] // @Security JWT func (h *ClusterHandler) CreateBootstrapKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -312,13 +320,14 @@ func (h *ClusterHandler) CreateBootstrapKubeconfig(w http.ResponseWriter, r *htt } // GetBootstrapKubeconfig godoc +// // @Tags Clusters // @Summary Get bootstrap kubeconfig for BYOH // @Description Get bootstrap kubeconfig for BYOH // @Accept json // @Produce json // @Success 200 {object} domain.GetBootstrapKubeconfigResponse -// @Router /api/1.0/clusters/{clusterId}/bootstrap-kubeconfig [get] +// @Router /clusters/{clusterId}/bootstrap-kubeconfig [get] // @Security JWT func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -341,6 +350,7 @@ func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.R } // GetNodes godoc +// // @Tags Clusters // @Summary Get nodes information for BYOH // @Description Get nodes information for BYOH @@ -348,7 +358,7 @@ func (h *ClusterHandler) GetBootstrapKubeconfig(w http.ResponseWriter, r *http.R // @Produce json // @Param clusterId path string true "clusterId" // @Success 200 {object} domain.GetClusterNodesResponse -// @Router /api/1.0/clusters/{clusterId}/nodes [get] +// @Router /clusters/{clusterId}/nodes [get] // @Security JWT func (h *ClusterHandler) GetNodes(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index f1d07433..5a5bdbd1 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -24,6 +24,7 @@ func NewDashboardHandler(h usecase.Usecase) *DashboardHandler { } // GetCharts godoc +// // @Tags Dashboards // @Summary Get charts data // @Description Get charts data @@ -34,7 +35,7 @@ func NewDashboardHandler(h usecase.Usecase) *DashboardHandler { // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardChartsResponse -// @Router /api/1.0/organizations/{organizationId}/dashboard/charts [get] +// @Router /organizations/{organizationId}/dashboard/charts [get] // @Security JWT func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -83,6 +84,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { } // GetCharts godoc +// // @Tags Dashboards // @Summary Get chart data // @Description Get chart data @@ -93,7 +95,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardChartResponse -// @Router /api/1.0/organizations/{organizationId}/dashboard/charts/{chartType} [get] +// @Router /organizations/{organizationId}/dashboard/charts/{chartType} [get] // @Security JWT func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -159,6 +161,7 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { } // GetStacks godoc +// // @Tags Dashboards // @Summary Get stacks // @Description Get stacks @@ -166,7 +169,7 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetDashboardStacksResponse -// @Router /api/1.0/organizations/{organizationId}/dashboard/stacks [get] +// @Router /organizations/{organizationId}/dashboard/stacks [get] // @Security JWT func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -200,6 +203,7 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } // GetResources godoc +// // @Tags Dashboards // @Summary Get resources // @Description Get resources @@ -207,7 +211,7 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetDashboardResourcesResponse -// @Router /api/1.0/organizations/{organizationId}/dashboard/resources [get] +// @Router /organizations/{organizationId}/dashboard/resources [get] // @Security JWT func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index d5a1f0f3..26bbb8d7 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -31,6 +31,7 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { } // CreateOrganization godoc +// // @Tags Organizations // @Summary Create organization // @Description Create organization @@ -38,7 +39,7 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { // @Produce json // @Param body body domain.CreateOrganizationRequest true "create organization request" // @Success 200 {object} object -// @Router /api/1.0/organizations [post] +// @Router /organizations [post] // @Security JWT func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http.Request) { input := domain.CreateOrganizationRequest{} @@ -126,6 +127,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } // GetOrganizations godoc +// // @Tags Organizations // @Summary Get organization list // @Description Get organization list @@ -137,7 +139,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.ListOrganizationBody -// @Router /api/1.0/organizations [get] +// @Router /organizations [get] // @Security JWT func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -169,6 +171,7 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re } // GetOrganization godoc +// // @Tags Organizations // @Summary Get organization detail // @Description Get organization detail @@ -176,7 +179,7 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetOrganizationResponse -// @Router /api/1.0/organizations/{organizationId} [get] +// @Router /organizations/{organizationId} [get] // @Security JWT func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -206,6 +209,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req } // DeleteOrganization godoc +// // @Tags Organizations // @Summary Delete organization // @Description Delete organization @@ -213,7 +217,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.Organization -// @Router /api/1.0/organizations/{organizationId} [delete] +// @Router /organizations/{organizationId} [delete] // @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -253,6 +257,7 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. } // UpdateOrganization godoc +// // @Tags Organizations // @Summary Update organization detail // @Description Update organization detail @@ -261,7 +266,7 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. // @Param organizationId path string true "organizationId" // @Param body body domain.UpdateOrganizationRequest true "update organization request" // @Success 200 {object} domain.UpdateOrganizationResponse -// @Router /api/1.0/organizations/{organizationId} [put] +// @Router /organizations/{organizationId} [put] // @Security JWT func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -298,6 +303,7 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. } // UpdatePrimaryCluster godoc +// // @Tags Organizations // @Summary Update primary cluster // @Description Update primary cluster @@ -306,7 +312,7 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. // @Param organizationId path string true "organizationId" // @Param body body domain.UpdatePrimaryClusterRequest true "update primary cluster request" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/primary-cluster [patch] +// @Router /organizations/{organizationId}/primary-cluster [patch] // @Security JWT func (h *OrganizationHandler) UpdatePrimaryCluster(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index eeaba849..f52bf0ab 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -76,7 +76,7 @@ func NewProjectHandler(u usecase.Usecase) IProjectHandler { // @Param organizationId path string true "Organization ID" // @Param request body outdomain.CreateProjectRequest true "Request body to create project" // @Success 200 {object} outdomain.CreateProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects [post] +// @Router /organizations/{organizationId}/projects [post] // @Security JWT func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -156,7 +156,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param query query string false "(all | only)" // @Success 200 {object} outdomain.GetProjectsResponse -// @Router /api/1.0/organizations/{organizationId}/projects [get] +// @Router /organizations/{organizationId}/projects [get] // @Security JWT func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -209,7 +209,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} outdomain.GetProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId} [get] +// @Router /organizations/{organizationId}/projects/{projectId} [get] // @Security JWT func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -286,7 +286,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { // @Param type query string false "type (name)" // @Param value query string true "value (project name)" // @Success 200 {object} outdomain.CheckExistedResponse -// @Router /api/1.0/organizations/{organizationId}/projects/existence [get] +// @Router /organizations/{organizationId}/projects/existence [get] // @Security JWT func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -323,7 +323,7 @@ func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Reques // @Param projectId path string true "Project ID" // @Param request body outdomain.UpdateProjectRequest true "Request body to update project" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId} [put] +// @Router /organizations/{organizationId}/projects/{projectId} [put] // @Security JWT func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -390,7 +390,7 @@ func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param projectRoleId path string true "Project Role ID" // @Success 200 {object} outdomain.GetProjectRoleResponse -// @Router /api/1.0/organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] +// @Router /organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] // @Security JWT func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -433,7 +433,7 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" // @Success 200 {object} outdomain.GetProjectRolesResponse -// @Router /api/1.0/organizations/{organizationId}/projects/project-roles [get] +// @Router /organizations/{organizationId}/projects/project-roles [get] // @Security JWT func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -481,7 +481,7 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) // @Param projectId path string true "Project ID" // @Param request body outdomain.AddProjectMemberRequest true "Request body to add project member" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [post] +// @Router /organizations/{organizationId}/projects/{projectId}/members [post] // @Security JWT func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -580,7 +580,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" // @Success 200 {object} outdomain.GetProjectMemberResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] +// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] // @Security JWT func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -650,7 +650,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) // @Param projectId path string true "Project ID" // @Param query query string false "project member search by query (query=all), (query=leader), (query=member), (query=viewer)" // @Success 200 {object} outdomain.GetProjectMembersResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [get] +// @Router /organizations/{organizationId}/projects/{projectId}/members [get] // @Security JWT func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -738,7 +738,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} outdomain.GetProjectMemberCountResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/count [get] +// @Router /organizations/{organizationId}/projects/{projectId}/members/count [get] // @Security JWT func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -782,7 +782,7 @@ func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Req // @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] +// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] // @Security JWT func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -848,7 +848,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque // @Param projectId path string true "Project ID" // @Param request body outdomain.RemoveProjectMemberRequest true "Request body to remove project member" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [delete] +// @Router /organizations/{organizationId}/projects/{projectId}/members [delete] // @Security JWT func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -917,7 +917,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // @Param projectMemberId path string true "Project Member ID" // @Param request body outdomain.UpdateProjectMemberRoleRequest true "Request body to update project member role" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] +// @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] // @Security JWT func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1014,7 +1014,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R // @Param projectId path string true "Project ID" // @Param request body outdomain.UpdateProjectMembersRoleRequest true "Request body to update project member role" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/members [put] +// @Router /organizations/{organizationId}/projects/{projectId}/members [put] // @Security JWT func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1106,7 +1106,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. // @Param projectId path string true "Project ID" // @Param request body outdomain.CreateProjectNamespaceRequest true "Request body to create project namespace" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [post] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces [post] // @Security JWT func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1170,7 +1170,7 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re // @Param stackId path string true "Project Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} outdomain.CheckExistedResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence [get] // @Security JWT func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1221,7 +1221,7 @@ func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.R // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} outdomain.GetProjectNamespacesResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1289,7 +1289,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ // @Param projectNamespace path string true "Project Namespace" // @Param stackId path string true "Project Stack ID" // @Success 200 {object} outdomain.GetProjectNamespaceResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [get] // @Security JWT func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1365,7 +1365,7 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque // @Param stackId path string true "Project Stack ID" // @Param request body outdomain.UpdateProjectNamespaceRequest true "Request body to update project namespace" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] // @Security JWT func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1432,7 +1432,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} outdomain.CommonProjectResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] // @Security JWT func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { @@ -1509,7 +1509,7 @@ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r * // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} outdomain.GetProjectKubeconfigResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/kubeconfig [get] +// @Router /organizations/{organizationId}/projects/{projectId}/kubeconfig [get] // @Security JWT func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1553,7 +1553,7 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} outdomain.GetProjectNamespaceK8sResourcesResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1606,7 +1606,7 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} outdomain.GetProjectNamespaceResourcesUsageResponse -// @Router /api/1.0/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 646ffe50..0244e3f8 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -36,7 +36,7 @@ func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { // @Produce json // @Param body body domain.CreateStackTemplateRequest true "create stack template request" // @Success 200 {object} domain.CreateStackTemplateResponse -// @Router /admin/1.0/stack-templates [post] +// @Router /admin/stack-templates [post] // @Security JWT func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *http.Request) { input := domain.CreateStackTemplateRequest{} @@ -76,7 +76,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetStackTemplatesResponse -// @Router /api/1.0/stack-templates [get] +// @Router /stack-templates [get] // @Security JWT func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -116,7 +116,7 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. // @Produce json // @Param stackTemplateId path string true "stackTemplateId" // @Success 200 {object} domain.GetStackTemplateResponse -// @Router /admin/1.0/stack-templates/{stackTemplateId} [get] +// @Router /admin/stack-templates/{stackTemplateId} [get] // @Security JWT func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -168,7 +168,7 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R // @Produce json // @Param body body domain.UpdateStackTemplateRequest true "Update stack template request" // @Success 200 {object} nil -// @Router /admin/1.0/stack-templates/{stackTemplateId} [put] +// @Router /admin/stack-templates/{stackTemplateId} [put] // @Security JWT func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *http.Request) { /* @@ -210,7 +210,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt // @Produce json // @Param stackTemplateId path string true "stackTemplateId" // @Success 200 {object} nil -// @Router /admin/1.0/stack-templates/{stackTemplateId} [delete] +// @Router /admin/stack-templates/{stackTemplateId} [delete] // @Security JWT func (h *StackTemplateHandler) DeleteStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -231,7 +231,7 @@ func (h *StackTemplateHandler) DeleteStackTemplate(w http.ResponseWriter, r *htt // @Accept json // @Produce json // @Success 200 {object} domain.GetStackTemplateServicesResponse -// @Router /admin/1.0/stack-templates/services [get] +// @Router /admin/stack-templates/services [get] // @Security JWT func (h *StackTemplateHandler) GetStackTemplateServices(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 18aa5639..fd84da4e 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -25,6 +25,7 @@ func NewStackHandler(h usecase.Usecase) *StackHandler { } // CreateStack godoc +// // @Tags Stacks // @Summary Create Stack // @Description Create Stack @@ -33,7 +34,7 @@ func NewStackHandler(h usecase.Usecase) *StackHandler { // @Param organizationId path string true "organizationId" // @Param body body domain.CreateStackRequest true "create cloud setting request" // @Success 200 {object} domain.CreateStackResponse -// @Router /api/1.0/organizations/{organizationId}/stacks [post] +// @Router /organizations/{organizationId}/stacks [post] // @Security JWT func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -89,6 +90,7 @@ func (h *StackHandler) InstallStack(w http.ResponseWriter, r *http.Request) { } // GetStack godoc +// // @Tags Stacks // @Summary Get Stacks // @Description Get Stacks @@ -101,7 +103,7 @@ func (h *StackHandler) InstallStack(w http.ResponseWriter, r *http.Request) { // @Param sortOrder query string false "sortOrder" // @Param combinedFilter query string false "combinedFilter" // @Success 200 {object} domain.GetStacksResponse -// @Router /api/1.0/organizations/{organizationId}/stacks [get] +// @Router /organizations/{organizationId}/stacks [get] // @Security JWT func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -141,6 +143,7 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } // GetStack godoc +// // @Tags Stacks // @Summary Get Stack // @Description Get Stack @@ -149,7 +152,7 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} domain.GetStackResponse -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [get] +// @Router /organizations/{organizationId}/stacks/{stackId} [get] // @Security JWT func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -179,6 +182,7 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { } // GetStackStatus godoc +// // @Tags Stacks // @Summary Get Stack Status // @Description Get Stack Status @@ -187,7 +191,7 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} domain.GetStackStatusResponse -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/status [get] +// @Router /organizations/{organizationId}/stacks/{stackId}/status [get] // @Security JWT func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -217,6 +221,7 @@ func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { } // UpdateStack godoc +// // @Tags Stacks // @Summary Update Stack // @Description Update Stack @@ -226,7 +231,7 @@ func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { // @Param stackId path string true "stackId" // @Param body body domain.UpdateStackRequest true "Update cloud setting request" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [put] +// @Router /organizations/{organizationId}/stacks/{stackId} [put] // @Security JWT func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -272,6 +277,7 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { } // DeleteStack godoc +// // @Tags Stacks // @Summary Delete Stack // @Description Delete Stack @@ -280,7 +286,7 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId} [delete] +// @Router /organizations/{organizationId}/stacks/{stackId} [delete] // @Security JWT func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -310,6 +316,7 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { } // CheckStackName godoc +// // @Tags Stacks // @Summary Check name for stack // @Description Check name for stack @@ -319,7 +326,7 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { // @Param stackId path string true "stackId" // @Param name path string true "name" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/name/{name}/existence [GET] +// @Router /organizations/{organizationId}/stacks/name/{name}/existence [GET] // @Security JWT func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -353,6 +360,7 @@ func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { } // GetStackKubeConfig godoc +// // @Tags Stacks // @Summary Get KubeConfig by stack // @Description Get KubeConfig by stack @@ -361,7 +369,7 @@ func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "organizationId" // @Success 200 {object} domain.GetStackKubeConfigResponse -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/kube-config [get] +// @Router /organizations/{organizationId}/stacks/{stackId}/kube-config [get] // @Security JWT func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -396,6 +404,7 @@ func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request } // SetFavorite godoc +// // @Tags Stacks // @Summary Set favorite stack // @Description Set favorite stack @@ -404,7 +413,7 @@ func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite [post] +// @Router /organizations/{organizationId}/stacks/{stackId}/favorite [post] // @Security JWT func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -423,6 +432,7 @@ func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { } // DeleteFavorite godoc +// // @Tags Stacks // @Summary Delete favorite stack // @Description Delete favorite stack @@ -431,7 +441,7 @@ func (h *StackHandler) SetFavorite(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param stackId path string true "stackId" // @Success 200 {object} nil -// @Router /api/1.0/organizations/{organizationId}/stacks/{stackId}/favorite [delete] +// @Router /organizations/{organizationId}/stacks/{stackId}/favorite [delete] // @Security JWT func (h *StackHandler) DeleteFavorite(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 0d6a1d22..b9c62c33 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -57,6 +57,7 @@ func NewUserHandler(h usecase.Usecase) IUserHandler { } // Create godoc +// // @Tags Users // @Summary Create user // @Description Create user @@ -65,7 +66,7 @@ func NewUserHandler(h usecase.Usecase) IUserHandler { // @Param organizationId path string true "organizationId" // @Param body body domain.CreateUserRequest true "create user request" // @Success 200 {object} domain.CreateUserResponse "create user response" -// @Router /api/1.0/organizations/{organizationId}/users [post] +// @Router /organizations/{organizationId}/users [post] // @Security JWT func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -128,6 +129,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { } // Get godoc +// // @Tags Users // @Summary Get user detail // @Description Get user detail @@ -136,7 +138,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 {object} domain.GetUserResponse -// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [get] +// @Router /organizations/{organizationId}/users/{accountId} [get] // @Security JWT func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -173,6 +175,7 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { } // List godoc +// // @Tags Users // @Summary Get user list // @Description Get user list @@ -185,7 +188,7 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} []domain.ListUserBody -// @Router /api/1.0/organizations/{organizationId}/users [get] +// @Router /organizations/{organizationId}/users [get] // @Security JWT func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -220,6 +223,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { } // Delete godoc +// // @Tags Users // @Summary Delete user // @Description Delete user @@ -228,7 +232,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 {object} domain.User -// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [delete] +// @Router /organizations/{organizationId}/users/{accountId} [delete] // @Security JWT func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -259,6 +263,7 @@ func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { } // Update godoc +// // @Tags Users // @Summary Update user // @Description Update user @@ -268,7 +273,7 @@ func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { // @Param accountId path string true "accountId" // @Param body body domain.UpdateUserRequest true "input" // @Success 200 {object} domain.UpdateUserResponse -// @Router /api/1.0/organizations/{organizationId}/users/{accountId} [put] +// @Router /organizations/{organizationId}/users/{accountId} [put] // @Security JWT func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -338,6 +343,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } // ResetPassword godoc +// // @Tags Users // @Summary Reset user's password as temporary password by admin // @Description Reset user's password as temporary password by admin and send email to user @@ -346,7 +352,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 -// @Router /api/1.0/organizations/{organizationId}/users/{accountId}/reset-password [put] +// @Router /organizations/{organizationId}/users/{accountId}/reset-password [put] // @Security JWT func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -371,6 +377,7 @@ func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { } // GetMyProfile godoc +// // @Tags My-profile // @Summary Get my profile detail // @Description Get my profile detail @@ -378,7 +385,7 @@ func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetMyProfileResponse -// @Router /api/1.0/organizations/{organizationId}/my-profile [get] +// @Router /organizations/{organizationId}/my-profile [get] // @Security JWT func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -403,6 +410,7 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { } // UpdateMyProfile godoc +// // @Tags My-profile // @Summary Update my profile detail // @Description Update my profile detail @@ -411,7 +419,7 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param body body domain.UpdateMyProfileRequest true "Required fields: password due to double-check" // @Success 200 {object} domain.UpdateMyProfileResponse -// @Router /api/1.0/organizations/{organizationId}/my-profile [put] +// @Router /organizations/{organizationId}/my-profile [put] // @Security JWT func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -472,6 +480,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { } // UpdateMyPassword godoc +// // @Tags My-profile // @Summary Update user password detail // @Description Update user password detail @@ -480,7 +489,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param body body domain.UpdatePasswordRequest true "update user password request" // @Success 200 -// @Router /api/1.0/organizations/{organizationId}/my-profile/password [put] +// @Router /organizations/{organizationId}/my-profile/password [put] // @Security JWT func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -522,6 +531,7 @@ func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { } // RenewPasswordExpiredDate godoc +// // @Tags My-profile // @Summary Update user's password expired date to current date // @Description Update user's password expired date to current date @@ -530,7 +540,7 @@ func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Success 200 // @Failure 400 {object} httpErrors.RestError -// @Router /api/1.0/organizations/{organizationId}/my-profile/next-password-change [put] +// @Router /organizations/{organizationId}/my-profile/next-password-change [put] // @Security JWT func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -549,6 +559,7 @@ func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Req } // DeleteMyProfile godoc +// // @Tags My-profile // @Summary Delete myProfile // @Description Delete myProfile @@ -557,7 +568,7 @@ func (u UserHandler) RenewPasswordExpiredDate(w http.ResponseWriter, r *http.Req // @Param organizationId path string true "organizationId" // @Success 200 // @Failure 400 -// @Router /api/1.0/organizations/{organizationId}/my-profile [delete] +// @Router /organizations/{organizationId}/my-profile [delete] // @Security JWT func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { requestUserInfo, ok := request.UserFrom(r.Context()) @@ -574,6 +585,7 @@ func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { } // CheckId godoc +// // @Tags Users // @Summary Get user id existence // @Description return true when accountId exists @@ -581,7 +593,7 @@ func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 {object} domain.CheckExistedResponse -// @Router /api/1.0/organizations/{organizationId}/users/account-id/{accountId}/existence [get] +// @Router /organizations/{organizationId}/users/account-id/{accountId}/existence [get] // @Security JWT func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -614,6 +626,7 @@ func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { } // CheckEmail godoc +// // @Tags Users // @Summary Get user email existence // @Description return true when email exists @@ -621,7 +634,7 @@ func (u UserHandler) CheckId(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "email" // @Success 200 {object} domain.CheckExistedResponse -// @Router /api/1.0/organizations/{organizationId}/users/email/{email}/existence [get] +// @Router /organizations/{organizationId}/users/email/{email}/existence [get] // @Security JWT func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -662,7 +675,7 @@ func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param body body admin_domain.CreateUserRequest true "create user request" // @Success 200 {object} admin_domain.CreateUserResponse "create user response" -// @Router /api/1.0/admin/organizations/{organizationId}/users [post] +// @Router /admin/organizations/{organizationId}/users [post] // @Security JWT func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { @@ -761,7 +774,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} admin_domain.ListUserResponse "user list response" -// @Router /api/1.0/admin/organizations/{organizationId}/users [get] +// @Router /admin/organizations/{organizationId}/users [get] // @Security JWT func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { @@ -797,6 +810,7 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { } // Admin_Get godoc +// // @Tags Admin // @Summary Get user detail by admin // @Description Get user detail by admin @@ -805,7 +819,7 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 {object} admin_domain.GetUserResponse -// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [get] +// @Router /admin/organizations/{organizationId}/users/{accountId} [get] func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) userId, ok := vars["accountId"] @@ -849,7 +863,7 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" // @Success 200 {object} admin_domain.User -// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [delete] +// @Router /admin/organizations/{organizationId}/users/{accountId} [delete] // @Security JWT func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { @@ -902,6 +916,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { } // Admin_Update godoc +// // @Tags Admin // @Summary Update user by admin // @Description Update user by admin @@ -911,7 +926,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { // @Param accountId path string true "accountId" // @Param body body admin_domain.UpdateUserRequest true "input" // @Success 200 {object} admin_domain.UpdateUserResponse -// @Router /api/1.0/admin/organizations/{organizationId}/users/{accountId} [put] +// @Router /admin/organizations/{organizationId}/users/{accountId} [put] // @Security JWT func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) From 1a1122cf5445b6db9119dba403008671fe6a113c Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 6 Mar 2024 15:52:12 +0900 Subject: [PATCH 093/502] fix SQL statement to get the number of members in a project --- internal/repository/project.go | 52 ++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/internal/repository/project.go b/internal/repository/project.go index 13fc1428..ccdc34ca 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -69,60 +69,76 @@ func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ - " from projects as p, "+ - " (select pm.project_id, pm.project_user_id, pm.project_role_id, pm.created_at, pm.is_project_leader, "+ + " from projects as p "+ + " left join "+ + " (select pm.project_id as project_id, pm.project_user_id as project_user_id, pm.project_role_id as project_role_id, "+ + " pm.created_at as created_at, pm.is_project_leader as is_project_leader, "+ " pr.name as pr_name "+ " from project_members as pm "+ " left join project_roles as pr on pr.id = pm.project_role_id "+ " left join users on users.id = pm.project_user_id "+ - " where pm.project_user_id = @userId) as pm, "+ - " (select count(pn.stack_id || pn.project_id) as count "+ + " where pm.project_user_id = @userId) as pm on p.id = pm.project_id "+ + " left join "+ + " (select p.id as project_id, count(pn.stack_id || pn.project_id) as count "+ " from project_namespaces as pn "+ " left join projects as p on pn.project_id = p.id "+ " left join project_members as pm on pn.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId) as pn, "+ - " (select count(asa.id) as count "+ + " and pm.project_user_id = @userId "+ + " group by p.id) as pn on p.id = pn.project_id "+ + " left join "+ + " (select p.id as project_id, count(asa.id) as count "+ " from app_serve_apps as asa "+ " left join projects as p on asa.project_id = p.id "+ " left join project_members as pm on asa.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId) as asa, "+ - " (select count(pm.id) as count "+ + " and pm.project_user_id = @userId "+ + " group by p.id) as asa on p.id = asa.project_id "+ + " left join "+ + " (select p.id as project_id, count(pm.id) as count "+ " from project_members as pm "+ " left join projects as p on pm.project_id = p.id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId) as pm_count "+ + " and pm.project_user_id = @userId "+ + " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ " and p.organization_id = @organizationId "+ "union "+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " false as is_my_project, '' as project_role_id, '' as project_role_name, "+ " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ - " from projects as p, "+ - " (select pm.project_id, pm.project_user_id, pm.project_role_id, pm.created_at, pm.is_project_leader, "+ + " from projects as p "+ + " left join "+ + " (select pm.project_id as project_id, pm.project_user_id as project_user_id, pm.project_role_id as project_role_id, "+ + " pm.created_at as created_at, pm.is_project_leader as is_project_leader, "+ " pr.name as pr_name "+ " from project_members as pm "+ " left join project_roles as pr on pr.id = pm.project_role_id "+ " left join users on users.id = pm.project_user_id "+ - " where pm.project_user_id <> @userId) as pm, "+ - " (select count(pn.stack_id || pn.project_id) as count "+ + " where pm.project_user_id <> @userId) as pm on p.id = pm.project_id "+ + " left join "+ + " (select p.id as project_id, count(pn.stack_id || pn.project_id) as count "+ " from project_namespaces as pn "+ " left join projects as p on pn.project_id = p.id "+ " left join project_members as pm on pn.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id <> @userId) as pn, "+ - " (select count(asa.id) as count "+ + " and pm.project_user_id <> @userId "+ + " group by p.id) as pn on p.id = pn.project_id "+ + " left join "+ + " (select p.id as project_id, count(asa.id) as count "+ " from app_serve_apps as asa "+ " left join projects as p on asa.project_id = p.id "+ " left join project_members as pm on asa.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id <> @userId) as asa, "+ - " (select count(pm.id) as count "+ + " and pm.project_user_id <> @userId "+ + " group by p.id) as asa on p.id = asa.project_id "+ + " left join "+ + " (select p.id as project_id, count(pm.id) as count "+ " from project_members as pm "+ " left join projects as p on pm.project_id = p.id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id <> @userId) as pm_count "+ + " and pm.project_user_id <> @userId "+ + " group by p.id) as pm_count on p.id = pm_count.project_id"+ " where p.id = pm.project_id "+ " and p.organization_id = @organizationId "+ " and p.id not in (select projects.id "+ From c832c91c30adb2ae6a4450603c15fb5cc0b75a64 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 6 Mar 2024 16:46:31 +0900 Subject: [PATCH 094/502] bug fix: missing JWT function --- internal/delivery/http/permission.go | 6 ++++++ internal/delivery/http/role.go | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 0b473a32..0116ac9c 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -33,6 +33,8 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { // @Produce json // @Success 200 {object} domain.PermissionSet // @Router /permissions/templates [get] +// @Security JWT + func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { permissionSet := domain.NewDefaultPermissionSet() @@ -55,6 +57,8 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http // @Produce json // @Success 200 {object} domain.PermissionSet // @Router /roles/{roleId}/permissions [get] +// @Security JWT + func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { // path parameter var roleId string @@ -94,6 +98,8 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http // @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" // @Success 200 // @Router /roles/{roleId}/permissions [put] +// @Security JWT + func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { // path parameter log.Debug("UpdatePermissionsByRoleId Called") diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 7408878d..1e72fd05 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -44,6 +44,7 @@ func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { // @Param body body domain.CreateTksRoleRequest true "Create Tks Role Request" // @Success 200 {object} domain.CreateTksRoleResponse // @Router /organizations/{organizationId}/roles [post] +// @Security JWT func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { // path parameter @@ -101,6 +102,8 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.ListTksRoleResponse // @Router /organizations/{organizationId}/roles [get] +// @Security JWT + func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { // path parameter var organizationId string @@ -155,6 +158,7 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { // @Param roleId path string true "Role ID" // @Success 200 {object} domain.GetTksRoleResponse // @Router /organizations/{organizationId}/roles/{roleId} [get] +// @Security JWT func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // path parameter @@ -196,6 +200,7 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // @Param roleId path string true "Role ID" // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId} [delete] +// @Security JWT func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { // path parameter @@ -229,6 +234,7 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { // @Param body body domain.UpdateTksRoleRequest true "Update Tks Role Request" // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId} [put] +// @Security JWT func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // path parameter From 4c49b83dd25f367223bf4b48025d23f3438514f4 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 6 Mar 2024 16:50:03 +0900 Subject: [PATCH 095/502] minor fix --- internal/delivery/http/permission.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 0116ac9c..84a04875 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -56,7 +56,7 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http // @Accept json // @Produce json // @Success 200 {object} domain.PermissionSet -// @Router /roles/{roleId}/permissions [get] +// @Router organizations/{organizationId}/roles/{roleId}/permissions [get] // @Security JWT func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { @@ -97,7 +97,7 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http // @Param roleId path string true "Role ID" // @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" // @Success 200 -// @Router /roles/{roleId}/permissions [put] +// @Router organizations/{organizationId}/roles/{roleId}/permissions [put] // @Security JWT func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { From 4d6817d779647454aab2e9a6a02a4686d7edb29b Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 6 Mar 2024 18:44:37 +0900 Subject: [PATCH 096/502] add manage tks admin user logic --- internal/delivery/http/permission.go | 6 +- internal/delivery/http/role.go | 14 ++--- internal/delivery/http/user.go | 88 ++++++++++++++++------------ pkg/domain/admin/user.go | 6 +- 4 files changed, 62 insertions(+), 52 deletions(-) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 84a04875..154c9815 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -26,6 +26,7 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { } // GetPermissionTemplates godoc +// // @Tags Permission // @Summary Get Permission Templates // @Description Get Permission Templates @@ -34,7 +35,6 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { // @Success 200 {object} domain.PermissionSet // @Router /permissions/templates [get] // @Security JWT - func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { permissionSet := domain.NewDefaultPermissionSet() @@ -50,6 +50,7 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http } // GetPermissionsByRoleId godoc +// // @Tags Permission // @Summary Get Permissions By Role ID // @Description Get Permissions By Role ID @@ -58,7 +59,6 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http // @Success 200 {object} domain.PermissionSet // @Router organizations/{organizationId}/roles/{roleId}/permissions [get] // @Security JWT - func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { // path parameter var roleId string @@ -89,6 +89,7 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http } // UpdatePermissionsByRoleId godoc +// // @Tags Permission // @Summary Update Permissions By Role ID // @Description Update Permissions By Role ID @@ -99,7 +100,6 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http // @Success 200 // @Router organizations/{organizationId}/roles/{roleId}/permissions [put] // @Security JWT - func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { // path parameter log.Debug("UpdatePermissionsByRoleId Called") diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 1e72fd05..1ad67b29 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -35,6 +35,7 @@ func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { } // CreateTksRole godoc +// // @Tags Role // @Summary Create Tks Role // @Description Create Tks Role @@ -45,7 +46,6 @@ func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { // @Success 200 {object} domain.CreateTksRoleResponse // @Router /organizations/{organizationId}/roles [post] // @Security JWT - func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { // path parameter var organizationId string @@ -95,6 +95,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // ListTksRoles godoc +// // @Tags Role // @Summary List Tks Roles // @Description List Tks Roles @@ -103,7 +104,6 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { // @Success 200 {object} domain.ListTksRoleResponse // @Router /organizations/{organizationId}/roles [get] // @Security JWT - func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { // path parameter var organizationId string @@ -150,6 +150,7 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { } // GetTksRole godoc +// // @Tags Role // @Summary Get Tks Role // @Description Get Tks Role @@ -159,7 +160,6 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { // @Success 200 {object} domain.GetTksRoleResponse // @Router /organizations/{organizationId}/roles/{roleId} [get] // @Security JWT - func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // path parameter vars := mux.Vars(r) @@ -192,6 +192,7 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { } // DeleteTksRole godoc +// // @Tags Role // @Summary Delete Tks Role // @Description Delete Tks Role @@ -201,7 +202,6 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId} [delete] // @Security JWT - func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { // path parameter vars := mux.Vars(r) @@ -224,6 +224,7 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { } // UpdateTksRole godoc +// // @Tags Role // @Summary Update Tks Role // @Description Update Tks Role @@ -235,7 +236,6 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId} [put] // @Security JWT - func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // path parameter vars := mux.Vars(r) @@ -272,6 +272,7 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { } // Admin_ListTksRoles godoc +// // @Tags Role // @Summary Admin List Tks Roles // @Description Admin List Tks Roles @@ -279,7 +280,6 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.ListTksRoleResponse // @Router /admin/organizations/{organizationId}/roles [get] - func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) { // Same as ListTksRoles @@ -327,6 +327,7 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) } // Admin_GetTksRole godoc +// // @Tags Role // @Summary Admin Get Tks Role // @Description Admin Get Tks Role @@ -335,7 +336,6 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) // @Param roleId path string true "Role ID" // @Success 200 {object} domain.GetTksRoleResponse // @Router /admin/organizations/{organizationId}/roles/{roleId} [get] - func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { // Same as GetTksRole diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index b9c62c33..7df3a3bc 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -695,6 +695,21 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { return } + // TKS 관리자가 아닌 경우 Password 확인 + if organizationId != "master" { + // check admin password + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) + return + } + err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + if err != nil { + ErrorJSON(w, r, err) + return + } + } + user := domain.User{ Name: input.Name, AccountId: input.AccountId, @@ -721,18 +736,6 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { ID: organizationId, } - // check admin password - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) - return - } - _, err = u.authUsecase.Login(requestUserInfo.GetAccountId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) - if err != nil { - ErrorJSON(w, r, err) - return - } - user.Password = u.usecase.GenerateRandomPassword() resUser, err := u.usecase.Create(r.Context(), &user) @@ -880,27 +883,31 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { } input := admin_domain.DeleteUserRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } + // TKS 관리자가 아닌 경우 Password 확인 + if organizationId != "master" { + err := UnmarshalRequestInput(r, &input) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - // check admin password - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) - return - } - err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) - if err != nil { - ErrorJSON(w, r, err) - return + ErrorJSON(w, r, err) + return + } + + // check admin password + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) + return + } + err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + if err != nil { + ErrorJSON(w, r, err) + return + } } - err = u.usecase.DeleteByAccountId(r.Context(), userId, organizationId) + err := u.usecase.DeleteByAccountId(r.Context(), userId, organizationId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) @@ -950,16 +957,19 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { return } - // check admin password - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) - return - } - err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) - if err != nil { - ErrorJSON(w, r, err) - return + // TKS 관리자가 아닌 경우 Password 확인 + if organizationId != "master" { + // check admin password + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) + return + } + err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + if err != nil { + ErrorJSON(w, r, err) + return + } } ctx := r.Context() diff --git a/pkg/domain/admin/user.go b/pkg/domain/admin/user.go index da3a218c..7d53a51e 100644 --- a/pkg/domain/admin/user.go +++ b/pkg/domain/admin/user.go @@ -12,7 +12,7 @@ type CreateUserRequest struct { Role string `json:"role" validate:"required"` Department string `json:"department" validate:"min=0,max=50"` Description string `json:"description" validate:"min=0,max=100"` - AdminPassword string `json:"adminPassword" validate:"required"` + AdminPassword string `json:"adminPassword"` } type CreateUserResponse struct { @@ -46,7 +46,7 @@ type UpdateUserRequest struct { Department string `json:"department" validate:"min=0,max=50"` Role string `json:"role" validate:"required"` Description string `json:"description" validate:"min=0,max=100"` - AdminPassword string `json:"adminPassword" validate:"required"` + AdminPassword string `json:"adminPassword"` } type UpdateUserResponse struct { @@ -65,5 +65,5 @@ type UpdateUserResponse struct { } type DeleteUserRequest struct { - AdminPassword string `json:"adminPassword" validate:"required"` + AdminPassword string `json:"adminPassword"` } From d7ca7b1623932def6ab3d3d01d2461d170099470 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 7 Mar 2024 13:36:47 +0900 Subject: [PATCH 097/502] add admin project --- internal/database/database.go | 10 +- internal/delivery/api/endpoint.go | 3 + .../delivery/api/generated_endpoints.go.go | 8 + internal/delivery/http/project.go | 213 +++++++++++------- .../{domain/domain.go => model/project.go} | 2 +- internal/repository/project.go | 190 ++++++++++------ internal/route/route.go | 1 + internal/usecase/project.go | 122 +++++----- 8 files changed, 334 insertions(+), 215 deletions(-) rename internal/{domain/domain.go => model/project.go} (99%) diff --git a/internal/database/database.go b/internal/database/database.go index 9bb20356..2e9ad696 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -12,7 +12,7 @@ import ( "gorm.io/gorm" "gorm.io/gorm/logger" - indomain "github.com/openinfradev/tks-api/internal/domain" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" ) @@ -126,16 +126,16 @@ func migrateSchema(db *gorm.DB) error { } // Project - if err := db.AutoMigrate(&indomain.Project{}); err != nil { + if err := db.AutoMigrate(&model.Project{}); err != nil { return err } - if err := db.AutoMigrate(&indomain.ProjectMember{}); err != nil { + if err := db.AutoMigrate(&model.ProjectMember{}); err != nil { return err } - if err := db.AutoMigrate(&indomain.ProjectNamespace{}); err != nil { + if err := db.AutoMigrate(&model.ProjectNamespace{}); err != nil { return err } - if err := db.AutoMigrate(&indomain.ProjectRole{}); err != nil { + if err := db.AutoMigrate(&model.ProjectRole{}); err != nil { return err } diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index bba7a2cc..3ce75e2e 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -180,4 +180,7 @@ const ( // Admin Role Admin_ListTksRoles Admin_GetTksRole + + // Admin Project + Admin_GetProjects ) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 7bc7a17b..11c42f81 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -543,6 +543,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_GetTksRole", Group: "Admin Role", }, + Admin_GetProjects: { + Name: "Admin_GetProjects", + Group: "Admin Project", + }, } func (e Endpoint) String() string { switch e { @@ -816,6 +820,8 @@ func (e Endpoint) String() string { return "Admin_ListTksRoles" case Admin_GetTksRole: return "Admin_GetTksRole" + case Admin_GetProjects: + return "Admin_GetProjects" default: return "" } @@ -1092,6 +1098,8 @@ func GetEndpoint(name string) Endpoint { return Admin_ListTksRoles case "Admin_GetTksRole": return Admin_GetTksRole + case "Admin_GetProjects": + return Admin_GetProjects default: return -1 } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index f52bf0ab..fa9c8c5e 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -12,9 +12,9 @@ import ( "github.com/openinfradev/tks-api/internal/serializer" "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal/domain" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/usecase" - outdomain "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" ) @@ -28,6 +28,7 @@ type IProjectHandler interface { GetProject(w http.ResponseWriter, r *http.Request) IsProjectNameExist(w http.ResponseWriter, r *http.Request) GetProjects(w http.ResponseWriter, r *http.Request) + Admin_GetProjects(w http.ResponseWriter, r *http.Request) AddProjectMember(w http.ResponseWriter, r *http.Request) GetProjectMember(w http.ResponseWriter, r *http.Request) @@ -74,8 +75,8 @@ func NewProjectHandler(u usecase.Usecase) IProjectHandler { // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" -// @Param request body outdomain.CreateProjectRequest true "Request body to create project" -// @Success 200 {object} outdomain.CreateProjectResponse +// @Param request body domain.CreateProjectRequest true "Request body to create project" +// @Success 200 {object} domain.CreateProjectResponse // @Router /organizations/{organizationId}/projects [post] // @Security JWT func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { @@ -87,14 +88,14 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { "C_INVALID_ORGANIZATION_ID", "")) return } - var projectReq outdomain.CreateProjectRequest + var projectReq domain.CreateProjectRequest if err := UnmarshalRequestInput(r, &projectReq); err != nil { ErrorJSON(w, r, err) return } now := time.Now() - project := &domain.Project{ + project := &model.Project{ OrganizationId: organizationId, Name: projectReq.Name, Description: projectReq.Description, @@ -124,10 +125,10 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { } //Don't add ProjectUser Object because of Cascading - pm := &domain.ProjectMember{ + pm := &model.ProjectMember{ ProjectId: projectId, - //ProjectUser: &domain.ProjectUser{ID: ProjectLeaderId}, - //ProjectRole: &domain.ProjectRole{ID: projectReq.ProjectRoleId}, + //ProjectUser: &model.ProjectUser{ID: ProjectLeaderId}, + //ProjectRole: &model.ProjectRole{ID: projectReq.ProjectRoleId}, ProjectUserId: ProjectLeaderId, ProjectRoleId: prs[0].ID, IsProjectLeader: true, @@ -141,7 +142,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } - out := outdomain.CreateProjectResponse{ProjectId: projectId} + out := domain.CreateProjectResponse{ProjectId: projectId} ResponseJSON(w, r, http.StatusOK, out) } @@ -155,7 +156,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "Organization ID" // @Param query query string false "(all | only)" -// @Success 200 {object} outdomain.GetProjectsResponse +// @Success 200 {object} domain.GetProjectsResponse // @Router /organizations/{organizationId}/projects [get] // @Security JWT func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { @@ -186,14 +187,56 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { return } - var out outdomain.GetProjectsResponse + var out domain.GetProjectsResponse out.Projects = pr if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } if pr == nil { - ResponseJSON(w, r, http.StatusNotFound, outdomain.GetProjectsResponse{}) + ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectsResponse{}) + } else { + ResponseJSON(w, r, http.StatusOK, out) + } +} + +// Admin_GetProjects godoc +// +// @Tags Projects +// @Summary Get projects as admin +// @Description Get projects as admin +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetProjectsResponse +// @Router /admin/organizations/{organizationId}/projects [get] +// @Security JWT +func (p ProjectHandler) Admin_GetProjects(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + pr, err := p.usecase.GetProjects(r.Context(), organizationId, "", false, pg) + if err != nil { + log.ErrorWithContext(r.Context(), "Failed to retrieve projects ", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetProjectsResponse + out.Projects = pr + if out.Pagination, err = pg.Response(); err != nil { + log.InfoWithContext(r.Context(), err) + } + + if pr == nil { + ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectsResponse{}) } else { ResponseJSON(w, r, http.StatusOK, out) } @@ -208,7 +251,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Success 200 {object} outdomain.GetProjectResponse +// @Success 200 {object} domain.GetProjectResponse // @Router /organizations/{organizationId}/projects/{projectId} [get] // @Security JWT func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { @@ -240,7 +283,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { // return //} - var out outdomain.GetProjectResponse + var out domain.GetProjectResponse if project == nil { ResponseJSON(w, r, http.StatusNotFound, out) return @@ -257,7 +300,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { projectRoleName = pu.ProjectRole.Name } - var pdr outdomain.ProjectDetailResponse + var pdr domain.ProjectDetailResponse if err = serializer.Map(*project, &pdr); err != nil { log.Error(err) ErrorJSON(w, r, err) @@ -285,7 +328,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "Organization ID" // @Param type query string false "type (name)" // @Param value query string true "value (project name)" -// @Success 200 {object} outdomain.CheckExistedResponse +// @Success 200 {object} domain.CheckExistedResponse // @Router /organizations/{organizationId}/projects/existence [get] // @Security JWT func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Request) { @@ -306,7 +349,7 @@ func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Reques return } - var out outdomain.CheckExistedResponse + var out domain.CheckExistedResponse out.Existed = exist ResponseJSON(w, r, http.StatusOK, out) @@ -321,8 +364,8 @@ func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Reques // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Param request body outdomain.UpdateProjectRequest true "Request body to update project" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Param request body domain.UpdateProjectRequest true "Request body to update project" +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId} [put] // @Security JWT func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { @@ -342,7 +385,7 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { return } - var projectReq outdomain.UpdateProjectRequest + var projectReq domain.UpdateProjectRequest if err := UnmarshalRequestInput(r, &projectReq); err != nil { ErrorJSON(w, r, err) return @@ -371,7 +414,7 @@ func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { return } - ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { @@ -389,7 +432,7 @@ func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectRoleId path string true "Project Role ID" -// @Success 200 {object} outdomain.GetProjectRoleResponse +// @Success 200 {object} domain.GetProjectRoleResponse // @Router /organizations/{organizationId}/projects/project-roles/{projectRoleId} [get] // @Security JWT func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { @@ -417,8 +460,8 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { return } - var out outdomain.GetProjectRoleResponse - out.ProjectRole = outdomain.ProjectRoleResponse(*pr) + var out domain.GetProjectRoleResponse + out.ProjectRole = domain.ProjectRoleResponse(*pr) ResponseJSON(w, r, http.StatusOK, out) } @@ -432,7 +475,7 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "Organization ID" // @Param query query string false "project role search by query (query=all), (query=leader), (query=member), (query=viewer)" -// @Success 200 {object} outdomain.GetProjectRolesResponse +// @Success 200 {object} domain.GetProjectRolesResponse // @Router /organizations/{organizationId}/projects/project-roles [get] // @Security JWT func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) { @@ -462,9 +505,9 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) return } - var out outdomain.GetProjectRolesResponse + var out domain.GetProjectRolesResponse for _, pr := range prs { - out.ProjectRoles = append(out.ProjectRoles, outdomain.ProjectRoleResponse(pr)) + out.ProjectRoles = append(out.ProjectRoles, domain.ProjectRoleResponse(pr)) } ResponseJSON(w, r, http.StatusOK, out) @@ -479,8 +522,8 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Param request body outdomain.AddProjectMemberRequest true "Request body to add project member" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Param request body domain.AddProjectMemberRequest true "Request body to add project member" +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [post] // @Security JWT func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { @@ -499,7 +542,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } - var projectMemberReq outdomain.AddProjectMemberRequest + var projectMemberReq domain.AddProjectMemberRequest if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { ErrorJSON(w, r, err) return @@ -540,7 +583,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } - pm := &domain.ProjectMember{ + pm := &model.ProjectMember{ ProjectId: projectId, ProjectUserId: pu.ID, ProjectUser: nil, @@ -565,7 +608,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) } } - out := outdomain.CommonProjectResponse{Result: "OK"} + out := domain.CommonProjectResponse{Result: "OK"} ResponseJSON(w, r, http.StatusOK, out) } @@ -579,7 +622,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" -// @Success 200 {object} outdomain.GetProjectMemberResponse +// @Success 200 {object} domain.GetProjectMemberResponse // @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [get] // @Security JWT func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) { @@ -615,13 +658,13 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) return } - var out outdomain.GetProjectMemberResponse + var out domain.GetProjectMemberResponse if pm == nil { ResponseJSON(w, r, http.StatusNotFound, out) return } - pmr := &outdomain.ProjectMemberResponse{ + pmr := &domain.ProjectMemberResponse{ ID: pm.ID, ProjectId: pm.ProjectId, ProjectUserId: pm.ProjectUser.ID.String(), @@ -649,7 +692,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Param query query string false "project member search by query (query=all), (query=leader), (query=member), (query=viewer)" -// @Success 200 {object} outdomain.GetProjectMembersResponse +// @Success 200 {object} domain.GetProjectMembersResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [get] // @Security JWT func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request) { @@ -696,15 +739,15 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request return } - var out outdomain.GetProjectMembersResponse + var out domain.GetProjectMembersResponse if pms == nil { ResponseJSON(w, r, http.StatusNotFound, out) return } - pmrs := make([]outdomain.ProjectMemberResponse, 0) + pmrs := make([]domain.ProjectMemberResponse, 0) for _, pm := range pms { - pmr := outdomain.ProjectMemberResponse{ + pmr := domain.ProjectMemberResponse{ ID: pm.ID, ProjectId: pm.ProjectId, ProjectUserId: pm.ProjectUser.ID.String(), @@ -720,7 +763,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request pmrs = append(pmrs, pmr) } - out = outdomain.GetProjectMembersResponse{ProjectMembers: pmrs} + out = domain.GetProjectMembersResponse{ProjectMembers: pmrs} if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) } @@ -737,7 +780,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Success 200 {object} outdomain.GetProjectMemberCountResponse +// @Success 200 {object} domain.GetProjectMemberCountResponse // @Router /organizations/{organizationId}/projects/{projectId}/members/count [get] // @Security JWT func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Request) { @@ -765,7 +808,7 @@ func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Req } if pmcr == nil { - ResponseJSON(w, r, http.StatusNotFound, outdomain.GetProjectMembersResponse{}) + ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectMembersResponse{}) return } ResponseJSON(w, r, http.StatusOK, pmcr) @@ -781,7 +824,7 @@ func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Req // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId} [delete] // @Security JWT func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { @@ -834,7 +877,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque return } - ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } // RemoveProjectMembers godoc @@ -846,8 +889,8 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Param request body outdomain.RemoveProjectMemberRequest true "Request body to remove project member" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Param request body domain.RemoveProjectMemberRequest true "Request body to remove project member" +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [delete] // @Security JWT func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Request) { @@ -868,7 +911,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ return } - var projectMemberReq outdomain.RemoveProjectMemberRequest + var projectMemberReq domain.RemoveProjectMemberRequest if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { ErrorJSON(w, r, err) return @@ -902,7 +945,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ return } } - ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } // UpdateProjectMemberRole godoc @@ -915,8 +958,8 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Param projectMemberId path string true "Project Member ID" -// @Param request body outdomain.UpdateProjectMemberRoleRequest true "Request body to update project member role" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Param request body domain.UpdateProjectMemberRoleRequest true "Request body to update project member role" +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] // @Security JWT func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) { @@ -944,7 +987,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R return } - var pmrReq outdomain.UpdateProjectMemberRoleRequest + var pmrReq domain.UpdateProjectMemberRoleRequest if err := UnmarshalRequestInput(r, &pmrReq); err != nil { ErrorJSON(w, r, err) return @@ -1000,7 +1043,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } } - ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } // UpdateProjectMembersRole godoc @@ -1012,8 +1055,8 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Param request body outdomain.UpdateProjectMembersRoleRequest true "Request body to update project member role" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Param request body domain.UpdateProjectMembersRoleRequest true "Request body to update project member role" +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [put] // @Security JWT func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http.Request) { @@ -1035,7 +1078,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } now := time.Now() - var projectMemberReq outdomain.UpdateProjectMembersRoleRequest + var projectMemberReq domain.UpdateProjectMembersRoleRequest if err := UnmarshalRequestInput(r, &projectMemberReq); err != nil { ErrorJSON(w, r, err) return @@ -1092,7 +1135,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } } - ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } // CreateProjectNamespace godoc @@ -1104,8 +1147,8 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Param request body outdomain.CreateProjectNamespaceRequest true "Request body to create project namespace" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Param request body domain.CreateProjectNamespaceRequest true "Request body to create project namespace" +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces [post] // @Security JWT func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Request) { @@ -1123,14 +1166,14 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re return } - var projectNamespaceReq outdomain.CreateProjectNamespaceRequest + var projectNamespaceReq domain.CreateProjectNamespaceRequest if err := UnmarshalRequestInput(r, &projectNamespaceReq); err != nil { ErrorJSON(w, r, err) return } now := time.Now() - pn := &domain.ProjectNamespace{ + pn := &model.ProjectNamespace{ StackId: projectNamespaceReq.StackId, Namespace: projectNamespaceReq.Namespace, ProjectId: projectId, @@ -1154,7 +1197,7 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - out := outdomain.CommonProjectResponse{Result: "OK"} + out := domain.CommonProjectResponse{Result: "OK"} ResponseJSON(w, r, http.StatusOK, out) } @@ -1169,7 +1212,7 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re // @Param projectId path string true "Project ID" // @Param stackId path string true "Project Stack ID" // @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} outdomain.CheckExistedResponse +// @Success 200 {object} domain.CheckExistedResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence [get] // @Security JWT func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.Request) { @@ -1205,7 +1248,7 @@ func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.R return } - var out outdomain.CheckExistedResponse + var out domain.CheckExistedResponse out.Existed = exist ResponseJSON(w, r, http.StatusOK, out) @@ -1220,7 +1263,7 @@ func (p ProjectHandler) IsProjectNamespaceExist(w http.ResponseWriter, r *http.R // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Success 200 {object} outdomain.GetProjectNamespacesResponse +// @Success 200 {object} domain.GetProjectNamespacesResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Request) { @@ -1247,14 +1290,14 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ return } - var out outdomain.GetProjectNamespacesResponse + var out domain.GetProjectNamespacesResponse if pns == nil { ResponseJSON(w, r, http.StatusNotFound, out) return } - pnrs := make([]outdomain.ProjectNamespaceResponse, 0) + pnrs := make([]domain.ProjectNamespaceResponse, 0) for _, pn := range pns { - var pnr outdomain.ProjectNamespaceResponse + var pnr domain.ProjectNamespaceResponse if err = serializer.Map(pn, &pnr); err != nil { log.Error(err) ErrorJSON(w, r, err) @@ -1288,7 +1331,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ // @Param projectId path string true "Project ID" // @Param projectNamespace path string true "Project Namespace" // @Param stackId path string true "Project Stack ID" -// @Success 200 {object} outdomain.GetProjectNamespaceResponse +// @Success 200 {object} domain.GetProjectNamespaceResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [get] // @Security JWT func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Request) { @@ -1332,13 +1375,13 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque return } - var out outdomain.GetProjectNamespaceResponse + var out domain.GetProjectNamespaceResponse if pn == nil { ResponseJSON(w, r, http.StatusNotFound, out) return } - var pnr outdomain.ProjectNamespaceResponse + var pnr domain.ProjectNamespaceResponse if err = serializer.Map(*pn, &pnr); err != nil { log.Error(err) ErrorJSON(w, r, err) @@ -1363,8 +1406,8 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque // @Param projectId path string true "Project ID" // @Param projectNamespace path string true "Project Namespace" // @Param stackId path string true "Project Stack ID" -// @Param request body outdomain.UpdateProjectNamespaceRequest true "Request body to update project namespace" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Param request body domain.UpdateProjectNamespaceRequest true "Request body to update project namespace" +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [put] // @Security JWT func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Request) { @@ -1395,7 +1438,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re return } - var projectNamespaceReq outdomain.UpdateProjectNamespaceRequest + var projectNamespaceReq domain.UpdateProjectNamespaceRequest if err := UnmarshalRequestInput(r, &projectNamespaceReq); err != nil { ErrorJSON(w, r, err) return @@ -1417,7 +1460,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re return } - ResponseJSON(w, r, http.StatusOK, outdomain.CommonProjectResponse{Result: "OK"}) + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } // DeleteProjectNamespace godoc @@ -1431,7 +1474,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re // @Param projectId path string true "Project ID" // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} outdomain.CommonProjectResponse +// @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId} [delete] // @Security JWT func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Request) { @@ -1480,7 +1523,7 @@ func (p ProjectHandler) DeleteProjectNamespace(w http.ResponseWriter, r *http.Re // return // //} - //ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) + //ResponseJSON(w, r, http.StatusOK, model.CommonProjectResponse{Result: "OK"}) } func (p ProjectHandler) SetFavoriteProject(w http.ResponseWriter, r *http.Request) { @@ -1508,7 +1551,7 @@ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r * // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Success 200 {object} outdomain.GetProjectKubeconfigResponse +// @Success 200 {object} domain.GetProjectKubeconfigResponse // @Router /organizations/{organizationId}/projects/{projectId}/kubeconfig [get] // @Security JWT func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) { @@ -1534,7 +1577,7 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ return } - out := outdomain.GetProjectKubeconfigResponse{ + out := domain.GetProjectKubeconfigResponse{ Kubeconfig: kubeconfig, } @@ -1552,7 +1595,7 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ // @Param projectId path string true "Project ID" // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} outdomain.GetProjectNamespaceK8sResourcesResponse +// @Success 200 {object} domain.GetProjectNamespaceK8sResourcesResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r *http.Request) { @@ -1580,14 +1623,14 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r return } - k8sResources, err := p.usecase.GetK8sResources(r.Context(), organizationId, projectId, projectNamespace, outdomain.StackId(stackId)) + k8sResources, err := p.usecase.GetK8sResources(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) ErrorJSON(w, r, err) return } - var out outdomain.GetProjectNamespaceK8sResourcesResponse + var out domain.GetProjectNamespaceK8sResourcesResponse if err = serializer.Map(k8sResources, &out.K8sResources); err != nil { log.Error(err) } @@ -1605,7 +1648,7 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r // @Param projectId path string true "Project ID" // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} outdomain.GetProjectNamespaceResourcesUsageResponse +// @Success 200 {object} domain.GetProjectNamespaceResourcesUsageResponse // @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, r *http.Request) { @@ -1633,14 +1676,14 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, return } - resourcesUsage, err := p.usecase.GetResourcesUsage(r.Context(), organizationId, projectId, projectNamespace, outdomain.StackId(stackId)) + resourcesUsage, err := p.usecase.GetResourcesUsage(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) ErrorJSON(w, r, err) return } - var out outdomain.GetProjectNamespaceResourcesUsageResponse + var out domain.GetProjectNamespaceResourcesUsageResponse if err = serializer.Map(resourcesUsage, &out.ResourcesUsage); err != nil { log.Error(err) } diff --git a/internal/domain/domain.go b/internal/model/project.go similarity index 99% rename from internal/domain/domain.go rename to internal/model/project.go index a35a3062..011e7704 100644 --- a/internal/domain/domain.go +++ b/internal/model/project.go @@ -1,4 +1,4 @@ -package domain +package model import ( "time" diff --git a/internal/repository/project.go b/internal/repository/project.go index ccdc34ca..198e89a4 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -5,38 +5,39 @@ import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/domain" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - out_domain "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gorm.io/gorm" ) type IProjectRepository interface { - CreateProject(p *domain.Project) (string, error) - GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]out_domain.ProjectResponse, error) - GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]out_domain.ProjectResponse, error) - GetProjectById(organizationId string, projectId string) (*domain.Project, error) - GetProjectByIdAndLeader(organizationId string, projectId string) (*domain.Project, error) - GetProjectByName(organizationId string, projectName string) (*domain.Project, error) - UpdateProject(p *domain.Project) error - GetAllProjectRoles() ([]domain.ProjectRole, error) - GetProjectRoleByName(name string) (*domain.ProjectRole, error) - GetProjectRoleById(id string) (*domain.ProjectRole, error) - AddProjectMember(*domain.ProjectMember) (string, error) - GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) ([]domain.ProjectMember, error) - GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) ([]domain.ProjectMember, error) - GetProjectMemberCountByProjectId(projectId string) (*out_domain.GetProjectMemberCountResponse, error) - GetProjectMemberById(projectMemberId string) (*domain.ProjectMember, error) - GetProjectMemberByUserId(projectId string, projectUserId string) (pm *domain.ProjectMember, err error) + CreateProject(p *model.Project) (string, error) + GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetAllProjects(organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) + GetProjectById(organizationId string, projectId string) (*model.Project, error) + GetProjectByIdAndLeader(organizationId string, projectId string) (*model.Project, error) + GetProjectByName(organizationId string, projectName string) (*model.Project, error) + UpdateProject(p *model.Project) error + GetAllProjectRoles() ([]model.ProjectRole, error) + GetProjectRoleByName(name string) (*model.ProjectRole, error) + GetProjectRoleById(id string) (*model.ProjectRole, error) + AddProjectMember(*model.ProjectMember) (string, error) + GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) ([]model.ProjectMember, error) + GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) ([]model.ProjectMember, error) + GetProjectMemberCountByProjectId(projectId string) (*domain.GetProjectMemberCountResponse, error) + GetProjectMemberById(projectMemberId string) (*model.ProjectMember, error) + GetProjectMemberByUserId(projectId string, projectUserId string) (pm *model.ProjectMember, err error) RemoveProjectMember(projectMemberId string) error - UpdateProjectMemberRole(pm *domain.ProjectMember) error - CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error - GetProjectNamespaceByName(organizationId string, projectId string, stackId string, projectNamespace string) (*domain.ProjectNamespace, error) - GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) - GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) - UpdateProjectNamespace(pn *domain.ProjectNamespace) error + UpdateProjectMemberRole(pm *model.ProjectMember) error + CreateProjectNamespace(organizationId string, pn *model.ProjectNamespace) error + GetProjectNamespaceByName(organizationId string, projectId string, stackId string, projectNamespace string) (*model.ProjectNamespace, error) + GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) ([]model.ProjectNamespace, error) + GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, projectNamespace string, stackId string) (*model.ProjectNamespace, error) + UpdateProjectNamespace(pn *model.ProjectNamespace) error DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error GetAppCountByProjectId(organizationId string, projectId string) (int, error) GetAppCountByNamespace(organizationId string, projectId string, namespace string) (int, error) @@ -52,7 +53,7 @@ func NewProjectRepository(db *gorm.DB) IProjectRepository { } } -func (r *ProjectRepository) CreateProject(p *domain.Project) (string, error) { +func (r *ProjectRepository) CreateProject(p *model.Project) (string, error) { res := r.db.Create(&p) if res.Error != nil { return "", res.Error @@ -61,7 +62,7 @@ func (r *ProjectRepository) CreateProject(p *domain.Project) (string, error) { return p.ID, nil } -func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []out_domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { if pg == nil { pg = pagination.NewPagination(nil) } @@ -155,38 +156,46 @@ func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, return pr, nil } -func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []out_domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { if pg == nil { pg = pagination.NewPagination(nil) } res := r.db.Raw(""+ - "select p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ + "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ - " from projects as p, "+ - " (select pm.project_id, pm.project_user_id, pm.project_role_id, pm.created_at, pm.is_project_leader, "+ + " from projects as p "+ + " left join "+ + " (select pm.project_id as project_id, pm.project_user_id as project_user_id, pm.project_role_id as project_role_id, "+ + " pm.created_at as created_at, pm.is_project_leader as is_project_leader, "+ " pr.name as pr_name "+ " from project_members as pm "+ " left join project_roles as pr on pr.id = pm.project_role_id "+ " left join users on users.id = pm.project_user_id "+ - " where pm.project_user_id = @userId) as pm, "+ - " (select count(pn.stack_id || pn.project_id) as count "+ + " where pm.project_user_id = @userId) as pm on p.id = pm.project_id "+ + " left join "+ + " (select p.id as project_id, count(pn.stack_id || pn.project_id) as count "+ " from project_namespaces as pn "+ " left join projects as p on pn.project_id = p.id "+ " left join project_members as pm on pn.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId) as pn, "+ - " (select count(asa.id) as count "+ + " and pm.project_user_id = @userId "+ + " group by p.id) as pn on p.id = pn.project_id "+ + " left join "+ + " (select p.id as project_id, count(asa.id) as count "+ " from app_serve_apps as asa "+ " left join projects as p on asa.project_id = p.id "+ " left join project_members as pm on asa.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId) as asa, "+ - " (select count(pm.id) as count "+ + " and pm.project_user_id = @userId "+ + " group by p.id) as asa on p.id = asa.project_id "+ + " left join "+ + " (select p.id as project_id, count(pm.id) as count "+ " from project_members as pm "+ " left join projects as p on pm.project_id = p.id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId) as pm_count "+ + " and pm.project_user_id = @userId "+ + " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ " and p.organization_id = @organizationId", sql.Named("organizationId", organizationId), sql.Named("userId", userId)). Scan(&pr) @@ -204,7 +213,60 @@ func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uu return pr, nil } -func (r *ProjectRepository) GetProjectById(organizationId string, projectId string) (p *domain.Project, err error) { +func (r *ProjectRepository) GetAllProjects(organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + res := r.db.Raw(""+ + "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ + " false as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ + " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ + " from projects as p "+ + " left join "+ + " (select distinct pm.project_id as project_id, '' as project_user_id, '' as project_role_id, "+ + " pm.created_at as created_at, pm.is_project_leader as is_project_leader, "+ + " '' as pr_name "+ + " from project_members as pm "+ + " left join project_roles as pr on pr.id = pm.project_role_id "+ + " left join users on users.id = pm.project_user_id) as pm on p.id = pm.project_id "+ + " left join "+ + " (select p.id as project_id, count(pn.stack_id || pn.project_id) as count "+ + " from project_namespaces as pn "+ + " left join projects as p on pn.project_id = p.id "+ + " left join project_members as pm on pn.project_id = pm.project_id "+ + " where p.organization_id = @organizationId "+ + " group by p.id) as pn on p.id = pn.project_id "+ + " left join "+ + " (select p.id as project_id, count(asa.id) as count "+ + " from app_serve_apps as asa "+ + " left join projects as p on asa.project_id = p.id "+ + " left join project_members as pm on asa.project_id = pm.project_id "+ + " where p.organization_id = @organizationId "+ + " group by p.id) as asa on p.id = asa.project_id "+ + " left join "+ + " (select p.id as project_id, count(pm.id) as count "+ + " from project_members as pm "+ + " left join projects as p on pm.project_id = p.id "+ + " where p.organization_id = @organizationId "+ + " group by p.id) as pm_count on p.id = pm_count.project_id "+ + " where p.id = pm.project_id "+ + " and p.organization_id = @organizationId", sql.Named("organizationId", organizationId)). + Scan(&pr) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Cannot find project") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + return pr, nil +} + +func (r *ProjectRepository) GetProjectById(organizationId string, projectId string) (p *model.Project, err error) { res := r.db.Limit(1).Where("organization_id = ? and id = ?", organizationId, projectId).First(&p) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -219,7 +281,7 @@ func (r *ProjectRepository) GetProjectById(organizationId string, projectId stri return p, nil } -func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, projectId string) (p *domain.Project, err error) { +func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, projectId string) (p *model.Project, err error) { res := r.db.Limit(1). Preload("ProjectMembers", "is_project_leader = ?", true). Preload("ProjectMembers.ProjectRole"). @@ -239,7 +301,7 @@ func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, proje return p, nil } -func (r *ProjectRepository) GetProjectByName(organizationId string, projectName string) (p *domain.Project, err error) { +func (r *ProjectRepository) GetProjectByName(organizationId string, projectName string) (p *model.Project, err error) { res := r.db.Limit(1). Where("organization_id = ? and name = ?", organizationId, projectName). First(&p) @@ -256,8 +318,8 @@ func (r *ProjectRepository) GetProjectByName(organizationId string, projectName return p, nil } -func (r *ProjectRepository) UpdateProject(p *domain.Project) error { - res := r.db.Model(&p).Updates(domain.Project{Name: p.Name, Description: p.Description, UpdatedAt: p.UpdatedAt}) +func (r *ProjectRepository) UpdateProject(p *model.Project) error { + res := r.db.Model(&p).Updates(model.Project{Name: p.Name, Description: p.Description, UpdatedAt: p.UpdatedAt}) if res.Error != nil { return res.Error } @@ -265,8 +327,8 @@ func (r *ProjectRepository) UpdateProject(p *domain.Project) error { return nil } -func (r *ProjectRepository) GetProjectRoleById(id string) (*domain.ProjectRole, error) { - var pr = &domain.ProjectRole{ID: id} +func (r *ProjectRepository) GetProjectRoleById(id string) (*model.ProjectRole, error) { + var pr = &model.ProjectRole{ID: id} res := r.db.First(pr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -281,7 +343,7 @@ func (r *ProjectRepository) GetProjectRoleById(id string) (*domain.ProjectRole, return pr, nil } -func (r *ProjectRepository) GetAllProjectRoles() (prs []domain.ProjectRole, err error) { +func (r *ProjectRepository) GetAllProjectRoles() (prs []model.ProjectRole, err error) { res := r.db.Find(&prs) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -296,7 +358,7 @@ func (r *ProjectRepository) GetAllProjectRoles() (prs []domain.ProjectRole, err return prs, nil } -func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *domain.ProjectRole, err error) { +func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *model.ProjectRole, err error) { res := r.db.Where("name = ?", name).First(&pr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -311,7 +373,7 @@ func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *domain.Projec return pr, nil } -func (r *ProjectRepository) AddProjectMember(pm *domain.ProjectMember) (string, error) { +func (r *ProjectRepository) AddProjectMember(pm *model.ProjectMember) (string, error) { res := r.db.Create(&pm) if res.Error != nil { return "", res.Error @@ -320,7 +382,7 @@ func (r *ProjectRepository) AddProjectMember(pm *domain.ProjectMember) (string, return pm.ID, nil } -func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) (pms []domain.ProjectMember, err error) { +func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { if pg == nil { pg = pagination.NewPagination(nil) } @@ -341,12 +403,12 @@ func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string, pg *p return pms, nil } -func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) (pms []domain.ProjectMember, err error) { +func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { if pg == nil { pg = pagination.NewPagination(nil) } _, res := pg.Fetch(r.db.Joins("ProjectUser"). - InnerJoins("ProjectRole", r.db.Where(&domain.ProjectRole{Name: memberRole})). + InnerJoins("ProjectRole", r.db.Where(&model.ProjectRole{Name: memberRole})). Order("project_members.created_at ASC"). Where("project_members.project_id = ?", projectId), &pms) @@ -363,7 +425,7 @@ func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId st return pms, nil } -func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) (pmcr *out_domain.GetProjectMemberCountResponse, err error) { +func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { res := r.db.Raw(""+ "select (plc.count + pmc.count + pvc.count) as project_member_all_count,"+ " plc.count as project_leader_count,"+ @@ -398,7 +460,7 @@ func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) ( return pmcr, nil } -func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm *domain.ProjectMember, err error) { +func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm *model.ProjectMember, err error) { res := r.db.Preload("ProjectUser"). Joins("ProjectRole").Where("project_members.id = ?", projectMemberId).First(&pm) if res.Error != nil { @@ -414,7 +476,7 @@ func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm *do return pm, nil } -func (r *ProjectRepository) GetProjectMemberByUserId(projectId string, projectUserId string) (pm *domain.ProjectMember, err error) { +func (r *ProjectRepository) GetProjectMemberByUserId(projectId string, projectUserId string) (pm *model.ProjectMember, err error) { res := r.db.Preload("ProjectUser"). Joins("ProjectRole").Where("project_id = ? and project_user_id = ?", projectId, projectUserId).First(&pm) if res.Error != nil { @@ -431,7 +493,7 @@ func (r *ProjectRepository) GetProjectMemberByUserId(projectId string, projectUs } func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { - res := r.db.Delete(&domain.ProjectMember{ID: projectMemberId}) + res := r.db.Delete(&model.ProjectMember{ID: projectMemberId}) if res.Error != nil { return res.Error } @@ -440,7 +502,7 @@ func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { } //func (r *ProjectRepository) UpdateProjectMemberRole(projectMemberId string, projectRoleId string) error { -// res := r.db.Model(&domain.ProjectMember{ID: projectMemberId}).Update("project_role_id", projectRoleId) +// res := r.db.Model(&model.ProjectMember{ID: projectMemberId}).Update("project_role_id", projectRoleId) // if res.Error != nil { // return res.Error // } @@ -448,9 +510,9 @@ func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { // return nil //} -func (r *ProjectRepository) UpdateProjectMemberRole(pm *domain.ProjectMember) error { +func (r *ProjectRepository) UpdateProjectMemberRole(pm *model.ProjectMember) error { res := r.db.Model(&pm).Updates( - domain.ProjectMember{ + model.ProjectMember{ ProjectRoleId: pm.ProjectRoleId, IsProjectLeader: pm.IsProjectLeader, UpdatedAt: pm.UpdatedAt, @@ -462,7 +524,7 @@ func (r *ProjectRepository) UpdateProjectMemberRole(pm *domain.ProjectMember) er return nil } -func (r *ProjectRepository) CreateProjectNamespace(organizationId string, pn *domain.ProjectNamespace) error { +func (r *ProjectRepository) CreateProjectNamespace(organizationId string, pn *model.ProjectNamespace) error { res := r.db.Create(&pn) if res.Error != nil { return res.Error @@ -473,7 +535,7 @@ func (r *ProjectRepository) CreateProjectNamespace(organizationId string, pn *do } func (r *ProjectRepository) GetProjectNamespaceByName(organizationId string, projectId string, stackId string, - projectNamespace string) (pn *domain.ProjectNamespace, err error) { + projectNamespace string) (pn *model.ProjectNamespace, err error) { res := r.db.Limit(1). Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). First(&pn) @@ -490,7 +552,7 @@ func (r *ProjectRepository) GetProjectNamespaceByName(organizationId string, pro return pn, nil } -func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) (pns []domain.ProjectNamespace, err error) { +func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) (pns []model.ProjectNamespace, err error) { if pg == nil { pg = pagination.NewPagination(nil) } @@ -510,7 +572,7 @@ func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectI } func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, - projectNamespace string, stackId string) (pn *domain.ProjectNamespace, err error) { + projectNamespace string, stackId string) (pn *model.ProjectNamespace, err error) { res := r.db.Limit(1). Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). Preload("Stack"). @@ -528,8 +590,8 @@ func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(organizationId strin return pn, nil } -func (r *ProjectRepository) UpdateProjectNamespace(pn *domain.ProjectNamespace) error { - res := r.db.Model(&pn).Updates(domain.ProjectNamespace{Description: pn.Description, UpdatedAt: pn.UpdatedAt}) +func (r *ProjectRepository) UpdateProjectNamespace(pn *model.ProjectNamespace) error { + res := r.db.Model(&pn).Updates(model.ProjectNamespace{Description: pn.Description, UpdatedAt: pn.UpdatedAt}) if res.Error != nil { return res.Error } @@ -540,7 +602,7 @@ func (r *ProjectRepository) UpdateProjectNamespace(pn *domain.ProjectNamespace) func (r *ProjectRepository) DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error { res := r.db.Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). - Delete(&domain.ProjectNamespace{StackId: stackId, Namespace: projectNamespace}) + Delete(&model.ProjectNamespace{StackId: stackId, Namespace: projectNamespace}) if res.Error != nil { return res.Error } diff --git a/internal/route/route.go b/internal/route/route.go index ef028cab..db4bceea 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -260,6 +260,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa // Admin r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.Admin_ListTksRoles, http.HandlerFunc(roleHandler.Admin_ListTksRoles))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.Admin_GetTksRole, http.HandlerFunc(roleHandler.Admin_GetTksRole))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/projects", customMiddleware.Handle(internalApi.Admin_GetProjects, http.HandlerFunc(projectHandler.Admin_GetProjects))).Methods(http.MethodGet) permissionHandler := delivery.NewPermissionHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index ac9785ab..756692a9 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -3,17 +3,18 @@ package usecase import ( "context" "fmt" + "strconv" "time" "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/domain" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" argowf "github.com/openinfradev/tks-api/pkg/argo-client" - out_domain "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gopkg.in/yaml.v3" @@ -28,26 +29,26 @@ const ( ) type IProjectUsecase interface { - CreateProject(ctx context.Context, p *domain.Project) (string, error) - GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) ([]out_domain.ProjectResponse, error) - GetProject(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) - GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) + CreateProject(ctx context.Context, p *model.Project) (string, error) + GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProject(ctx context.Context, organizationId string, projectId string) (*model.Project, error) + GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*model.Project, error) IsProjectNameExist(ctx context.Context, organizationId string, projectName string) (bool, error) - UpdateProject(ctx context.Context, p *domain.Project, newLeaderId string) error - GetProjectRole(ctx context.Context, id string) (*domain.ProjectRole, error) - GetProjectRoles(ctx context.Context, query int) ([]domain.ProjectRole, error) - AddProjectMember(ctx context.Context, pm *domain.ProjectMember) (string, error) - GetProjectUser(ctx context.Context, projectUserId string) (*domain.ProjectUser, error) - GetProjectMember(ctx context.Context, projectMemberId string) (*domain.ProjectMember, error) - GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) ([]domain.ProjectMember, error) - GetProjectMemberCount(ctx context.Context, projectMemberId string) (*out_domain.GetProjectMemberCountResponse, error) + UpdateProject(ctx context.Context, p *model.Project, newLeaderId string) error + GetProjectRole(ctx context.Context, id string) (*model.ProjectRole, error) + GetProjectRoles(ctx context.Context, query int) ([]model.ProjectRole, error) + AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) + GetProjectUser(ctx context.Context, projectUserId string) (*model.ProjectUser, error) + GetProjectMember(ctx context.Context, projectMemberId string) (*model.ProjectMember, error) + GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) ([]model.ProjectMember, error) + GetProjectMemberCount(ctx context.Context, projectMemberId string) (*domain.GetProjectMemberCountResponse, error) RemoveProjectMember(ctx context.Context, projectMemberId string) error - UpdateProjectMemberRole(ctx context.Context, pm *domain.ProjectMember) error - CreateProjectNamespace(ctx context.Context, organizationId string, pn *domain.ProjectNamespace) error + UpdateProjectMemberRole(ctx context.Context, pm *model.ProjectMember) error + CreateProjectNamespace(ctx context.Context, organizationId string, pn *model.ProjectNamespace) error IsProjectNamespaceExist(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) - GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) - GetProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) - UpdateProjectNamespace(ctx context.Context, pn *domain.ProjectNamespace) error + GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]model.ProjectNamespace, error) + GetProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*model.ProjectNamespace, error) + UpdateProjectNamespace(ctx context.Context, pn *model.ProjectNamespace) error DeleteProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) error GetAppCount(ctx context.Context, organizationId string, projectId string, namespace string) (appCount int, err error) EnsureRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error @@ -55,8 +56,8 @@ type IProjectUsecase interface { CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error DeleteK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) - GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceK8sResources, err error) - GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceResourcesUsage, err error) + GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) + GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error } @@ -85,7 +86,7 @@ func NewProjectUsecase(r repository.Repository, kc keycloak.IKeycloak, argoClien } } -func (u *ProjectUsecase) CreateProject(ctx context.Context, p *domain.Project) (string, error) { +func (u *ProjectUsecase) CreateProject(ctx context.Context, p *model.Project) (string, error) { projectId, err := u.projectRepo.CreateProject(p) if err != nil { log.ErrorWithContext(ctx, err) @@ -95,29 +96,30 @@ func (u *ProjectUsecase) CreateProject(ctx context.Context, p *domain.Project) ( return projectId, nil } -func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []out_domain.ProjectResponse, err error) { - userUuid, err := uuid.Parse(userId) - if err != nil { - log.ErrorWithContext(ctx, err) - return nil, errors.Wrap(err, "Failed to parse uuid to string") - } - if onlyMyProject == false { - pr, err = u.projectRepo.GetProjects(organizationId, userUuid, pg) - if err != nil { - log.ErrorWithContext(ctx, err) - return nil, errors.Wrap(err, "Failed to get projects.") - } +func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { + if userId == "" { + pr, err = u.projectRepo.GetAllProjects(organizationId, pg) } else { - pr, err = u.projectRepo.GetProjectsByUserId(organizationId, userUuid, pg) + userUuid, err := uuid.Parse(userId) if err != nil { log.ErrorWithContext(ctx, err) - return nil, errors.Wrap(err, "Failed to get projects.") + return nil, errors.Wrap(err, "Failed to parse uuid to string") + } + if onlyMyProject == false { + pr, err = u.projectRepo.GetProjects(organizationId, userUuid, pg) + } else { + pr, err = u.projectRepo.GetProjectsByUserId(organizationId, userUuid, pg) } } + if err != nil { + log.ErrorWithContext(ctx, err) + return nil, errors.Wrap(err, "Failed to get projects.") + } + return pr, err } -func (u *ProjectUsecase) GetProject(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) { +func (u *ProjectUsecase) GetProject(ctx context.Context, organizationId string, projectId string) (*model.Project, error) { p, err := u.projectRepo.GetProjectById(organizationId, projectId) if err != nil { log.ErrorWithContext(ctx, err) @@ -126,7 +128,7 @@ func (u *ProjectUsecase) GetProject(ctx context.Context, organizationId string, return p, err } -func (u *ProjectUsecase) GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*domain.Project, error) { +func (u *ProjectUsecase) GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*model.Project, error) { p, err := u.projectRepo.GetProjectByIdAndLeader(organizationId, projectId) if err != nil { log.ErrorWithContext(ctx, err) @@ -149,7 +151,7 @@ func (u *ProjectUsecase) IsProjectNameExist(ctx context.Context, organizationId return exist, nil } -func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *domain.Project, newLeaderId string) error { +func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, newLeaderId string) error { var currentMemberId, currentLeaderId, projectRoleId string for _, pm := range p.ProjectMembers { @@ -184,7 +186,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *domain.Project, n return err } if pm == nil { - newPm := &domain.ProjectMember{ + newPm := &model.ProjectMember{ ProjectId: p.ID, ProjectUserId: pu.ID, ProjectUser: nil, @@ -215,7 +217,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *domain.Project, n return nil } -func (u *ProjectUsecase) GetProjectRole(ctx context.Context, id string) (*domain.ProjectRole, error) { +func (u *ProjectUsecase) GetProjectRole(ctx context.Context, id string) (*model.ProjectRole, error) { pr, err := u.projectRepo.GetProjectRoleById(id) if err != nil { log.ErrorWithContext(ctx, err) @@ -225,8 +227,8 @@ func (u *ProjectUsecase) GetProjectRole(ctx context.Context, id string) (*domain return pr, nil } -func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs []domain.ProjectRole, err error) { - var pr *domain.ProjectRole +func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs []model.ProjectRole, err error) { + var pr *model.ProjectRole if query == ProjectLeader { pr, err = u.projectRepo.GetProjectRoleByName("project-leader") @@ -249,7 +251,7 @@ func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs [] return prs, nil } -func (u *ProjectUsecase) AddProjectMember(ctx context.Context, pm *domain.ProjectMember) (string, error) { +func (u *ProjectUsecase) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { projectMemberId, err := u.projectRepo.AddProjectMember(pm) if err != nil { log.ErrorWithContext(ctx, err) @@ -258,7 +260,7 @@ func (u *ProjectUsecase) AddProjectMember(ctx context.Context, pm *domain.Projec return projectMemberId, nil } -func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId string) (*domain.ProjectUser, error) { +func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId string) (*model.ProjectUser, error) { var uid uuid.UUID uid, err := uuid.Parse(projectUserId) if err != nil { @@ -271,7 +273,7 @@ func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId strin log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve user by id") } - var pu domain.ProjectUser + var pu model.ProjectUser if err = serializer.Map(user, &pu); err != nil { log.ErrorWithContext(ctx, err) return nil, err @@ -279,7 +281,7 @@ func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId strin return &pu, nil } -func (u *ProjectUsecase) GetProjectMember(ctx context.Context, projectMemberId string) (pm *domain.ProjectMember, err error) { +func (u *ProjectUsecase) GetProjectMember(ctx context.Context, projectMemberId string) (pm *model.ProjectMember, err error) { pm, err = u.projectRepo.GetProjectMemberById(projectMemberId) if err != nil { log.ErrorWithContext(ctx, err) @@ -289,7 +291,7 @@ func (u *ProjectUsecase) GetProjectMember(ctx context.Context, projectMemberId s return pm, nil } -func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) (pms []domain.ProjectMember, err error) { +func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { if query == ProjectLeader { pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-leader", pg) } else if query == ProjectMember { @@ -307,7 +309,7 @@ func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string return pms, nil } -func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMemberId string) (pmcr *out_domain.GetProjectMemberCountResponse, err error) { +func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMemberId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { pmcr, err = u.projectRepo.GetProjectMemberCountByProjectId(projectMemberId) if err != nil { log.ErrorWithContext(ctx, err) @@ -325,7 +327,7 @@ func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, projectMemberI return nil } -func (u *ProjectUsecase) UpdateProjectMemberRole(ctx context.Context, pm *domain.ProjectMember) error { +func (u *ProjectUsecase) UpdateProjectMemberRole(ctx context.Context, pm *model.ProjectMember) error { if err := u.projectRepo.UpdateProjectMemberRole(pm); err != nil { log.ErrorWithContext(ctx, err) @@ -334,7 +336,7 @@ func (u *ProjectUsecase) UpdateProjectMemberRole(ctx context.Context, pm *domain return nil } -func (u *ProjectUsecase) CreateProjectNamespace(ctx context.Context, organizationId string, pn *domain.ProjectNamespace) error { +func (u *ProjectUsecase) CreateProjectNamespace(ctx context.Context, organizationId string, pn *model.ProjectNamespace) error { if err := u.projectRepo.CreateProjectNamespace(organizationId, pn); err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -356,7 +358,7 @@ func (u *ProjectUsecase) IsProjectNamespaceExist(ctx context.Context, organizati return exist, nil } -func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]domain.ProjectNamespace, error) { +func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]model.ProjectNamespace, error) { pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, pg) if err != nil { log.ErrorWithContext(ctx, err) @@ -366,7 +368,7 @@ func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationI return pns, nil } -func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*domain.ProjectNamespace, error) { +func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*model.ProjectNamespace, error) { pn, err := u.projectRepo.GetProjectNamespaceByPrimaryKey(organizationId, projectId, projectNamespace, stackId) if err != nil { log.ErrorWithContext(ctx, err) @@ -376,7 +378,7 @@ func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId return pn, nil } -func (u *ProjectUsecase) UpdateProjectNamespace(ctx context.Context, pn *domain.ProjectNamespace) error { +func (u *ProjectUsecase) UpdateProjectNamespace(ctx context.Context, pn *model.ProjectNamespace) error { if err := u.projectRepo.UpdateProjectNamespace(pn); err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to update project namespace") @@ -563,7 +565,7 @@ func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizat } func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, stackId string) error { // create Roles in keycloak - for _, role := range []string{string(ProjectLeader), string(ProjectMember), string(ProjectViewer)} { + for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { err := u.kc.EnsureClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) if err != nil { log.ErrorWithContext(ctx, err) @@ -576,7 +578,7 @@ func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organiza // first check whether the stac // delete Roles in keycloak - for _, role := range []string{string(ProjectLeader), string(ProjectMember), string(ProjectViewer)} { + for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { err := u.kc.DeleteClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) if err != nil { log.ErrorWithContext(ctx, err) @@ -706,8 +708,8 @@ func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationI return kubernetes.MergeKubeconfigsWithSingleUser(kubeconfigs) } -func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceK8sResources, err error) { - _, err = u.clusterRepository.Get(out_domain.ClusterId(stackId)) +func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) { + _, err = u.clusterRepository.Get(domain.ClusterId(stackId)) if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } @@ -778,8 +780,8 @@ func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId str return } -func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId out_domain.StackId) (out out_domain.ProjectNamespaceResourcesUsage, err error) { - _, err = u.clusterRepository.Get(out_domain.ClusterId(stackId)) +func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) { + _, err = u.clusterRepository.Get(domain.ClusterId(stackId)) if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } From 27ae54cfbb79d04d19ce39e8c5803af4b919892f Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 7 Mar 2024 13:37:45 +0900 Subject: [PATCH 098/502] add admin project swagger --- api/swagger/docs.go | 286 +++++---------------------------------- api/swagger/swagger.json | 286 +++++---------------------------------- api/swagger/swagger.yaml | 186 ++++--------------------- 3 files changed, 97 insertions(+), 661 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index b003ac38..0d28b4b6 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -22,6 +22,43 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/admin/organizations/{organizationId}/projects": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get projects as admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get projects as admin", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse" + } + } + } + } + }, "/admin/organizations/{organizationId}/users/{accountId}": { "get": { "description": "Get user detail by admin", @@ -4679,35 +4716,6 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/roles": { - "get": { - "description": "List Tks Roles", - "produces": [ - "application/json" - ], - "tags": [ - "Role" - ], - "summary": "List Tks Roles", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" - } - } - } - } - }, "/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -5544,88 +5552,6 @@ const docTemplate = `{ } } }, - "/permissions/templates": { - "get": { - "description": "Get Permission Templates", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Permission" - ], - "summary": "Get Permission Templates", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" - } - } - } - } - }, - "/roles/{roleId}/permissions": { - "get": { - "description": "Get Permissions By Role ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Permission" - ], - "summary": "Get Permissions By Role ID", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" - } - } - } - }, - "put": { - "description": "Update Permissions By Role ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Permission" - ], - "summary": "Update Permissions By Role ID", - "parameters": [ - { - "type": "string", - "description": "Role ID", - "name": "roleId", - "in": "path", - "required": true - }, - { - "description": "Update Permissions By Role ID Request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/stack-templates": { "get": { "security": [ @@ -7383,20 +7309,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "group": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -7958,32 +7870,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetUserResponse": { "type": "object", "properties": { @@ -8098,20 +7984,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" - }, - "roles": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ListUserBody": { "type": "object", "properties": { @@ -8304,79 +8176,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Permission": { - "type": "object", - "properties": { - "ID": { - "type": "string" - }, - "children": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - } - }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, - "endpoints": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" - } - }, - "id": { - "type": "integer" - }, - "is_allowed": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "parent_id": { - "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" - }, - "role_id": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { - "type": "object", - "properties": { - "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "security_policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { "type": "object", "required": [ @@ -9374,17 +9173,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { - "type": "object", - "properties": { - "permissions": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 07d2d34d..8300a733 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -16,6 +16,43 @@ "host": "tks-api-dev.taco-cat.xyz", "basePath": "/api/1.0/", "paths": { + "/admin/organizations/{organizationId}/projects": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get projects as admin", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get projects as admin", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse" + } + } + } + } + }, "/admin/organizations/{organizationId}/users/{accountId}": { "get": { "description": "Get user detail by admin", @@ -4673,35 +4710,6 @@ } } }, - "/organizations/{organizationId}/roles": { - "get": { - "description": "List Tks Roles", - "produces": [ - "application/json" - ], - "tags": [ - "Role" - ], - "summary": "List Tks Roles", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" - } - } - } - } - }, "/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -5538,88 +5546,6 @@ } } }, - "/permissions/templates": { - "get": { - "description": "Get Permission Templates", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Permission" - ], - "summary": "Get Permission Templates", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" - } - } - } - } - }, - "/roles/{roleId}/permissions": { - "get": { - "description": "Get Permissions By Role ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Permission" - ], - "summary": "Get Permissions By Role ID", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" - } - } - } - }, - "put": { - "description": "Update Permissions By Role ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Permission" - ], - "summary": "Update Permissions By Role ID", - "parameters": [ - { - "type": "string", - "description": "Role ID", - "name": "roleId", - "in": "path", - "required": true - }, - { - "description": "Update Permissions By Role ID Request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/stack-templates": { "get": { "security": [ @@ -7377,20 +7303,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "group": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -7952,32 +7864,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetUserResponse": { "type": "object", "properties": { @@ -8092,20 +7978,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" - }, - "roles": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ListUserBody": { "type": "object", "properties": { @@ -8298,79 +8170,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Permission": { - "type": "object", - "properties": { - "ID": { - "type": "string" - }, - "children": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - } - }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, - "endpoints": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" - } - }, - "id": { - "type": "integer" - }, - "is_allowed": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "parent_id": { - "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" - }, - "role_id": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { - "type": "object", - "properties": { - "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "security_policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - }, - "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { "type": "object", "required": [ @@ -9368,17 +9167,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { - "type": "object", - "properties": { - "permissions": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 2e678e2a..37552933 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1139,15 +1139,6 @@ definitions: - accessKeyId - secretAccessKey type: object - github_com_openinfradev_tks-api_pkg_domain.Endpoint: - properties: - createdAt: - type: string - group: - type: string - name: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: column: @@ -1509,23 +1500,6 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse' type: array type: object - github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse: - properties: - createdAt: - type: string - creator: - type: string - description: - type: string - id: - type: string - name: - type: string - organizationId: - type: string - updatedAt: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.GetUserResponse: properties: user: @@ -1601,15 +1575,6 @@ definitions: updatedAt: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse: - properties: - pagination: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' - roles: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse' - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.ListUserBody: properties: accountId: @@ -1741,54 +1706,6 @@ definitions: totalRows: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.Permission: - properties: - ID: - type: string - children: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - type: array - createdAt: - type: string - deletedAt: - $ref: '#/definitions/gorm.DeletedAt' - endpoints: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint' - type: array - id: - type: integer - is_allowed: - type: boolean - name: - type: string - parent: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - parent_id: - type: string - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' - role_id: - type: string - updatedAt: - type: string - type: object - github_com_openinfradev_tks-api_pkg_domain.PermissionSet: - properties: - configuration: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - dashboard: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - notification: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - project_management: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - security_policy: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - stack: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - type: object github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest: properties: organizationId: @@ -2450,13 +2367,6 @@ definitions: - newPassword - originPassword type: object - github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest: - properties: - permissions: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest: properties: primaryClusterId: @@ -2737,6 +2647,29 @@ info: title: tks-api service version: "1.0" paths: + /admin/organizations/{organizationId}/projects: + get: + consumes: + - application/json + description: Get projects as admin + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse' + security: + - JWT: [] + summary: Get projects as admin + tags: + - Projects /admin/organizations/{organizationId}/users/{accountId}: get: consumes: @@ -5726,25 +5659,6 @@ paths: summary: Get project role tags: - Projects - /organizations/{organizationId}/roles: - get: - description: List Tks Roles - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' - summary: List Tks Roles - tags: - - Role /organizations/{organizationId}/stacks: get: consumes: @@ -6281,60 +6195,6 @@ paths: summary: Get user email existence tags: - Users - /permissions/templates: - get: - consumes: - - application/json - description: Get Permission Templates - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' - summary: Get Permission Templates - tags: - - Permission - /roles/{roleId}/permissions: - get: - consumes: - - application/json - description: Get Permissions By Role ID - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' - summary: Get Permissions By Role ID - tags: - - Permission - put: - consumes: - - application/json - description: Update Permissions By Role ID - parameters: - - description: Role ID - in: path - name: roleId - required: true - type: string - - description: Update Permissions By Role ID Request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest' - produces: - - application/json - responses: - "200": - description: OK - summary: Update Permissions By Role ID - tags: - - Permission /stack-templates: get: consumes: From 8e20dd91c5cd75050c4099b87da04e66f33b3521 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 7 Mar 2024 13:40:01 +0900 Subject: [PATCH 099/502] add admin project swagger format --- internal/delivery/http/project.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index fa9c8c5e..74e0d1f1 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -74,7 +74,7 @@ func NewProjectHandler(u usecase.Usecase) IProjectHandler { // @Description Create new project // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" +// @Param organizationId path string true "Organization ID" // @Param request body domain.CreateProjectRequest true "Request body to create project" // @Success 200 {object} domain.CreateProjectResponse // @Router /organizations/{organizationId}/projects [post] @@ -362,8 +362,8 @@ func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Reques // @Description Update project // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param request body domain.UpdateProjectRequest true "Request body to update project" // @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId} [put] @@ -520,8 +520,8 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) // @Description Add project member to project // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param request body domain.AddProjectMemberRequest true "Request body to add project member" // @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [post] @@ -887,8 +887,8 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque // @Description Remove project members to project // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param request body domain.RemoveProjectMemberRequest true "Request body to remove project member" // @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [delete] @@ -955,9 +955,9 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // @Description Update project member Role // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param projectMemberId path string true "Project Member ID" +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param projectMemberId path string true "Project Member ID" // @Param request body domain.UpdateProjectMemberRoleRequest true "Request body to update project member role" // @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role [put] @@ -1053,8 +1053,8 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R // @Description Update project member Role // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" // @Param request body domain.UpdateProjectMembersRoleRequest true "Request body to update project member role" // @Success 200 {object} domain.CommonProjectResponse // @Router /organizations/{organizationId}/projects/{projectId}/members [put] From e32ab6f9f3857bafc3d37c4054c6a7b836cd92bf Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 7 Mar 2024 13:40:13 +0900 Subject: [PATCH 100/502] bug fix: restore missing variable due to refactoring --- pkg/domain/organization.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 7e764d94..fed0cfe9 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -58,6 +58,7 @@ type Organization struct { Description string `json:"description"` Phone string `json:"phone"` PrimaryClusterId string `json:"primaryClusterId"` + WorkflowId string `json:"-"` Status OrganizationStatus `json:"status"` StatusDesc string `json:"statusDesc"` Creator string `json:"creator"` From 87045eda5c0f923c55cc234e71be38cf80963488 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 7 Mar 2024 13:46:48 +0900 Subject: [PATCH 101/502] bug fix: fix path on docs --- internal/delivery/http/permission.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 84a04875..a4bf4b77 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -56,7 +56,7 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http // @Accept json // @Produce json // @Success 200 {object} domain.PermissionSet -// @Router organizations/{organizationId}/roles/{roleId}/permissions [get] +// @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] // @Security JWT func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { @@ -97,7 +97,7 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http // @Param roleId path string true "Role ID" // @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" // @Success 200 -// @Router organizations/{organizationId}/roles/{roleId}/permissions [put] +// @Router /organizations/{organizationId}/roles/{roleId}/permissions [put] // @Security JWT func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { From 5d862be8bdaeb5a617ba8934653f4c2bb00c90b8 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 7 Mar 2024 16:23:50 +0900 Subject: [PATCH 102/502] trivial. resolve build error --- internal/usecase/role_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/usecase/role_test.go b/internal/usecase/role_test.go index e4931993..a0b47c5b 100644 --- a/internal/usecase/role_test.go +++ b/internal/usecase/role_test.go @@ -2,14 +2,14 @@ package usecase_test import ( "fmt" + "gorm_test/config" + "testing" + "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/domain" myRepository "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/usecase" "gorm.io/driver/postgres" "gorm.io/gorm" - "gorm_test/config" - "testing" ) func TestNewRoleUsecase(t *testing.T) { From bbc437fa8176f7a04d96b1b6dd7ed0da575bb605 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 6 Mar 2024 18:10:09 +0900 Subject: [PATCH 103/502] feature. add api for stackTemplates. CUR --- api/swagger/docs.go | 880 +++++++++++++++--- api/swagger/swagger.json | 880 +++++++++++++++--- api/swagger/swagger.yaml | 454 ++++++++- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 + internal/delivery/http/stack-template.go | 103 +- internal/pagination/pagination.go | 15 + internal/repository/stack-template.go | 23 +- internal/route/route.go | 2 + internal/usecase/stack-template.go | 67 +- pkg/domain/stack-template.go | 14 +- pkg/httpErrors/errorCode.go | 5 + 12 files changed, 2110 insertions(+), 342 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0d28b4b6..4d0948f0 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -59,6 +59,71 @@ const docTemplate = `{ } } }, + "/admin/organizations/{organizationId}/roles": { + "get": { + "description": "Admin List Tks Roles", + "produces": [ + "application/json" + ], + "tags": [ + "Role" + ], + "summary": "Admin List Tks Roles", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" + } + } + } + } + }, + "/admin/organizations/{organizationId}/roles/{roleId}": { + "get": { + "description": "Admin Get Tks Role", + "produces": [ + "application/json" + ], + "tags": [ + "Role" + ], + "summary": "Admin Get Tks Role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } + } + } + } + }, "/admin/organizations/{organizationId}/users/{accountId}": { "get": { "description": "Get user detail by admin", @@ -150,6 +215,68 @@ const docTemplate = `{ } }, "/admin/stack-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + }, "post": { "security": [ { @@ -319,6 +446,42 @@ const docTemplate = `{ } } }, + "/admin/stack-templates/{stackTemplateId}/organizations": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update StackTemplate organizations", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Update StackTemplate organizations", + "parameters": [ + { + "description": "Update stack template organizations request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/app-groups": { "get": { "security": [ @@ -4716,68 +4879,35 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/roles": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", - "consumes": [ - "application/json" - ], + "description": "List Tks Roles", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Get Stacks", + "summary": "List Tks Roles", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", - "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" } } } @@ -4788,7 +4918,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Create Stack", + "description": "Create Tks Role", "consumes": [ "application/json" ], @@ -4796,24 +4926,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Create Stack", + "summary": "Create Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { - "description": "create cloud setting request", + "description": "Create Tks Role Request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest" } } ], @@ -4821,68 +4951,59 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse" } } } } }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { + "/organizations/{organizationId}/roles/{roleId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Check name for stack", - "consumes": [ - "application/json" - ], + "description": "Get Tks Role", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Check name for stack", + "summary": "Get Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } } } - } - }, - "/organizations/{organizationId}/stacks/{stackId}": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Get Stack", + "description": "Update Tks Role", "consumes": [ "application/json" ], @@ -4890,68 +5011,382 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Get Stack", + "summary": "Update Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true + }, + { + "description": "Update Tks Role Request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest" + } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" - } + "description": "OK" } } }, - "put": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Update Stack", - "consumes": [ - "application/json" - ], + "description": "Delete Tks Role", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Update Stack", + "summary": "Delete Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true - }, - { - "description": "Update cloud setting request", + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/roles/{roleId}/permissions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permissions By Role ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Get Permissions By Role ID", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update Permissions By Role ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Update Permissions By Role ID", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Update Permissions By Role ID Request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stacks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stacks", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "string", + "description": "combinedFilter", + "name": "combinedFilter", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Create Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Check name for stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Update Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", "name": "body", "in": "body", "required": true, @@ -5552,14 +5987,14 @@ const docTemplate = `{ } } }, - "/stack-templates": { + "/permissions/templates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get StackTemplates", + "description": "Get Permission Templates", "consumes": [ "application/json" ], @@ -5567,50 +6002,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplates", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } + "Permission" ], + "summary": "Get Permission Templates", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" } } } @@ -7125,6 +7524,30 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest": { "type": "object", "required": [ @@ -7309,6 +7732,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "group": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -7870,6 +8307,32 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetUserResponse": { "type": "object", "properties": { @@ -7984,6 +8447,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListUserBody": { "type": "object", "properties": { @@ -8176,6 +8653,79 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Permission": { + "type": "object", + "properties": { + "ID": { + "type": "string" + }, + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, + "endpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" + } + }, + "id": { + "type": "integer" + }, + "is_allowed": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "parent": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "parent_id": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "role_id": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { + "type": "object", + "properties": { + "configuration": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "dashboard": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "notification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "project_management": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "security_policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "stack": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { "type": "object", "required": [ @@ -9173,6 +9723,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { "type": "object", "properties": { @@ -9241,11 +9802,65 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest": { + "type": "object", + "required": [ + "organizationIds" + ], + "properties": { + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { "type": "object", + "required": [ + "serviceIds" + ], "properties": { + "cloudService": { + "type": "string" + }, "description": { "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "serviceIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { + "type": "object", + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 } } }, @@ -9479,7 +10094,6 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest": { "type": "object", "required": [ - "adminPassword", "email", "role" ], diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 8300a733..855a8c0f 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -53,6 +53,71 @@ } } }, + "/admin/organizations/{organizationId}/roles": { + "get": { + "description": "Admin List Tks Roles", + "produces": [ + "application/json" + ], + "tags": [ + "Role" + ], + "summary": "Admin List Tks Roles", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" + } + } + } + } + }, + "/admin/organizations/{organizationId}/roles/{roleId}": { + "get": { + "description": "Admin Get Tks Role", + "produces": [ + "application/json" + ], + "tags": [ + "Role" + ], + "summary": "Admin Get Tks Role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } + } + } + } + }, "/admin/organizations/{organizationId}/users/{accountId}": { "get": { "description": "Get user detail by admin", @@ -144,6 +209,68 @@ } }, "/admin/stack-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get StackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get StackTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + }, "post": { "security": [ { @@ -313,6 +440,42 @@ } } }, + "/admin/stack-templates/{stackTemplateId}/organizations": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update StackTemplate organizations", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Update StackTemplate organizations", + "parameters": [ + { + "description": "Update stack template organizations request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/app-groups": { "get": { "security": [ @@ -4710,68 +4873,35 @@ } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/roles": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", - "consumes": [ - "application/json" - ], + "description": "List Tks Roles", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Get Stacks", + "summary": "List Tks Roles", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", - "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" } } } @@ -4782,7 +4912,7 @@ "JWT": [] } ], - "description": "Create Stack", + "description": "Create Tks Role", "consumes": [ "application/json" ], @@ -4790,24 +4920,24 @@ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Create Stack", + "summary": "Create Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { - "description": "create cloud setting request", + "description": "Create Tks Role Request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest" } } ], @@ -4815,68 +4945,59 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse" } } } } }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { + "/organizations/{organizationId}/roles/{roleId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Check name for stack", - "consumes": [ - "application/json" - ], + "description": "Get Tks Role", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Check name for stack", + "summary": "Get Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "name", - "name": "name", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } } } - } - }, - "/organizations/{organizationId}/stacks/{stackId}": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Get Stack", + "description": "Update Tks Role", "consumes": [ "application/json" ], @@ -4884,68 +5005,382 @@ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Get Stack", + "summary": "Update Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true + }, + { + "description": "Update Tks Role Request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest" + } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" - } + "description": "OK" } } }, - "put": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Update Stack", - "consumes": [ - "application/json" - ], + "description": "Delete Tks Role", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Role" ], - "summary": "Update Stack", + "summary": "Delete Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true - }, - { - "description": "Update cloud setting request", + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/roles/{roleId}/permissions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permissions By Role ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Get Permissions By Role ID", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update Permissions By Role ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Update Permissions By Role ID", + "parameters": [ + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Update Permissions By Role ID Request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stacks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stacks", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "string", + "description": "combinedFilter", + "name": "combinedFilter", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Create Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Check name for stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Update Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", "name": "body", "in": "body", "required": true, @@ -5546,14 +5981,14 @@ } } }, - "/stack-templates": { + "/permissions/templates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get StackTemplates", + "description": "Get Permission Templates", "consumes": [ "application/json" ], @@ -5561,50 +5996,14 @@ "application/json" ], "tags": [ - "StackTemplates" - ], - "summary": "Get StackTemplates", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } + "Permission" ], + "summary": "Get Permission Templates", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" } } } @@ -7119,6 +7518,30 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest": { "type": "object", "required": [ @@ -7303,6 +7726,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "group": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -7864,6 +8301,32 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetUserResponse": { "type": "object", "properties": { @@ -7978,6 +8441,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListUserBody": { "type": "object", "properties": { @@ -8170,6 +8647,79 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Permission": { + "type": "object", + "properties": { + "ID": { + "type": "string" + }, + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, + "endpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" + } + }, + "id": { + "type": "integer" + }, + "is_allowed": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "parent": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "parent_id": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "role_id": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { + "type": "object", + "properties": { + "configuration": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "dashboard": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "notification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "project_management": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "security_policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + }, + "stack": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { "type": "object", "required": [ @@ -9167,6 +9717,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { "type": "object", "properties": { @@ -9235,11 +9796,65 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest": { + "type": "object", + "required": [ + "organizationIds" + ], + "properties": { + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { "type": "object", + "required": [ + "serviceIds" + ], "properties": { + "cloudService": { + "type": "string" + }, "description": { "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "serviceIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { + "type": "object", + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 } } }, @@ -9473,7 +10088,6 @@ "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest": { "type": "object", "required": [ - "adminPassword", "email", "role" ], diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 37552933..6c544727 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1014,6 +1014,22 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest: + properties: + description: + maxLength: 100 + minLength: 0 + type: string + name: + type: string + required: + - name + type: object + github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse: + properties: + id: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest: properties: accountId: @@ -1139,6 +1155,15 @@ definitions: - accessKeyId - secretAccessKey type: object + github_com_openinfradev_tks-api_pkg_domain.Endpoint: + properties: + createdAt: + type: string + group: + type: string + name: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: column: @@ -1500,6 +1525,23 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse: + properties: + createdAt: + type: string + creator: + type: string + description: + type: string + id: + type: string + name: + type: string + organizationId: + type: string + updatedAt: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.GetUserResponse: properties: user: @@ -1575,6 +1617,15 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.ListUserBody: properties: accountId: @@ -1706,6 +1757,54 @@ definitions: totalRows: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.Permission: + properties: + ID: + type: string + children: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + type: array + createdAt: + type: string + deletedAt: + $ref: '#/definitions/gorm.DeletedAt' + endpoints: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint' + type: array + id: + type: integer + is_allowed: + type: boolean + name: + type: string + parent: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + parent_id: + type: string + role: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + role_id: + type: string + updatedAt: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.PermissionSet: + properties: + configuration: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + dashboard: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + notification: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + project_management: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + security_policy: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + stack: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + type: object github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest: properties: organizationId: @@ -2367,6 +2466,13 @@ definitions: - newPassword - originPassword type: object + github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest: + properties: + permissions: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest: properties: primaryClusterId: @@ -2410,10 +2516,46 @@ definitions: description: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest: + properties: + organizationIds: + items: + type: string + type: array + required: + - organizationIds + type: object github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest: properties: + cloudService: + type: string description: type: string + kubeType: + type: string + kubeVersion: + type: string + platform: + type: string + serviceIds: + items: + type: string + type: array + template: + type: string + templateType: + type: string + version: + type: string + required: + - serviceIds + type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest: + properties: + description: + maxLength: 100 + minLength: 0 + type: string type: object github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest: properties: @@ -2586,7 +2728,6 @@ definitions: role: type: string required: - - adminPassword - email - role type: object @@ -2670,6 +2811,49 @@ paths: summary: Get projects as admin tags: - Projects + /admin/organizations/{organizationId}/roles: + get: + description: Admin List Tks Roles + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' + summary: Admin List Tks Roles + tags: + - Role + /admin/organizations/{organizationId}/roles/{roleId}: + get: + description: Admin Get Tks Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse' + summary: Admin Get Tks Role + tags: + - Role /admin/organizations/{organizationId}/users/{accountId}: get: consumes: @@ -2730,6 +2914,46 @@ paths: tags: - Admin /admin/stack-templates: + get: + consumes: + - application/json + description: Get StackTemplates + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' + security: + - JWT: [] + summary: Get StackTemplates + tags: + - StackTemplates post: consumes: - application/json @@ -2817,6 +3041,28 @@ paths: summary: Update StackTemplate 'NOT IMPLEMENTED' tags: - StackTemplates + /admin/stack-templates/{stackTemplateId}/organizations: + put: + consumes: + - application/json + description: Update StackTemplate organizations + parameters: + - description: Update stack template organizations request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update StackTemplate organizations + tags: + - StackTemplates /admin/stack-templates/services: get: consumes: @@ -5659,6 +5905,178 @@ paths: summary: Get project role tags: - Projects + /organizations/{organizationId}/roles: + get: + description: List Tks Roles + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' + security: + - JWT: [] + summary: List Tks Roles + tags: + - Role + post: + consumes: + - application/json + description: Create Tks Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Create Tks Role Request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse' + security: + - JWT: [] + summary: Create Tks Role + tags: + - Role + /organizations/{organizationId}/roles/{roleId}: + delete: + description: Delete Tks Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete Tks Role + tags: + - Role + get: + description: Get Tks Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse' + security: + - JWT: [] + summary: Get Tks Role + tags: + - Role + put: + consumes: + - application/json + description: Update Tks Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string + - description: Update Tks Role Request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update Tks Role + tags: + - Role + /organizations/{organizationId}/roles/{roleId}/permissions: + get: + consumes: + - application/json + description: Get Permissions By Role ID + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' + security: + - JWT: [] + summary: Get Permissions By Role ID + tags: + - Permission + put: + consumes: + - application/json + description: Update Permissions By Role ID + parameters: + - description: Role ID + in: path + name: roleId + required: true + type: string + - description: Update Permissions By Role ID Request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update Permissions By Role ID + tags: + - Permission /organizations/{organizationId}/stacks: get: consumes: @@ -6195,47 +6613,23 @@ paths: summary: Get user email existence tags: - Users - /stack-templates: + /permissions/templates: get: consumes: - application/json - description: Get StackTemplates - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filters - type: array + description: Get Permission Templates produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' security: - JWT: [] - summary: Get StackTemplates + summary: Get Permission Templates tags: - - StackTemplates + - Permission /system-api/organizations/{organizationId}/alerts: post: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 3ce75e2e..152eaca4 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -100,6 +100,7 @@ const ( GetStackTemplate UpdateStackTemplate DeleteStackTemplate + UpdateStackTemplateOrganizations // Dashboard GetChartsDashboard // 대시보드/대시보드/조회 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 11c42f81..f0ae9089 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -295,6 +295,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "DeleteStackTemplate", Group: "StackTemplate", }, + UpdateStackTemplateOrganizations: { + Name: "UpdateStackTemplateOrganizations", + Group: "StackTemplate", + }, GetChartsDashboard: { Name: "GetChartsDashboard", Group: "Dashboard", @@ -696,6 +700,8 @@ func (e Endpoint) String() string { return "UpdateStackTemplate" case DeleteStackTemplate: return "DeleteStackTemplate" + case UpdateStackTemplateOrganizations: + return "UpdateStackTemplateOrganizations" case GetChartsDashboard: return "GetChartsDashboard" case GetChartDashboard: @@ -974,6 +980,8 @@ func GetEndpoint(name string) Endpoint { return UpdateStackTemplate case "DeleteStackTemplate": return DeleteStackTemplate + case "UpdateStackTemplateOrganizations": + return UpdateStackTemplateOrganizations case "GetChartsDashboard": return GetChartsDashboard case "GetChartDashboard": diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 0244e3f8..107e621b 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -76,7 +76,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.GetStackTemplatesResponse -// @Router /stack-templates [get] +// @Router /admin/stack-templates [get] // @Security JWT func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -94,6 +94,14 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. log.InfoWithContext(r.Context(), err) } + out.StackTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) + for j, organization := range stackTemplate.Organizations { + if err := serializer.Map(organization, &out.StackTemplates[i].Organizations[j]); err != nil { + log.InfoWithContext(r.Context(), err) + continue + } + } + err := json.Unmarshal(stackTemplate.Services, &out.StackTemplates[i].Services) if err != nil { log.ErrorWithContext(r.Context(), err) @@ -171,34 +179,31 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R // @Router /admin/stack-templates/{stackTemplateId} [put] // @Security JWT func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *http.Request) { - /* - vars := mux.Vars(r) - strId, ok := vars["stackTemplateId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid stackTemplateId"))) - return - } - - stackTemplateId, err := uuid.Parse(strId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"))) - return - } + vars := mux.Vars(r) + strId, ok := vars["stackTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } - var dto domain.StackTemplate - if err := serializer.Map(r, &dto); err != nil { - log.InfoWithContext(r.Context(),err) - } - dto.ID = stackTemplateId + stackTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } - err = h.usecase.Update(r.Context(), dto) - if err != nil { - ErrorJSON(w, r, err) - return - } - */ + var dto domain.StackTemplate + if err := serializer.Map(r, &dto); err != nil { + log.InfoWithContext(r.Context(), err) + } + dto.ID = stackTemplateId - ErrorJSON(w, r, fmt.Errorf("need implementation")) + err = h.usecase.Update(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) } // DeleteStackTemplate godoc @@ -249,3 +254,49 @@ func (h *StackTemplateHandler) GetStackTemplateServices(w http.ResponseWriter, r ResponseJSON(w, r, http.StatusOK, out) } + +// UpdateStackTemplateOrganizations godoc +// +// @Tags StackTemplates +// @Summary Update StackTemplate organizations +// @Description Update StackTemplate organizations +// @Accept json +// @Produce json +// @Param body body domain.UpdateStackTemplateOrganizationsRequest true "Update stack template organizations request" +// @Success 200 {object} nil +// @Router /admin/stack-templates/{stackTemplateId}/organizations [put] +// @Security JWT +func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["stackTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + stackTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + input := domain.UpdateStackTemplateOrganizationsRequest{} + err = UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto domain.StackTemplate + if err := serializer.Map(input, &dto); err != nil { + log.InfoWithContext(r.Context(), err) + } + dto.ID = stackTemplateId + + err = h.usecase.UpdateOrganizations(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 22e4ad47..0de16f10 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -150,6 +150,21 @@ func (p *Pagination) Response() (out domain.PaginationResponse, err error) { return out, err } +func NewPaginationWithFilter(column string, releation string, op string, values []string) *Pagination { + pg := newDefaultPagination() + + pg.Filters = append(pg.Filters, Filter{ + Column: helper.ToSnakeCase(strings.Replace(column, "[]", "", -1)), + Relation: releation, + Operator: op, + Values: values, + Or: false, + }) + pg.MakePaginationRequest() + + return pg +} + func NewPagination(urlParams *url.Values) *Pagination { pg := newDefaultPagination() diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 73c322d4..9c55df46 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -78,7 +78,7 @@ func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db, &stackTemplates) + _, res := pg.Fetch(r.db.Preload(clause.Associations), &stackTemplates) if res.Error != nil { return nil, res.Error } @@ -94,10 +94,14 @@ func (r *StackTemplateRepository) Create(dto domain.StackTemplate) (stackTemplat stackTemplate := StackTemplate{ Name: dto.Name, Description: dto.Description, - CloudService: dto.CloudService, - Platform: dto.Platform, Template: dto.Template, TemplateType: dto.TemplateType, + Version: dto.Version, + CloudService: dto.CloudService, + Platform: dto.Platform, + KubeVersion: dto.KubeVersion, + KubeType: dto.KubeType, + Services: dto.Services, CreatorId: &dto.CreatorId, UpdatorId: &dto.CreatorId} res := r.db.Create(&stackTemplate) @@ -111,8 +115,16 @@ func (r *StackTemplateRepository) Update(dto domain.StackTemplate) (err error) { res := r.db.Model(&StackTemplate{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ - "Description": dto.Description, - "UpdatorId": dto.UpdatorId}) + "Template": dto.Template, + "TemplateType": dto.TemplateType, + "Version": dto.Version, + "CloudService": dto.CloudService, + "Platform": dto.Platform, + "KubeVersion": dto.KubeVersion, + "KubeType": dto.KubeType, + "Services": dto.Services, + "Description": dto.Description, + "UpdatorId": dto.UpdatorId}) if res.Error != nil { return res.Error } @@ -148,6 +160,7 @@ func reflectStackTemplate(stackTemplate StackTemplate) (out domain.StackTemplate if err := serializer.Map(stackTemplate, &out); err != nil { log.Error(err) } + out.Services = stackTemplate.Services return } diff --git a/internal/route/route.go b/internal/route/route.go index db4bceea..df6842c1 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -189,6 +189,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}/organizations", customMiddleware.Handle(internalApi.UpdateStackTemplateOrganizations, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplateOrganizations))).Methods(http.MethodPut) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 4f9284c2..2a258d16 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" @@ -19,7 +20,7 @@ type IStackTemplateUsecase interface { Create(ctx context.Context, dto domain.StackTemplate) (stackTemplate uuid.UUID, err error) Update(ctx context.Context, dto domain.StackTemplate) error Delete(ctx context.Context, dto domain.StackTemplate) error - UpdateOrganization(ctx context.Context, stackTemplateId uuid.UUID, organizationIds []string) error + UpdateOrganizations(ctx context.Context, dto domain.StackTemplate) error } type StackTemplateUsecase struct { @@ -39,24 +40,35 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTempl if !ok { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - dto.CreatorId = user.GetUserId() dto.UpdatorId = user.GetUserId() + + pg := pagination.NewPaginationWithFilter("name", "", "$eq", []string{dto.Name}) + stackTemplates, _ := u.Fetch(ctx, pg) + if len(stackTemplates) > 0 { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate stackTemplate name"), "ST_CREATE_ALREADY_EXISTED_NAME", "") + } + + services := "[" + for _, serviceId := range dto.ServiceIds { + switch serviceId { + case "LMA": + services = services + internal.SERVICE_LMA + "," + case "SERVICE_MESH": + services = services + internal.SERVICE_SERVICE_MESH + } + } + services = services + "]" + dto.Services = []byte(services) + stackTemplateId, err = u.repo.Create(dto) if err != nil { return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") } log.InfoWithContext(ctx, "newly created StackTemplate ID:", stackTemplateId) - organizations := make([]domain.Organization, 0) - for _, organizationId := range dto.OrganizationIds { - organization, err := u.organizationRepo.Get(organizationId) - if err == nil { - organizations = append(organizations, organization) - } - } - - err = u.repo.UpdateOrganizations(stackTemplateId, organizations) + dto.ID = stackTemplateId + err = u.UpdateOrganizations(ctx, dto) if err != nil { return uuid.Nil, err } @@ -65,11 +77,20 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTempl } func (u *StackTemplateUsecase) Update(ctx context.Context, dto domain.StackTemplate) error { + _, err := u.repo.Get(dto.ID) + if err != nil { + return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") + } + + err = u.repo.Update(dto) + if err != nil { + return err + } return nil } -func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplate uuid.UUID) (res domain.StackTemplate, err error) { - res, err = u.repo.Get(stackTemplate) +func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res domain.StackTemplate, err error) { + res, err = u.repo.Get(stackTemplateId) if err != nil { return domain.StackTemplate{}, err } @@ -88,6 +109,24 @@ func (u *StackTemplateUsecase) Delete(ctx context.Context, dto domain.StackTempl return nil } -func (u *StackTemplateUsecase) UpdateOrganization(ctx context.Context, stackTemplateId uuid.UUID, organizationIds []string) error { +func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto domain.StackTemplate) error { + _, err := u.repo.Get(dto.ID) + if err != nil { + return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") + } + + organizations := make([]domain.Organization, 0) + for _, organizationId := range dto.OrganizationIds { + organization, err := u.organizationRepo.Get(organizationId) + if err == nil { + organizations = append(organizations, organization) + } + } + + err = u.repo.UpdateOrganizations(dto.ID, organizations) + if err != nil { + return httpErrors.NewBadRequestError(err, "ST_FAILED_UPDATE_ORGANIZATION", "") + } + return nil } diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index 97be560a..13b6e9da 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -105,9 +105,21 @@ type CreateStackTemplateResponse struct { } type UpdateStackTemplateRequest struct { - Description string `json:"description"` + Description string `json:"description"` + Template string `json:"template"` + TemplateType string `json:"templateType"` + CloudService string `json:"cloudService"` + Version string `json:"version"` + Platform string `json:"platform"` + KubeVersion string `json:"kubeVersion"` + KubeType string `json:"kubeType"` + ServiceIds []string `json:"serviceIds" validate:"required"` } type GetStackTemplateServicesResponse struct { Services []StackTemplateServiceResponse `json:"services"` } + +type UpdateStackTemplateOrganizationsRequest struct { + OrganizationIds []string `json:"organizationIds" validate:"required"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index b43f22f8..3a7a7e30 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -77,6 +77,11 @@ var errorMap = map[ErrorCode]string{ "AG_NOT_FOUND_APPGROUP": "지장한 앱그룹이 존재하지 않습니다.", "AG_FAILED_TO_CREATE_APPGROUP": "앱그룹 생성에 실패하였습니다.", "AG_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패하였습니다.", + + // StackTemplate + "ST_CREATE_ALREADY_EXISTED_NAME": "스택 템플릿에 이미 존재하는 이름입니다.", + "ST_FAILED_UPDATE_ORGANIZATION": "스택 템플릿에 조직을 설정하는데 실패했습니다.", + "ST_NOT_EXISTED_STACK_TEMPLATE": "업데이트할 스택템플릿이 존재하지 않습니다.", } func (m ErrorCode) GetText() string { From 07a6413b894f69c834aa63dc13cd9ddef0c531a5 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 7 Mar 2024 17:28:36 +0900 Subject: [PATCH 104/502] feature. change api path for admin --- internal/delivery/api/endpoint.go | 13 +-- .../delivery/api/generated_endpoints.go.go | 80 ++++++++++--------- internal/route/route.go | 20 ++--- 3 files changed, 58 insertions(+), 55 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 152eaca4..e53bca40 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -95,12 +95,13 @@ const ( GetResourceQuota // StackTemplate - GetStackTemplates - CreateStackTemplate - GetStackTemplate - UpdateStackTemplate - DeleteStackTemplate - UpdateStackTemplateOrganizations + Admin_GetStackTemplates + Admin_GetStackTemplate + Admin_GetStackTemplateServices + Admin_CreateStackTemplate + Admin_UpdateStackTemplate + Admin_DeleteStackTemplate + Admin_UpdateStackTemplateOrganizations // Dashboard GetChartsDashboard // 대시보드/대시보드/조회 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index f0ae9089..ca6fb98c 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -275,28 +275,32 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetResourceQuota", Group: "CloudAccount", }, - GetStackTemplates: { - Name: "GetStackTemplates", + Admin_GetStackTemplates: { + Name: "Admin_GetStackTemplates", Group: "StackTemplate", }, - CreateStackTemplate: { - Name: "CreateStackTemplate", + Admin_GetStackTemplate: { + Name: "Admin_GetStackTemplate", Group: "StackTemplate", }, - GetStackTemplate: { - Name: "GetStackTemplate", + Admin_GetStackTemplateServices: { + Name: "Admin_GetStackTemplateServices", Group: "StackTemplate", }, - UpdateStackTemplate: { - Name: "UpdateStackTemplate", + Admin_CreateStackTemplate: { + Name: "Admin_CreateStackTemplate", Group: "StackTemplate", }, - DeleteStackTemplate: { - Name: "DeleteStackTemplate", + Admin_UpdateStackTemplate: { + Name: "Admin_UpdateStackTemplate", Group: "StackTemplate", }, - UpdateStackTemplateOrganizations: { - Name: "UpdateStackTemplateOrganizations", + Admin_DeleteStackTemplate: { + Name: "Admin_DeleteStackTemplate", + Group: "StackTemplate", + }, + Admin_UpdateStackTemplateOrganizations: { + Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, GetChartsDashboard: { @@ -690,18 +694,20 @@ func (e Endpoint) String() string { return "DeleteForceCloudAccount" case GetResourceQuota: return "GetResourceQuota" - case GetStackTemplates: - return "GetStackTemplates" - case CreateStackTemplate: - return "CreateStackTemplate" - case GetStackTemplate: - return "GetStackTemplate" - case UpdateStackTemplate: - return "UpdateStackTemplate" - case DeleteStackTemplate: - return "DeleteStackTemplate" - case UpdateStackTemplateOrganizations: - return "UpdateStackTemplateOrganizations" + case Admin_GetStackTemplates: + return "Admin_GetStackTemplates" + case Admin_GetStackTemplate: + return "Admin_GetStackTemplate" + case Admin_GetStackTemplateServices: + return "Admin_GetStackTemplateServices" + case Admin_CreateStackTemplate: + return "Admin_CreateStackTemplate" + case Admin_UpdateStackTemplate: + return "Admin_UpdateStackTemplate" + case Admin_DeleteStackTemplate: + return "Admin_DeleteStackTemplate" + case Admin_UpdateStackTemplateOrganizations: + return "Admin_UpdateStackTemplateOrganizations" case GetChartsDashboard: return "GetChartsDashboard" case GetChartDashboard: @@ -970,18 +976,20 @@ func GetEndpoint(name string) Endpoint { return DeleteForceCloudAccount case "GetResourceQuota": return GetResourceQuota - case "GetStackTemplates": - return GetStackTemplates - case "CreateStackTemplate": - return CreateStackTemplate - case "GetStackTemplate": - return GetStackTemplate - case "UpdateStackTemplate": - return UpdateStackTemplate - case "DeleteStackTemplate": - return DeleteStackTemplate - case "UpdateStackTemplateOrganizations": - return UpdateStackTemplateOrganizations + case "Admin_GetStackTemplates": + return Admin_GetStackTemplates + case "Admin_GetStackTemplate": + return Admin_GetStackTemplate + case "Admin_GetStackTemplateServices": + return Admin_GetStackTemplateServices + case "Admin_CreateStackTemplate": + return Admin_CreateStackTemplate + case "Admin_UpdateStackTemplate": + return Admin_UpdateStackTemplate + case "Admin_DeleteStackTemplate": + return Admin_DeleteStackTemplate + case "Admin_UpdateStackTemplateOrganizations": + return Admin_UpdateStackTemplateOrganizations case "GetChartsDashboard": return GetChartsDashboard case "GetChartDashboard": diff --git a/internal/route/route.go b/internal/route/route.go index df6842c1..98dce40b 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -178,19 +178,13 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/cloud-accounts/{cloudAccountId}/quotas", customMiddleware.Handle(internalApi.GetResourceQuota, http.HandlerFunc(cloudAccountHandler.GetResourceQuota))).Methods(http.MethodGet) stackTemplateHandler := delivery.NewStackTemplateHandler(usecaseFactory) - /* REMOVE START */ - r.Handle(API_PREFIX+API_VERSION+"/stack-templates", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates", customMiddleware.Handle(internalApi.CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetStackTemplate, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) - /* REMOVE END */ - - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}/organizations", customMiddleware.Handle(internalApi.UpdateStackTemplateOrganizations, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplateOrganizations))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}/organizations", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplateOrganizations, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplateOrganizations))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) From 98c7be88edb8c7b7539647c2a0d3782aa382985c Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sun, 10 Mar 2024 23:26:48 +0900 Subject: [PATCH 105/502] policy template admin api initial version --- api/swagger/docs.go | 1030 ++++++++++++++++- api/swagger/swagger.json | 1030 ++++++++++++++++- api/swagger/swagger.yaml | 635 ++++++++++ go.mod | 37 +- go.sum | 413 +------ internal/database/database.go | 9 + internal/delivery/api/endpoint.go | 54 + .../delivery/api/generated_endpoints.go.go | 344 ++++++ internal/delivery/http/policy-template.go | 647 +++++++++++ internal/delivery/http/utility.go | 73 ++ internal/repository/policy-template.go | 553 +++++++++ internal/repository/repository.go | 29 +- internal/route/route.go | 80 +- internal/usecase/policy-template.go | 228 ++++ internal/usecase/usecase.go | 32 +- internal/usecase/utility.go | 161 +++ pkg/domain/policy-template.go | 278 +++++ pkg/domain/rego.go | 25 + 18 files changed, 5156 insertions(+), 502 deletions(-) create mode 100644 internal/delivery/http/policy-template.go create mode 100644 internal/delivery/http/utility.go create mode 100644 internal/repository/policy-template.go create mode 100644 internal/usecase/policy-template.go create mode 100644 internal/usecase/utility.go create mode 100644 pkg/domain/policy-template.go create mode 100644 pkg/domain/rego.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 4d0948f0..47e43b6b 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -482,6 +482,529 @@ const docTemplate = `{ } } }, + "/api/1.0/admin/policytemplates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿을 신규 생성(v1.0.0을 생성)한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", + "parameters": [ + { + "description": "create policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 이름", + "name": "policyTemplateKind", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/name/{policyTemplateName}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 이름", + "name": "policyTemplateName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿을 삭제한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿의 업데이트 가능한 필드들을 업데이트한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "update policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}/deploy": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}/statistics": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}/versions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "create policy template version request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "조회할 버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "삭제할 버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/app-groups": { "get": { "security": [ @@ -6048,6 +6571,52 @@ const docTemplate = `{ } } } + }, + "/utility/rego-compile": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Rego" + ], + "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", + "parameters": [ + { + "type": "boolean", + "description": "파라미터 파싱 여부", + "name": "parseParameter", + "in": "query", + "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" + } + } + } + } } }, "definitions": { @@ -7296,51 +7865,169 @@ const docTemplate = `{ "tksInfraNode": { "type": "integer" }, - "tksInfraNodeMax": { - "type": "integer" + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { + "type": "object", + "required": [ + "Email", + "name" + ], + "properties": { + "Email": { + "type": "string" + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest": { + "type": "object", + "properties": { + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "kind": { + "type": "string", + "example": "K8sRequiredLabels" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "permittedOrganizationIds": { + "type": "array", + "items": { + "type": "string" + } }, - "tksInfraNodeType": { - "type": "string" + "rego": { + "type": "string", + "example": "rego 코드" }, - "tksUserNode": { - "type": "integer" + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" }, - "tksUserNodeMax": { - "type": "integer" + "target": { + "type": "string", + "example": "admission.k8s.gatekeeper.sh" }, - "tksUserNodeType": { - "type": "string" + "templateName": { + "type": "string", + "example": "필수 Label 검사" } } }, - "github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest": { "type": "object", "properties": { - "id": { - "type": "string" + "currentVersion": { + "type": "string", + "example": "v1.0.0" + }, + "expectedVersion": { + "type": "string", + "example": "v1.1.0" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "versionUpType": { + "type": "string", + "enum": [ + "major", + "minor", + "patch" + ], + "example": "minor" } } }, - "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse": { "type": "object", - "required": [ - "Email", - "name" - ], "properties": { - "Email": { - "type": "string" - }, - "description": { + "version": { "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" + "example": "v1.1.1" } } }, @@ -7746,6 +8433,9 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse": { + "type": "object" + }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -8107,6 +8797,33 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse": { + "type": "object", + "properties": { + "deployVersion": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse": { + "type": "object", + "properties": { + "policyTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse": { + "type": "object", + "properties": { + "policyTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse": { "type": "object", "properties": { @@ -8447,6 +9164,47 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "policyTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse": { + "type": "object", + "properties": { + "policyTemplateStatistics": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateStatistics" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse": { + "type": "object", + "properties": { + "versions": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "v1.1.0", + "v1.0.1", + "v1.0.0" + ] + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { "type": "object", "properties": { @@ -8653,6 +9411,29 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ParameterDef": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "defaultValue": { + "type": "string" + }, + "isArray": { + "type": "boolean" + }, + "key": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.Permission": { "type": "object", "properties": { @@ -8726,6 +9507,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization": { + "type": "object", + "properties": { + "organizationId": { + "type": "string" + }, + "organizationName": { + "type": "string" + }, + "permitted": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { "type": "object", "required": [ @@ -8752,6 +9547,103 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "kind": { + "type": "string", + "example": "K8sRequiredLabels" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "permittedOrganizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "type": { + "type": "string", + "enum": [ + "tks", + "organization" + ], + "example": "tks" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "version": { + "type": "string", + "example": "v1.0.1" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateStatistics": { + "type": "object", + "properties": { + "organizationId": { + "type": "string" + }, + "organizationName": { + "type": "string" + }, + "usageCount": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse": { "type": "object", "properties": { @@ -8990,6 +9882,53 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RegoCompieError": { + "type": "object", + "properties": { + "code": { + "type": "string", + "example": "P_INVALID_REGO_SYNTAX" + }, + "message": { + "type": "string", + "example": "Invalid rego syntax" + }, + "status": { + "type": "integer", + "example": 400 + }, + "text": { + "type": "string", + "example": "Rego 문법 에러입니다. 라인:2 컬럼:1 에러메시지: var testnum is not safe" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest": { + "type": "object", + "properties": { + "rego": { + "type": "string", + "example": "Rego 코드" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError" + } + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest": { "type": "object", "properties": { @@ -9734,6 +10673,37 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { + "type": "object", + "properties": { + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string" + }, + "permittedOrganizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 855a8c0f..42ee1952 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -476,6 +476,529 @@ } } }, + "/api/1.0/admin/policytemplates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿을 신규 생성(v1.0.0을 생성)한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", + "parameters": [ + { + "description": "create policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 이름", + "name": "policyTemplateKind", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/name/{policyTemplateName}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 이름", + "name": "policyTemplateName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿을 삭제한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿의 업데이트 가능한 필드들을 업데이트한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "update policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}/deploy": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}/statistics": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}/versions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "create policy template version request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" + } + } + } + } + }, + "/api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "조회할 버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "삭제할 버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/app-groups": { "get": { "security": [ @@ -6042,6 +6565,52 @@ } } } + }, + "/utility/rego-compile": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Rego" + ], + "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", + "parameters": [ + { + "type": "boolean", + "description": "파라미터 파싱 여부", + "name": "parseParameter", + "in": "query", + "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" + } + } + } + } } }, "definitions": { @@ -7290,51 +7859,169 @@ "tksInfraNode": { "type": "integer" }, - "tksInfraNodeMax": { - "type": "integer" + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { + "type": "object", + "required": [ + "Email", + "name" + ], + "properties": { + "Email": { + "type": "string" + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest": { + "type": "object", + "properties": { + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "kind": { + "type": "string", + "example": "K8sRequiredLabels" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "permittedOrganizationIds": { + "type": "array", + "items": { + "type": "string" + } }, - "tksInfraNodeType": { - "type": "string" + "rego": { + "type": "string", + "example": "rego 코드" }, - "tksUserNode": { - "type": "integer" + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" }, - "tksUserNodeMax": { - "type": "integer" + "target": { + "type": "string", + "example": "admission.k8s.gatekeeper.sh" }, - "tksUserNodeType": { - "type": "string" + "templateName": { + "type": "string", + "example": "필수 Label 검사" } } }, - "github_com_openinfradev_tks-api_pkg_domain.CreateClusterResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest": { "type": "object", "properties": { - "id": { - "type": "string" + "currentVersion": { + "type": "string", + "example": "v1.0.0" + }, + "expectedVersion": { + "type": "string", + "example": "v1.1.0" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "versionUpType": { + "type": "string", + "enum": [ + "major", + "minor", + "patch" + ], + "example": "minor" } } }, - "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse": { "type": "object", - "required": [ - "Email", - "name" - ], "properties": { - "Email": { - "type": "string" - }, - "description": { + "version": { "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" + "example": "v1.1.1" } } }, @@ -7740,6 +8427,9 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse": { + "type": "object" + }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -8101,6 +8791,33 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse": { + "type": "object", + "properties": { + "deployVersion": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse": { + "type": "object", + "properties": { + "policyTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse": { + "type": "object", + "properties": { + "policyTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse": { "type": "object", "properties": { @@ -8441,6 +9158,47 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "policyTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse": { + "type": "object", + "properties": { + "policyTemplateStatistics": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateStatistics" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse": { + "type": "object", + "properties": { + "versions": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "v1.1.0", + "v1.0.1", + "v1.0.0" + ] + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { "type": "object", "properties": { @@ -8647,6 +9405,29 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ParameterDef": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "defaultValue": { + "type": "string" + }, + "isArray": { + "type": "boolean" + }, + "key": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.Permission": { "type": "object", "properties": { @@ -8720,6 +9501,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization": { + "type": "object", + "properties": { + "organizationId": { + "type": "string" + }, + "organizationName": { + "type": "string" + }, + "permitted": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { "type": "object", "required": [ @@ -8746,6 +9541,103 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "kind": { + "type": "string", + "example": "K8sRequiredLabels" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "permittedOrganizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "type": { + "type": "string", + "enum": [ + "tks", + "organization" + ], + "example": "tks" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "version": { + "type": "string", + "example": "v1.0.1" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateStatistics": { + "type": "object", + "properties": { + "organizationId": { + "type": "string" + }, + "organizationName": { + "type": "string" + }, + "usageCount": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse": { "type": "object", "properties": { @@ -8984,6 +9876,53 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RegoCompieError": { + "type": "object", + "properties": { + "code": { + "type": "string", + "example": "P_INVALID_REGO_SYNTAX" + }, + "message": { + "type": "string", + "example": "Invalid rego syntax" + }, + "status": { + "type": "integer", + "example": 400 + }, + "text": { + "type": "string", + "example": "Rego 문법 에러입니다. 라인:2 컬럼:1 에러메시지: var testnum is not safe" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest": { + "type": "object", + "properties": { + "rego": { + "type": "string", + "example": "Rego 코드" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError" + } + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest": { "type": "object", "properties": { @@ -9728,6 +10667,37 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { + "type": "object", + "properties": { + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string" + }, + "permittedOrganizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 6c544727..0f3906d9 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -892,6 +892,89 @@ definitions: - Email - name type: object + github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse: + properties: + id: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest: + properties: + deprecated: + example: false + type: boolean + description: + example: 이 정책은 ... + type: string + kind: + example: K8sRequiredLabels + type: string + libs: + example: + - rego 코드 + items: + type: string + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + permittedOrganizationIds: + items: + type: string + type: array + rego: + example: rego 코드 + type: string + severity: + enum: + - low + - medium + - high + example: medium + type: string + target: + example: admission.k8s.gatekeeper.sh + type: string + templateName: + example: 필수 Label 검사 + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest: + properties: + currentVersion: + example: v1.0.0 + type: string + expectedVersion: + example: v1.1.0 + type: string + libs: + example: + - rego 코드 + items: + type: string + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + rego: + example: rego 코드 + type: string + versionUpType: + enum: + - major + - minor + - patch + example: minor + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse: + properties: + version: + example: v1.1.1 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest: properties: description: @@ -1164,6 +1247,8 @@ definitions: name: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse: + type: object github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: column: @@ -1398,6 +1483,23 @@ definitions: type: string type: object type: object + github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse: + properties: + deployVersion: + additionalProperties: + type: string + type: object + type: object + github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse: + properties: + policyTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse' + type: object + github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse: + properties: + policyTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse: properties: kubeconfig: @@ -1617,6 +1719,33 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + policyTemplates: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse: + properties: + policyTemplateStatistics: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateStatistics' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse: + properties: + versions: + example: + - v1.1.0 + - v1.0.1 + - v1.0.0 + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse: properties: pagination: @@ -1757,6 +1886,21 @@ definitions: totalRows: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.ParameterDef: + properties: + children: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + defaultValue: + type: string + isArray: + type: boolean + key: + type: string + type: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.Permission: properties: ID: @@ -1805,6 +1949,15 @@ definitions: stack: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' type: object + github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization: + properties: + organizationId: + type: string + organizationName: + type: string + permitted: + type: boolean + type: object github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest: properties: organizationId: @@ -1822,6 +1975,74 @@ definitions: value: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse: + properties: + createdAt: + type: string + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + deprecated: + example: false + type: boolean + description: + example: 이 정책은 ... + type: string + id: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + kind: + example: K8sRequiredLabels + type: string + libs: + example: + - rego 코드 + items: + type: string + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + permittedOrganizations: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization' + type: array + rego: + example: rego 코드 + type: string + severity: + enum: + - low + - medium + - high + example: medium + type: string + templateName: + example: 필수 Label 검사 + type: string + type: + enum: + - tks + - organization + example: tks + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + version: + example: v1.0.1 + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateStatistics: + properties: + organizationId: + type: string + organizationName: + type: string + usageCount: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse: properties: createdAt: @@ -1982,6 +2203,38 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.RegoCompieError: + properties: + code: + example: P_INVALID_REGO_SYNTAX + type: string + message: + example: Invalid rego syntax + type: string + status: + example: 400 + type: integer + text: + example: 'Rego 문법 에러입니다. 라인:2 컬럼:1 에러메시지: var testnum is not safe' + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest: + properties: + rego: + example: Rego 코드 + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse: + properties: + errors: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError' + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest: properties: projectMembers: @@ -2473,6 +2726,28 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest: + properties: + deprecated: + example: false + type: boolean + description: + type: string + permittedOrganizationIds: + items: + type: string + type: array + severity: + enum: + - low + - medium + - high + example: medium + type: string + templateName: + example: 필수 Label 검사 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest: properties: primaryClusterId: @@ -3080,6 +3355,336 @@ paths: summary: Get GetStackTemplateServices tags: - StackTemplates + /api/1.0/admin/policytemplates: + get: + consumes: + - application/json + description: 정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다. + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse' + security: + - JWT: [] + summary: '[ListPolicyTemplate] 정책 템플릿 목록 조회' + tags: + - PolicyTemplate + post: + consumes: + - application/json + description: 정책 템플릿을 신규 생성(v1.0.0을 생성)한다. + parameters: + - description: create policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse' + security: + - JWT: [] + summary: '[CreatePolicyTemplate] 정책 템플릿 신규 생성' + tags: + - PolicyTemplate + /api/1.0/admin/policytemplates/{policyTemplateId}: + delete: + consumes: + - application/json + description: 정책 템플릿을 삭제한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[DeletePolicyTemplate] 정책 템플릿 삭제' + tags: + - PolicyTemplate + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse' + security: + - JWT: [] + summary: '[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)' + tags: + - PolicyTemplate + patch: + consumes: + - application/json + description: 정책 템플릿의 업데이트 가능한 필드들을 업데이트한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: update policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[UpdatePolicyTemplate] 정책 템플릿 업데이트' + tags: + - PolicyTemplate + /api/1.0/admin/policytemplates/{policyTemplateId}/deploy: + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse' + security: + - JWT: [] + summary: '[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회' + tags: + - PolicyTemplate + /api/1.0/admin/policytemplates/{policyTemplateId}/statistics: + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 + tks로 설정한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse' + security: + - JWT: [] + summary: '[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회' + tags: + - PolicyTemplate + /api/1.0/admin/policytemplates/{policyTemplateId}/versions: + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse' + security: + - JWT: [] + summary: '[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회' + tags: + - PolicyTemplate + post: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: create policy template version request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse' + security: + - JWT: [] + summary: '[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장' + tags: + - PolicyTemplate + /api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version}: + delete: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: 삭제할 버전(v0.0.0 형식) + in: path + name: version + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제' + tags: + - PolicyTemplate + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: 조회할 버전(v0.0.0 형식) + in: path + name: version + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse' + security: + - JWT: [] + summary: '[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' + tags: + - PolicyTemplate + /api/1.0/admin/policytemplates/kind/{policyTemplateKind}/existence: + get: + consumes: + - application/json + description: 해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다. + parameters: + - description: 정책 템플릿 이름 + in: path + name: policyTemplateKind + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse' + security: + - JWT: [] + summary: '[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인' + tags: + - PolicyTemplate + /api/1.0/admin/policytemplates/name/{policyTemplateName}/existence: + get: + consumes: + - application/json + description: 해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다. + parameters: + - description: 정책 템플릿 이름 + in: path + name: policyTemplateName + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' + security: + - JWT: [] + summary: '[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인' + tags: + - PolicyTemplate /app-groups: delete: consumes: @@ -6651,6 +7256,36 @@ paths: summary: Create alert. ADMIN ONLY tags: - Alerts + /utility/rego-compile: + post: + consumes: + - application/json + description: Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 + false로 하면 컴파일만 수행할 수 있다. + parameters: + - description: 파라미터 파싱 여부 + in: query + name: parseParameter + required: true + type: boolean + - description: Rego 코드 + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse' + security: + - JWT: [] + summary: '[CompileRego] Rego 코드 컴파일 및 파라미터 파싱' + tags: + - Rego securityDefinitions: JWT: in: header diff --git a/go.mod b/go.mod index 0674b4e6..4f2e46d4 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/openinfradev/tks-api go 1.21 require ( + github.com/Masterminds/semver/v3 v3.2.0 github.com/Nerzal/gocloak/v13 v13.9.0 github.com/aws/aws-sdk-go-v2 v1.25.0 github.com/aws/aws-sdk-go-v2/config v1.27.0 @@ -24,6 +25,7 @@ require ( github.com/gorilla/handlers v1.5.2 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 + github.com/open-policy-agent/opa v0.62.1 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 @@ -34,8 +36,8 @@ require ( github.com/swaggo/swag v1.16.3 github.com/thoas/go-funk v0.9.3 github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0 - golang.org/x/crypto v0.19.0 - golang.org/x/net v0.21.0 + golang.org/x/crypto v0.21.0 + golang.org/x/net v0.22.0 golang.org/x/oauth2 v0.17.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 @@ -52,6 +54,7 @@ require ( require ( github.com/Code-Hex/uniseg v0.2.0 // indirect github.com/KyleBanks/depth v1.2.1 // indirect + github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 // indirect @@ -63,14 +66,14 @@ require ( github.com/aws/smithy-go v1.20.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/spec v0.20.6 // indirect @@ -82,7 +85,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.15 // indirect @@ -97,17 +100,17 @@ require ( github.com/leodido/go-urn v1.4.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.14.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/segmentio/ksuid v1.0.4 // indirect @@ -117,17 +120,19 @@ require ( github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/term v0.17.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/tools v0.15.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -141,7 +146,7 @@ require ( sigs.k8s.io/controller-runtime v0.14.5 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace github.com/openinfradev/tks-api => ./ diff --git a/go.sum b/go.sum index fc216539..99f38a76 100644 --- a/go.sum +++ b/go.sum @@ -1,50 +1,17 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Code-Hex/uniseg v0.2.0 h1:QB/2UJFvEuRLSZqe+Sb1XQBTWjqGVbZoC6oSWzQRKws= github.com/Code-Hex/uniseg v0.2.0/go.mod h1:/ndS2tP+X1lk2HUOcXWGtVTxVq0lWilwgMa4CbzdRsg= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Nerzal/gocloak/v13 v13.9.0 h1:YWsJsdM5b0yhM2Ba3MLydiOlujkBry4TtdzfIzSVZhw= github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpKDj8d6GuyM10= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= +github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aws/aws-sdk-go-v2 v1.25.0 h1:sv7+1JVJxOu/dD/sz/csHX7jFqmP001TIY7aytBWDSQ= github.com/aws/aws-sdk-go-v2 v1.25.0/go.mod h1:G104G1Aho5WqF+SR3mDIobTABQzpYV0WxMsKxlMggOA= @@ -84,8 +51,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 h1:cjTRjh700H36MQ8M0LnDn33W3Jmw github.com/aws/aws-sdk-go-v2/service/sts v1.27.0/go.mod h1:nXfOBMWPokIbOY+Gi7a1psWMSvskUCemZzI+SMB7Akc= github.com/aws/smithy-go v1.20.0 h1:6+kZsCXZwKxZS9RfISnPc4EXlHoyAkm2hPuM8X2BrrQ= github.com/aws/smithy-go v1.20.0/go.mod h1:uo5RKksAl4PzhqaAbjd4rLgFoq5koTsQKYuGe7dklGc= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= @@ -93,12 +58,8 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -124,8 +85,8 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= @@ -134,20 +95,9 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -174,12 +124,10 @@ github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSM github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= @@ -191,26 +139,15 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2V github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -223,41 +160,25 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -265,11 +186,8 @@ github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWS github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -289,21 +207,10 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -323,9 +230,6 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microsoft/go-mssqldb v0.21.0 h1:p2rpHIL7TlSv1QrbXJUAcbyRKnIT0C9rRkH2E4OjLn8= github.com/microsoft/go-mssqldb v0.21.0/go.mod h1:+4wZTUnz/SV6nffv+RRRB/ss8jPng5Sho2SmM1l2ts4= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -333,71 +237,49 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/gomega v1.27.5 h1:T/X6I0RNFw/kTqgfkZPcQ5KU6vCnWNBGdtrIx2dpGeQ= github.com/onsi/gomega v1.27.5/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/open-policy-agent/opa v0.62.1 h1:UcxBQ0fe6NEjkYc775j4PWoUFFhx4f6yXKIKSTAuTVk= +github.com/open-policy-agent/opa v0.62.1/go.mod h1:YqiSIIuvKwyomtnnXkJvy0E3KtVKbavjPJ/hNMuOmeM= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -413,10 +295,8 @@ github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -439,18 +319,14 @@ github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xz github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0 h1:BBu+4LBAa6kMzOwhA5hchMa8NVW2JlyUMldoRrcd67g= github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0/go.mod h1:4N15SpYBrqBFtblYzwp3RkRXVYlT69UZIZKbpU96FTQ= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -460,287 +336,103 @@ go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= @@ -752,14 +444,12 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -768,20 +458,15 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -804,12 +489,7 @@ gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= goyave.dev/goyave/v4 v4.4.11 h1:HdJJ82ZWrkB7sBsituVRgQhcDvmAavfVbd6xynaUN8Y= goyave.dev/goyave/v4 v4.4.11/go.mod h1:kMbB3bf7ZhUD4Cq1Zy6nM4fHBHYO5mPSkTF6WStf4ik= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= @@ -828,9 +508,6 @@ k8s.io/kubectl v0.25.2 h1:2993lTeVimxKSWx/7z2PiJxUILygRa3tmC4QhFaeioA= k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg= k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/cluster-api v1.4.4 h1:+V+mzDe+gsWYclosvWlH0wadC8vIUsBvZLcWOYnVWRA= sigs.k8s.io/cluster-api v1.4.4/go.mod h1:/SeFds4NXJ+Gp2etqHyoNuO6yoxTfVq6Zmd2OGxd/qM= sigs.k8s.io/controller-runtime v0.14.5 h1:6xaWFqzT5KuAQ9ufgUaj1G/+C4Y1GRkhrxl+BJ9i+5s= @@ -839,5 +516,5 @@ sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/internal/database/database.go b/internal/database/database.go index 2e9ad696..1fd29171 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -186,5 +186,14 @@ func EnsureDefaultRows(db *gorm.DB) error { return err } + // PolicyTemplate + if err := db.AutoMigrate(&repository.PolicyTemplateSupportedVersion{}); err != nil { + return err + } + + if err := db.AutoMigrate(&repository.PolicyTemplate{}); err != nil { + return err + } + return nil } diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index e53bca40..9d7c0966 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -185,4 +185,58 @@ const ( // Admin Project Admin_GetProjects + // PolicyTemplate + ListPolicyTemplate + CreatePolicyTemplate + DeletePolicyTemplate + GetPolicyTemplate + UpdatePolicyTemplate + GetPolicyTemplateDeploy + ListPolicyTemplateStatistics + ListPolicyTemplateVersions + CreatePolicyTemplateVersion + DeletePolicyTemplateVersion + GetPolicyTemplateVersion + ExistsPolicyTemplateKind + ExistsPolicyTemplateName + + // ClusterPolicyStatus + ListClusterPolicyStatus + GetClusterPolicyTemplateStatus + UpdateClusterPolicyTemplateStatus + + // Policy + GetMandatoryPolicies + SetMandatoryPolicies + ListPolicy + CreatePolicy + DeletePolicy + GetPolicy + UpdatePolicy + UpdatePolicyTargetClusters + ExistsPolicyName + + // OrganizationPolicyTemplate + ListOrganizationPolicyTemplate + CreateOrganizationPolicyTemplate + DeleteOrganizationPolicyTemplate + GetOrganizationPolicyTemplate + UpdateOrganizationPolicyTemplate + GetOrganizationPolicyTemplateDeploy + ListOrganizationPolicyTemplateStatistics + ListOrganizationPolicyTemplateVersions + CreateOrganizationPolicyTemplateVersion + DeleteOrganizationPolicyTemplateVersion + GetOrganizationPolicyTemplateVersion + ExistsOrganizationPolicyTemplateKind + ExistsOrganizationPolicyTemplateName + + // PolicyTemplateExample + ListPolicyTemplateExample + GetPolicyTemplateExample + UpdatePolicyTemplateExample + DeletePolicyTemplateExample + + // Utility + CompileRego ) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index ca6fb98c..aeea2305 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -555,6 +555,178 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_GetProjects", Group: "Admin Project", }, + ListPolicyTemplate: { + Name: "ListPolicyTemplate", + Group: "PolicyTemplate", + }, + CreatePolicyTemplate: { + Name: "CreatePolicyTemplate", + Group: "PolicyTemplate", + }, + DeletePolicyTemplate: { + Name: "DeletePolicyTemplate", + Group: "PolicyTemplate", + }, + GetPolicyTemplate: { + Name: "GetPolicyTemplate", + Group: "PolicyTemplate", + }, + UpdatePolicyTemplate: { + Name: "UpdatePolicyTemplate", + Group: "PolicyTemplate", + }, + GetPolicyTemplateDeploy: { + Name: "GetPolicyTemplateDeploy", + Group: "PolicyTemplate", + }, + ListPolicyTemplateStatistics: { + Name: "ListPolicyTemplateStatistics", + Group: "PolicyTemplate", + }, + ListPolicyTemplateVersions: { + Name: "ListPolicyTemplateVersions", + Group: "PolicyTemplate", + }, + CreatePolicyTemplateVersion: { + Name: "CreatePolicyTemplateVersion", + Group: "PolicyTemplate", + }, + DeletePolicyTemplateVersion: { + Name: "DeletePolicyTemplateVersion", + Group: "PolicyTemplate", + }, + GetPolicyTemplateVersion: { + Name: "GetPolicyTemplateVersion", + Group: "PolicyTemplate", + }, + ExistsPolicyTemplateKind: { + Name: "ExistsPolicyTemplateKind", + Group: "PolicyTemplate", + }, + ExistsPolicyTemplateName: { + Name: "ExistsPolicyTemplateName", + Group: "PolicyTemplate", + }, + ListClusterPolicyStatus: { + Name: "ListClusterPolicyStatus", + Group: "ClusterPolicyStatus", + }, + GetClusterPolicyTemplateStatus: { + Name: "GetClusterPolicyTemplateStatus", + Group: "ClusterPolicyStatus", + }, + UpdateClusterPolicyTemplateStatus: { + Name: "UpdateClusterPolicyTemplateStatus", + Group: "ClusterPolicyStatus", + }, + GetMandatoryPolicies: { + Name: "GetMandatoryPolicies", + Group: "Policy", + }, + SetMandatoryPolicies: { + Name: "SetMandatoryPolicies", + Group: "Policy", + }, + ListPolicy: { + Name: "ListPolicy", + Group: "Policy", + }, + CreatePolicy: { + Name: "CreatePolicy", + Group: "Policy", + }, + DeletePolicy: { + Name: "DeletePolicy", + Group: "Policy", + }, + GetPolicy: { + Name: "GetPolicy", + Group: "Policy", + }, + UpdatePolicy: { + Name: "UpdatePolicy", + Group: "Policy", + }, + UpdatePolicyTargetClusters: { + Name: "UpdatePolicyTargetClusters", + Group: "Policy", + }, + ExistsPolicyName: { + Name: "ExistsPolicyName", + Group: "Policy", + }, + ListOrganizationPolicyTemplate: { + Name: "ListOrganizationPolicyTemplate", + Group: "OrganizationPolicyTemplate", + }, + CreateOrganizationPolicyTemplate: { + Name: "CreateOrganizationPolicyTemplate", + Group: "OrganizationPolicyTemplate", + }, + DeleteOrganizationPolicyTemplate: { + Name: "DeleteOrganizationPolicyTemplate", + Group: "OrganizationPolicyTemplate", + }, + GetOrganizationPolicyTemplate: { + Name: "GetOrganizationPolicyTemplate", + Group: "OrganizationPolicyTemplate", + }, + UpdateOrganizationPolicyTemplate: { + Name: "UpdateOrganizationPolicyTemplate", + Group: "OrganizationPolicyTemplate", + }, + GetOrganizationPolicyTemplateDeploy: { + Name: "GetOrganizationPolicyTemplateDeploy", + Group: "OrganizationPolicyTemplate", + }, + ListOrganizationPolicyTemplateStatistics: { + Name: "ListOrganizationPolicyTemplateStatistics", + Group: "OrganizationPolicyTemplate", + }, + ListOrganizationPolicyTemplateVersions: { + Name: "ListOrganizationPolicyTemplateVersions", + Group: "OrganizationPolicyTemplate", + }, + CreateOrganizationPolicyTemplateVersion: { + Name: "CreateOrganizationPolicyTemplateVersion", + Group: "OrganizationPolicyTemplate", + }, + DeleteOrganizationPolicyTemplateVersion: { + Name: "DeleteOrganizationPolicyTemplateVersion", + Group: "OrganizationPolicyTemplate", + }, + GetOrganizationPolicyTemplateVersion: { + Name: "GetOrganizationPolicyTemplateVersion", + Group: "OrganizationPolicyTemplate", + }, + ExistsOrganizationPolicyTemplateKind: { + Name: "ExistsOrganizationPolicyTemplateKind", + Group: "OrganizationPolicyTemplate", + }, + ExistsOrganizationPolicyTemplateName: { + Name: "ExistsOrganizationPolicyTemplateName", + Group: "OrganizationPolicyTemplate", + }, + ListPolicyTemplateExample: { + Name: "ListPolicyTemplateExample", + Group: "PolicyTemplateExample", + }, + GetPolicyTemplateExample: { + Name: "GetPolicyTemplateExample", + Group: "PolicyTemplateExample", + }, + UpdatePolicyTemplateExample: { + Name: "UpdatePolicyTemplateExample", + Group: "PolicyTemplateExample", + }, + DeletePolicyTemplateExample: { + Name: "DeletePolicyTemplateExample", + Group: "PolicyTemplateExample", + }, + CompileRego: { + Name: "CompileRego", + Group: "Utility", + }, } func (e Endpoint) String() string { switch e { @@ -834,6 +1006,92 @@ func (e Endpoint) String() string { return "Admin_GetTksRole" case Admin_GetProjects: return "Admin_GetProjects" + case ListPolicyTemplate: + return "ListPolicyTemplate" + case CreatePolicyTemplate: + return "CreatePolicyTemplate" + case DeletePolicyTemplate: + return "DeletePolicyTemplate" + case GetPolicyTemplate: + return "GetPolicyTemplate" + case UpdatePolicyTemplate: + return "UpdatePolicyTemplate" + case GetPolicyTemplateDeploy: + return "GetPolicyTemplateDeploy" + case ListPolicyTemplateStatistics: + return "ListPolicyTemplateStatistics" + case ListPolicyTemplateVersions: + return "ListPolicyTemplateVersions" + case CreatePolicyTemplateVersion: + return "CreatePolicyTemplateVersion" + case DeletePolicyTemplateVersion: + return "DeletePolicyTemplateVersion" + case GetPolicyTemplateVersion: + return "GetPolicyTemplateVersion" + case ExistsPolicyTemplateKind: + return "ExistsPolicyTemplateKind" + case ExistsPolicyTemplateName: + return "ExistsPolicyTemplateName" + case ListClusterPolicyStatus: + return "ListClusterPolicyStatus" + case GetClusterPolicyTemplateStatus: + return "GetClusterPolicyTemplateStatus" + case UpdateClusterPolicyTemplateStatus: + return "UpdateClusterPolicyTemplateStatus" + case GetMandatoryPolicies: + return "GetMandatoryPolicies" + case SetMandatoryPolicies: + return "SetMandatoryPolicies" + case ListPolicy: + return "ListPolicy" + case CreatePolicy: + return "CreatePolicy" + case DeletePolicy: + return "DeletePolicy" + case GetPolicy: + return "GetPolicy" + case UpdatePolicy: + return "UpdatePolicy" + case UpdatePolicyTargetClusters: + return "UpdatePolicyTargetClusters" + case ExistsPolicyName: + return "ExistsPolicyName" + case ListOrganizationPolicyTemplate: + return "ListOrganizationPolicyTemplate" + case CreateOrganizationPolicyTemplate: + return "CreateOrganizationPolicyTemplate" + case DeleteOrganizationPolicyTemplate: + return "DeleteOrganizationPolicyTemplate" + case GetOrganizationPolicyTemplate: + return "GetOrganizationPolicyTemplate" + case UpdateOrganizationPolicyTemplate: + return "UpdateOrganizationPolicyTemplate" + case GetOrganizationPolicyTemplateDeploy: + return "GetOrganizationPolicyTemplateDeploy" + case ListOrganizationPolicyTemplateStatistics: + return "ListOrganizationPolicyTemplateStatistics" + case ListOrganizationPolicyTemplateVersions: + return "ListOrganizationPolicyTemplateVersions" + case CreateOrganizationPolicyTemplateVersion: + return "CreateOrganizationPolicyTemplateVersion" + case DeleteOrganizationPolicyTemplateVersion: + return "DeleteOrganizationPolicyTemplateVersion" + case GetOrganizationPolicyTemplateVersion: + return "GetOrganizationPolicyTemplateVersion" + case ExistsOrganizationPolicyTemplateKind: + return "ExistsOrganizationPolicyTemplateKind" + case ExistsOrganizationPolicyTemplateName: + return "ExistsOrganizationPolicyTemplateName" + case ListPolicyTemplateExample: + return "ListPolicyTemplateExample" + case GetPolicyTemplateExample: + return "GetPolicyTemplateExample" + case UpdatePolicyTemplateExample: + return "UpdatePolicyTemplateExample" + case DeletePolicyTemplateExample: + return "DeletePolicyTemplateExample" + case CompileRego: + return "CompileRego" default: return "" } @@ -1116,6 +1374,92 @@ func GetEndpoint(name string) Endpoint { return Admin_GetTksRole case "Admin_GetProjects": return Admin_GetProjects + case "ListPolicyTemplate": + return ListPolicyTemplate + case "CreatePolicyTemplate": + return CreatePolicyTemplate + case "DeletePolicyTemplate": + return DeletePolicyTemplate + case "GetPolicyTemplate": + return GetPolicyTemplate + case "UpdatePolicyTemplate": + return UpdatePolicyTemplate + case "GetPolicyTemplateDeploy": + return GetPolicyTemplateDeploy + case "ListPolicyTemplateStatistics": + return ListPolicyTemplateStatistics + case "ListPolicyTemplateVersions": + return ListPolicyTemplateVersions + case "CreatePolicyTemplateVersion": + return CreatePolicyTemplateVersion + case "DeletePolicyTemplateVersion": + return DeletePolicyTemplateVersion + case "GetPolicyTemplateVersion": + return GetPolicyTemplateVersion + case "ExistsPolicyTemplateKind": + return ExistsPolicyTemplateKind + case "ExistsPolicyTemplateName": + return ExistsPolicyTemplateName + case "ListClusterPolicyStatus": + return ListClusterPolicyStatus + case "GetClusterPolicyTemplateStatus": + return GetClusterPolicyTemplateStatus + case "UpdateClusterPolicyTemplateStatus": + return UpdateClusterPolicyTemplateStatus + case "GetMandatoryPolicies": + return GetMandatoryPolicies + case "SetMandatoryPolicies": + return SetMandatoryPolicies + case "ListPolicy": + return ListPolicy + case "CreatePolicy": + return CreatePolicy + case "DeletePolicy": + return DeletePolicy + case "GetPolicy": + return GetPolicy + case "UpdatePolicy": + return UpdatePolicy + case "UpdatePolicyTargetClusters": + return UpdatePolicyTargetClusters + case "ExistsPolicyName": + return ExistsPolicyName + case "ListOrganizationPolicyTemplate": + return ListOrganizationPolicyTemplate + case "CreateOrganizationPolicyTemplate": + return CreateOrganizationPolicyTemplate + case "DeleteOrganizationPolicyTemplate": + return DeleteOrganizationPolicyTemplate + case "GetOrganizationPolicyTemplate": + return GetOrganizationPolicyTemplate + case "UpdateOrganizationPolicyTemplate": + return UpdateOrganizationPolicyTemplate + case "GetOrganizationPolicyTemplateDeploy": + return GetOrganizationPolicyTemplateDeploy + case "ListOrganizationPolicyTemplateStatistics": + return ListOrganizationPolicyTemplateStatistics + case "ListOrganizationPolicyTemplateVersions": + return ListOrganizationPolicyTemplateVersions + case "CreateOrganizationPolicyTemplateVersion": + return CreateOrganizationPolicyTemplateVersion + case "DeleteOrganizationPolicyTemplateVersion": + return DeleteOrganizationPolicyTemplateVersion + case "GetOrganizationPolicyTemplateVersion": + return GetOrganizationPolicyTemplateVersion + case "ExistsOrganizationPolicyTemplateKind": + return ExistsOrganizationPolicyTemplateKind + case "ExistsOrganizationPolicyTemplateName": + return ExistsOrganizationPolicyTemplateName + case "ListPolicyTemplateExample": + return ListPolicyTemplateExample + case "GetPolicyTemplateExample": + return GetPolicyTemplateExample + case "UpdatePolicyTemplateExample": + return UpdatePolicyTemplateExample + case "DeletePolicyTemplateExample": + return DeletePolicyTemplateExample + case "CompileRego": + return CompileRego default: return -1 } diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go new file mode 100644 index 00000000..3206545c --- /dev/null +++ b/internal/delivery/http/policy-template.go @@ -0,0 +1,647 @@ +package http + +import ( + "fmt" + "net/http" + "strings" + + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + + "github.com/Masterminds/semver/v3" +) + +type PolicyTemplateHandler struct { + usecase usecase.IPolicyTemplateUsecase +} + +type IPolicyTemplateHandler interface { + CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) + UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) + DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) + GetPolicyTemplate(w http.ResponseWriter, r *http.Request) + ListPolicyTemplate(w http.ResponseWriter, r *http.Request) + ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) + ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) + ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) + GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) + CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) +} + +func NewPolicyTemplateHandler(u usecase.Usecase) IPolicyTemplateHandler { + return &PolicyTemplateHandler{ + usecase: u.PolicyTemplate, + } +} + +// CreatePolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [CreatePolicyTemplate] 정책 템플릿 신규 생성 +// @Description 정책 템플릿을 신규 생성(v1.0.0을 생성)한다. +// @Accept json +// @Produce json +// @Param body body domain.CreatePolicyTemplateRequest true "create policy template request" +// @Success 200 {object} domain.CreatePolicyTemplateReponse +// @Router /api/1.0/admin/policytemplates [post] +// @Security JWT +func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) { + input := domain.CreatePolicyTemplateRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + var dto domain.PolicyTemplate + if err = serializer.Map(input, &dto); err != nil { + log.InfoWithContext(r.Context(), err) + } + + policyTemplateId, err := h.usecase.Create(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CreatePolicyTemplateReponse + out.ID = domain.PolicyTemplateId(policyTemplateId) + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdatePolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [UpdatePolicyTemplate] 정책 템플릿 업데이트 +// @Description 정책 템플릿의 업데이트 가능한 필드들을 업데이트한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param body body domain.UpdatePolicyTemplateRequest true "update policy template request" +// @Success 200 {object} nil +// @Router /api/1.0/admin/policytemplates/{policyTemplateId} [patch] +// @Security JWT +func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + input := domain.UpdatePolicyTemplateRequest{} + + err = UnmarshalRequestInput(r, &input) + + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + err = h.usecase.Update(r.Context(), id, input) + + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, "") +} + +// DeletePolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [DeletePolicyTemplate] 정책 템플릿 삭제 +// @Description 정책 템플릿을 삭제한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} nil +// @Router /api/1.0/admin/policytemplates/{policyTemplateId} [delete] +// @Security JWT +func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + err = h.usecase.Delete(r.Context(), id) + + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, "") +} + +// GetPolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [GetPolicyTemplate] 정책 템플릿 조회(최신 버전) +// @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.GetPolicyTemplateResponse +// @Router /api/1.0/admin/policytemplates/{policyTemplateId} [get] +// @Security JWT +func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + policyTemplate, err := h.usecase.Get(r.Context(), id) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + var out domain.GetPolicyTemplateResponse + if err = serializer.Map(*policyTemplate, &out.PolicyTemplate); err != nil { + log.ErrorWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ListPolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [ListPolicyTemplate] 정책 템플릿 목록 조회 +// @Description 정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다. +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.ListPolicyTemplateResponse +// @Router /api/1.0/admin/policytemplates [get] +// @Security JWT +func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *http.Request) { + urlParams := r.URL.Query() + + pg := pagination.NewPagination(&urlParams) + + policyTemplates, err := h.usecase.Fetch(r.Context(), pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ListPolicyTemplateResponse + out.PolicyTemplates = make([]domain.PolicyTemplateResponse, len(policyTemplates)) + for i, policyTemplate := range policyTemplates { + if err := serializer.Map(policyTemplate, &out.PolicyTemplates[i]); err != nil { + log.InfoWithContext(r.Context(), err) + continue + } + } + + if out.Pagination, err = pg.Response(); err != nil { + log.InfoWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ListPolicyTemplateVersions godoc +// +// @Tags PolicyTemplate +// @Summary [ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회 +// @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.ListPolicyTemplateVersionsResponse +// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/versions [get] +// @Security JWT +func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + policyTemplateVersions, err := h.usecase.ListPolicyTemplateVersions(r.Context(), id) + + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + var out domain.ListPolicyTemplateVersionsResponse + if err = serializer.Map(*policyTemplateVersions, &out); err != nil { + log.ErrorWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ListPolicyTemplateStatistics godoc +// +// @Tags PolicyTemplate +// @Summary [ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회 +// @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.ListPolicyTemplateStatisticsResponse +// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/statistics [get] +// @Security JWT +func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { + // result := domain.ListPolicyTemplateStatisticsResponse{ + // PolicyTemplateStatistics: []domain.PolicyTemplateStatistics{ + // { + // OrganizationId: util.UUIDGen(), + // OrganizationName: "개발팀", + // UsageCount: 10, + // }, + // { + // OrganizationId: util.UUIDGen(), + // OrganizationName: "운영팀", + // UsageCount: 5, + // }, + // }, + // } + // util.JsonResponse(w, result) +} + +// GetPolicyTemplateDeploy godoc +// +// @Tags PolicyTemplate +// @Summary [GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회 +// @Description 해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.GetPolicyTemplateDeployResponse +// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/deploy [get] +// @Security JWT +func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { + // c1 := util.UUIDGen() + // c2 := util.UUIDGen() + // c3 := util.UUIDGen() + + // result := domain.GetPolicyTemplateDeployResponse{ + // DeployVersion: map[string]string{ + // c1: "v1.0.1", + // c2: "v1.1.0", + // c3: "v1.1.0", + // }, + // } + // util.JsonResponse(w, result) +} + +// GetPolicyTemplateVersion godoc +// +// @Tags PolicyTemplate +// @Summary [GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회 +// @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param version path string true "조회할 버전(v0.0.0 형식)" +// @Success 200 {object} domain.GetPolicyTemplateVersionResponse +// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version} [get] +// @Security JWT +func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + version, ok := vars["version"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid version"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + policyTemplate, err := h.usecase.GetPolicyTemplateVersion(r.Context(), id, version) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + var out domain.GetPolicyTemplateVersionResponse + if err = serializer.Map(*policyTemplate, &out.PolicyTemplate); err != nil { + log.ErrorWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// CreatePolicyTemplateVersion godoc +// +// @Tags PolicyTemplate +// @Summary [CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장 +// @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param body body domain.CreatePolicyTemplateVersionRequest true "create policy template version request" +// @Success 200 {object} domain.CreatePolicyTemplateVersionResponse +// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/versions [post] +// @Security JWT +func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + input := domain.CreatePolicyTemplateVersionRequest{} + + err = UnmarshalRequestInput(r, &input) + + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + currentVer, err := semver.NewVersion(input.CurrentVersion) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid currentVersion"), "C_INVALID_CURRENT_VERSION", fmt.Sprintf("invalid version format '%s'", input.CurrentVersion))) + return + } + + versionUpType := strings.ToLower(input.VersionUpType) + + var expectedVersion string + + switch versionUpType { + case "major": + newVersion := currentVer.IncMajor() + expectedVersion = newVersion.Original() + case "minor": + newVersion := currentVer.IncMinor() + expectedVersion = newVersion.Original() + case "patch": + newVersion := currentVer.IncPatch() + expectedVersion = newVersion.Original() + } + + if expectedVersion != input.ExpectedVersion { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid expectedVersion"), "C_INVALID_EXPECTED_VERSION", fmt.Sprintf("expected version mismatch '%s' != '%s'", + input.ExpectedVersion, expectedVersion))) + } + + createdVersion, err := h.usecase.CreatePolicyTemplateVersion(r.Context(), id, expectedVersion, input.ParametersSchema, input.Rego, input.Libs) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CreatePolicyTemplateVersionResponse + out.Version = createdVersion + + ResponseJSON(w, r, http.StatusOK, out) +} + +// DeletePolicyTemplateVersion godoc +// +// @Tags PolicyTemplate +// @Summary [DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제 +// @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param version path string true "삭제할 버전(v0.0.0 형식)" +// @Success 200 {object} nil +// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version} [delete] +// @Security JWT +func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + version, ok := vars["version"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid version"), "C_INVALID_VERSION", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + err = h.usecase.DeletePolicyTemplateVersion(r.Context(), id, version) + + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, "") +} + +// ExistsPolicyTemplateName godoc +// +// @Tags PolicyTemplate +// @Summary [ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인 +// @Description 해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다. +// @Accept json +// @Produce json +// @Param policyTemplateName path string true "정책 템플릿 이름" +// @Success 200 {object} domain.CheckExistedResponse +// @Router /api/1.0/admin/policytemplates/name/{policyTemplateName}/existence [get] +// @Security JWT +func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateName, ok := vars["policyTemplateName"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyTemplateName not found in path"), + "C_INVALID_POLICYTEMPLATE_NAME", "")) + return + } + + exist, err := h.usecase.IsPolicyTemplateNameExist(r.Context(), policyTemplateName) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CheckExistedResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ExistsPolicyTemplateKind godoc +// +// @Tags PolicyTemplate +// @Summary [ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인 +// @Description 해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다. +// @Accept json +// @Produce json +// @Param policyTemplateKind path string true "정책 템플릿 이름" +// @Success 200 {object} domain.ExistsPolicyTemplateKindResponse +// @Router /api/1.0/admin/policytemplates/kind/{policyTemplateKind}/existence [get] +// @Security JWT +func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateKind, ok := vars["policyTemplateKind"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyTemplateKind not found in path"), + "C_INVALID_POLICY_TEMPLATE_KIND", "")) + return + } + + exist, err := h.usecase.IsPolicyTemplateKindExist(r.Context(), policyTemplateKind) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CheckExistedResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/delivery/http/utility.go b/internal/delivery/http/utility.go new file mode 100644 index 00000000..f22d18fc --- /dev/null +++ b/internal/delivery/http/utility.go @@ -0,0 +1,73 @@ +package http + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" +) + +type UtilityHandler struct { + usecase usecase.IUtilityUsecase +} + +type IUtilityHandler interface { + RegoCompile(w http.ResponseWriter, r *http.Request) +} + +func NewUtilityHandler(u usecase.Usecase) IUtilityHandler { + return &UtilityHandler{ + usecase: u.Utility, + } +} + +// CompileRego godoc +// +// @Tags Rego +// @Summary [CompileRego] Rego 코드 컴파일 및 파라미터 파싱 +// @Description Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다. +// @Accept json +// @Produce json +// @Param parseParameter query bool true "파라미터 파싱 여부" +// @Param body body domain.RegoCompileRequest true "Rego 코드" +// @Success 200 {object} domain.RegoCompileResponse +// @Router /utility/rego-compile [post] +// @Security JWT +func (h *UtilityHandler) RegoCompile(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + parseParameter := false + + parse, ok := vars["parseParameter"] + if ok { + parsedBool, err := strconv.ParseBool(parse) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid parseParameter: '%s'", parse), "U_INVALID_REGO_PARSEPARAM", "")) + return + } + parseParameter = parsedBool + } + + input := domain.RegoCompileRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + response, err := h.usecase.RegoCompile(&input, parseParameter) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusCreated, response) +} diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go new file mode 100644 index 00000000..bc12f8fe --- /dev/null +++ b/internal/repository/policy-template.go @@ -0,0 +1,553 @@ +package repository + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +type IPolicyTemplateRepository interface { + Create(dto domain.PolicyTemplate) (policyTemplateId uuid.UUID, err error) + Update(dto domain.UpdatePolicyTemplateUpdate) (err error) + Fetch(pg *pagination.Pagination) (out []domain.PolicyTemplate, err error) + GetByName(policyTemplateName string) (out *domain.PolicyTemplate, err error) + GetByKind(policyTemplateKind string) (out *domain.PolicyTemplate, err error) + GetByID(policyTemplateId uuid.UUID) (out *domain.PolicyTemplate, err error) + Delete(policyTemplateId uuid.UUID) (err error) + ExistByName(policyTemplateName string) (exist bool, err error) + ExistByKind(policyTemplateKind string) (exist bool, err error) + ExistByID(policyTemplateId uuid.UUID) (exist bool, err error) + ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) + GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) + DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) + CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) +} + +type PolicyTemplateRepository struct { + db *gorm.DB +} + +func NewPolicyTemplateRepository(db *gorm.DB) IPolicyTemplateRepository { + return &PolicyTemplateRepository{ + db: db, + } +} + +type PolicyTemplateSupportedVersion struct { + gorm.Model + + PolicyTemplateId uuid.UUID `gorm:"index:template_version,unique"` + Version string `gorm:"index:template_version,unique"` + + ParameterSchema string `gorm:"type:text"` + Rego string `gorm:"type:text"` + Libs string `gorm:"type:text"` +} + +type PolicyTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` + Type string // Org or Tks + Name string + Version string + SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` + Description string + Kind string + Deprecated bool + Mandatory bool // Tks 인 경우에는 무시 + Severity string + PermittedOrganizations []domain.Organization `gorm:"many2many:policy_template_permitted_organiations;"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` +} + +func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + +func (r *PolicyTemplateRepository) Create(dto domain.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { + jsonByte, err := json.Marshal(dto.ParametersSchema) + + if err != nil { + return uuid.Nil, err + } + + policyTemplate := PolicyTemplate{ + Type: "tks", + Name: dto.TemplateName, + Version: "v1.0.0", + SupportedVersions: []PolicyTemplateSupportedVersion{ + { + Version: "v1.0.0", + ParameterSchema: string(jsonByte), + Rego: dto.Rego, + }, + }, + Description: dto.Description, + Kind: dto.Kind, + Deprecated: false, + Mandatory: false, // Tks 인 경우에는 무시 + Severity: dto.Severity, + } + + err = r.db.Transaction(func(tx *gorm.DB) error { + err := tx.Create(&policyTemplate).Error + + if err != nil { + return err + } + + if dto.PermittedOrganizationIds != nil { + permittedOrganizations := make([]domain.Organization, len(dto.PermittedOrganizationIds)) + for i, permittedOrganizationId := range dto.PermittedOrganizationIds { + permittedOrganizations[i] = domain.Organization{ID: permittedOrganizationId} + } + + err = tx.Model(&policyTemplate).Association("PermittedOrganizations").Replace(permittedOrganizations) + + if err != nil { + return err + } + } + + return nil + }) + + if err != nil { + return uuid.Nil, err + } + + return policyTemplate.ID, nil +} + +func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) (err error) { + updateMap := make(map[string]interface{}) + + updateMap["updator_id"] = dto.UpdatorId + + if dto.Description != nil { + updateMap["description"] = dto.Description + } + + if dto.Deprecated != nil { + updateMap["deprecated"] = dto.Deprecated + } + + if dto.Severity != nil { + updateMap["severity"] = dto.Severity + } + + if dto.TemplateName != nil { + updateMap["name"] = dto.TemplateName + } + + fmt.Printf("--updateMap=%+v\n--", updateMap) + + var policyTemplate PolicyTemplate + policyTemplate.ID = dto.ID + + return r.db.Transaction(func(tx *gorm.DB) error { + if dto.PermittedOrganizationIds != nil { + permittedOrganizations := make([]domain.Organization, len(*dto.PermittedOrganizationIds)) + for i, permittedOrganizationId := range *dto.PermittedOrganizationIds { + permittedOrganizations[i] = domain.Organization{ID: permittedOrganizationId} + } + + err = r.db.Model(&policyTemplate).Limit(1). + Association("PermittedOrganizations").Replace(permittedOrganizations) + + if err != nil { + return err + } + } + + if len(updateMap) > 0 { + err = r.db.Model(&policyTemplate).Limit(1). + Where("id = ? and type = 'tks'", dto.ID). + Updates(updateMap).Error + + if err != nil { + return err + } + } + + // return nil will commit the whole transaction + return nil + }) +} + +func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain.PolicyTemplate, err error) { + var policyTemplates []PolicyTemplate + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch(r.db.Preload(clause.Associations).Model(&PolicyTemplate{}). + Where("type = 'tks'"), &policyTemplates) + if res.Error != nil { + return nil, res.Error + } + + for _, policyTemplate := range policyTemplates { + var policyTemplateVersion PolicyTemplateSupportedVersion + res = r.db. + Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). + First(&policyTemplateVersion) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found policyTemplate version") + } else { + log.Error(res.Error) + } + } + + outPolicyTemplate := r.reflectPolicyTemplate(policyTemplate, policyTemplateVersion) + out = append(out, outPolicyTemplate) + } + return out, nil +} + +func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTemplate, policyTemplateVersion PolicyTemplateSupportedVersion) (out domain.PolicyTemplate) { + if err := serializer.Map(policyTemplate.Model, &out); err != nil { + log.Error(err) + } + if err := serializer.Map(policyTemplate, &out); err != nil { + log.Error(err) + } + out.TemplateName = policyTemplate.Name + out.ID = domain.PolicyTemplateId(policyTemplate.ID.String()) + + var schemas []domain.ParameterDef + + if len(policyTemplateVersion.ParameterSchema) > 0 { + if err := json.Unmarshal([]byte(policyTemplateVersion.ParameterSchema), &schemas); err != nil { + log.Error(err) + } else { + out.ParametersSchema = schemas + } + } + + out.PermittedOrganizations = make([]domain.PermittedOrganization, len(policyTemplate.PermittedOrganizations)) + for i, org := range policyTemplate.PermittedOrganizations { + out.PermittedOrganizations[i] = domain.PermittedOrganization{ + OrganizationId: org.ID, + OrganizationName: org.Name, + Permitted: true, + } + } + + out.Rego = policyTemplateVersion.Rego + out.Libs = strings.Split(policyTemplateVersion.Libs, "---\n") + + return +} + +func (r *PolicyTemplateRepository) ExistsBy(key string, value interface{}) (exists bool, err error) { + query := fmt.Sprintf("%s = ?", key) + + var policyTemplate PolicyTemplate + res := r.db.Where(query, value). + First(&policyTemplate) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Infof("Not found policyTemplate %s='%v'", key, value) + return false, nil + } else { + log.Error(res.Error) + return false, res.Error + } + } + + return true, nil +} + +func (r *PolicyTemplateRepository) ExistByName(policyTemplateName string) (exist bool, err error) { + return r.ExistsBy("name", policyTemplateName) +} + +func (r *PolicyTemplateRepository) ExistByKind(policyTemplateKind string) (exist bool, err error) { + return r.ExistsBy("kind", policyTemplateKind) +} + +func (r *PolicyTemplateRepository) ExistByID(policyTemplateId uuid.UUID) (exist bool, err error) { + return r.ExistsBy("id", policyTemplateId) +} + +func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *domain.PolicyTemplate, err error) { + query := fmt.Sprintf("%s = ?", key) + + var policyTemplate PolicyTemplate + res := r.db.Preload(clause.Associations).Where(query, value). + First(&policyTemplate) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Infof("Not found policyTemplate %s='%v'", key, value) + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + var policyTemplateVersion PolicyTemplateSupportedVersion + res = r.db.Limit(1). + Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). + First(&policyTemplateVersion) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found policyTemplate version") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + fmt.Printf("BBBB %+v\n", policyTemplate.PermittedOrganizations) + + result := r.reflectPolicyTemplate(policyTemplate, policyTemplateVersion) + fmt.Printf("2222BBBB %+v\n", result.PermittedOrganizations) + + return &result, nil +} + +func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *domain.PolicyTemplate, err error) { + return r.GetBy("id", policyTemplateId) + + // var policyTemplate PolicyTemplate + // res := r.db.Preload(clause.Associations).Where("id = ?", policyTemplateId). + // First(&policyTemplate) + + // if res.Error != nil { + // if errors.Is(res.Error, gorm.ErrRecordNotFound) { + // log.Info("Not found policyTemplate id") + // return nil, nil + // } else { + // log.Error(res.Error) + // return nil, res.Error + // } + // } + + // result := r.reflect(policyTemplate) + + // return &result, nil +} + +func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *domain.PolicyTemplate, err error) { + return r.GetBy("name", policyTemplateName) + + // var policyTemplate PolicyTemplate + // res := r.db.Limit(1). + // Where("name = ?", policyTemplateName). + // First(&policyTemplate) + // if res.Error != nil { + // if errors.Is(res.Error, gorm.ErrRecordNotFound) { + // log.Info("Not found policyTemplate name") + // return nil, nil + // } else { + // log.Error(res.Error) + // return nil, res.Error + // } + // } + + // result := r.reflect(policyTemplate) + + // return &result, nil +} + +func (r *PolicyTemplateRepository) GetByKind(policyTemplateKind string) (out *domain.PolicyTemplate, err error) { + return r.GetBy("kind", policyTemplateKind) +} + +func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error) { + return r.db.Transaction(func(tx *gorm.DB) error { + if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&PolicyTemplateSupportedVersion{}).Error; err != nil { + return err + } + + if err := tx.Model(&PolicyTemplate{ID: policyTemplateId}).Association("PermittedOrganizations").Clear(); err != nil { + return err + } + + if err := tx.Where("id = ?", policyTemplateId).Delete(&PolicyTemplate{}).Error; err != nil { + return err + } + + return nil + }) +} + +func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { + var supportedVersions []PolicyTemplateSupportedVersion + res := r.db.Where("policy_template_id = ?", policyTemplateId).Find(&supportedVersions) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found policyTemplate kind") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + versions := make([]string, len(supportedVersions)) + + for i, supportedVersion := range supportedVersions { + versions[i] = supportedVersion.Version + } + + result := &domain.ListPolicyTemplateVersionsResponse{ + Versions: versions, + } + + return result, nil +} + +func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) { + var policyTemplateVersion PolicyTemplateSupportedVersion + res := r.db. + Where("policy_template_id = ? and version = ?", policyTemplateId, version). + First(&policyTemplateVersion) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found policyTemplate version") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + var policyTemplate PolicyTemplate + res = r.db. + Where("id = ?", policyTemplateId). + First(&policyTemplate) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found policyTemplate id") + return nil, nil + } else { + log.Error(res.Error) + return nil, res.Error + } + } + + result := r.reflectPolicyTemplate(policyTemplate, policyTemplateVersion) + + return &result, nil +} + +func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) { + var policyTemplate PolicyTemplate + res := r.db.Select("version").First(&policyTemplate) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found policyTemplate id") + return nil + } else { + log.Error(res.Error) + return res.Error + } + } + + // 현재 버전이 템플릿에서 최신 버전으로 사용 중이면 삭제 금지 + if policyTemplate.Version == version { + return fmt.Errorf("version '%s' is currently in use", version) + } + + // TODO: Operator에 현재 버전 사용중인 정책이 있는지 체크 필요 + + var policyTemplateVersion PolicyTemplateSupportedVersion + res = r.db.Where("policy_template_id = ? and version = ?", policyTemplateId, version). + Delete(&policyTemplateVersion) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info("Not found policyTemplate version") + return nil + } else { + log.Error(res.Error) + return res.Error + } + } + + return nil +} + +func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { + var policyTemplateVersion PolicyTemplateSupportedVersion + res := r.db.Limit(1). + Where("policy_template_id = ? and version = ?", policyTemplateId, version). + First(&policyTemplateVersion) + + if res.Error == nil { + err = errors.Errorf("Version %s already exists for the policyTemplate", newVersion) + + log.Error(res.Error) + + return "", err + } + + if !errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Error(res.Error) + return "", res.Error + } + + libsString := "" + if len(libs) > 0 { + libsString = strings.Join(libs, "---\n") + } + + jsonBytes, err := json.Marshal(schema) + + if err != nil { + parseErr := errors.Errorf("Unable to parse parameter schema: %v", err) + + log.Error(parseErr) + + return "", parseErr + } + + newPolicyTemplateVersion := &PolicyTemplateSupportedVersion{ + PolicyTemplateId: policyTemplateId, + Version: newVersion, + Rego: rego, + Libs: libsString, + ParameterSchema: string(jsonBytes), + } + + err = r.db.Transaction(func(tx *gorm.DB) error { + if err := tx.Create(newPolicyTemplateVersion).Error; err != nil { + return err + } + + if err := tx.Model(&PolicyTemplate{}).Where("id = ?", policyTemplateId).Update("version", newVersion).Error; err != nil { + return err + } + + return nil + }) + + if err != nil { + return "", err + } + + return newVersion, nil +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 46138c9d..7190cf18 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -12,20 +12,21 @@ import ( type FilterFunc func(user *gorm.DB) *gorm.DB type Repository struct { - Auth IAuthRepository - User IUserRepository - Cluster IClusterRepository - Organization IOrganizationRepository - AppGroup IAppGroupRepository - AppServeApp IAppServeAppRepository - CloudAccount ICloudAccountRepository - StackTemplate IStackTemplateRepository - Alert IAlertRepository - Role IRoleRepository - Permission IPermissionRepository - Endpoint IEndpointRepository - Project IProjectRepository - Audit IAuditRepository + Auth IAuthRepository + User IUserRepository + Cluster IClusterRepository + Organization IOrganizationRepository + AppGroup IAppGroupRepository + AppServeApp IAppServeAppRepository + CloudAccount ICloudAccountRepository + StackTemplate IStackTemplateRepository + Alert IAlertRepository + Role IRoleRepository + Permission IPermissionRepository + Endpoint IEndpointRepository + Project IProjectRepository + Audit IAuditRepository + PolicyTemplate IPolicyTemplateRepository } func CombinedGormFilter(table string, filters []pagination.Filter, combinedFilter pagination.CombinedFilter) FilterFunc { diff --git a/internal/route/route.go b/internal/route/route.go index 98dce40b..76106a23 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -41,38 +41,41 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa cache := gcache.New(5*time.Minute, 10*time.Minute) repoFactory := repository.Repository{ - Auth: repository.NewAuthRepository(db), - User: repository.NewUserRepository(db), - Cluster: repository.NewClusterRepository(db), - Organization: repository.NewOrganizationRepository(db), - AppGroup: repository.NewAppGroupRepository(db), - AppServeApp: repository.NewAppServeAppRepository(db), - CloudAccount: repository.NewCloudAccountRepository(db), - StackTemplate: repository.NewStackTemplateRepository(db), - Alert: repository.NewAlertRepository(db), - Role: repository.NewRoleRepository(db), - Project: repository.NewProjectRepository(db), - Permission: repository.NewPermissionRepository(db), - Endpoint: repository.NewEndpointRepository(db), - Audit: repository.NewAuditRepository(db), + Auth: repository.NewAuthRepository(db), + User: repository.NewUserRepository(db), + Cluster: repository.NewClusterRepository(db), + Organization: repository.NewOrganizationRepository(db), + AppGroup: repository.NewAppGroupRepository(db), + AppServeApp: repository.NewAppServeAppRepository(db), + CloudAccount: repository.NewCloudAccountRepository(db), + StackTemplate: repository.NewStackTemplateRepository(db), + Alert: repository.NewAlertRepository(db), + Role: repository.NewRoleRepository(db), + Project: repository.NewProjectRepository(db), + Permission: repository.NewPermissionRepository(db), + Endpoint: repository.NewEndpointRepository(db), + Audit: repository.NewAuditRepository(db), + PolicyTemplate: repository.NewPolicyTemplateRepository(db), } usecaseFactory := usecase.Usecase{ - Auth: usecase.NewAuthUsecase(repoFactory, kc), - User: usecase.NewUserUsecase(repoFactory, kc), - Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache), - Organization: usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), - AppGroup: usecase.NewAppGroupUsecase(repoFactory, argoClient), - AppServeApp: usecase.NewAppServeAppUsecase(repoFactory, argoClient), - CloudAccount: usecase.NewCloudAccountUsecase(repoFactory, argoClient), - StackTemplate: usecase.NewStackTemplateUsecase(repoFactory), - Dashboard: usecase.NewDashboardUsecase(repoFactory, cache), - Alert: usecase.NewAlertUsecase(repoFactory), - Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), - Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), - Audit: usecase.NewAuditUsecase(repoFactory), - Role: usecase.NewRoleUsecase(repoFactory), - Permission: usecase.NewPermissionUsecase(repoFactory), + Auth: usecase.NewAuthUsecase(repoFactory, kc), + User: usecase.NewUserUsecase(repoFactory, kc), + Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache), + Organization: usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), + AppGroup: usecase.NewAppGroupUsecase(repoFactory, argoClient), + AppServeApp: usecase.NewAppServeAppUsecase(repoFactory, argoClient), + CloudAccount: usecase.NewCloudAccountUsecase(repoFactory, argoClient), + StackTemplate: usecase.NewStackTemplateUsecase(repoFactory), + Dashboard: usecase.NewDashboardUsecase(repoFactory, cache), + Alert: usecase.NewAlertUsecase(repoFactory), + Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), + Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), + Audit: usecase.NewAuditUsecase(repoFactory), + Role: usecase.NewRoleUsecase(repoFactory), + Permission: usecase.NewPermissionUsecase(repoFactory), + PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), + Utility: usecase.NewUtilityUsecase(repoFactory), } customMiddleware := internalMiddleware.NewMiddleware( @@ -264,6 +267,25 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) + + policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates", customMiddleware.Handle(internalApi.CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}", customMiddleware.Handle(internalApi.DeletePolicyTemplate, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplate))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetPolicyTemplate, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.UpdatePolicyTemplate))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/deploy ", customMiddleware.Handle(internalApi.GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateDeploy))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/statistics", customMiddleware.Handle(internalApi.ListPolicyTemplateStatistics, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateStatistics))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.ListPolicyTemplateVersions, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateVersions))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplateVersion))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.DeletePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplateVersion))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateVersion))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateKind))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateName))).Methods(http.MethodGet) + + utilityHandler := delivery.NewUtilityHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+"/utility/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(utilityHandler.RegoCompile))).Methods(http.MethodPost) + // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) r.PathPrefix("/").Handler(httpSwagger.WrapHandler).Methods(http.MethodGet) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go new file mode 100644 index 00000000..2b48af42 --- /dev/null +++ b/internal/usecase/policy-template.go @@ -0,0 +1,228 @@ +package usecase + +import ( + "context" + "fmt" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" +) + +type IPolicyTemplateUsecase interface { + Create(ctx context.Context, policyTemplate domain.PolicyTemplate) (policyTemplateId string, err error) + Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []domain.PolicyTemplate, err error) + Update(ctx context.Context, policyTemplateId uuid.UUID, update domain.UpdatePolicyTemplateRequest) (err error) + Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *domain.PolicyTemplate, err error) + Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) + IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) + IsPolicyTemplateKindExist(ctx context.Context, policyTemplateKind string) (bool, error) + GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) + ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) + DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) + CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) +} + +type PolicyTemplateUsecase struct { + organizationRepo repository.IOrganizationRepository + clusterRepo repository.IClusterRepository + repo repository.IPolicyTemplateRepository +} + +func NewPolicyTemplateUsecase(r repository.Repository) IPolicyTemplateUsecase { + return &PolicyTemplateUsecase{ + repo: r.PolicyTemplate, + organizationRepo: r.Organization, + clusterRepo: r.Cluster, + } +} + +func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto domain.PolicyTemplate) (policyTemplateId string, err error) { + user, ok := request.UserFrom(ctx) + if !ok { + return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "P_INVALID_TOKEN", "") + } + + exists, err := u.repo.ExistByName(dto.TemplateName) + if err == nil && exists { + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") + } + + exists, err = u.repo.ExistByKind(dto.Kind) + if err == nil && exists { + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_KIND", "policy template kind already exists") + } + + for _, organizationId := range dto.PermittedOrganizationIds { + _, err = u.organizationRepo.Get(organizationId) + if err != nil { + return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "", "") + } + } + + userId := user.GetUserId() + dto.CreatorId = &userId + id, err := u.repo.Create(dto) + + if err != nil { + return "", err + } + + return id.String(), nil +} + +func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []domain.PolicyTemplate, err error) { + policyTemplates, err = u.repo.Fetch(pg) + + if err != nil { + return nil, err + } + + organizations, err := u.organizationRepo.Fetch(nil) + if err == nil { + for i, policyTemplate := range policyTemplates { + permittedOrgIdSet := u.getPermittedOrganiationIdSet(&policyTemplate) + + u.updatePermittedOrganizations(organizations, permittedOrgIdSet, &policyTemplates[i]) + } + } + + return policyTemplates, nil + +} + +func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *domain.PolicyTemplate, err error) { + policyTemplate, err := u.repo.GetByID(policyTemplateID) + + if err != nil { + return nil, err + } + + permittedOrgIdSet := u.getPermittedOrganiationIdSet(policyTemplate) + + organizations, err := u.organizationRepo.Fetch(nil) + if err == nil { + u.updatePermittedOrganizations(organizations, permittedOrgIdSet, policyTemplate) + } + + return policyTemplate, nil +} + +func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uuid.UUID, update domain.UpdatePolicyTemplateRequest) (err error) { + user, ok := request.UserFrom(ctx) + if !ok { + return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + } + + _, err = u.repo.GetByID(policyTemplateId) + if err != nil { + return httpErrors.NewNotFoundError(err, "P_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + exists, err := u.repo.ExistByName(*update.TemplateName) + if err == nil && exists { + return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") + } + + if update.PermittedOrganizationIds != nil { + for _, organizationId := range *update.PermittedOrganizationIds { + _, err = u.organizationRepo.Get(organizationId) + if err != nil { + return httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "", "") + } + } + } + + updatorId := user.GetUserId() + dto := domain.UpdatePolicyTemplateUpdate{ + ID: policyTemplateId, + Type: "tks", + UpdatorId: updatorId, + TemplateName: update.TemplateName, + Description: update.Description, + Severity: update.Severity, + Deprecated: update.Deprecated, + PermittedOrganizationIds: update.PermittedOrganizationIds, + } + + err = u.repo.Update(dto) + if err != nil { + return err + } + + return nil +} + +func (u *PolicyTemplateUsecase) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) { + return u.repo.Delete(policyTemplateId) +} + +func (u *PolicyTemplateUsecase) IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) { + return u.repo.ExistByName(policyTemplateName) +} + +func (u *PolicyTemplateUsecase) IsPolicyTemplateKindExist(ctx context.Context, policyTemplateKind string) (bool, error) { + return u.repo.ExistByKind(policyTemplateKind) +} + +func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) { + policyTemplate, err := u.repo.GetPolicyTemplateVersion(policyTemplateId, version) + + if err != nil { + return nil, err + } + + permittedOrgIdSet := u.getPermittedOrganiationIdSet(policyTemplate) + + organizations, err := u.organizationRepo.Fetch(nil) + if err == nil { + u.updatePermittedOrganizations(organizations, permittedOrgIdSet, policyTemplate) + } + + return policyTemplate, nil +} + +func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]domain.Organization, permittedOrgIdSet map[string]string, policyTemplate *domain.PolicyTemplate) { + // 허용리스트가 비어있으면 모든 Org에 대해서 허용 + permitted := len(permittedOrgIdSet) == 0 + + for _, organization := range *organizations { + + _, ok := permittedOrgIdSet[organization.ID] + + if !ok { + policyTemplate.PermittedOrganizations = append( + policyTemplate.PermittedOrganizations, + domain.PermittedOrganization{ + OrganizationId: organization.ID, + OrganizationName: organization.Name, + Permitted: permitted, + }) + } + } +} + +func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *domain.PolicyTemplate) map[string]string { + permittedOrgIdSet := make(map[string]string) + + for _, permittedOrg := range policyTemplate.PermittedOrganizations { + // Set 처리를 위해서 키만 사용, 값은 아무거나 + permittedOrgIdSet[permittedOrg.OrganizationId] = "1" + } + return permittedOrgIdSet +} + +func (u *PolicyTemplateUsecase) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { + return u.repo.ListPolicyTemplateVersions(policyTemplateId) +} + +func (u *PolicyTemplateUsecase) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) { + return u.repo.DeletePolicyTemplateVersion(policyTemplateId, version) +} + +func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { + return u.repo.CreatePolicyTemplateVersion(policyTemplateId, newVersion, schema, rego, libs) +} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index 4e7da85b..48f47ae2 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -1,19 +1,21 @@ package usecase type Usecase struct { - Auth IAuthUsecase - User IUserUsecase - Cluster IClusterUsecase - Organization IOrganizationUsecase - AppGroup IAppGroupUsecase - AppServeApp IAppServeAppUsecase - CloudAccount ICloudAccountUsecase - StackTemplate IStackTemplateUsecase - Dashboard IDashboardUsecase - Alert IAlertUsecase - Stack IStackUsecase - Project IProjectUsecase - Role IRoleUsecase - Permission IPermissionUsecase - Audit IAuditUsecase + Auth IAuthUsecase + User IUserUsecase + Cluster IClusterUsecase + Organization IOrganizationUsecase + AppGroup IAppGroupUsecase + AppServeApp IAppServeAppUsecase + CloudAccount ICloudAccountUsecase + StackTemplate IStackTemplateUsecase + Dashboard IDashboardUsecase + Alert IAlertUsecase + Stack IStackUsecase + Project IProjectUsecase + Role IRoleUsecase + Permission IPermissionUsecase + Audit IAuditUsecase + PolicyTemplate IPolicyTemplateUsecase + Utility IUtilityUsecase } diff --git a/internal/usecase/utility.go b/internal/usecase/utility.go new file mode 100644 index 00000000..c7f421f9 --- /dev/null +++ b/internal/usecase/utility.go @@ -0,0 +1,161 @@ +package usecase + +import ( + "fmt" + "regexp" + "strings" + + "github.com/open-policy-agent/opa/ast" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" +) + +type IUtilityUsecase interface { + RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) +} + +type UtilityUsecase struct { +} + +func NewUtilityUsecase(r repository.Repository) IUtilityUsecase { + return &UtilityUsecase{} +} + +func (u *UtilityUsecase) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) { + modules := map[string]*ast.Module{} + + response = &domain.RegoCompileResponse{} + response.Errors = []domain.RegoCompieError{} + + mod, err := ast.ParseModuleWithOpts("rego", request.Rego, ast.ParserOptions{}) + if err != nil { + return nil, err + } + modules["rego"] = mod + + compiler := ast.NewCompiler() + compiler.Compile(modules) + + if compiler.Failed() { + for _, compileError := range compiler.Errors { + response.Errors = append(response.Errors, domain.RegoCompieError{ + Status: 400, + Code: "P_INVALID_REGO_SYNTAX", + Message: "Invalid rego syntax", + Text: fmt.Sprintf("[%d:%d] %s", + compileError.Location.Row, compileError.Location.Col, + compileError.Message), + }) + } + } + + if parseParameter { + response.ParametersSchema = extractParameter(request.Rego) + } + + return response, nil +} + +func extractParameter(rego string) []*domain.ParameterDef { + pattern := `input\.parameters\.[\w\.\[\]]+` + + prefix := "input.parameters." + + // Compile the regex pattern + regex := regexp.MustCompile(pattern) + + matches := regex.FindAllString(rego, -1) + + defStore := NewParamDefStore() + + for _, match := range matches { + remainder := match[len(prefix):] + + // 문법 변환: aa["a"]["B"][_]->aa.a.B[_] + regex := regexp.MustCompile(`\[\"(\w+)\"\]`) + remainder = regex.ReplaceAllString(remainder, ".$1") + + params := strings.Split(remainder, ".") + + if len(params) == 0 { + continue + } + + defStore.AddDefinition(params) + } + + return defStore.store +} + +type ParamDefStore struct { + store []*domain.ParameterDef +} + +func NewParamDefStore() *ParamDefStore { + return &ParamDefStore{store: []*domain.ParameterDef{}} +} + +func (s *ParamDefStore) GetStore() []*domain.ParameterDef { + return s.store +} + +func (s *ParamDefStore) AddDefinition(params []string) { + init := &s.store + + for i, param := range params { + isLast := i == len(params)-1 + + key := findKey(s.store, param) + + if key == nil { + key = createKey(param, isLast) + *init = append(*init, key) + } + + init = &key.Children + } +} + +func findKey(defs []*domain.ParameterDef, key string) *domain.ParameterDef { + for _, def := range defs { + if def.Key == key || def.Key+"[_]" == key { + return def + } + } + + return nil +} + +func createKey(key string, isLast bool) *domain.ParameterDef { + finalType := "any" + + pKey := key + isArray := false + + if strings.HasSuffix(pKey, "[_]") { + pKey, _ = strings.CutSuffix(pKey, "[_]") + isArray = true + } + + if isLast { + if isArray { + finalType = "any[]" + } else { + finalType = "any" + } + } else { + if isArray { + finalType = "object[]" + } else { + finalType = "object" + } + } + + newDef := &domain.ParameterDef{ + Key: pKey, + Type: finalType, + Children: []*domain.ParameterDef{}, + } + + return newDef +} diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go new file mode 100644 index 00000000..acea768d --- /dev/null +++ b/pkg/domain/policy-template.go @@ -0,0 +1,278 @@ +package domain + +import ( + "time" + + "github.com/google/uuid" +) + +type PolicyTemplateId string + +func (pp PolicyTemplateId) String() string { + return string(pp) +} + +func (pp PolicyTemplateId) Validate() bool { + // return helper.ValidatePolicyTemplateId(pp.String()) + return true +} + +type CommonPolicyTemplate struct { + ID PolicyTemplateId `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + Type string `json:"type" enums:"tks,organization" example:"tks"` + Creator SimpleUserResponse `json:"creator,omitempty"` + Updator SimpleUserResponse `json:"updator,omitempty"` + CreatedAt time.Time `json:"createdAt" format:"date-time"` + UpdatedAt time.Time `json:"updatedAt" format:"date-time"` + + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Kind string `json:"kind" example:"K8sRequiredLabels"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Version string `json:"version,omitempty" example:"v1.0.1"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` + // Target string `json:"target,omitempty" example:"admission.k8s.gatekeeper.sh"` + // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" + + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` + + // Tags []string `json:"tags,omitempty" example:"k8s,label"` +} + +type OrganizationPolicyTemplate struct { + Mandatory bool `json:"mandatory"` + CommonPolicyTemplate +} + +type PermittedOrganization struct { + OrganizationId string `json:"organizationId"` + OrganizationName string `json:"organizationName"` + Permitted bool `json:"permitted"` +} + +type PolicyTemplateResponse struct { + ID PolicyTemplateId `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + Type string `json:"type" enums:"tks,organization" example:"tks"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Kind string `json:"kind" example:"K8sRequiredLabels"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Version string `json:"version,omitempty" example:"v1.0.1"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` + + PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` +} + +type PolicyTemplate struct { + ID PolicyTemplateId + Type string + CreatorId *uuid.UUID + Creator User + UpdatorId *uuid.UUID + Updator User + CreatedAt time.Time + UpdatedAt time.Time + + TemplateName string + Kind string + Severity string + Deprecated bool + Version string + Description string + ParametersSchema []ParameterDef + + Rego string + Libs []string + + PermittedOrganizationIds []string // 생성 시에만 사용 + PermittedOrganizations []PermittedOrganization +} + +type CreateCommonPolicyTemplateRequest struct { + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Kind string `json:"kind" example:"K8sRequiredLabels"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` + // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" + + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` + + // Tags []string `json:"tags,omitempty" example:"k8s,label"` +} + +type CreatePolicyTemplateRequest struct { + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Kind string `json:"kind" example:"K8sRequiredLabels"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Target string `json:"target,omitempty" example:"admission.k8s.gatekeeper.sh"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` + // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" + + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` + + PermittedOrganizationIds []string `json:"permittedOrganizationIds"` +} + +type CreateOrganizationPolicyTemplateRequest struct { + CreateCommonPolicyTemplateRequest + Mandatory bool `json:"mandatory"` +} + +type CreatePolicyTemplateReponse struct { + ID PolicyTemplateId `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` +} + +type CreateOrganizationPolicyTemplateReponse struct { + ID PolicyTemplateId `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` +} + +type UpdateCommmonPolicyTemplateRequest struct { + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Description string `json:"description,omitempty"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + // Tags []string `json:"tags,omitempty"` +} + +type UpdatePolicyTemplateUpdate struct { + ID uuid.UUID + Type string + UpdatorId uuid.UUID + TemplateName *string + Description *string + Severity *string + Deprecated *bool + PermittedOrganizationIds *[]string +} + +func (dto *UpdatePolicyTemplateUpdate) IsNothingToUpdate() bool { + return dto.TemplateName == nil && + dto.Description == nil && + dto.Severity == nil && + dto.Deprecated == nil && + dto.PermittedOrganizationIds == nil +} + +type UpdatePolicyTemplateRequest struct { + TemplateName *string `json:"templateName,omitempty" example:"필수 Label 검사"` + Description *string `json:"description,omitempty"` + Severity *string `json:"severity,omitempty" enums:"low,medium,high" example:"medium"` + Deprecated *bool `json:"deprecated,omitempty" example:"false"` + PermittedOrganizationIds *[]string `json:"permittedOrganizationIds,omitempty"` +} + +type UpdateOrganizationPolicyTemplateRequest struct { + UpdateCommmonPolicyTemplateRequest + Mandatory bool `json:"mandatory"` +} + +// type GetPolicyTemplateVersionResponse struct { +// PolicyTemplate PolicyTemplate `json:"policyTemplate"` +// } +type GetPolicyTemplateDeployResponse struct { + DeployVersion map[string]string `json:"deployVersion"` +} + +type GetOrganizationPolicyTemplateDeployResponse struct { + DeployVersion map[string]string `json:"deployVersion"` +} + +type ListPolicyTemplateVersionsResponse struct { + Versions []string `json:"versions" example:"v1.1.0,v1.0.1,v1.0.0"` +} + +type ListOrganizationPolicyTemplateVersionsResponse struct { + Versions []string `json:"versions" example:"v1.1.0,v1.0.1,v1.0.0"` +} + +type GetPolicyTemplateVersionResponse struct { + PolicyTemplate PolicyTemplateResponse `json:"policyTemplate"` +} + +type GetOrganizationPolicyTemplateVersionResponse struct { + PolicyTemplate OrganizationPolicyTemplate `json:"policyTemplate"` +} + +type CreatePolicyTemplateVersionRequest struct { + VersionUpType string `json:"versionUpType" enums:"major,minor,patch" example:"minor"` + CurrentVersion string `json:"currentVersion" example:"v1.0.0"` + ExpectedVersion string `json:"expectedVersion" example:"v1.1.0"` + + ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` + // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" + + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` +} + +type CreateOrganizationPolicyTemplateVersionRequest struct { + CreatePolicyTemplateVersionRequest +} + +type CreatePolicyTemplateVersionResponse struct { + Version string `json:"version" example:"v1.1.1"` +} + +type CreateOrganizationPolicyTemplateVersionResponse struct { + Version string `json:"version" example:"v1.1.1"` +} + +type GetPolicyTemplateResponse struct { + PolicyTemplate PolicyTemplateResponse `json:"policyTemplate"` +} + +type GetOrganizationPolicyTemplateResponse struct { + PolicyTemplate OrganizationPolicyTemplate `json:"policyTemplate"` +} + +type ListPolicyTemplateResponse struct { + PolicyTemplates []PolicyTemplateResponse `json:"policyTemplates"` + Pagination PaginationResponse `json:"pagination"` +} + +type ListOrganizationPolicyTemplateResponse struct { + PolicyTemplates []OrganizationPolicyTemplate `json:"policyTemplates"` + Pagination PaginationResponse `json:"pagination"` +} + +type PolicyTemplateStatistics struct { + OrganizationId string `json:"organizationId"` + OrganizationName string `json:"organizationName"` + UsageCount int `json:"usageCount"` +} + +type OrganizationPolicyTemplateStatistics struct { + OrganizationId string `json:"organizationId"` + OrganizationName string `json:"organizationName"` + UsageCount int `json:"usageCount"` +} + +type ListPolicyTemplateStatisticsResponse struct { + PolicyTemplateStatistics []PolicyTemplateStatistics `json:"policyTemplateStatistics"` +} + +type ListOrganizationPolicyTemplateStatisticsResponse struct { + PolicyTemplateStatistics []OrganizationPolicyTemplateStatistics `json:"policyTemplateStatistics"` +} + +type ExistsPolicyTemplateNameResponse struct { +} + +type ExistsPolicyTemplateKindResponse struct { +} diff --git a/pkg/domain/rego.go b/pkg/domain/rego.go new file mode 100644 index 00000000..056111bb --- /dev/null +++ b/pkg/domain/rego.go @@ -0,0 +1,25 @@ +package domain + +type ParameterDef struct { + Key string `json:"key"` + Type string `json:"type"` + DefaultValue string `json:"defaultValue"` + Children []*ParameterDef `json:"children"` + IsArray bool +} + +type RegoCompileRequest struct { + Rego string `json:"rego" example:"Rego 코드"` +} + +type RegoCompieError struct { + Status int `json:"status" example:"400"` + Code string `json:"code" example:"P_INVALID_REGO_SYNTAX"` + Message string `json:"message" example:"Invalid rego syntax"` + Text string `json:"text" example:"Rego 문법 에러입니다. 라인:2 컬럼:1 에러메시지: var testnum is not safe"` +} + +type RegoCompileResponse struct { + ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` + Errors []RegoCompieError `json:"errors,omitempty"` +} From 4bc7ecbdea9731cd16f38008b2991b50badadf89 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 11 Mar 2024 11:59:37 +0900 Subject: [PATCH 106/502] rego-compile: utility->policytemplates, /ap1/1.0 prefix duplication removal --- api/swagger/docs.go | 506 +++++++++++----------- api/swagger/swagger.json | 506 +++++++++++----------- api/swagger/swagger.yaml | 396 ++++++++--------- internal/delivery/http/policy-template.go | 74 +++- internal/delivery/http/utility.go | 73 ---- internal/route/route.go | 5 +- internal/usecase/policy-template.go | 144 ++++++ internal/usecase/usecase.go | 1 - internal/usecase/utility.go | 161 ------- pkg/domain/policy-template.go | 24 + pkg/domain/rego.go | 25 -- 11 files changed, 934 insertions(+), 981 deletions(-) delete mode 100644 internal/delivery/http/utility.go delete mode 100644 internal/usecase/utility.go delete mode 100644 pkg/domain/rego.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 47e43b6b..b40b355d 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -214,14 +214,14 @@ const docTemplate = `{ } } }, - "/admin/stack-templates": { + "/admin/policytemplates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get StackTemplates", + "description": "정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다.", "consumes": [ "application/json" ], @@ -229,9 +229,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Get StackTemplates", + "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", "parameters": [ { "type": "string", @@ -272,7 +272,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" } } } @@ -283,7 +283,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Create StackTemplate", + "description": "정책 템플릿을 신규 생성(v1.0.0을 생성)한다.", "consumes": [ "application/json" ], @@ -291,17 +291,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", "parameters": [ { - "description": "create stack template request", + "description": "create policy template request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" } } ], @@ -309,20 +309,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" } } } } }, - "/admin/stack-templates/services": { + "/admin/policytemplates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get GetStackTemplateServices", + "description": "해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다.", "consumes": [ "application/json" ], @@ -330,27 +330,36 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" + ], + "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 이름", + "name": "policyTemplateKind", + "in": "path", + "required": true + } ], - "summary": "Get GetStackTemplateServices", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" } } } } }, - "/admin/stack-templates/{stackTemplateId}": { + "/admin/policytemplates/name/{policyTemplateName}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get StackTemplate", + "description": "해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다.", "consumes": [ "application/json" ], @@ -358,14 +367,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Get StackTemplate", + "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", "parameters": [ { "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", + "description": "정책 템플릿 이름", + "name": "policyTemplateName", "in": "path", "required": true } @@ -374,18 +383,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } - }, - "put": { + } + }, + "/admin/policytemplates/{policyTemplateId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update StackTemplate", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", "consumes": [ "application/json" ], @@ -393,23 +404,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", "parameters": [ { - "description": "Update stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" - } + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" + } } } }, @@ -419,7 +431,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Delete StackTemplate", + "description": "정책 템플릿을 삭제한다.", "consumes": [ "application/json" ], @@ -427,14 +439,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", "parameters": [ { "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true } @@ -444,16 +456,14 @@ const docTemplate = `{ "description": "OK" } } - } - }, - "/admin/stack-templates/{stackTemplateId}/organizations": { - "put": { + }, + "patch": { "security": [ { "JWT": [] } ], - "description": "Update StackTemplate organizations", + "description": "정책 템플릿의 업데이트 가능한 필드들을 업데이트한다.", "consumes": [ "application/json" ], @@ -461,17 +471,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Update StackTemplate organizations", + "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", "parameters": [ { - "description": "Update stack template organizations request", + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "update policy template request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" } } ], @@ -482,14 +499,14 @@ const docTemplate = `{ } } }, - "/api/1.0/admin/policytemplates": { + "/admin/policytemplates/{policyTemplateId}/deploy": { "get": { "security": [ { "JWT": [] } ], - "description": "정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다.", + "description": "해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다.", "consumes": [ "application/json" ], @@ -499,59 +516,34 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", + "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", "parameters": [ { "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" } } } - }, - "post": { + } + }, + "/admin/policytemplates/{policyTemplateId}/statistics": { + "get": { "security": [ { "JWT": [] } ], - "description": "정책 템플릿을 신규 생성(v1.0.0을 생성)한다.", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다.", "consumes": [ "application/json" ], @@ -561,36 +553,34 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", + "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", "parameters": [ { - "description": "create policy template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" - } + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" } } } } }, - "/api/1.0/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "/admin/policytemplates/{policyTemplateId}/versions": { "get": { "security": [ { "JWT": [] } ], - "description": "해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다.", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", "consumes": [ "application/json" ], @@ -600,12 +590,12 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", + "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", "parameters": [ { "type": "string", - "description": "정책 템플릿 이름", - "name": "policyTemplateKind", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true } @@ -614,20 +604,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" } } } - } - }, - "/api/1.0/admin/policytemplates/name/{policyTemplateName}/existence": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다.", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다.", "consumes": [ "application/json" ], @@ -637,34 +625,43 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", "parameters": [ { "type": "string", - "description": "정책 템플릿 이름", - "name": "policyTemplateName", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true + }, + { + "description": "create policy template version request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" } } } } }, - "/api/1.0/admin/policytemplates/{policyTemplateId}": { + "/admin/policytemplates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다.", "consumes": [ "application/json" ], @@ -674,7 +671,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", + "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", "parameters": [ { "type": "string", @@ -682,13 +679,20 @@ const docTemplate = `{ "name": "policyTemplateId", "in": "path", "required": true + }, + { + "type": "string", + "description": "조회할 버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" } } } @@ -699,7 +703,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "정책 템플릿을 삭제한다.", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다.", "consumes": [ "application/json" ], @@ -709,7 +713,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", + "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", "parameters": [ { "type": "string", @@ -717,6 +721,13 @@ const docTemplate = `{ "name": "policyTemplateId", "in": "path", "required": true + }, + { + "type": "string", + "description": "삭제할 버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true } ], "responses": { @@ -724,14 +735,16 @@ const docTemplate = `{ "description": "OK" } } - }, - "patch": { + } + }, + "/admin/stack-templates": { + "get": { "security": [ { "JWT": [] } ], - "description": "정책 템플릿의 업데이트 가능한 필드들을 업데이트한다.", + "description": "Get StackTemplates", "consumes": [ "application/json" ], @@ -739,42 +752,61 @@ const docTemplate = `{ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", + "summary": "Get StackTemplates", "parameters": [ { "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true + "description": "pageSize", + "name": "limit", + "in": "query" }, { - "description": "update policy template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" - } + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } } } - } - }, - "/api/1.0/admin/policytemplates/{policyTemplateId}/deploy": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다.", + "description": "Create StackTemplate", "consumes": [ "application/json" ], @@ -782,36 +814,38 @@ const docTemplate = `{ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", + "summary": "Create StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true + "description": "create stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" } } } } }, - "/api/1.0/admin/policytemplates/{policyTemplateId}/statistics": { + "/admin/stack-templates/services": { "get": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다.", + "description": "Get GetStackTemplateServices", "consumes": [ "application/json" ], @@ -819,36 +853,27 @@ const docTemplate = `{ "application/json" ], "tags": [ - "PolicyTemplate" - ], - "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", - "parameters": [ - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true - } + "StackTemplates" ], + "summary": "Get GetStackTemplateServices", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse" } } } } }, - "/api/1.0/admin/policytemplates/{policyTemplateId}/versions": { + "/admin/stack-templates/{stackTemplateId}": { "get": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", + "description": "Get StackTemplate", "consumes": [ "application/json" ], @@ -856,14 +881,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", + "summary": "Get StackTemplate", "parameters": [ { "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", + "description": "stackTemplateId", + "name": "stackTemplateId", "in": "path", "required": true } @@ -872,18 +897,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" } } } }, - "post": { + "put": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다.", + "description": "Update StackTemplate", "consumes": [ "application/json" ], @@ -891,45 +916,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", + "summary": "Update StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true - }, - { - "description": "create policy template version request", + "description": "Update stack template request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" - } + "description": "OK" } } - } - }, - "/api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version}": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다.", + "description": "Delete StackTemplate", "consumes": [ "application/json" ], @@ -937,41 +950,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", + "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "조회할 버전(v0.0.0 형식)", - "name": "version", + "description": "stackTemplateId", + "name": "stackTemplateId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" - } + "description": "OK" } } - }, - "delete": { + } + }, + "/admin/stack-templates/{stackTemplateId}/organizations": { + "put": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다.", + "description": "Update StackTemplate organizations", "consumes": [ "application/json" ], @@ -979,23 +984,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", + "summary": "Update StackTemplate organizations", "parameters": [ { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "삭제할 버전(v0.0.0 형식)", - "name": "version", - "in": "path", - "required": true + "description": "Update stack template organizations request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest" + } } ], "responses": { @@ -6538,14 +6538,14 @@ const docTemplate = `{ } } }, - "/system-api/organizations/{organizationId}/alerts": { + "/policytemplates/rego-compile": { "post": { "security": [ { "JWT": [] } ], - "description": "Create alert. ADMIN ONLY", + "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", "consumes": [ "application/json" ], @@ -6553,33 +6553,45 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Alerts" + "PolicyTemplate" ], - "summary": "Create alert. ADMIN ONLY", + "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", + "type": "boolean", + "description": "파라미터 파싱 여부", + "name": "parseParameter", + "in": "query", "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" + } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" + } } } } }, - "/utility/rego-compile": { + "/system-api/organizations/{organizationId}/alerts": { "post": { "security": [ { "JWT": [] } ], - "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", + "description": "Create alert. ADMIN ONLY", "consumes": [ "application/json" ], @@ -6587,33 +6599,21 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Rego" + "Alerts" ], - "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", + "summary": "Create alert. ADMIN ONLY", "parameters": [ { - "type": "boolean", - "description": "파라미터 파싱 여부", - "name": "parseParameter", - "in": "query", + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", "required": true - }, - { - "description": "Rego 코드", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" - } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" - } + "description": "OK" } } } diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 42ee1952..647962a1 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -208,14 +208,14 @@ } } }, - "/admin/stack-templates": { + "/admin/policytemplates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get StackTemplates", + "description": "정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다.", "consumes": [ "application/json" ], @@ -223,9 +223,9 @@ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Get StackTemplates", + "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", "parameters": [ { "type": "string", @@ -266,7 +266,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" } } } @@ -277,7 +277,7 @@ "JWT": [] } ], - "description": "Create StackTemplate", + "description": "정책 템플릿을 신규 생성(v1.0.0을 생성)한다.", "consumes": [ "application/json" ], @@ -285,17 +285,17 @@ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", "parameters": [ { - "description": "create stack template request", + "description": "create policy template request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" } } ], @@ -303,20 +303,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" } } } } }, - "/admin/stack-templates/services": { + "/admin/policytemplates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get GetStackTemplateServices", + "description": "해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다.", "consumes": [ "application/json" ], @@ -324,27 +324,36 @@ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" + ], + "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 이름", + "name": "policyTemplateKind", + "in": "path", + "required": true + } ], - "summary": "Get GetStackTemplateServices", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" } } } } }, - "/admin/stack-templates/{stackTemplateId}": { + "/admin/policytemplates/name/{policyTemplateName}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get StackTemplate", + "description": "해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다.", "consumes": [ "application/json" ], @@ -352,14 +361,14 @@ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Get StackTemplate", + "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", "parameters": [ { "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", + "description": "정책 템플릿 이름", + "name": "policyTemplateName", "in": "path", "required": true } @@ -368,18 +377,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } - }, - "put": { + } + }, + "/admin/policytemplates/{policyTemplateId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update StackTemplate", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", "consumes": [ "application/json" ], @@ -387,23 +398,24 @@ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", "parameters": [ { - "description": "Update stack template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" - } + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" + } } } }, @@ -413,7 +425,7 @@ "JWT": [] } ], - "description": "Delete StackTemplate", + "description": "정책 템플릿을 삭제한다.", "consumes": [ "application/json" ], @@ -421,14 +433,14 @@ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", "parameters": [ { "type": "string", - "description": "stackTemplateId", - "name": "stackTemplateId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true } @@ -438,16 +450,14 @@ "description": "OK" } } - } - }, - "/admin/stack-templates/{stackTemplateId}/organizations": { - "put": { + }, + "patch": { "security": [ { "JWT": [] } ], - "description": "Update StackTemplate organizations", + "description": "정책 템플릿의 업데이트 가능한 필드들을 업데이트한다.", "consumes": [ "application/json" ], @@ -455,17 +465,24 @@ "application/json" ], "tags": [ - "StackTemplates" + "PolicyTemplate" ], - "summary": "Update StackTemplate organizations", + "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", "parameters": [ { - "description": "Update stack template organizations request", + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "update policy template request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" } } ], @@ -476,14 +493,14 @@ } } }, - "/api/1.0/admin/policytemplates": { + "/admin/policytemplates/{policyTemplateId}/deploy": { "get": { "security": [ { "JWT": [] } ], - "description": "정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다.", + "description": "해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다.", "consumes": [ "application/json" ], @@ -493,59 +510,34 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", + "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", "parameters": [ { "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" } } } - }, - "post": { + } + }, + "/admin/policytemplates/{policyTemplateId}/statistics": { + "get": { "security": [ { "JWT": [] } ], - "description": "정책 템플릿을 신규 생성(v1.0.0을 생성)한다.", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다.", "consumes": [ "application/json" ], @@ -555,36 +547,34 @@ "tags": [ "PolicyTemplate" ], - "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", + "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", "parameters": [ { - "description": "create policy template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" - } + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" } } } } }, - "/api/1.0/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "/admin/policytemplates/{policyTemplateId}/versions": { "get": { "security": [ { "JWT": [] } ], - "description": "해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다.", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", "consumes": [ "application/json" ], @@ -594,12 +584,12 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", + "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", "parameters": [ { "type": "string", - "description": "정책 템플릿 이름", - "name": "policyTemplateKind", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true } @@ -608,20 +598,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" } } } - } - }, - "/api/1.0/admin/policytemplates/name/{policyTemplateName}/existence": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다.", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다.", "consumes": [ "application/json" ], @@ -631,34 +619,43 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", "parameters": [ { "type": "string", - "description": "정책 템플릿 이름", - "name": "policyTemplateName", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true + }, + { + "description": "create policy template version request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" } } } } }, - "/api/1.0/admin/policytemplates/{policyTemplateId}": { + "/admin/policytemplates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다.", "consumes": [ "application/json" ], @@ -668,7 +665,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", + "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", "parameters": [ { "type": "string", @@ -676,13 +673,20 @@ "name": "policyTemplateId", "in": "path", "required": true + }, + { + "type": "string", + "description": "조회할 버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" } } } @@ -693,7 +697,7 @@ "JWT": [] } ], - "description": "정책 템플릿을 삭제한다.", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다.", "consumes": [ "application/json" ], @@ -703,7 +707,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", + "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", "parameters": [ { "type": "string", @@ -711,6 +715,13 @@ "name": "policyTemplateId", "in": "path", "required": true + }, + { + "type": "string", + "description": "삭제할 버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true } ], "responses": { @@ -718,14 +729,16 @@ "description": "OK" } } - }, - "patch": { + } + }, + "/admin/stack-templates": { + "get": { "security": [ { "JWT": [] } ], - "description": "정책 템플릿의 업데이트 가능한 필드들을 업데이트한다.", + "description": "Get StackTemplates", "consumes": [ "application/json" ], @@ -733,42 +746,61 @@ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", + "summary": "Get StackTemplates", "parameters": [ { "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true + "description": "pageSize", + "name": "limit", + "in": "query" }, { - "description": "update policy template request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" - } + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } } } - } - }, - "/api/1.0/admin/policytemplates/{policyTemplateId}/deploy": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다.", + "description": "Create StackTemplate", "consumes": [ "application/json" ], @@ -776,36 +808,38 @@ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", + "summary": "Create StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true + "description": "create stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse" } } } } }, - "/api/1.0/admin/policytemplates/{policyTemplateId}/statistics": { + "/admin/stack-templates/services": { "get": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다.", + "description": "Get GetStackTemplateServices", "consumes": [ "application/json" ], @@ -813,36 +847,27 @@ "application/json" ], "tags": [ - "PolicyTemplate" - ], - "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", - "parameters": [ - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true - } + "StackTemplates" ], + "summary": "Get GetStackTemplateServices", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse" } } } } }, - "/api/1.0/admin/policytemplates/{policyTemplateId}/versions": { + "/admin/stack-templates/{stackTemplateId}": { "get": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", + "description": "Get StackTemplate", "consumes": [ "application/json" ], @@ -850,14 +875,14 @@ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", + "summary": "Get StackTemplate", "parameters": [ { "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", + "description": "stackTemplateId", + "name": "stackTemplateId", "in": "path", "required": true } @@ -866,18 +891,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" } } } }, - "post": { + "put": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다.", + "description": "Update StackTemplate", "consumes": [ "application/json" ], @@ -885,45 +910,33 @@ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", + "summary": "Update StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true - }, - { - "description": "create policy template version request", + "description": "Update stack template request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest" } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" - } + "description": "OK" } } - } - }, - "/api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version}": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다.", + "description": "Delete StackTemplate", "consumes": [ "application/json" ], @@ -931,41 +944,33 @@ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", + "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "조회할 버전(v0.0.0 형식)", - "name": "version", + "description": "stackTemplateId", + "name": "stackTemplateId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" - } + "description": "OK" } } - }, - "delete": { + } + }, + "/admin/stack-templates/{stackTemplateId}/organizations": { + "put": { "security": [ { "JWT": [] } ], - "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다.", + "description": "Update StackTemplate organizations", "consumes": [ "application/json" ], @@ -973,23 +978,18 @@ "application/json" ], "tags": [ - "PolicyTemplate" + "StackTemplates" ], - "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", + "summary": "Update StackTemplate organizations", "parameters": [ { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "policyTemplateId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "삭제할 버전(v0.0.0 형식)", - "name": "version", - "in": "path", - "required": true + "description": "Update stack template organizations request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest" + } } ], "responses": { @@ -6532,14 +6532,14 @@ } } }, - "/system-api/organizations/{organizationId}/alerts": { + "/policytemplates/rego-compile": { "post": { "security": [ { "JWT": [] } ], - "description": "Create alert. ADMIN ONLY", + "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", "consumes": [ "application/json" ], @@ -6547,33 +6547,45 @@ "application/json" ], "tags": [ - "Alerts" + "PolicyTemplate" ], - "summary": "Create alert. ADMIN ONLY", + "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", + "type": "boolean", + "description": "파라미터 파싱 여부", + "name": "parseParameter", + "in": "query", "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" + } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" + } } } } }, - "/utility/rego-compile": { + "/system-api/organizations/{organizationId}/alerts": { "post": { "security": [ { "JWT": [] } ], - "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", + "description": "Create alert. ADMIN ONLY", "consumes": [ "application/json" ], @@ -6581,33 +6593,21 @@ "application/json" ], "tags": [ - "Rego" + "Alerts" ], - "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", + "summary": "Create alert. ADMIN ONLY", "parameters": [ { - "type": "boolean", - "description": "파라미터 파싱 여부", - "name": "parseParameter", - "in": "query", + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", "required": true - }, - { - "description": "Rego 코드", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" - } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" - } + "description": "OK" } } } diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 0f3906d9..60216b96 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -3188,174 +3188,7 @@ paths: summary: Update user by admin tags: - Admin - /admin/stack-templates: - get: - consumes: - - application/json - description: Get StackTemplates - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' - security: - - JWT: [] - summary: Get StackTemplates - tags: - - StackTemplates - post: - consumes: - - application/json - description: Create StackTemplate - parameters: - - description: create stack template request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse' - security: - - JWT: [] - summary: Create StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates - /admin/stack-templates/{stackTemplateId}: - delete: - consumes: - - application/json - description: Delete StackTemplate - parameters: - - description: stackTemplateId - in: path - name: stackTemplateId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates - get: - consumes: - - application/json - description: Get StackTemplate - parameters: - - description: stackTemplateId - in: path - name: stackTemplateId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse' - security: - - JWT: [] - summary: Get StackTemplate - tags: - - StackTemplates - put: - consumes: - - application/json - description: Update StackTemplate - parameters: - - description: Update stack template request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update StackTemplate 'NOT IMPLEMENTED' - tags: - - StackTemplates - /admin/stack-templates/{stackTemplateId}/organizations: - put: - consumes: - - application/json - description: Update StackTemplate organizations - parameters: - - description: Update stack template organizations request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update StackTemplate organizations - tags: - - StackTemplates - /admin/stack-templates/services: - get: - consumes: - - application/json - description: Get GetStackTemplateServices - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse' - security: - - JWT: [] - summary: Get GetStackTemplateServices - tags: - - StackTemplates - /api/1.0/admin/policytemplates: + /admin/policytemplates: get: consumes: - application/json @@ -3419,7 +3252,7 @@ paths: summary: '[CreatePolicyTemplate] 정책 템플릿 신규 생성' tags: - PolicyTemplate - /api/1.0/admin/policytemplates/{policyTemplateId}: + /admin/policytemplates/{policyTemplateId}: delete: consumes: - application/json @@ -3488,7 +3321,7 @@ paths: summary: '[UpdatePolicyTemplate] 정책 템플릿 업데이트' tags: - PolicyTemplate - /api/1.0/admin/policytemplates/{policyTemplateId}/deploy: + /admin/policytemplates/{policyTemplateId}/deploy: get: consumes: - application/json @@ -3511,7 +3344,7 @@ paths: summary: '[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회' tags: - PolicyTemplate - /api/1.0/admin/policytemplates/{policyTemplateId}/statistics: + /admin/policytemplates/{policyTemplateId}/statistics: get: consumes: - application/json @@ -3535,7 +3368,7 @@ paths: summary: '[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회' tags: - PolicyTemplate - /api/1.0/admin/policytemplates/{policyTemplateId}/versions: + /admin/policytemplates/{policyTemplateId}/versions: get: consumes: - application/json @@ -3586,7 +3419,7 @@ paths: summary: '[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장' tags: - PolicyTemplate - /api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version}: + /admin/policytemplates/{policyTemplateId}/versions/{version}: delete: consumes: - application/json @@ -3639,7 +3472,7 @@ paths: summary: '[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' tags: - PolicyTemplate - /api/1.0/admin/policytemplates/kind/{policyTemplateKind}/existence: + /admin/policytemplates/kind/{policyTemplateKind}/existence: get: consumes: - application/json @@ -3662,7 +3495,7 @@ paths: summary: '[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인' tags: - PolicyTemplate - /api/1.0/admin/policytemplates/name/{policyTemplateName}/existence: + /admin/policytemplates/name/{policyTemplateName}/existence: get: consumes: - application/json @@ -3685,6 +3518,173 @@ paths: summary: '[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인' tags: - PolicyTemplate + /admin/stack-templates: + get: + consumes: + - application/json + description: Get StackTemplates + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' + security: + - JWT: [] + summary: Get StackTemplates + tags: + - StackTemplates + post: + consumes: + - application/json + description: Create StackTemplate + parameters: + - description: create stack template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse' + security: + - JWT: [] + summary: Create StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + /admin/stack-templates/{stackTemplateId}: + delete: + consumes: + - application/json + description: Delete StackTemplate + parameters: + - description: stackTemplateId + in: path + name: stackTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + get: + consumes: + - application/json + description: Get StackTemplate + parameters: + - description: stackTemplateId + in: path + name: stackTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse' + security: + - JWT: [] + summary: Get StackTemplate + tags: + - StackTemplates + put: + consumes: + - application/json + description: Update StackTemplate + parameters: + - description: Update stack template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update StackTemplate 'NOT IMPLEMENTED' + tags: + - StackTemplates + /admin/stack-templates/{stackTemplateId}/organizations: + put: + consumes: + - application/json + description: Update StackTemplate organizations + parameters: + - description: Update stack template organizations request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update StackTemplate organizations + tags: + - StackTemplates + /admin/stack-templates/services: + get: + consumes: + - application/json + description: Get GetStackTemplateServices + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateServicesResponse' + security: + - JWT: [] + summary: Get GetStackTemplateServices + tags: + - StackTemplates /app-groups: delete: consumes: @@ -7235,28 +7235,7 @@ paths: summary: Get Permission Templates tags: - Permission - /system-api/organizations/{organizationId}/alerts: - post: - consumes: - - application/json - description: Create alert. ADMIN ONLY - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Create alert. ADMIN ONLY - tags: - - Alerts - /utility/rego-compile: + /policytemplates/rego-compile: post: consumes: - application/json @@ -7285,7 +7264,28 @@ paths: - JWT: [] summary: '[CompileRego] Rego 코드 컴파일 및 파라미터 파싱' tags: - - Rego + - PolicyTemplate + /system-api/organizations/{organizationId}/alerts: + post: + consumes: + - application/json + description: Create alert. ADMIN ONLY + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Create alert. ADMIN ONLY + tags: + - Alerts securityDefinitions: JWT: in: header diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 3206545c..2e4a4202 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -3,6 +3,7 @@ package http import ( "fmt" "net/http" + "strconv" "strings" "github.com/google/uuid" @@ -35,6 +36,7 @@ type IPolicyTemplateHandler interface { GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) + RegoCompile(w http.ResponseWriter, r *http.Request) } func NewPolicyTemplateHandler(u usecase.Usecase) IPolicyTemplateHandler { @@ -52,7 +54,7 @@ func NewPolicyTemplateHandler(u usecase.Usecase) IPolicyTemplateHandler { // @Produce json // @Param body body domain.CreatePolicyTemplateRequest true "create policy template request" // @Success 200 {object} domain.CreatePolicyTemplateReponse -// @Router /api/1.0/admin/policytemplates [post] +// @Router /admin/policytemplates [post] // @Security JWT func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) { input := domain.CreatePolicyTemplateRequest{} @@ -92,7 +94,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param body body domain.UpdatePolicyTemplateRequest true "update policy template request" // @Success 200 {object} nil -// @Router /api/1.0/admin/policytemplates/{policyTemplateId} [patch] +// @Router /admin/policytemplates/{policyTemplateId} [patch] // @Security JWT func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -149,7 +151,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} nil -// @Router /api/1.0/admin/policytemplates/{policyTemplateId} [delete] +// @Router /admin/policytemplates/{policyTemplateId} [delete] // @Security JWT func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -196,7 +198,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *h // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.GetPolicyTemplateResponse -// @Router /api/1.0/admin/policytemplates/{policyTemplateId} [get] +// @Router /admin/policytemplates/{policyTemplateId} [get] // @Security JWT func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -251,7 +253,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.ListPolicyTemplateResponse -// @Router /api/1.0/admin/policytemplates [get] +// @Router /admin/policytemplates [get] // @Security JWT func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -289,7 +291,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.ListPolicyTemplateVersionsResponse -// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/versions [get] +// @Router /admin/policytemplates/{policyTemplateId}/versions [get] // @Security JWT func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -342,7 +344,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.ListPolicyTemplateStatisticsResponse -// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/statistics [get] +// @Router /admin/policytemplates/{policyTemplateId}/statistics [get] // @Security JWT func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { // result := domain.ListPolicyTemplateStatisticsResponse{ @@ -371,7 +373,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWrit // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.GetPolicyTemplateDeployResponse -// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/deploy [get] +// @Router /admin/policytemplates/{policyTemplateId}/deploy [get] // @Security JWT func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { // c1 := util.UUIDGen() @@ -398,7 +400,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param version path string true "조회할 버전(v0.0.0 형식)" // @Success 200 {object} domain.GetPolicyTemplateVersionResponse -// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version} [get] +// @Router /admin/policytemplates/{policyTemplateId}/versions/{version} [get] // @Security JWT func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -456,7 +458,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param body body domain.CreatePolicyTemplateVersionRequest true "create policy template version request" // @Success 200 {object} domain.CreatePolicyTemplateVersionResponse -// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/versions [post] +// @Router /admin/policytemplates/{policyTemplateId}/versions [post] // @Security JWT func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -538,7 +540,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param version path string true "삭제할 버전(v0.0.0 형식)" // @Success 200 {object} nil -// @Router /api/1.0/admin/policytemplates/{policyTemplateId}/versions/{version} [delete] +// @Router /admin/policytemplates/{policyTemplateId}/versions/{version} [delete] // @Security JWT func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -591,7 +593,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite // @Produce json // @Param policyTemplateName path string true "정책 템플릿 이름" // @Success 200 {object} domain.CheckExistedResponse -// @Router /api/1.0/admin/policytemplates/name/{policyTemplateName}/existence [get] +// @Router /admin/policytemplates/name/{policyTemplateName}/existence [get] // @Security JWT func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -623,7 +625,7 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, // @Produce json // @Param policyTemplateKind path string true "정책 템플릿 이름" // @Success 200 {object} domain.ExistsPolicyTemplateKindResponse -// @Router /api/1.0/admin/policytemplates/kind/{policyTemplateKind}/existence [get] +// @Router /admin/policytemplates/kind/{policyTemplateKind}/existence [get] // @Security JWT func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -645,3 +647,49 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, ResponseJSON(w, r, http.StatusOK, out) } + +// CompileRego godoc +// +// @Tags PolicyTemplate +// @Summary [CompileRego] Rego 코드 컴파일 및 파라미터 파싱 +// @Description Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다. +// @Accept json +// @Produce json +// @Param parseParameter query bool true "파라미터 파싱 여부" +// @Param body body domain.RegoCompileRequest true "Rego 코드" +// @Success 200 {object} domain.RegoCompileResponse +// @Router /policytemplates/rego-compile [post] +// @Security JWT +func (h *PolicyTemplateHandler) RegoCompile(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + parseParameter := false + + parse, ok := vars["parseParameter"] + if ok { + parsedBool, err := strconv.ParseBool(parse) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid parseParameter: '%s'", parse), "U_INVALID_REGO_PARSEPARAM", "")) + return + } + parseParameter = parsedBool + } + + input := domain.RegoCompileRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + response, err := h.usecase.RegoCompile(&input, parseParameter) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusCreated, response) +} diff --git a/internal/delivery/http/utility.go b/internal/delivery/http/utility.go deleted file mode 100644 index f22d18fc..00000000 --- a/internal/delivery/http/utility.go +++ /dev/null @@ -1,73 +0,0 @@ -package http - -import ( - "fmt" - "net/http" - "strconv" - - "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal/usecase" - "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" -) - -type UtilityHandler struct { - usecase usecase.IUtilityUsecase -} - -type IUtilityHandler interface { - RegoCompile(w http.ResponseWriter, r *http.Request) -} - -func NewUtilityHandler(u usecase.Usecase) IUtilityHandler { - return &UtilityHandler{ - usecase: u.Utility, - } -} - -// CompileRego godoc -// -// @Tags Rego -// @Summary [CompileRego] Rego 코드 컴파일 및 파라미터 파싱 -// @Description Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다. -// @Accept json -// @Produce json -// @Param parseParameter query bool true "파라미터 파싱 여부" -// @Param body body domain.RegoCompileRequest true "Rego 코드" -// @Success 200 {object} domain.RegoCompileResponse -// @Router /utility/rego-compile [post] -// @Security JWT -func (h *UtilityHandler) RegoCompile(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - parseParameter := false - - parse, ok := vars["parseParameter"] - if ok { - parsedBool, err := strconv.ParseBool(parse) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid parseParameter: '%s'", parse), "U_INVALID_REGO_PARSEPARAM", "")) - return - } - parseParameter = parsedBool - } - - input := domain.RegoCompileRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - - ErrorJSON(w, r, err) - return - } - - response, err := h.usecase.RegoCompile(&input, parseParameter) - if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - - ErrorJSON(w, r, err) - return - } - - ResponseJSON(w, r, http.StatusCreated, response) -} diff --git a/internal/route/route.go b/internal/route/route.go index 76106a23..c28e1da8 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -75,7 +75,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Role: usecase.NewRoleUsecase(repoFactory), Permission: usecase.NewPermissionUsecase(repoFactory), PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), - Utility: usecase.NewUtilityUsecase(repoFactory), } customMiddleware := internalMiddleware.NewMiddleware( @@ -282,9 +281,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateVersion))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateKind))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateName))).Methods(http.MethodGet) - - utilityHandler := delivery.NewUtilityHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/utility/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(utilityHandler.RegoCompile))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/policytemplates/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(policyTemplateHandler.RegoCompile))).Methods(http.MethodPost) // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 2b48af42..46f647fe 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -3,8 +3,11 @@ package usecase import ( "context" "fmt" + "regexp" + "strings" "github.com/google/uuid" + "github.com/open-policy-agent/opa/ast" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" @@ -24,6 +27,8 @@ type IPolicyTemplateUsecase interface { ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) + + RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) } type PolicyTemplateUsecase struct { @@ -226,3 +231,142 @@ func (u *PolicyTemplateUsecase) DeletePolicyTemplateVersion(ctx context.Context, func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { return u.repo.CreatePolicyTemplateVersion(policyTemplateId, newVersion, schema, rego, libs) } + +func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) { + modules := map[string]*ast.Module{} + + response = &domain.RegoCompileResponse{} + response.Errors = []domain.RegoCompieError{} + + mod, err := ast.ParseModuleWithOpts("rego", request.Rego, ast.ParserOptions{}) + if err != nil { + return nil, err + } + modules["rego"] = mod + + compiler := ast.NewCompiler() + compiler.Compile(modules) + + if compiler.Failed() { + for _, compileError := range compiler.Errors { + response.Errors = append(response.Errors, domain.RegoCompieError{ + Status: 400, + Code: "P_INVALID_REGO_SYNTAX", + Message: "Invalid rego syntax", + Text: fmt.Sprintf("[%d:%d] %s", + compileError.Location.Row, compileError.Location.Col, + compileError.Message), + }) + } + } + + if parseParameter { + response.ParametersSchema = extractParameter(request.Rego) + } + + return response, nil +} + +func extractParameter(rego string) []*domain.ParameterDef { + pattern := `input\.parameters\.[\w\.\[\]]+` + + prefix := "input.parameters." + + // Compile the regex pattern + regex := regexp.MustCompile(pattern) + + matches := regex.FindAllString(rego, -1) + + defStore := NewParamDefStore() + + for _, match := range matches { + remainder := match[len(prefix):] + + // 문법 변환: aa["a"]["B"][_]->aa.a.B[_] + regex := regexp.MustCompile(`\[\"(\w+)\"\]`) + remainder = regex.ReplaceAllString(remainder, ".$1") + + params := strings.Split(remainder, ".") + + if len(params) == 0 { + continue + } + + defStore.AddDefinition(params) + } + + return defStore.store +} + +type ParamDefStore struct { + store []*domain.ParameterDef +} + +func NewParamDefStore() *ParamDefStore { + return &ParamDefStore{store: []*domain.ParameterDef{}} +} + +func (s *ParamDefStore) GetStore() []*domain.ParameterDef { + return s.store +} + +func (s *ParamDefStore) AddDefinition(params []string) { + init := &s.store + + for i, param := range params { + isLast := i == len(params)-1 + + key := findKey(s.store, param) + + if key == nil { + key = createKey(param, isLast) + *init = append(*init, key) + } + + init = &key.Children + } +} + +func findKey(defs []*domain.ParameterDef, key string) *domain.ParameterDef { + for _, def := range defs { + if def.Key == key || def.Key+"[_]" == key { + return def + } + } + + return nil +} + +func createKey(key string, isLast bool) *domain.ParameterDef { + finalType := "any" + + pKey := key + isArray := false + + if strings.HasSuffix(pKey, "[_]") { + pKey, _ = strings.CutSuffix(pKey, "[_]") + isArray = true + } + + if isLast { + if isArray { + finalType = "any[]" + } else { + finalType = "any" + } + } else { + if isArray { + finalType = "object[]" + } else { + finalType = "object" + } + } + + newDef := &domain.ParameterDef{ + Key: pKey, + Type: finalType, + Children: []*domain.ParameterDef{}, + } + + return newDef +} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index 48f47ae2..f0ad4014 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -17,5 +17,4 @@ type Usecase struct { Permission IPermissionUsecase Audit IAuditUsecase PolicyTemplate IPolicyTemplateUsecase - Utility IUtilityUsecase } diff --git a/internal/usecase/utility.go b/internal/usecase/utility.go deleted file mode 100644 index c7f421f9..00000000 --- a/internal/usecase/utility.go +++ /dev/null @@ -1,161 +0,0 @@ -package usecase - -import ( - "fmt" - "regexp" - "strings" - - "github.com/open-policy-agent/opa/ast" - "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" -) - -type IUtilityUsecase interface { - RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) -} - -type UtilityUsecase struct { -} - -func NewUtilityUsecase(r repository.Repository) IUtilityUsecase { - return &UtilityUsecase{} -} - -func (u *UtilityUsecase) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) { - modules := map[string]*ast.Module{} - - response = &domain.RegoCompileResponse{} - response.Errors = []domain.RegoCompieError{} - - mod, err := ast.ParseModuleWithOpts("rego", request.Rego, ast.ParserOptions{}) - if err != nil { - return nil, err - } - modules["rego"] = mod - - compiler := ast.NewCompiler() - compiler.Compile(modules) - - if compiler.Failed() { - for _, compileError := range compiler.Errors { - response.Errors = append(response.Errors, domain.RegoCompieError{ - Status: 400, - Code: "P_INVALID_REGO_SYNTAX", - Message: "Invalid rego syntax", - Text: fmt.Sprintf("[%d:%d] %s", - compileError.Location.Row, compileError.Location.Col, - compileError.Message), - }) - } - } - - if parseParameter { - response.ParametersSchema = extractParameter(request.Rego) - } - - return response, nil -} - -func extractParameter(rego string) []*domain.ParameterDef { - pattern := `input\.parameters\.[\w\.\[\]]+` - - prefix := "input.parameters." - - // Compile the regex pattern - regex := regexp.MustCompile(pattern) - - matches := regex.FindAllString(rego, -1) - - defStore := NewParamDefStore() - - for _, match := range matches { - remainder := match[len(prefix):] - - // 문법 변환: aa["a"]["B"][_]->aa.a.B[_] - regex := regexp.MustCompile(`\[\"(\w+)\"\]`) - remainder = regex.ReplaceAllString(remainder, ".$1") - - params := strings.Split(remainder, ".") - - if len(params) == 0 { - continue - } - - defStore.AddDefinition(params) - } - - return defStore.store -} - -type ParamDefStore struct { - store []*domain.ParameterDef -} - -func NewParamDefStore() *ParamDefStore { - return &ParamDefStore{store: []*domain.ParameterDef{}} -} - -func (s *ParamDefStore) GetStore() []*domain.ParameterDef { - return s.store -} - -func (s *ParamDefStore) AddDefinition(params []string) { - init := &s.store - - for i, param := range params { - isLast := i == len(params)-1 - - key := findKey(s.store, param) - - if key == nil { - key = createKey(param, isLast) - *init = append(*init, key) - } - - init = &key.Children - } -} - -func findKey(defs []*domain.ParameterDef, key string) *domain.ParameterDef { - for _, def := range defs { - if def.Key == key || def.Key+"[_]" == key { - return def - } - } - - return nil -} - -func createKey(key string, isLast bool) *domain.ParameterDef { - finalType := "any" - - pKey := key - isArray := false - - if strings.HasSuffix(pKey, "[_]") { - pKey, _ = strings.CutSuffix(pKey, "[_]") - isArray = true - } - - if isLast { - if isArray { - finalType = "any[]" - } else { - finalType = "any" - } - } else { - if isArray { - finalType = "object[]" - } else { - finalType = "object" - } - } - - newDef := &domain.ParameterDef{ - Key: pKey, - Type: finalType, - Children: []*domain.ParameterDef{}, - } - - return newDef -} diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index acea768d..169714ef 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -276,3 +276,27 @@ type ExistsPolicyTemplateNameResponse struct { type ExistsPolicyTemplateKindResponse struct { } + +type ParameterDef struct { + Key string `json:"key"` + Type string `json:"type"` + DefaultValue string `json:"defaultValue"` + Children []*ParameterDef `json:"children"` + IsArray bool +} + +type RegoCompileRequest struct { + Rego string `json:"rego" example:"Rego 코드"` +} + +type RegoCompieError struct { + Status int `json:"status" example:"400"` + Code string `json:"code" example:"P_INVALID_REGO_SYNTAX"` + Message string `json:"message" example:"Invalid rego syntax"` + Text string `json:"text" example:"Rego 문법 에러입니다. 라인:2 컬럼:1 에러메시지: var testnum is not safe"` +} + +type RegoCompileResponse struct { + ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` + Errors []RegoCompieError `json:"errors,omitempty"` +} diff --git a/pkg/domain/rego.go b/pkg/domain/rego.go deleted file mode 100644 index 056111bb..00000000 --- a/pkg/domain/rego.go +++ /dev/null @@ -1,25 +0,0 @@ -package domain - -type ParameterDef struct { - Key string `json:"key"` - Type string `json:"type"` - DefaultValue string `json:"defaultValue"` - Children []*ParameterDef `json:"children"` - IsArray bool -} - -type RegoCompileRequest struct { - Rego string `json:"rego" example:"Rego 코드"` -} - -type RegoCompieError struct { - Status int `json:"status" example:"400"` - Code string `json:"code" example:"P_INVALID_REGO_SYNTAX"` - Message string `json:"message" example:"Invalid rego syntax"` - Text string `json:"text" example:"Rego 문법 에러입니다. 라인:2 컬럼:1 에러메시지: var testnum is not safe"` -} - -type RegoCompileResponse struct { - ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` - Errors []RegoCompieError `json:"errors,omitempty"` -} From d84d983dcf128977b1af15f6b555167c38c35dee Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 11 Mar 2024 15:00:55 +0900 Subject: [PATCH 107/502] errCode fix --- internal/delivery/http/policy-template.go | 75 ++++++++--------------- internal/usecase/policy-template.go | 18 +++--- pkg/httpErrors/errorCode.go | 42 ++++++++----- 3 files changed, 61 insertions(+), 74 deletions(-) diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 2e4a4202..8126e00f 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -100,19 +100,14 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_ORGANIZATION_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } id, err := uuid.Parse(policyTemplateId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - ErrorJSON(w, r, err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -157,7 +152,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *h vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -204,7 +199,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_ORGANIZATION_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -212,7 +207,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -224,7 +219,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE", "")) return } @@ -298,19 +293,14 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter policyTemplateId, ok := vars["policyTemplateId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_ORGANIZATION_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } id, err := uuid.Parse(policyTemplateId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - ErrorJSON(w, r, err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -319,7 +309,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) return } @@ -406,25 +396,19 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_ORGANIZATION_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } version, ok := vars["version"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid version"), "C_INVALID_ORGANIZATION_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid version"), "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) return } id, err := uuid.Parse(policyTemplateId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - ErrorJSON(w, r, err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -432,7 +416,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) return } @@ -464,19 +448,13 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } id, err := uuid.Parse(policyTemplateId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - ErrorJSON(w, r, err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -492,7 +470,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite currentVer, err := semver.NewVersion(input.CurrentVersion) if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid currentVersion"), "C_INVALID_CURRENT_VERSION", fmt.Sprintf("invalid version format '%s'", input.CurrentVersion))) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid currentVersion"), "PT_INVALID_POLICY_TEMPLATE_VERSION", fmt.Sprintf("invalid version format '%s'", input.CurrentVersion))) return } @@ -513,7 +491,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite } if expectedVersion != input.ExpectedVersion { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid expectedVersion"), "C_INVALID_EXPECTED_VERSION", fmt.Sprintf("expected version mismatch '%s' != '%s'", + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid expectedVersion"), "PT_INVALID_POLICY_TEMPLATE_VERSION", fmt.Sprintf("expected version mismatch '%s' != '%s'", input.ExpectedVersion, expectedVersion))) } @@ -546,25 +524,20 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } version, ok := vars["version"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid version"), "C_INVALID_VERSION", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid version"), "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) return } id, err := uuid.Parse(policyTemplateId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - ErrorJSON(w, r, err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) return } @@ -573,7 +546,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) return } @@ -600,7 +573,7 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, policyTemplateName, ok := vars["policyTemplateName"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyTemplateName not found in path"), - "C_INVALID_POLICYTEMPLATE_NAME", "")) + "PT_INVALID_POLICY_TEMPLATE_NAME", "")) return } @@ -632,7 +605,7 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, policyTemplateKind, ok := vars["policyTemplateKind"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyTemplateKind not found in path"), - "C_INVALID_POLICY_TEMPLATE_KIND", "")) + "PT_INVALID_POLICY_TEMPLATE_KIND", "")) return } @@ -668,7 +641,7 @@ func (h *PolicyTemplateHandler) RegoCompile(w http.ResponseWriter, r *http.Reque if ok { parsedBool, err := strconv.ParseBool(parse) if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid parseParameter: '%s'", parse), "U_INVALID_REGO_PARSEPARAM", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid parseParameter: '%s'", parse), "PT_INVALID_REGO_PARSEPARAMETER", "")) return } parseParameter = parsedBool diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 46f647fe..9f1b8263 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -48,23 +48,23 @@ func NewPolicyTemplateUsecase(r repository.Repository) IPolicyTemplateUsecase { func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto domain.PolicyTemplate) (policyTemplateId string, err error) { user, ok := request.UserFrom(ctx) if !ok { - return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "P_INVALID_TOKEN", "") + return "", httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } exists, err := u.repo.ExistByName(dto.TemplateName) if err == nil && exists { - return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") } exists, err = u.repo.ExistByKind(dto.Kind) if err == nil && exists { - return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_KIND", "policy template kind already exists") + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_KIND", "policy template kind already exists") } for _, organizationId := range dto.PermittedOrganizationIds { _, err = u.organizationRepo.Get(organizationId) if err != nil { - return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "", "") + return "", httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } } @@ -119,12 +119,12 @@ func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.U func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uuid.UUID, update domain.UpdatePolicyTemplateRequest) (err error) { user, ok := request.UserFrom(ctx) if !ok { - return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + return httpErrors.NewBadRequestError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } _, err = u.repo.GetByID(policyTemplateId) if err != nil { - return httpErrors.NewNotFoundError(err, "P_FAILED_FETCH_POLICY_TEMPLATE", "") + return httpErrors.NewNotFoundError(err, "PT_FAILED_FETCH_POLICY_TEMPLATE", "") } exists, err := u.repo.ExistByName(*update.TemplateName) @@ -136,7 +136,7 @@ func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uui for _, organizationId := range *update.PermittedOrganizationIds { _, err = u.organizationRepo.Get(organizationId) if err != nil { - return httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "", "") + return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } } } @@ -251,8 +251,8 @@ func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, for _, compileError := range compiler.Errors { response.Errors = append(response.Errors, domain.RegoCompieError{ Status: 400, - Code: "P_INVALID_REGO_SYNTAX", - Message: "Invalid rego syntax", + Code: "PT_INVALID_REGO_SYNTAX", + Message: "invalid rego syntax", Text: fmt.Sprintf("[%d:%d] %s", compileError.Location.Row, compileError.Location.Col, compileError.Message), diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 3a7a7e30..342fecc5 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -4,20 +4,21 @@ type ErrorCode string var errorMap = map[ErrorCode]string{ // Common - "C_INTERNAL_ERROR": "예상하지 못한 오류가 발생했습니다. 문제가 계속되면 관리자에게 문의해주세요.", - "C_INVALID_ACCOUNT_ID": "유효하지 않은 어카운트 아이디입니다. 어카운트 아이디를 확인하세요.", - "C_INVALID_STACK_ID": "유효하지 않은 스택 아이디입니다. 스택 아이디를 확인하세요.", - "C_INVALID_CLUSTER_ID": "유효하지 않은 클러스터 아이디입니다. 클러스터 아이디를 확인하세요.", - "C_INVALID_APPGROUP_ID": "유효하지 않은 앱그룹 아이디입니다. 앱그룹 아이디를 확인하세요.", - "C_INVALID_ORGANIZATION_ID": "유효하지 않은 조직 아이디입니다. 조직 아이디를 확인하세요.", - "C_INVALID_PROJECT_ID": "유효하지 않은 프로젝트 아이디입니다. 아이디를 확인하세요.", - "C_INVALID_CLOUD_ACCOUNT_ID": "유효하지 않은 클라우드어카운트 아이디입니다. 클라우드어카운트 아이디를 확인하세요.", - "C_INVALID_STACK_TEMPLATE_ID": "유효하지 않은 스택템플릿 아이디입니다. 스택템플릿 아이디를 확인하세요.", - "C_INVALID_ASA_ID": "유효하지 않은 앱서빙앱 아이디입니다. 앱서빙앱 아이디를 확인하세요.", - "C_INVALID_ASA_TASK_ID": "유효하지 않은 테스크 아이디입니다. 테스크 아이디를 확인하세요.", - "C_INVALID_CLOUD_SERVICE": "유효하지 않은 클라우드서비스입니다.", - "C_INVALID_AUDIT_ID": "유효하지 않은 로그 아이디입니다. 로그 아이디를 확인하세요.", - "C_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패했습니다.", + "C_INTERNAL_ERROR": "예상하지 못한 오류가 발생했습니다. 문제가 계속되면 관리자에게 문의해주세요.", + "C_INVALID_ACCOUNT_ID": "유효하지 않은 어카운트 아이디입니다. 어카운트 아이디를 확인하세요.", + "C_INVALID_STACK_ID": "유효하지 않은 스택 아이디입니다. 스택 아이디를 확인하세요.", + "C_INVALID_CLUSTER_ID": "유효하지 않은 클러스터 아이디입니다. 클러스터 아이디를 확인하세요.", + "C_INVALID_APPGROUP_ID": "유효하지 않은 앱그룹 아이디입니다. 앱그룹 아이디를 확인하세요.", + "C_INVALID_ORGANIZATION_ID": "유효하지 않은 조직 아이디입니다. 조직 아이디를 확인하세요.", + "C_INVALID_PROJECT_ID": "유효하지 않은 프로젝트 아이디입니다. 아이디를 확인하세요.", + "C_INVALID_CLOUD_ACCOUNT_ID": "유효하지 않은 클라우드어카운트 아이디입니다. 클라우드어카운트 아이디를 확인하세요.", + "C_INVALID_STACK_TEMPLATE_ID": "유효하지 않은 스택템플릿 아이디입니다. 스택템플릿 아이디를 확인하세요.", + "C_INVALID_ASA_ID": "유효하지 않은 앱서빙앱 아이디입니다. 앱서빙앱 아이디를 확인하세요.", + "C_INVALID_ASA_TASK_ID": "유효하지 않은 테스크 아이디입니다. 테스크 아이디를 확인하세요.", + "C_INVALID_CLOUD_SERVICE": "유효하지 않은 클라우드서비스입니다.", + "C_INVALID_AUDIT_ID": "유효하지 않은 로그 아이디입니다. 로그 아이디를 확인하세요.", + "C_INVALID_POLICY_TEMPLATE_ID": "유효하지 않은 정책 템플릿 아이디입니다. 정책 템플릿 아이디를 확인하세요.", + "C_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패했습니다.", // Auth "A_INVALID_ID": "아이디가 존재하지 않습니다.", @@ -82,6 +83,19 @@ var errorMap = map[ErrorCode]string{ "ST_CREATE_ALREADY_EXISTED_NAME": "스택 템플릿에 이미 존재하는 이름입니다.", "ST_FAILED_UPDATE_ORGANIZATION": "스택 템플릿에 조직을 설정하는데 실패했습니다.", "ST_NOT_EXISTED_STACK_TEMPLATE": "업데이트할 스택템플릿이 존재하지 않습니다.", + + // PolicyTemplate + "PT_CREATE_ALREADY_EXISTED_NAME": "정첵 템플릿에 이미 존재하는 이름입니다.", + "PT_CREATE_ALREADY_EXISTED_KIND": "정책 템플릿에 이미 존재하는 유형입니다.", + "PT_NOT_FOUND_POLICY_TEMPLATE": "정책 템플릿이 존재하지 않습니다.", + "PT_INVALID_KIND": "유효하지 않은 정책 템플릿 유형입니다. 정책 템플릿 유형을 확인하세요.", + "PT_FAILED_FETCH_POLICY_TEMPLATE": "정책 템플릿 ID에 해당하는 정책 템플릿을 가져오는데 실패했습니다.", + "PT_INVALID_REGO_SYNTAX": "Rego 문법 오류입니다.", + "PT_INVALID_POLICY_TEMPLATE_VERSION": "유효하지 않은 정책 템플릿 버전닙니다. 정책 템플릿 버전을 확인하세요.", + "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION": "정책 템플릿 버전이 존재하지 않습니다.", + "PT_INVALID_POLICY_TEMPLATE_NAME": "유효하지 않은 정책 템플릿 이름입니다. 정책 템플릿 이름을 확인하세요.", + "PT_INVALID_POLICY_TEMPLATE_KIND": "유효하지 않은 정책 템플릿 유형입니다. 정책 템플릿 유형을 확인하세요.", + "PT_INVALID_REGO_PARSEPARAMETER": "유효하지 않은 Rego 파싱 설정입니다. Rego 파싱 설정을 확인하세요.", } func (m ErrorCode) GetText() string { From 03333a25eabda083ad0d9e42bfd2b6a40aff0519 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 11 Mar 2024 15:42:13 +0900 Subject: [PATCH 108/502] add validation on request --- api/swagger/docs.go | 17 +++++++++++++---- api/swagger/swagger.json | 17 +++++++++++++---- api/swagger/swagger.yaml | 13 ++++++++++--- pkg/domain/policy-template.go | 23 +++++++++++------------ 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index b40b355d..4464bf58 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -7924,6 +7924,10 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest": { "type": "object", + "required": [ + "kind", + "rego" + ], "properties": { "deprecated": { "type": "boolean", @@ -7971,10 +7975,6 @@ const docTemplate = `{ ], "example": "medium" }, - "target": { - "type": "string", - "example": "admission.k8s.gatekeeper.sh" - }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -7983,6 +7983,12 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest": { "type": "object", + "required": [ + "currentVersion", + "expectedVersion", + "rego", + "versionUpType" + ], "properties": { "currentVersion": { "type": "string", @@ -9905,6 +9911,9 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest": { "type": "object", + "required": [ + "rego" + ], "properties": { "rego": { "type": "string", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 647962a1..86d8b058 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -7918,6 +7918,10 @@ }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest": { "type": "object", + "required": [ + "kind", + "rego" + ], "properties": { "deprecated": { "type": "boolean", @@ -7965,10 +7969,6 @@ ], "example": "medium" }, - "target": { - "type": "string", - "example": "admission.k8s.gatekeeper.sh" - }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -7977,6 +7977,12 @@ }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest": { "type": "object", + "required": [ + "currentVersion", + "expectedVersion", + "rego", + "versionUpType" + ], "properties": { "currentVersion": { "type": "string", @@ -9899,6 +9905,9 @@ }, "github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest": { "type": "object", + "required": [ + "rego" + ], "properties": { "rego": { "type": "string", diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 60216b96..188af9fd 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -933,12 +933,12 @@ definitions: - high example: medium type: string - target: - example: admission.k8s.gatekeeper.sh - type: string templateName: example: 필수 Label 검사 type: string + required: + - kind + - rego type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest: properties: @@ -968,6 +968,11 @@ definitions: - patch example: minor type: string + required: + - currentVersion + - expectedVersion + - rego + - versionUpType type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse: properties: @@ -2223,6 +2228,8 @@ definitions: rego: example: Rego 코드 type: string + required: + - rego type: object github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse: properties: diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 169714ef..baf8990f 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -99,31 +99,30 @@ type PolicyTemplate struct { } type CreateCommonPolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사"` - Kind string `json:"kind" example:"K8sRequiredLabels"` + TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` Severity string `json:"severity" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` Description string `json:"description,omitempty" example:"이 정책은 ..."` ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - Rego string `json:"rego" example:"rego 코드"` + Rego string `json:"rego" example:"rego 코드" validate:"required"` Libs []string `json:"libs" example:"rego 코드"` // Tags []string `json:"tags,omitempty" example:"k8s,label"` } type CreatePolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사"` - Kind string `json:"kind" example:"K8sRequiredLabels"` + TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` Severity string `json:"severity" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` - Target string `json:"target,omitempty" example:"admission.k8s.gatekeeper.sh"` Description string `json:"description,omitempty" example:"이 정책은 ..."` ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - Rego string `json:"rego" example:"rego 코드"` + Rego string `json:"rego" example:"rego 코드" validate:"required"` Libs []string `json:"libs" example:"rego 코드"` PermittedOrganizationIds []string `json:"permittedOrganizationIds"` @@ -210,14 +209,14 @@ type GetOrganizationPolicyTemplateVersionResponse struct { } type CreatePolicyTemplateVersionRequest struct { - VersionUpType string `json:"versionUpType" enums:"major,minor,patch" example:"minor"` - CurrentVersion string `json:"currentVersion" example:"v1.0.0"` - ExpectedVersion string `json:"expectedVersion" example:"v1.1.0"` + VersionUpType string `json:"versionUpType" enums:"major,minor,patch" example:"minor" validate:"required"` + CurrentVersion string `json:"currentVersion" example:"v1.0.0" validate:"required"` + ExpectedVersion string `json:"expectedVersion" example:"v1.1.0" validate:"required"` ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - Rego string `json:"rego" example:"rego 코드"` + Rego string `json:"rego" example:"rego 코드" validate:"required"` Libs []string `json:"libs" example:"rego 코드"` } @@ -286,7 +285,7 @@ type ParameterDef struct { } type RegoCompileRequest struct { - Rego string `json:"rego" example:"Rego 코드"` + Rego string `json:"rego" example:"Rego 코드" validate:"required"` } type RegoCompieError struct { From 68da31089e5640ebb00d720683db2f43d6ffd964 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 13 Mar 2024 10:40:24 +0900 Subject: [PATCH 109/502] feature. refactoring model. (pkg/domain -> internal/model and pkg/domain) --- api/swagger/docs.go | 744 ++++++++--------------- api/swagger/swagger.json | 744 ++++++++--------------- api/swagger/swagger.yaml | 507 ++++++--------- internal/database/database.go | 38 +- internal/delivery/http/alert.go | 3 +- internal/delivery/http/app-group.go | 5 +- internal/delivery/http/app-serve-app.go | 51 +- internal/delivery/http/auth.go | 5 +- internal/delivery/http/cloud-account.go | 7 +- internal/delivery/http/cluster.go | 34 +- internal/delivery/http/organization.go | 9 +- internal/delivery/http/permission.go | 57 +- internal/delivery/http/role.go | 10 +- internal/delivery/http/stack-template.go | 7 +- internal/delivery/http/stack.go | 15 +- internal/delivery/http/user.go | 21 +- internal/filter/settings.go | 1 + internal/keycloak/keycloak.go | 34 +- internal/middleware/audit/audit.go | 4 +- internal/model/alert.go | 60 ++ internal/model/app-group.go | 47 ++ internal/model/app-serve-app.go | 67 ++ internal/model/audit.go | 26 + internal/model/cloud-account.go | 38 ++ internal/model/cluster.go | 84 +++ internal/model/dashboard.go | 34 ++ internal/model/end-point.go | 11 + internal/model/organization.go | 21 + internal/model/permission.go | 615 +++++++++++++++++++ internal/model/role.go | 27 + internal/model/stack-template.go | 35 ++ internal/model/stack.go | 45 ++ internal/model/user.go | 34 ++ internal/pagination/pagination.go | 4 +- internal/repository/alert.go | 143 +---- internal/repository/app-group.go | 127 +--- internal/repository/app-serve-app.go | 63 +- internal/repository/audit.go | 63 +- internal/repository/cloud-account.go | 103 +--- internal/repository/cluster.go | 183 ++---- internal/repository/endpoint.go | 27 +- internal/repository/organization.go | 73 +-- internal/repository/permission.go | 26 +- internal/repository/role.go | 51 +- internal/repository/stack-template.go | 107 +--- internal/repository/user.go | 104 ++-- internal/serializer/serializer.go | 18 +- internal/usecase/alert.go | 42 +- internal/usecase/app-group.go | 23 +- internal/usecase/app-serve-app.go | 33 +- internal/usecase/audit.go | 20 +- internal/usecase/auth.go | 17 +- internal/usecase/cloud-account.go | 51 +- internal/usecase/cluster.go | 58 +- internal/usecase/dashboard.go | 23 +- internal/usecase/organization.go | 23 +- internal/usecase/permission.go | 54 +- internal/usecase/role.go | 22 +- internal/usecase/stack-template.go | 35 +- internal/usecase/stack.go | 37 +- internal/usecase/user.go | 50 +- pkg/domain/admin/user.go | 45 +- pkg/domain/alert.go | 44 -- pkg/domain/app-group.go | 27 - pkg/domain/app-serve-app.go | 119 ++-- pkg/domain/audit.go | 18 - pkg/domain/auth.go | 14 +- pkg/domain/cloud-account.go | 26 - pkg/domain/cluster.go | 30 +- pkg/domain/dashboard.go | 27 - pkg/domain/endpoint.go | 13 +- pkg/domain/mapper.go | 140 ----- pkg/domain/mapper_test.go | 117 ---- pkg/domain/organization.go | 10 +- pkg/domain/permission.go | 629 +------------------ pkg/domain/project.go | 23 +- pkg/domain/role.go | 31 +- pkg/domain/stack-template.go | 27 - pkg/domain/stack.go | 53 +- pkg/domain/user.go | 181 +++--- 80 files changed, 2861 insertions(+), 3733 deletions(-) create mode 100644 internal/model/alert.go create mode 100644 internal/model/app-group.go create mode 100644 internal/model/app-serve-app.go create mode 100644 internal/model/audit.go create mode 100644 internal/model/cloud-account.go create mode 100644 internal/model/cluster.go create mode 100644 internal/model/dashboard.go create mode 100644 internal/model/end-point.go create mode 100644 internal/model/organization.go create mode 100644 internal/model/permission.go create mode 100644 internal/model/role.go create mode 100644 internal/model/stack-template.go create mode 100644 internal/model/stack.go create mode 100644 internal/model/user.go delete mode 100644 pkg/domain/mapper.go delete mode 100644 pkg/domain/mapper_test.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 4464bf58..b6f5d90f 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1688,7 +1688,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse" } } } @@ -1721,10 +1721,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" - } + "description": "OK" } } } @@ -2103,10 +2100,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - } + "description": "OK" } } } @@ -3771,7 +3765,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" } } } @@ -4438,7 +4432,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" } } } @@ -5627,7 +5621,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" } } } @@ -6461,10 +6455,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - } + "description": "OK" } } } @@ -6532,7 +6523,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" } } } @@ -6620,6 +6611,177 @@ const docTemplate = `{ } }, "definitions": { + "github_com_openinfradev_tks-api_internal_model.AppServeApp": { + "type": "object", + "properties": { + "appServeAppTasks": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask" + } + }, + "appType": { + "description": "appType (spring/springboot)", + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "endpointUrl": { + "description": "endpoint URL of deployed app", + "type": "string" + }, + "grafanaUrl": { + "description": "grafana dashboard URL for deployed app", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "description": "application name", + "type": "string" + }, + "namespace": { + "description": "application namespace", + "type": "string" + }, + "organizationId": { + "description": "contractId is a contract ID which this app belongs to", + "type": "string" + }, + "previewEndpointUrl": { + "description": "preview svc endpoint URL in B/G deployment", + "type": "string" + }, + "projectId": { + "description": "project ID which this app belongs to", + "type": "string" + }, + "status": { + "description": "status is status of deployed app", + "type": "string" + }, + "targetClusterId": { + "description": "target cluster to which the app is deployed", + "type": "string" + }, + "targetClusterName": { + "description": "target cluster name", + "type": "string" + }, + "type": { + "description": "type (build/deploy/all)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_internal_model.AppServeAppTask": { + "type": "object", + "properties": { + "appConfig": { + "description": "java app config", + "type": "string" + }, + "appSecret": { + "description": "java app secret", + "type": "string" + }, + "appServeAppId": { + "description": "ID for appServeApp that this task belongs to", + "type": "string" + }, + "artifactUrl": { + "description": "URL of java app artifact (Eg, Jar)", + "type": "string" + }, + "availableRollback": { + "type": "boolean" + }, + "createdAt": { + "description": "createdAt is a creation timestamp for the application", + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "executablePath": { + "description": "Executable path of app image", + "type": "string" + }, + "extraEnv": { + "description": "env variable list for java app", + "type": "string" + }, + "helmRevision": { + "description": "revision of deployed helm release", + "type": "integer" + }, + "id": { + "type": "string" + }, + "imageUrl": { + "description": "URL of built image for app", + "type": "string" + }, + "output": { + "description": "output for task result", + "type": "string" + }, + "port": { + "description": "java app port", + "type": "string" + }, + "profile": { + "description": "java app profile", + "type": "string" + }, + "pvAccessMode": { + "type": "string" + }, + "pvEnabled": { + "type": "boolean" + }, + "pvMountPath": { + "type": "string" + }, + "pvSize": { + "type": "string" + }, + "pvStorageClass": { + "type": "string" + }, + "resourceSpec": { + "description": "resource spec of app pod", + "type": "string" + }, + "rollbackVersion": { + "description": "rollback target version", + "type": "string" + }, + "status": { + "description": "status is app status", + "type": "string" + }, + "strategy": { + "description": "deployment strategy (eg, rolling-update)", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "version": { + "description": "application version", + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { @@ -6828,13 +6990,13 @@ const docTemplate = `{ "AppGroupType_SERVICE_MESH" ] }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeApp": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse": { "type": "object", "properties": { "appServeAppTasks": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" } }, "appType": { @@ -6899,7 +7061,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse": { "type": "object", "properties": { "appConfig": { @@ -7086,9 +7248,6 @@ const docTemplate = `{ }, "user": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "userId": { - "type": "string" } } }, @@ -7158,12 +7317,9 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccount": { + "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { - "accessKeyId": { - "type": "string" - }, "awsAccountId": { "type": "string" }, @@ -7180,10 +7336,7 @@ const docTemplate = `{ "type": "boolean" }, "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -7200,245 +7353,53 @@ const docTemplate = `{ "resource": { "type": "string" }, - "secretAccessKey": { - "type": "string" - }, - "sessionToken": { - "type": "string" - }, "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus" - }, - "statusDesc": { "type": "string" }, "updatedAt": { "type": "string" }, "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" } } }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse": { "type": "object", "properties": { - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" + "tksCpNode": { + "type": "integer" }, - "clusters": { + "tksCpNodeMax": { "type": "integer" }, - "createdAt": { + "tksCpNodeType": { "type": "string" }, - "createdIAM": { - "type": "boolean" + "tksInfraNode": { + "type": "integer" }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + "tksInfraNodeMax": { + "type": "integer" }, - "description": { + "tksInfraNodeType": { "type": "string" }, - "id": { - "type": "string" + "tksUserNode": { + "type": "integer" }, - "name": { - "type": "string" + "tksUserNodeMax": { + "type": "integer" }, - "organizationId": { + "tksUserNodeType": { "type": "string" - }, - "resource": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 - ], - "x-enum-varnames": [ - "CloudAccountStatus_PENDING", - "CloudAccountStatus_CREATING", - "CloudAccountStatus_CREATED", - "CloudAccountStatus_DELETING", - "CloudAccountStatus_DELETED", - "CloudAccountStatus_CREATE_ERROR", - "CloudAccountStatus_DELETE_ERROR" - ] - }, - "github_com_openinfradev_tks-api_pkg_domain.Cluster": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccount": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount" - }, - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "integer" - }, - "conf": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "favorited": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "isStack": { - "type": "boolean" - }, - "kubeconfig": { - "type": "array", - "items": { - "type": "integer" - } - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplate": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate" - }, - "stackTemplateId": { - "type": "string" - }, - "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterConf": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterHost": { - "type": "object", - "properties": { - "name": { + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterHost": { + "type": "object", + "properties": { + "name": { "type": "string" }, "status": { @@ -7508,6 +7469,9 @@ const docTemplate = `{ "description": { "type": "string" }, + "favorited": { + "type": "boolean" + }, "id": { "type": "string" }, @@ -7584,33 +7548,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9 - ], - "x-enum-varnames": [ - "ClusterStatus_PENDING", - "ClusterStatus_INSTALLING", - "ClusterStatus_RUNNING", - "ClusterStatus_DELETING", - "ClusterStatus_DELETED", - "ClusterStatus_INSTALL_ERROR", - "ClusterStatus_DELETE_ERROR", - "ClusterStatus_BOOTSTRAPPING", - "ClusterStatus_BOOTSTRAPPED", - "ClusterStatus_BOOTSTRAP_ERROR" - ] - }, "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { @@ -8306,10 +8243,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -8425,7 +8362,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { + "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { "createdAt": { @@ -8436,6 +8373,9 @@ const docTemplate = `{ }, "name": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -8568,7 +8508,7 @@ const docTemplate = `{ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" }, "stages": { "type": "array", @@ -8582,10 +8522,10 @@ const docTemplate = `{ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" }, "appServeAppTask": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" }, "stages": { "type": "array", @@ -8680,6 +8620,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { + "type": "object", + "properties": { + "cluster": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse": { "type": "object", "properties": { @@ -8754,10 +8702,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -9087,10 +9035,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -9253,10 +9201,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -9298,13 +9246,13 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "passwordExpired": { "type": "boolean" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "token": { "type": "string" @@ -9327,7 +9275,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Organization": { + "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { "createdAt": { @@ -9336,9 +9284,6 @@ const docTemplate = `{ "creator": { "type": "string" }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "description": { "type": "string" }, @@ -9362,6 +9307,9 @@ const docTemplate = `{ }, "updatedAt": { "type": "string" + }, + "workflowId": { + "type": "string" } } }, @@ -9417,6 +9365,7 @@ const docTemplate = `{ } } }, +<<<<<<< Updated upstream "github_com_openinfradev_tks-api_pkg_domain.ParameterDef": { "type": "object", "properties": { @@ -9441,6 +9390,9 @@ const docTemplate = `{ } }, "github_com_openinfradev_tks-api_pkg_domain.Permission": { +======= + "github_com_openinfradev_tks-api_pkg_domain.PermissionResponse": { +>>>>>>> Stashed changes "type": "object", "properties": { "ID": { @@ -9449,24 +9401,15 @@ const docTemplate = `{ "children": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "endpoints": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse" } }, - "id": { - "type": "integer" - }, "is_allowed": { "type": "boolean" }, @@ -9474,42 +9417,39 @@ const docTemplate = `{ "type": "string" }, "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "parent_id": { "type": "string" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "role_id": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { + "github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse": { "type": "object", "properties": { "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "security_policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } } }, @@ -9861,6 +9801,9 @@ const docTemplate = `{ }, "projectRoleName": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -9982,7 +9925,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Role": { + "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { "type": "object", "properties": { "createdAt": { @@ -9991,9 +9934,6 @@ const docTemplate = `{ "creator": { "type": "string" }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "description": { "type": "string" }, @@ -10004,7 +9944,7 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "organizationId": { "type": "string" @@ -10261,86 +10201,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.StackTemplate": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "organizationIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "organizations": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - } - }, - "platform": { - "type": "string" - }, - "serviceIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "services": { - "type": "array", - "items": { - "type": "integer" - } - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse": { "type": "object", "properties": { @@ -10606,10 +10466,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -10677,7 +10537,7 @@ const docTemplate = `{ "permissions": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } } } @@ -10901,10 +10761,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -10913,62 +10773,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.User": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - }, - "organizationId": { - "type": "string" - }, - "password": { - "type": "string" - }, - "passwordExpired": { - "type": "boolean" - }, - "passwordUpdatedAt": { - "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" - }, - "roleId": { - "type": "string" - }, - "token": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ @@ -11058,10 +10862,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -11129,10 +10933,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -11157,18 +10961,6 @@ const docTemplate = `{ "type": "string" } } - }, - "gorm.DeletedAt": { - "type": "object", - "properties": { - "time": { - "type": "string" - }, - "valid": { - "description": "Valid is true if Time is not NULL", - "type": "boolean" - } - } } }, "securityDefinitions": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 86d8b058..15aaf32b 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1682,7 +1682,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse" } } } @@ -1715,10 +1715,7 @@ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" - } + "description": "OK" } } } @@ -2097,10 +2094,7 @@ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - } + "description": "OK" } } } @@ -3765,7 +3759,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" } } } @@ -4432,7 +4426,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" } } } @@ -5621,7 +5615,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" } } } @@ -6455,10 +6449,7 @@ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - } + "description": "OK" } } } @@ -6526,7 +6517,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" } } } @@ -6614,6 +6605,177 @@ } }, "definitions": { + "github_com_openinfradev_tks-api_internal_model.AppServeApp": { + "type": "object", + "properties": { + "appServeAppTasks": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask" + } + }, + "appType": { + "description": "appType (spring/springboot)", + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "endpointUrl": { + "description": "endpoint URL of deployed app", + "type": "string" + }, + "grafanaUrl": { + "description": "grafana dashboard URL for deployed app", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "description": "application name", + "type": "string" + }, + "namespace": { + "description": "application namespace", + "type": "string" + }, + "organizationId": { + "description": "contractId is a contract ID which this app belongs to", + "type": "string" + }, + "previewEndpointUrl": { + "description": "preview svc endpoint URL in B/G deployment", + "type": "string" + }, + "projectId": { + "description": "project ID which this app belongs to", + "type": "string" + }, + "status": { + "description": "status is status of deployed app", + "type": "string" + }, + "targetClusterId": { + "description": "target cluster to which the app is deployed", + "type": "string" + }, + "targetClusterName": { + "description": "target cluster name", + "type": "string" + }, + "type": { + "description": "type (build/deploy/all)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_internal_model.AppServeAppTask": { + "type": "object", + "properties": { + "appConfig": { + "description": "java app config", + "type": "string" + }, + "appSecret": { + "description": "java app secret", + "type": "string" + }, + "appServeAppId": { + "description": "ID for appServeApp that this task belongs to", + "type": "string" + }, + "artifactUrl": { + "description": "URL of java app artifact (Eg, Jar)", + "type": "string" + }, + "availableRollback": { + "type": "boolean" + }, + "createdAt": { + "description": "createdAt is a creation timestamp for the application", + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "executablePath": { + "description": "Executable path of app image", + "type": "string" + }, + "extraEnv": { + "description": "env variable list for java app", + "type": "string" + }, + "helmRevision": { + "description": "revision of deployed helm release", + "type": "integer" + }, + "id": { + "type": "string" + }, + "imageUrl": { + "description": "URL of built image for app", + "type": "string" + }, + "output": { + "description": "output for task result", + "type": "string" + }, + "port": { + "description": "java app port", + "type": "string" + }, + "profile": { + "description": "java app profile", + "type": "string" + }, + "pvAccessMode": { + "type": "string" + }, + "pvEnabled": { + "type": "boolean" + }, + "pvMountPath": { + "type": "string" + }, + "pvSize": { + "type": "string" + }, + "pvStorageClass": { + "type": "string" + }, + "resourceSpec": { + "description": "resource spec of app pod", + "type": "string" + }, + "rollbackVersion": { + "description": "rollback target version", + "type": "string" + }, + "status": { + "description": "status is app status", + "type": "string" + }, + "strategy": { + "description": "deployment strategy (eg, rolling-update)", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "version": { + "description": "application version", + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { @@ -6822,13 +6984,13 @@ "AppGroupType_SERVICE_MESH" ] }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeApp": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse": { "type": "object", "properties": { "appServeAppTasks": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" } }, "appType": { @@ -6893,7 +7055,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse": { "type": "object", "properties": { "appConfig": { @@ -7080,9 +7242,6 @@ }, "user": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "userId": { - "type": "string" } } }, @@ -7152,12 +7311,9 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccount": { + "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { - "accessKeyId": { - "type": "string" - }, "awsAccountId": { "type": "string" }, @@ -7174,10 +7330,7 @@ "type": "boolean" }, "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" @@ -7194,245 +7347,53 @@ "resource": { "type": "string" }, - "secretAccessKey": { - "type": "string" - }, - "sessionToken": { - "type": "string" - }, "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus" - }, - "statusDesc": { "type": "string" }, "updatedAt": { "type": "string" }, "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" } } }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { + "github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse": { "type": "object", "properties": { - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" + "tksCpNode": { + "type": "integer" }, - "clusters": { + "tksCpNodeMax": { "type": "integer" }, - "createdAt": { + "tksCpNodeType": { "type": "string" }, - "createdIAM": { - "type": "boolean" + "tksInfraNode": { + "type": "integer" }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + "tksInfraNodeMax": { + "type": "integer" }, - "description": { + "tksInfraNodeType": { "type": "string" }, - "id": { - "type": "string" + "tksUserNode": { + "type": "integer" }, - "name": { - "type": "string" + "tksUserNodeMax": { + "type": "integer" }, - "organizationId": { + "tksUserNodeType": { "type": "string" - }, - "resource": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 - ], - "x-enum-varnames": [ - "CloudAccountStatus_PENDING", - "CloudAccountStatus_CREATING", - "CloudAccountStatus_CREATED", - "CloudAccountStatus_DELETING", - "CloudAccountStatus_DELETED", - "CloudAccountStatus_CREATE_ERROR", - "CloudAccountStatus_DELETE_ERROR" - ] - }, - "github_com_openinfradev_tks-api_pkg_domain.Cluster": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccount": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount" - }, - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "integer" - }, - "conf": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "favorited": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "isStack": { - "type": "boolean" - }, - "kubeconfig": { - "type": "array", - "items": { - "type": "integer" - } - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "stackTemplate": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate" - }, - "stackTemplateId": { - "type": "string" - }, - "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterConf": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterHost": { - "type": "object", - "properties": { - "name": { + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterHost": { + "type": "object", + "properties": { + "name": { "type": "string" }, "status": { @@ -7502,6 +7463,9 @@ "description": { "type": "string" }, + "favorited": { + "type": "boolean" + }, "id": { "type": "string" }, @@ -7578,33 +7542,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9 - ], - "x-enum-varnames": [ - "ClusterStatus_PENDING", - "ClusterStatus_INSTALLING", - "ClusterStatus_RUNNING", - "ClusterStatus_DELETING", - "ClusterStatus_DELETED", - "ClusterStatus_INSTALL_ERROR", - "ClusterStatus_DELETE_ERROR", - "ClusterStatus_BOOTSTRAPPING", - "ClusterStatus_BOOTSTRAPPED", - "ClusterStatus_BOOTSTRAP_ERROR" - ] - }, "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { @@ -8300,10 +8237,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -8419,7 +8356,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { + "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { "createdAt": { @@ -8430,6 +8367,9 @@ }, "name": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -8562,7 +8502,7 @@ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" }, "stages": { "type": "array", @@ -8576,10 +8516,10 @@ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" }, "appServeAppTask": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" }, "stages": { "type": "array", @@ -8674,6 +8614,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { + "type": "object", + "properties": { + "cluster": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse": { "type": "object", "properties": { @@ -8748,10 +8696,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -9081,10 +9029,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -9247,10 +9195,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -9292,13 +9240,13 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "passwordExpired": { "type": "boolean" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "token": { "type": "string" @@ -9321,7 +9269,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Organization": { + "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { "createdAt": { @@ -9330,9 +9278,6 @@ "creator": { "type": "string" }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "description": { "type": "string" }, @@ -9356,6 +9301,9 @@ }, "updatedAt": { "type": "string" + }, + "workflowId": { + "type": "string" } } }, @@ -9411,6 +9359,7 @@ } } }, +<<<<<<< Updated upstream "github_com_openinfradev_tks-api_pkg_domain.ParameterDef": { "type": "object", "properties": { @@ -9435,6 +9384,9 @@ } }, "github_com_openinfradev_tks-api_pkg_domain.Permission": { +======= + "github_com_openinfradev_tks-api_pkg_domain.PermissionResponse": { +>>>>>>> Stashed changes "type": "object", "properties": { "ID": { @@ -9443,24 +9395,15 @@ "children": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "endpoints": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse" } }, - "id": { - "type": "integer" - }, "is_allowed": { "type": "boolean" }, @@ -9468,42 +9411,39 @@ "type": "string" }, "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "parent_id": { "type": "string" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "role_id": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { + "github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse": { "type": "object", "properties": { "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "security_policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } } }, @@ -9855,6 +9795,9 @@ }, "projectRoleName": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -9976,7 +9919,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Role": { + "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { "type": "object", "properties": { "createdAt": { @@ -9985,9 +9928,6 @@ "creator": { "type": "string" }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "description": { "type": "string" }, @@ -9998,7 +9938,7 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "organizationId": { "type": "string" @@ -10255,86 +10195,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.StackTemplate": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "organizationIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "organizations": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - } - }, - "platform": { - "type": "string" - }, - "serviceIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "services": { - "type": "array", - "items": { - "type": "integer" - } - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse": { "type": "object", "properties": { @@ -10600,10 +10460,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -10671,7 +10531,7 @@ "permissions": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } } } @@ -10895,10 +10755,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -10907,62 +10767,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.User": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - }, - "organizationId": { - "type": "string" - }, - "password": { - "type": "string" - }, - "passwordExpired": { - "type": "boolean" - }, - "passwordUpdatedAt": { - "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" - }, - "roleId": { - "type": "string" - }, - "token": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ @@ -11052,10 +10856,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -11123,10 +10927,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -11151,18 +10955,6 @@ "type": "string" } } - }, - "gorm.DeletedAt": { - "type": "object", - "properties": { - "time": { - "type": "string" - }, - "valid": { - "description": "Valid is true if Time is not NULL", - "type": "boolean" - } - } } }, "securityDefinitions": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 188af9fd..11ad7868 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1,5 +1,128 @@ basePath: /api/1.0/ definitions: + github_com_openinfradev_tks-api_internal_model.AppServeApp: + properties: + appServeAppTasks: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask' + type: array + appType: + description: appType (spring/springboot) + type: string + createdAt: + type: string + deletedAt: + type: string + endpointUrl: + description: endpoint URL of deployed app + type: string + grafanaUrl: + description: grafana dashboard URL for deployed app + type: string + id: + type: string + name: + description: application name + type: string + namespace: + description: application namespace + type: string + organizationId: + description: contractId is a contract ID which this app belongs to + type: string + previewEndpointUrl: + description: preview svc endpoint URL in B/G deployment + type: string + projectId: + description: project ID which this app belongs to + type: string + status: + description: status is status of deployed app + type: string + targetClusterId: + description: target cluster to which the app is deployed + type: string + targetClusterName: + description: target cluster name + type: string + type: + description: type (build/deploy/all) + type: string + updatedAt: + type: string + type: object + github_com_openinfradev_tks-api_internal_model.AppServeAppTask: + properties: + appConfig: + description: java app config + type: string + appSecret: + description: java app secret + type: string + appServeAppId: + description: ID for appServeApp that this task belongs to + type: string + artifactUrl: + description: URL of java app artifact (Eg, Jar) + type: string + availableRollback: + type: boolean + createdAt: + description: createdAt is a creation timestamp for the application + type: string + deletedAt: + type: string + executablePath: + description: Executable path of app image + type: string + extraEnv: + description: env variable list for java app + type: string + helmRevision: + description: revision of deployed helm release + type: integer + id: + type: string + imageUrl: + description: URL of built image for app + type: string + output: + description: output for task result + type: string + port: + description: java app port + type: string + profile: + description: java app profile + type: string + pvAccessMode: + type: string + pvEnabled: + type: boolean + pvMountPath: + type: string + pvSize: + type: string + pvStorageClass: + type: string + resourceSpec: + description: resource spec of app pod + type: string + rollbackVersion: + description: rollback target version + type: string + status: + description: status is app status + type: string + strategy: + description: deployment strategy (eg, rolling-update) + type: string + updatedAt: + type: string + version: + description: application version + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ActionResponse: properties: body: @@ -143,11 +266,11 @@ definitions: - AppGroupType_UNSPECIFIED - AppGroupType_LMA - AppGroupType_SERVICE_MESH - github_com_openinfradev_tks-api_pkg_domain.AppServeApp: + github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse: properties: appServeAppTasks: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse' type: array appType: description: appType (spring/springboot) @@ -194,7 +317,7 @@ definitions: updatedAt: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask: + github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse: properties: appConfig: description: java app config @@ -331,8 +454,6 @@ definitions: type: string user: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' - userId: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.Axis: properties: @@ -376,49 +497,6 @@ definitions: existed: type: boolean type: object - github_com_openinfradev_tks-api_pkg_domain.CloudAccount: - properties: - accessKeyId: - type: string - awsAccountId: - type: string - cloudService: - type: string - clusters: - type: integer - createdAt: - type: string - createdIAM: - type: boolean - creator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - creatorId: - type: string - description: - type: string - id: - type: string - name: - type: string - organizationId: - type: string - resource: - type: string - secretAccessKey: - type: string - sessionToken: - type: string - status: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus' - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - updatorId: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse: properties: awsAccountId: @@ -450,98 +528,6 @@ definitions: updator: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' type: object - github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus: - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - type: integer - x-enum-varnames: - - CloudAccountStatus_PENDING - - CloudAccountStatus_CREATING - - CloudAccountStatus_CREATED - - CloudAccountStatus_DELETING - - CloudAccountStatus_DELETED - - CloudAccountStatus_CREATE_ERROR - - CloudAccountStatus_DELETE_ERROR - github_com_openinfradev_tks-api_pkg_domain.Cluster: - properties: - byoClusterEndpointHost: - type: string - byoClusterEndpointPort: - type: integer - cloudAccount: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount' - cloudAccountId: - type: string - cloudService: - type: string - clusterType: - type: integer - conf: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf' - createdAt: - type: string - creator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - creatorId: - type: string - description: - type: string - favorited: - type: boolean - id: - type: string - isStack: - type: boolean - kubeconfig: - items: - type: integer - type: array - name: - type: string - organizationId: - type: string - stackTemplate: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate' - stackTemplateId: - type: string - status: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus' - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - updatorId: - type: string - type: object - github_com_openinfradev_tks-api_pkg_domain.ClusterConf: - properties: - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse: properties: tksCpNode: @@ -611,6 +597,8 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string + favorited: + type: boolean id: type: string isStack: @@ -661,30 +649,6 @@ definitions: tksUserNodeType: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.ClusterStatus: - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9 - type: integer - x-enum-varnames: - - ClusterStatus_PENDING - - ClusterStatus_INSTALLING - - ClusterStatus_RUNNING - - ClusterStatus_DELETING - - ClusterStatus_DELETED - - ClusterStatus_INSTALL_ERROR - - ClusterStatus_DELETE_ERROR - - ClusterStatus_BOOTSTRAPPING - - ClusterStatus_BOOTSTRAPPED - - ClusterStatus_BOOTSTRAP_ERROR github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse: properties: result: @@ -1164,9 +1128,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' type: object type: object github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse: @@ -1243,7 +1207,7 @@ definitions: - accessKeyId - secretAccessKey type: object - github_com_openinfradev_tks-api_pkg_domain.Endpoint: + github_com_openinfradev_tks-api_pkg_domain.EndpointResponse: properties: createdAt: type: string @@ -1251,6 +1215,8 @@ definitions: type: string name: type: string + updatedAt: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse: type: object @@ -1338,7 +1304,7 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse: properties: appServeApp: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse' stages: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' @@ -1347,9 +1313,9 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse: properties: appServeApp: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse' appServeAppTask: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse' stages: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' @@ -1409,6 +1375,11 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse: + properties: + cluster: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse: properties: clusters: @@ -1457,9 +1428,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' type: object type: object github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse: @@ -1670,9 +1641,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object @@ -1779,9 +1750,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object @@ -1809,11 +1780,11 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' passwordExpired: type: boolean role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' token: type: string type: object @@ -1827,14 +1798,12 @@ definitions: type: array type: object type: object - github_com_openinfradev_tks-api_pkg_domain.Organization: + github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse: properties: createdAt: type: string creator: type: string - deletedAt: - $ref: '#/definitions/gorm.DeletedAt' description: type: string id: @@ -1851,6 +1820,8 @@ definitions: type: string updatedAt: type: string + workflowId: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus: enum: @@ -1891,6 +1862,7 @@ definitions: totalRows: type: integer type: object +<<<<<<< Updated upstream github_com_openinfradev_tks-api_pkg_domain.ParameterDef: properties: children: @@ -1907,52 +1879,47 @@ definitions: type: string type: object github_com_openinfradev_tks-api_pkg_domain.Permission: +======= + github_com_openinfradev_tks-api_pkg_domain.PermissionResponse: +>>>>>>> Stashed changes properties: ID: type: string children: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' type: array - createdAt: - type: string - deletedAt: - $ref: '#/definitions/gorm.DeletedAt' endpoints: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse' type: array - id: - type: integer is_allowed: type: boolean name: type: string parent: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' parent_id: type: string role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' role_id: type: string - updatedAt: - type: string type: object - github_com_openinfradev_tks-api_pkg_domain.PermissionSet: + github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse: properties: configuration: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' dashboard: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' notification: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' project_management: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' security_policy: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' stack: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' type: object github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization: properties: @@ -2191,6 +2158,8 @@ definitions: type: string projectRoleName: type: string + updatedAt: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse: properties: @@ -2270,14 +2239,12 @@ definitions: usage: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.Role: + github_com_openinfradev_tks-api_pkg_domain.RoleResponse: properties: createdAt: type: string creator: type: string - deletedAt: - $ref: '#/definitions/gorm.DeletedAt' description: type: string id: @@ -2285,7 +2252,7 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' organizationId: type: string type: @@ -2454,59 +2421,6 @@ definitions: step: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.StackTemplate: - properties: - cloudService: - type: string - createdAt: - type: string - creator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - creatorId: - type: string - description: - type: string - id: - type: string - kubeType: - type: string - kubeVersion: - type: string - name: - type: string - organizationId: - type: string - organizationIds: - items: - type: string - type: array - organizations: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' - type: array - platform: - type: string - serviceIds: - items: - type: string - type: array - services: - items: - type: integer - type: array - template: - type: string - templateType: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - updatorId: - type: string - version: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse: properties: cloudService: @@ -2683,9 +2597,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' type: object type: object github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest: @@ -2730,7 +2644,7 @@ definitions: properties: permissions: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' type: array type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest: @@ -2880,50 +2794,13 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object type: object - github_com_openinfradev_tks-api_pkg_domain.User: - properties: - accountId: - type: string - createdAt: - type: string - creator: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' - organizationId: - type: string - password: - type: string - passwordExpired: - type: boolean - passwordUpdatedAt: - type: string - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' - roleId: - type: string - token: - type: string - updatedAt: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest: properties: email: @@ -2984,9 +2861,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object @@ -3032,9 +2909,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object @@ -3050,14 +2927,6 @@ definitions: text: type: string type: object - gorm.DeletedAt: - properties: - time: - type: string - valid: - description: Valid is true if Time is not NULL - type: boolean - type: object host: tks-api-dev.taco-cat.xyz info: contact: @@ -4106,8 +3975,6 @@ paths: responses: "200": description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster' security: - JWT: [] summary: Delete cluster @@ -4129,7 +3996,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse' security: - JWT: [] summary: Get cluster @@ -4341,8 +4208,6 @@ paths: responses: "200": description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' security: - JWT: [] summary: Delete organization @@ -5366,7 +5231,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp' type: array security: - JWT: [] @@ -5733,7 +5598,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp' type: array security: - JWT: [] @@ -6657,7 +6522,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse' security: - JWT: [] summary: Get Permissions By Role ID @@ -7079,8 +6944,6 @@ paths: responses: "200": description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' security: - JWT: [] summary: Delete user @@ -7236,7 +7099,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse' security: - JWT: [] summary: Get Permission Templates diff --git a/internal/database/database.go b/internal/database/database.go index 1fd29171..6ed0af45 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -14,7 +14,6 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" ) func InitDB() (*gorm.DB, error) { @@ -60,68 +59,68 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&repository.CacheEmailCode{}); err != nil { return err } - if err := db.AutoMigrate(&domain.User{}); err != nil { + if err := db.AutoMigrate(&model.User{}); err != nil { return err } - if err := db.AutoMigrate(&domain.Role{}); err != nil { + if err := db.AutoMigrate(&model.Role{}); err != nil { return err } // Organization - if err := db.AutoMigrate(&domain.Organization{}); err != nil { + if err := db.AutoMigrate(&model.Organization{}); err != nil { return err } // CloudAccount - if err := db.AutoMigrate(&repository.CloudAccount{}); err != nil { + if err := db.AutoMigrate(&model.CloudAccount{}); err != nil { return err } // StackTemplate - if err := db.AutoMigrate(&repository.StackTemplate{}); err != nil { + if err := db.AutoMigrate(&model.StackTemplate{}); err != nil { return err } // Cluster - if err := db.AutoMigrate(&repository.Cluster{}); err != nil { + if err := db.AutoMigrate(&model.Cluster{}); err != nil { return err } - if err := db.AutoMigrate(&repository.ClusterFavorite{}); err != nil { + if err := db.AutoMigrate(&model.ClusterFavorite{}); err != nil { return err } // Services - if err := db.AutoMigrate(&repository.AppGroup{}); err != nil { + if err := db.AutoMigrate(&model.AppGroup{}); err != nil { return err } - if err := db.AutoMigrate(&repository.Application{}); err != nil { + if err := db.AutoMigrate(&model.Application{}); err != nil { return err } // AppServe - if err := db.AutoMigrate(&domain.AppServeApp{}); err != nil { + if err := db.AutoMigrate(&model.AppServeApp{}); err != nil { return err } - if err := db.AutoMigrate(&domain.AppServeAppTask{}); err != nil { + if err := db.AutoMigrate(&model.AppServeAppTask{}); err != nil { return err } // Alert - if err := db.AutoMigrate(&repository.Alert{}); err != nil { + if err := db.AutoMigrate(&model.Alert{}); err != nil { return err } - if err := db.AutoMigrate(&repository.AlertAction{}); err != nil { + if err := db.AutoMigrate(&model.AlertAction{}); err != nil { return err } // Role - if err := db.AutoMigrate(&domain.Role{}); err != nil { + if err := db.AutoMigrate(&model.Role{}); err != nil { return err } - if err := db.AutoMigrate(&domain.Permission{}); err != nil { + if err := db.AutoMigrate(&model.Permission{}); err != nil { return err } - if err := db.AutoMigrate(&domain.Endpoint{}); err != nil { + if err := db.AutoMigrate(&model.Endpoint{}); err != nil { return err } @@ -172,7 +171,7 @@ func EnsureDefaultRows(db *gorm.DB) error { } for _, ep := range api.ApiMap { if _, ok := storedEps[ep.Name]; !ok { - if err := repoFactory.Endpoint.Create(&domain.Endpoint{ + if err := repoFactory.Endpoint.Create(&model.Endpoint{ Name: ep.Name, Group: ep.Group, }); err != nil { @@ -181,6 +180,7 @@ func EnsureDefaultRows(db *gorm.DB) error { } } +<<<<<<< Updated upstream // Audit if err := db.AutoMigrate(&repository.Audit{}); err != nil { return err @@ -195,5 +195,7 @@ func EnsureDefaultRows(db *gorm.DB) error { return err } +======= +>>>>>>> Stashed changes return nil } diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index 5b03746f..bf878aef 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -272,7 +273,7 @@ func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) log.InfoWithContext(r.Context(), "alert : ", helper.ModelToJson(input)) - var dto domain.AlertAction + var dto model.AlertAction if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 26dbb840..27543035 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -6,6 +6,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -43,7 +44,7 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) return } - var dto domain.AppGroup + var dto model.AppGroup if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -264,7 +265,7 @@ func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Reque return } - var dto domain.Application + var dto model.Application if err := serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index d738685f..aa6f92b1 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -12,6 +12,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -115,7 +116,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re (appReq).SetDefaultValue() - var app domain.AppServeApp + var app model.AppServeApp if err = serializer.Map(appReq, &app); err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -131,7 +132,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re app.Status = "PREPARING" app.CreatedAt = now - var task domain.AppServeAppTask + var task model.AppServeAppTask if err = serializer.Map(appReq, &task); err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -230,7 +231,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} []domain.AppServeApp +// @Success 200 {object} []model.AppServeApp // @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { @@ -264,7 +265,13 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ } var out domain.GetAppServeAppsResponse - out.AppServeApps = apps + out.AppServeApps = make([]domain.AppServeAppResponse, len(apps)) + for i, app := range apps { + if err := serializer.Map(app, &out.AppServeApps[i]); err != nil { + log.InfoWithContext(r.Context(), err) + continue + } + } if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) @@ -317,7 +324,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque return } - newTasks := make([]domain.AppServeAppTask, 0) + newTasks := make([]model.AppServeAppTask, 0) for idx, t := range app.AppServeAppTasks { // Rollbacking to latest task should be blocked. @@ -330,7 +337,10 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque app.AppServeAppTasks = newTasks var out domain.GetAppServeAppResponse - out.AppServeApp = *app + if err := serializer.Map(app, &out.AppServeApp); err != nil { + log.InfoWithContext(r.Context(), err) + } + // NOTE: makeStages function's been changed to use task instead of app //out.Stages = makeStages(app) @@ -377,7 +387,9 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - out.AppServeAppTask = *task + if err := serializer.Map(task, &out.AppServeAppTask); err != nil { + log.InfoWithContext(r.Context(), err) + } ResponseJSON(w, r, http.StatusOK, out) } @@ -435,7 +447,7 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. // @Param sortColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} []domain.AppServeApp +// @Success 200 {object} []model.AppServeApp // @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r *http.Request) { @@ -463,7 +475,13 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r } var out domain.GetAppServeAppTasksResponse - out.AppServeAppTasks = tasks + out.AppServeAppTasks = make([]domain.AppServeAppTaskResponse, len(tasks)) + for i, task := range tasks { + if err := serializer.Map(task, &out.AppServeAppTasks[i]); err != nil { + log.InfoWithContext(r.Context(), err) + continue + } + } if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) @@ -533,14 +551,19 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - out.AppServeApp = *app - out.AppServeAppTask = *task + if err := serializer.Map(app, &out.AppServeApp); err != nil { + log.InfoWithContext(r.Context(), err) + } + if err := serializer.Map(task, &out.AppServeAppTask); err != nil { + log.InfoWithContext(r.Context(), err) + } + out.Stages = makeStages(task, app) ResponseJSON(w, r, http.StatusOK, out) } -func makeStages(task *domain.AppServeAppTask, app *domain.AppServeApp) []domain.StageResponse { +func makeStages(task *model.AppServeAppTask, app *model.AppServeApp) []domain.StageResponse { stages := make([]domain.StageResponse, 0) var stage domain.StageResponse @@ -582,7 +605,7 @@ func makeStages(task *domain.AppServeAppTask, app *domain.AppServeApp) []domain. return stages } -func makeStage(task *domain.AppServeAppTask, app *domain.AppServeApp, pl string) domain.StageResponse { +func makeStage(task *model.AppServeAppTask, app *model.AppServeApp, pl string) domain.StageResponse { taskStatus := task.Status strategy := task.Strategy @@ -774,7 +797,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re // from existing app config. //appReq.SetDefaultValue() - var task domain.AppServeAppTask + var task model.AppServeAppTask //tasks := app.AppServeAppTasks //sort.Slice(tasks, func(i, j int) bool { // return tasks[i].CreatedAt.String() > tasks[j].CreatedAt.String() diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 72a56812..d2fea4d3 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -7,6 +7,7 @@ import ( "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" @@ -61,7 +62,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { user, err := h.usecase.Login(input.AccountId, input.Password, input.OrganizationId) if err != nil { errorResponse, _ := httpErrors.ErrorResponse(err) - _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ + _, _ = h.auditUsecase.Create(r.Context(), model.Audit{ OrganizationId: input.OrganizationId, Group: "Auth", Message: fmt.Sprintf("[%s]님이 로그인에 실패하였습니다.", input.AccountId), @@ -73,7 +74,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } else { - _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ + _, _ = h.auditUsecase.Create(r.Context(), model.Audit{ OrganizationId: input.OrganizationId, Group: "Auth", Message: fmt.Sprintf("[%s]님이 로그인 하였습니다.", input.AccountId), diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 15b4f6a1..d27fa317 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -7,6 +7,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -53,7 +54,7 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. return } - var dto domain.CloudAccount + var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -198,7 +199,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. return } - var dto domain.CloudAccount + var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -248,7 +249,7 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. return } - var dto domain.CloudAccount + var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 1f8fb6a9..d0811b04 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -4,8 +4,8 @@ import ( "fmt" "net/http" - "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -58,6 +58,13 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { log.InfoWithContext(r.Context(), err) continue } + + if cluster.Favorites != nil && len(*cluster.Favorites) > 0 { + out.Clusters[i].Favorited = true + } else { + out.Clusters[i].Favorited = false + } + } if out.Pagination, err = pg.Response(); err != nil { @@ -75,7 +82,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.Cluster +// @Success 200 {object} domain.GetClusterResponse // @Router /clusters/{clusterId} [get] // @Security JWT func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { @@ -150,19 +157,13 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Cluster + var dto model.Cluster if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } - if err = serializer.Map(input, &dto.Conf); err != nil { - log.InfoWithContext(r.Context(), err) - } - - // [TODO] set default value dto.ClusterType = domain.ClusterType_USER - dto.Conf.SetDefault() - log.InfoWithContext(r.Context(), dto.Conf) + dto.SetDefaultConf() //txHandle := r.Context().Value("txHandle").(*gorm.DB) clusterId := domain.ClusterId("") @@ -210,18 +211,13 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Cluster + var dto model.Cluster if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } + dto.SetDefaultConf() - if err = serializer.Map(input, &dto.Conf); err != nil { - log.InfoWithContext(r.Context(), err) - } - dto.Conf.SetDefault() - log.InfoWithContext(r.Context(), dto.Conf) - - dto.CloudAccountId = uuid.Nil + dto.CloudAccountId = nil clusterId, err := h.usecase.Import(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) @@ -270,7 +266,7 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) // @Accept json // @Produce json // @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.Cluster +// @Success 200 {object} nil // @Router /clusters/{clusterId} [delete] // @Security JWT func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 26bbb8d7..e2d9068d 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -6,6 +6,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -52,7 +53,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } ctx := r.Context() - var organization domain.Organization + var organization model.Organization if err = serializer.Map(input, &organization); err != nil { log.ErrorWithContext(r.Context(), err) } @@ -66,7 +67,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. organization.ID = organizationId // Role 생성 - adminRole := domain.Role{ + adminRole := model.Role{ OrganizationID: organizationId, Name: "admin", Description: "admin", @@ -78,7 +79,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. ErrorJSON(w, r, err) return } - userRole := domain.Role{ + userRole := model.Role{ OrganizationID: organizationId, Name: "user", Description: "user", @@ -216,7 +217,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.Organization +// @Success 200 {object} nil // @Router /organizations/{organizationId} [delete] // @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 22bdfb64..d7ca79d9 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -1,12 +1,15 @@ package http import ( + "net/http" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" - "net/http" ) type IPermissionHandler interface { @@ -32,19 +35,24 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { // @Description Get Permission Templates // @Accept json // @Produce json -// @Success 200 {object} domain.PermissionSet +// @Success 200 {object} domain.PermissionSetResponse // @Router /permissions/templates [get] // @Security JWT func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { - permissionSet := domain.NewDefaultPermissionSet() + permissionSet := model.NewDefaultPermissionSet() + + var premissionSetResponse domain.PermissionSetResponse + if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { + log.InfoWithContext(r.Context(), err) + } var out domain.GetPermissionTemplatesResponse - out.Permissions = append(out.Permissions, permissionSet.Dashboard) - out.Permissions = append(out.Permissions, permissionSet.Stack) - out.Permissions = append(out.Permissions, permissionSet.SecurityPolicy) - out.Permissions = append(out.Permissions, permissionSet.ProjectManagement) - out.Permissions = append(out.Permissions, permissionSet.Notification) - out.Permissions = append(out.Permissions, permissionSet.Configuration) + out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) + out.Permissions = append(out.Permissions, premissionSetResponse.Stack) + out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) + out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) + out.Permissions = append(out.Permissions, premissionSetResponse.Notification) + out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) ResponseJSON(w, r, http.StatusOK, out) } @@ -56,7 +64,7 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http // @Description Get Permissions By Role ID // @Accept json // @Produce json -// @Success 200 {object} domain.PermissionSet +// @Success 200 {object} domain.PermissionSetResponse // @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] // @Security JWT func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { @@ -77,13 +85,18 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http return } + var premissionSetResponse domain.PermissionSetResponse + if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { + log.InfoWithContext(r.Context(), err) + } + var out domain.GetPermissionsByRoleIdResponse - out.Permissions = append(out.Permissions, permissionSet.Dashboard) - out.Permissions = append(out.Permissions, permissionSet.Stack) - out.Permissions = append(out.Permissions, permissionSet.SecurityPolicy) - out.Permissions = append(out.Permissions, permissionSet.ProjectManagement) - out.Permissions = append(out.Permissions, permissionSet.Notification) - out.Permissions = append(out.Permissions, permissionSet.Configuration) + out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) + out.Permissions = append(out.Permissions, premissionSetResponse.Stack) + out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) + out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) + out.Permissions = append(out.Permissions, premissionSetResponse.Notification) + out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) ResponseJSON(w, r, http.StatusOK, out) } @@ -122,9 +135,15 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h } log.Debugf("input: %+v", input) - for _, permission := range input.Permissions { - log.Debugf("permission: %+v", permission) - if err := h.permissionUsecase.UpdatePermission(permission); err != nil { + for _, permissionResponse := range input.Permissions { + log.Debugf("permissionResponse: %+v", permissionResponse) + + var permission model.Permission + if err := serializer.Map(permissionResponse, &permission); err != nil { + log.InfoWithContext(r.Context(), err) + } + + if err := h.permissionUsecase.UpdatePermission(&permission); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 1ad67b29..7fdb1157 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -1,14 +1,16 @@ package http import ( + "net/http" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" - "net/http" ) type IRoleHandler interface { @@ -67,7 +69,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - dto := domain.Role{ + dto := model.Role{ OrganizationID: organizationId, Name: input.Name, Description: input.Description, @@ -82,7 +84,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // create permission - defaultPermissionSet := domain.NewDefaultPermissionSet() + defaultPermissionSet := model.NewDefaultPermissionSet() h.permissionUsecase.SetRoleIdToPermissionSet(roleId, defaultPermissionSet) err = h.permissionUsecase.CreatePermissionSet(defaultPermissionSet) if err != nil { @@ -256,7 +258,7 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - dto := domain.Role{ + dto := model.Role{ ID: roleId, Description: input.Description, } diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 107e621b..1bbb42ce 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -46,7 +47,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt return } - var dto domain.StackTemplate + var dto model.StackTemplate if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -192,7 +193,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt return } - var dto domain.StackTemplate + var dto model.StackTemplate if err := serializer.Map(r, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -287,7 +288,7 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW return } - var dto domain.StackTemplate + var dto model.StackTemplate if err := serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index fd84da4e..9a40cf22 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -51,13 +52,10 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Stack + var dto model.Stack if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } - if err = serializer.Map(input, &dto.Conf); err != nil { - log.InfoWithContext(r.Context(), err) - } dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -126,7 +124,10 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { for i, stack := range stacks { if err := serializer.Map(stack, &out.Stacks[i]); err != nil { log.InfoWithContext(r.Context(), err) - continue + } + + if err := serializer.Map(stack.CreatedAt, &out.Stacks[i].CreatedAt); err != nil { + log.InfoWithContext(r.Context(), err) } err = json.Unmarshal(stack.StackTemplate.Services, &out.Stacks[i].StackTemplate.Services) @@ -259,7 +260,7 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Stack + var dto model.Stack if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -302,7 +303,7 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Stack + var dto model.Stack dto.ID = domain.StackId(strId) dto.OrganizationId = organizationId diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 7df3a3bc..9fa3b8b7 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -9,6 +9,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -86,11 +87,11 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user domain.User + var user model.User if err = serializer.Map(input, &user); err != nil { log.ErrorWithContext(r.Context(), err) } - user.Organization = domain.Organization{ + user.Organization = model.Organization{ ID: organizationId, } @@ -231,7 +232,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Success 200 {object} domain.User +// @Success 200 {object} nil // @Router /organizations/{organizationId}/users/{accountId} [delete] // @Security JWT func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { @@ -298,12 +299,12 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user domain.User + var user model.User if err = serializer.Map(input, &user); err != nil { ErrorJSON(w, r, err) return } - user.Organization = domain.Organization{ + user.Organization = model.Organization{ ID: organizationId, } user.AccountId = accountId @@ -451,7 +452,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user domain.User + var user model.User if err = serializer.Map(input, &user); err != nil { log.ErrorWithContext(r.Context(), err) ErrorJSON(w, r, err) @@ -710,7 +711,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } } - user := domain.User{ + user := model.User{ Name: input.Name, AccountId: input.AccountId, Email: input.Email, @@ -732,7 +733,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } } - user.Organization = domain.Organization{ + user.Organization = model.Organization{ ID: organizationId, } @@ -973,14 +974,14 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - user := domain.User{ + user := model.User{ AccountId: accountId, Name: input.Name, Email: input.Email, Department: input.Department, Description: input.Description, } - user.Organization = domain.Organization{ + user.Organization = model.Organization{ ID: organizationId, } diff --git a/internal/filter/settings.go b/internal/filter/settings.go index ac2a31a8..6634545d 100644 --- a/internal/filter/settings.go +++ b/internal/filter/settings.go @@ -330,6 +330,7 @@ func getField(field string, sch *schema.Schema, blacklist *Blacklist) (*schema.F if !ok { return nil, nil, "" } + return col, s, joinName } diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 8d2252f5..610d59ad 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -10,7 +10,7 @@ import ( "time" "github.com/Nerzal/gocloak/v13" - "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" ) @@ -18,15 +18,15 @@ import ( type IKeycloak interface { InitializeKeycloak() error - LoginAdmin(accountId string, password string) (*domain.User, error) - Login(accountId string, password string, organizationId string) (*domain.User, error) + LoginAdmin(accountId string, password string) (*model.User, error) + Login(accountId string, password string, organizationId string) (*model.User, error) Logout(sessionId string, organizationId string) error CreateRealm(organizationId string) (string, error) - GetRealm(organizationId string) (*domain.Organization, error) - GetRealms() ([]*domain.Organization, error) + GetRealm(organizationId string) (*model.Organization, error) + GetRealms() ([]*model.Organization, error) DeleteRealm(organizationId string) error - UpdateRealm(organizationId string, organizationConfig domain.Organization) error + UpdateRealm(organizationId string, organizationConfig model.Organization) error CreateUser(organizationId string, user *gocloak.User) (string, error) GetUser(organizationId string, userAccountId string) (*gocloak.User, error) @@ -51,7 +51,7 @@ type Keycloak struct { adminCliToken *gocloak.JWT } -func (k *Keycloak) LoginAdmin(accountId string, password string) (*domain.User, error) { +func (k *Keycloak) LoginAdmin(accountId string, password string) (*model.User, error) { ctx := context.Background() JWTToken, err := k.client.LoginAdmin(ctx, accountId, password, DefaultMasterRealm) if err != nil { @@ -59,17 +59,17 @@ func (k *Keycloak) LoginAdmin(accountId string, password string) (*domain.User, return nil, err } - return &domain.User{Token: JWTToken.AccessToken}, nil + return &model.User{Token: JWTToken.AccessToken}, nil } -func (k *Keycloak) Login(accountId string, password string, organizationId string) (*domain.User, error) { +func (k *Keycloak) Login(accountId string, password string, organizationId string) (*model.User, error) { ctx := context.Background() JWTToken, err := k.client.Login(ctx, DefaultClientID, k.config.ClientSecret, organizationId, accountId, password) if err != nil { log.Error(err) return nil, err } - return &domain.User{Token: JWTToken.AccessToken}, nil + return &model.User{Token: JWTToken.AccessToken}, nil } func New(config *Config) IKeycloak { @@ -249,7 +249,7 @@ func (k *Keycloak) CreateRealm(organizationId string) (string, error) { return realmUUID, nil } -func (k *Keycloak) GetRealm(organizationId string) (*domain.Organization, error) { +func (k *Keycloak) GetRealm(organizationId string) (*model.Organization, error) { ctx := context.Background() token := k.adminCliToken realm, err := k.client.GetRealm(ctx, token.AccessToken, organizationId) @@ -260,14 +260,14 @@ func (k *Keycloak) GetRealm(organizationId string) (*domain.Organization, error) return k.reflectOrganization(*realm), nil } -func (k *Keycloak) GetRealms() ([]*domain.Organization, error) { +func (k *Keycloak) GetRealms() ([]*model.Organization, error) { ctx := context.Background() token := k.adminCliToken realms, err := k.client.GetRealms(ctx, token.AccessToken) if err != nil { return nil, err } - organization := make([]*domain.Organization, 0) + organization := make([]*model.Organization, 0) for _, realm := range realms { organization = append(organization, k.reflectOrganization(*realm)) } @@ -275,7 +275,7 @@ func (k *Keycloak) GetRealms() ([]*domain.Organization, error) { return organization, nil } -func (k *Keycloak) UpdateRealm(organizationId string, organizationConfig domain.Organization) error { +func (k *Keycloak) UpdateRealm(organizationId string, organizationConfig model.Organization) error { ctx := context.Background() token := k.adminCliToken realm := k.reflectRealmRepresentation(organizationConfig) @@ -844,14 +844,14 @@ func (k *Keycloak) createDefaultClient(ctx context.Context, accessToken string, return id, nil } -func (k *Keycloak) reflectOrganization(org gocloak.RealmRepresentation) *domain.Organization { - return &domain.Organization{ +func (k *Keycloak) reflectOrganization(org gocloak.RealmRepresentation) *model.Organization { + return &model.Organization{ ID: *org.ID, Name: *org.Realm, } } -func (k *Keycloak) reflectRealmRepresentation(org domain.Organization) *gocloak.RealmRepresentation { +func (k *Keycloak) reflectRealmRepresentation(org model.Organization) *gocloak.RealmRepresentation { return &gocloak.RealmRepresentation{ Realm: gocloak.StringP(org.Name), } diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 428f8d35..12360269 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -10,8 +10,8 @@ import ( internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/middleware/logging" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) @@ -59,7 +59,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han message, description = fn(lrw.GetBody(), body, statusCode) r.Body = io.NopCloser(bytes.NewBuffer(body)) - dto := domain.Audit{ + dto := model.Audit{ OrganizationId: organizationId, Group: internalApi.ApiMap[endpoint].Group, Message: message, diff --git a/internal/model/alert.go b/internal/model/alert.go new file mode 100644 index 00000000..5d360781 --- /dev/null +++ b/internal/model/alert.go @@ -0,0 +1,60 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +// Models +type Alert struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Name string + Code string + Description string + Grade string + Message string + ClusterId domain.ClusterId + Cluster Cluster `gorm:"foreignKey:ClusterId"` + Node string + CheckPoint string + GrafanaUrl string + FiredAt *time.Time `gorm:"-:all"` + TakedAt *time.Time `gorm:"-:all"` + ClosedAt *time.Time `gorm:"-:all"` + TakedSec int `gorm:"-:all"` + ProcessingSec int `gorm:"-:all"` + LastTaker User `gorm:"-:all"` + AlertActions []AlertAction + Summary string + RawData datatypes.JSON + Status domain.AlertActionStatus `gorm:"index"` +} + +func (c *Alert) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + +type AlertAction struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + AlertId uuid.UUID + Content string + Status domain.AlertActionStatus + TakerId *uuid.UUID `gorm:"type:uuid"` + Taker User `gorm:"foreignKey:TakerId"` +} + +func (c *AlertAction) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/app-group.go b/internal/model/app-group.go new file mode 100644 index 00000000..fea48726 --- /dev/null +++ b/internal/model/app-group.go @@ -0,0 +1,47 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +// Models +type AppGroup struct { + gorm.Model + + ID domain.AppGroupId `gorm:"primarykey"` + AppGroupType domain.AppGroupType + ClusterId domain.ClusterId + Name string + Description string + WorkflowId string + Status domain.AppGroupStatus + StatusDesc string + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = domain.AppGroupId(helper.GenerateApplicaionGroupId()) + return nil +} + +type Application struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid"` + AppGroupId domain.AppGroupId + Endpoint string + Metadata datatypes.JSON + Type domain.ApplicationType +} + +func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go new file mode 100644 index 00000000..4b6e779e --- /dev/null +++ b/internal/model/app-serve-app.go @@ -0,0 +1,67 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +type AppServeApp struct { + ID string `gorm:"primarykey" json:"id,omitempty"` + Name string `gorm:"index" json:"name,omitempty"` // application name + Namespace string `json:"namespace,omitempty"` // application namespace + OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to + Type string `json:"type,omitempty"` // type (build/deploy/all) + AppType string `json:"appType,omitempty"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed + TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name + Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` + AppServeAppTasks []AppServeAppTask `gorm:"foreignKey:AppServeAppId" json:"appServeAppTasks"` +} + +type AppServeAppTask struct { + ID string `gorm:"primarykey" json:"id,omitempty"` + AppServeAppId string `gorm:"not null" json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to + Version string `json:"version,omitempty"` // application version + Status string `json:"status,omitempty"` // status is app status + Output string `json:"output,omitempty"` // output for task result + ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) + ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app + ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image + Profile string `json:"profile,omitempty"` // java app profile + AppConfig string `json:"appConfig,omitempty"` // java app config + AppSecret string `json:"appSecret,omitempty"` // java app secret + ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app + Port string `json:"port,omitempty"` // java app port + ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod + HelmRevision int32 `gorm:"default:0" json:"helmRevision,omitempty"` // revision of deployed helm release + Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) + RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version + PvEnabled bool `json:"pvEnabled"` + PvStorageClass string `json:"pvStorageClass"` + PvAccessMode string `json:"pvAccessMode"` + PvSize string `json:"pvSize"` + PvMountPath string `json:"pvMountPath"` + AvailableRollback bool `gorm:"-:all" json:"availableRollback"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` // createdAt is a creation timestamp for the application + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +func (a *AppServeApp) BeforeCreate(tx *gorm.DB) (err error) { + a.ID = uuid.New().String() + return nil +} + +func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} diff --git a/internal/model/audit.go b/internal/model/audit.go new file mode 100644 index 00000000..bfa853c1 --- /dev/null +++ b/internal/model/audit.go @@ -0,0 +1,26 @@ +package model + +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) + +// Models +type Audit struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Group string + Message string + Description string + ClientIP string + UserId *uuid.UUID `gorm:"type:uuid"` + User User `gorm:"foreignKey:UserId"` +} + +func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/cloud-account.go b/internal/model/cloud-account.go new file mode 100644 index 00000000..33d3a14b --- /dev/null +++ b/internal/model/cloud-account.go @@ -0,0 +1,38 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +// Models +type CloudAccount struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Name string `gorm:"index"` + Description string `gorm:"index"` + Resource string + CloudService string + WorkflowId string + Status domain.CloudAccountStatus + StatusDesc string + AwsAccountId string + AccessKeyId string `gorm:"-:all"` + SecretAccessKey string `gorm:"-:all"` + SessionToken string `gorm:"-:all"` + Clusters int `gorm:"-:all"` + CreatedIAM bool + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/cluster.go b/internal/model/cluster.go new file mode 100644 index 00000000..8ca4b764 --- /dev/null +++ b/internal/model/cluster.go @@ -0,0 +1,84 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +// Models +type Cluster struct { + gorm.Model + + ID domain.ClusterId `gorm:"primarykey"` + Name string `gorm:"index"` + CloudService string `gorm:"default:AWS"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Description string `gorm:"index"` + WorkflowId string + Status domain.ClusterStatus + StatusDesc string + CloudAccountId *uuid.UUID + CloudAccount CloudAccount `gorm:"foreignKey:CloudAccountId"` + StackTemplateId uuid.UUID + StackTemplate StackTemplate `gorm:"foreignKey:StackTemplateId"` + Favorites *[]ClusterFavorite + ClusterType domain.ClusterType `gorm:"default:0"` + ByoClusterEndpointHost string + ByoClusterEndpointPort int + IsStack bool `gorm:"default:false"` + TksCpNode int + TksCpNodeMax int + TksCpNodeType string + TksInfraNode int + TksInfraNodeMax int + TksInfraNodeType string + TksUserNode int + TksUserNodeMax int + TksUserNodeType string + Kubeconfig []byte `gorm:"-:all"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (m *Cluster) SetDefaultConf() { + m.TksCpNodeMax = m.TksCpNode + + if m.TksInfraNode == 0 { + m.TksInfraNode = 3 + } + m.TksInfraNodeMax = m.TksInfraNode + + if m.TksUserNode == 0 { + m.TksUserNode = 1 + } + m.TksUserNodeMax = m.TksUserNode + + if m.TksCpNodeType == "" { + m.TksCpNodeType = "t3.xlarge" + } + if m.TksInfraNodeType == "" { + m.TksInfraNodeType = "t3.2xlarge" + } + if m.TksUserNodeType == "" { + m.TksUserNodeType = "t3.large" + } +} + +type ClusterFavorite struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid"` + ClusterId domain.ClusterId + Cluster Cluster `gorm:"foreignKey:ClusterId"` + UserId uuid.UUID `gorm:"type:uuid"` + User User `gorm:"foreignKey:UserId"` +} + +func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/dashboard.go b/internal/model/dashboard.go new file mode 100644 index 00000000..618f24be --- /dev/null +++ b/internal/model/dashboard.go @@ -0,0 +1,34 @@ +package model + +import ( + "time" + + "github.com/openinfradev/tks-api/pkg/domain" +) + +// 내부 +type DashboardChart struct { + ChartType domain.ChartType + OrganizationId string + Name string + Description string + Duration string // 1d, 7d, 30d ... + Interval string // 1h, 1d, ... + Year string + Month string + ChartData domain.ChartData + UpdatedAt time.Time +} + +type DashboardStack struct { + ID domain.StackId + Name string + Description string + Status string + StatusDesc string + Cpu string + Memory string + Storage string + CreatedAt time.Time + UpdatedAt time.Time +} diff --git a/internal/model/end-point.go b/internal/model/end-point.go new file mode 100644 index 00000000..912fa0ce --- /dev/null +++ b/internal/model/end-point.go @@ -0,0 +1,11 @@ +package model + +import ( + "time" +) + +type Endpoint struct { + Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` + Group string `gorm:"type:text;" json:"group"` + CreatedAt time.Time +} diff --git a/internal/model/organization.go b/internal/model/organization.go new file mode 100644 index 00000000..74264c16 --- /dev/null +++ b/internal/model/organization.go @@ -0,0 +1,21 @@ +package model + +import ( + "gorm.io/gorm" + + "github.com/openinfradev/tks-api/pkg/domain" +) + +type Organization struct { + gorm.Model + + ID string `gorm:"primarykey;type:varchar(36);not null"` + Name string + Description string + Phone string + PrimaryClusterId string + WorkflowId string + Status domain.OrganizationStatus + StatusDesc string + Creator string +} diff --git a/internal/model/permission.go b/internal/model/permission.go new file mode 100644 index 00000000..b83824af --- /dev/null +++ b/internal/model/permission.go @@ -0,0 +1,615 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/helper" + "gorm.io/gorm" +) + +type PermissionKind string + +const ( + DashBoardPermission PermissionKind = "대시보드" + StackPermission PermissionKind = "스택 관리" + SecurityPolicyPermission PermissionKind = "보안/정책 관리" + ProjectManagementPermission PermissionKind = "프로젝트 관리" + NotificationPermission PermissionKind = "알림" + ConfigurationPermission PermissionKind = "설정" +) + +type Permission struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` + Name string `json:"name"` + + IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` + RoleID *string `json:"role_id,omitempty"` + Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` + Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` + // omit empty + + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` + Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` +} + +func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { + if p.ID == uuid.Nil { + p.ID = uuid.New() + } + return nil +} + +type PermissionSet struct { + Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` + Stack *Permission `gorm:"-:all" json:"stack,omitempty"` + SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` + ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` + Notification *Permission `gorm:"-:all" json:"notification,omitempty"` + Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` +} + +func NewDefaultPermissionSet() *PermissionSet { + return &PermissionSet{ + Dashboard: newDashboard(), + Stack: newStack(), + SecurityPolicy: newSecurityPolicy(), + ProjectManagement: newProjectManagement(), + Notification: newNotification(), + Configuration: newConfiguration(), + } +} + +func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { + if root.Children == nil { + return append(edgePermissions, root) + } + + for _, child := range root.Children { + if f != nil && !(*f)(*child) { + continue + } + edgePermissions = GetEdgePermission(child, edgePermissions, f) + } + + return edgePermissions +} + +func SetRoleIDToPermission(roleID string, permission *Permission) { + permission.RoleID = helper.StringP(roleID) +} + +func endpointObjects(eps ...api.Endpoint) []*Endpoint { + var result []*Endpoint + for _, ep := range eps { + result = append(result, &Endpoint{ + Name: api.ApiMap[ep].Name, + Group: api.ApiMap[ep].Group, + }) + } + return result +} + +func newDashboard() *Permission { + dashboard := &Permission{ + Name: string(DashBoardPermission), + Children: []*Permission{ + { + Name: "대시보드", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetChartsDashboard, + api.GetChartDashboard, + api.GetStacksDashboard, + api.GetResourcesDashboard, + ), + }, + }, + }, + { + Name: "대시보드 설정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return dashboard +} + +func newStack() *Permission { + stack := &Permission{ + Name: string(StackPermission), + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetStacks, + api.GetStack, + api.CheckStackName, + api.GetStackStatus, + api.GetStackKubeConfig, + + api.SetFavoriteStack, + api.DeleteFavoriteStack, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateStack, + api.InstallStack, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateStack, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteStack, + ), + }, + }, + } + + return stack +} + +func newSecurityPolicy() *Permission { + security_policy := &Permission{ + Name: string(SecurityPolicyPermission), + Children: []*Permission{ + { + Name: "보안/정책", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return security_policy +} + +func newProjectManagement() *Permission { + projectManagement := &Permission{ + Name: string(ProjectManagementPermission), + Children: []*Permission{ + { + Name: "프로젝트", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProject, + ), + }, + }, + }, + { + Name: "앱 서빙", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetAppServeApps, + api.GetAppServeApp, + api.GetNumOfAppsOnStack, + api.GetAppServeAppLatestTask, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + ), + }, + { + Name: "빌드", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + Name: "배포", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteAppServeApp, + ), + }, + }, + }, + { + Name: "설정-일반", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + + api.GetProjectRoles, + api.GetProjectRole, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProject, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProject, + ), + }, + }, + }, + { + Name: "설정-멤버", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectMembers, + api.GetProjectMember, + api.GetProjectRoles, + api.GetProjectRole, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.AddProjectMember, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProjectMemberRole, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.RemoveProjectMember, + ), + }, + }, + }, + { + Name: "설정-네임스페이스", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectNamespaces, + api.GetProjectNamespace, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProjectNamespace, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects(), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProjectNamespace, + ), + }, + }, + }, + }, + } + + return projectManagement +} + +func newNotification() *Permission { + notification := &Permission{ + Name: string(NotificationPermission), + Children: []*Permission{ + { + Name: "시스템 경고", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "보안/정책 감사로그", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return notification +} + +func newConfiguration() *Permission { + configuration := &Permission{ + Name: string(ConfigurationPermission), + Children: []*Permission{ + { + Name: "일반", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "클라우드 계정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "스택 템플릿", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "프로젝트 관리", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자 권한 관리", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "알림 설정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return configuration +} + +func (p *PermissionSet) SetAllowedPermissionSet() { + edgePermissions := make([]*Permission, 0) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) + + for _, permission := range edgePermissions { + permission.IsAllowed = helper.BoolP(true) + } + + return +} + +func (p *PermissionSet) SetUserPermissionSet() { + f := func(permission Permission) bool { + return permission.Name == "조회" + } + edgePermissions := make([]*Permission, 0) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) + //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) + + for _, permission := range edgePermissions { + permission.IsAllowed = helper.BoolP(true) + } + + return +} + +func (p *PermissionSet) SetRoleId(roleId string) { + setRoleIdToPermission(p.Dashboard, roleId) + setRoleIdToPermission(p.Stack, roleId) + setRoleIdToPermission(p.SecurityPolicy, roleId) + setRoleIdToPermission(p.ProjectManagement, roleId) + setRoleIdToPermission(p.Notification, roleId) + setRoleIdToPermission(p.Configuration, roleId) +} + +func setRoleIdToPermission(root *Permission, roleId string) { + root.RoleID = helper.StringP(roleId) + + if root.Children == nil { + return + } + + for _, child := range root.Children { + setRoleIdToPermission(child, roleId) + } +} diff --git a/internal/model/role.go b/internal/model/role.go new file mode 100644 index 00000000..01f6497a --- /dev/null +++ b/internal/model/role.go @@ -0,0 +1,27 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { + r.ID = uuid.New().String() + return nil +} + +type Role struct { + gorm.Model + + ID string `gorm:"primarykey;" json:"id"` + Name string `json:"name"` + OrganizationID string `json:"organizationId"` + Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;" json:"organization"` + Type string `json:"type"` + Description string `json:"description"` + Creator uuid.UUID `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} diff --git a/internal/model/stack-template.go b/internal/model/stack-template.go new file mode 100644 index 00000000..3bdda2f8 --- /dev/null +++ b/internal/model/stack-template.go @@ -0,0 +1,35 @@ +package model + +import ( + "github.com/google/uuid" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +type StackTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index"` + Description string `gorm:"index"` + Template string + TemplateType string + Version string + CloudService string + Platform string + KubeVersion string + KubeType string + Organizations []Organization `gorm:"many2many:stack_template_organizations"` + Services datatypes.JSON + ServiceIds []string `gorm:"-:all"` + OrganizationIds []string `gorm:"-:all"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/stack.go b/internal/model/stack.go new file mode 100644 index 00000000..7d52f37a --- /dev/null +++ b/internal/model/stack.go @@ -0,0 +1,45 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +type Stack = struct { + gorm.Model + + ID domain.StackId + Name string + Description string + ClusterId string + OrganizationId string + CloudService string + CloudAccountId uuid.UUID + CloudAccount CloudAccount + StackTemplateId uuid.UUID + StackTemplate StackTemplate + Status domain.StackStatus + StatusDesc string + PrimaryCluster bool + GrafanaUrl string + CreatorId *uuid.UUID + Creator User + UpdatorId *uuid.UUID + Updator User + Favorited bool + ClusterEndpoint string + Resource DashboardStack +} + +type StackConf struct { + TksCpNode int + TksCpNodeMax int + TksCpNodeType string + TksInfraNode int + TksInfraNodeMax int + TksInfraNodeType string + TksUserNode int + TksUserNodeMax int + TksUserNodeType string +} diff --git a/internal/model/user.go b/internal/model/user.go new file mode 100644 index 00000000..96303110 --- /dev/null +++ b/internal/model/user.go @@ -0,0 +1,34 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +type User struct { + ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` + AccountId string `json:"accountId"` + Password string `gorm:"-:all" json:"password"` + Name string `json:"name"` + Token string `json:"token"` + RoleId string + Role Role `gorm:"foreignKey:RoleId;references:ID" json:"role"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` + PasswordExpired bool `json:"passwordExpired"` + + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` +} + +func (g *User) BeforeCreate(tx *gorm.DB) (err error) { + g.PasswordUpdatedAt = time.Now() + return nil +} diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 0de16f10..4b32fc39 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -9,6 +9,8 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" + "golang.org/x/text/cases" + "golang.org/x/text/language" "gorm.io/gorm" "goyave.dev/goyave/v4" @@ -212,7 +214,7 @@ func NewPagination(urlParams *url.Values) *Pagination { releation := "" arrColumns := strings.Split(column, ".") if len(arrColumns) > 1 { - releation = arrColumns[0] + releation = cases.Title(language.English, cases.Compact).String(arrColumns[0]) column = arrColumns[1] } diff --git a/internal/repository/alert.go b/internal/repository/alert.go index 4e8c8575..2d35f536 100644 --- a/internal/repository/alert.go +++ b/internal/repository/alert.go @@ -4,27 +4,25 @@ import ( "time" "github.com/google/uuid" - "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAlertRepository interface { - Get(alertId uuid.UUID) (domain.Alert, error) - GetByName(organizationId string, name string) (domain.Alert, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]domain.Alert, error) - FetchPodRestart(organizationId string, start time.Time, end time.Time) ([]domain.Alert, error) - Create(dto domain.Alert) (alertId uuid.UUID, err error) - Update(dto domain.Alert) (err error) - Delete(dto domain.Alert) (err error) - - CreateAlertAction(dto domain.AlertAction) (alertActionId uuid.UUID, err error) + Get(alertId uuid.UUID) (model.Alert, error) + GetByName(organizationId string, name string) (model.Alert, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]model.Alert, error) + FetchPodRestart(organizationId string, start time.Time, end time.Time) ([]model.Alert, error) + Create(dto model.Alert) (alertId uuid.UUID, err error) + Update(dto model.Alert) (err error) + Delete(dto model.Alert) (err error) + + CreateAlertAction(dto model.AlertAction) (alertActionId uuid.UUID, err error) } type AlertRepository struct { @@ -37,114 +35,55 @@ func NewAlertRepository(db *gorm.DB) IAlertRepository { } } -// Models -type Alert struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Name string - Code string - Description string - Grade string - Message string - ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - Node string - CheckPoint string - GrafanaUrl string - Summary string - AlertActions []AlertAction - RawData datatypes.JSON - Status domain.AlertActionStatus `gorm:"index"` -} - -func (c *Alert) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - -type AlertAction struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - AlertId uuid.UUID - Content string - Status domain.AlertActionStatus - TakerId *uuid.UUID `gorm:"type:uuid"` - Taker domain.User `gorm:"foreignKey:TakerId"` -} - -func (c *AlertAction) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *AlertRepository) Get(alertId uuid.UUID) (out domain.Alert, err error) { - var alert Alert - res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&alert, "id = ?", alertId) +func (r *AlertRepository) Get(alertId uuid.UUID) (out model.Alert, err error) { + res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "id = ?", alertId) if res.Error != nil { - return domain.Alert{}, res.Error + return model.Alert{}, res.Error } - out = reflectAlert(alert) return } -func (r *AlertRepository) GetByName(organizationId string, name string) (out domain.Alert, err error) { - var alert Alert - res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&alert, "organization_id = ? AND name = ?", organizationId, name) - +func (r *AlertRepository) GetByName(organizationId string, name string) (out model.Alert, err error) { + res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { - return domain.Alert{}, res.Error + return model.Alert{}, res.Error } - out = reflectAlert(alert) return } -func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.Alert, err error) { - var alerts []Alert +func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.Alert, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&Alert{}). + _, res := pg.Fetch(r.db.Model(&model.Alert{}). Preload("AlertActions", func(db *gorm.DB) *gorm.DB { return db.Order("created_at ASC") }).Preload("AlertActions.Taker"). Preload("Cluster", "status = 2"). Preload("Organization"). Joins("join clusters on clusters.id = alerts.cluster_id AND clusters.status = 2"). - Where("alerts.organization_id = ?", organizationId), &alerts) + Where("alerts.organization_id = ?", organizationId), &out) if res.Error != nil { return nil, res.Error } - - for _, alert := range alerts { - out = append(out, reflectAlert(alert)) - } return } -func (r *AlertRepository) FetchPodRestart(organizationId string, start time.Time, end time.Time) (out []domain.Alert, err error) { - var alerts []Alert +func (r *AlertRepository) FetchPodRestart(organizationId string, start time.Time, end time.Time) (out []model.Alert, err error) { res := r.db.Preload(clause.Associations).Order("created_at DESC"). Where("organization_id = ? AND name = 'pod-restart-frequently' AND created_at BETWEEN ? AND ?", organizationId, start, end). - Find(&alerts) + Find(&out) if res.Error != nil { return nil, res.Error } - - for _, alert := range alerts { - out = append(out, reflectAlert(alert)) - } return } -func (r *AlertRepository) Create(dto domain.Alert) (alertId uuid.UUID, err error) { - alert := Alert{ +func (r *AlertRepository) Create(dto model.Alert) (alertId uuid.UUID, err error) { + alert := model.Alert{ OrganizationId: dto.OrganizationId, Name: dto.Name, Code: dto.Code, @@ -166,8 +105,8 @@ func (r *AlertRepository) Create(dto domain.Alert) (alertId uuid.UUID, err error return alert.ID, nil } -func (r *AlertRepository) Update(dto domain.Alert) (err error) { - res := r.db.Model(&Alert{}). +func (r *AlertRepository) Update(dto model.Alert) (err error) { + res := r.db.Model(&model.Alert{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description}) if res.Error != nil { @@ -176,16 +115,16 @@ func (r *AlertRepository) Update(dto domain.Alert) (err error) { return nil } -func (r *AlertRepository) Delete(dto domain.Alert) (err error) { - res := r.db.Delete(&Alert{}, "id = ?", dto.ID) +func (r *AlertRepository) Delete(dto model.Alert) (err error) { + res := r.db.Delete(&model.Alert{}, "id = ?", dto.ID) if res.Error != nil { return res.Error } return nil } -func (r *AlertRepository) CreateAlertAction(dto domain.AlertAction) (alertActionId uuid.UUID, err error) { - alert := AlertAction{ +func (r *AlertRepository) CreateAlertAction(dto model.AlertAction) (alertActionId uuid.UUID, err error) { + alert := model.AlertAction{ AlertId: dto.AlertId, Content: dto.Content, Status: dto.Status, @@ -195,7 +134,7 @@ func (r *AlertRepository) CreateAlertAction(dto domain.AlertAction) (alertAction if res.Error != nil { return uuid.Nil, res.Error } - res = r.db.Model(&Alert{}). + res = r.db.Model(&model.Alert{}). Where("id = ?", dto.AlertId). Update("status", dto.Status) if res.Error != nil { @@ -204,25 +143,3 @@ func (r *AlertRepository) CreateAlertAction(dto domain.AlertAction) (alertAction return alert.ID, nil } - -func reflectAlert(alert Alert) (out domain.Alert) { - if err := serializer.Map(alert.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(alert, &out); err != nil { - log.Error(err) - } - - out.AlertActions = make([]domain.AlertAction, len(alert.AlertActions)) - for i, alertAction := range alert.AlertActions { - if err := serializer.Map(alertAction.Model, &out.AlertActions[i]); err != nil { - log.Error(err) - continue - } - if err := serializer.Map(alertAction, &out.AlertActions[i]); err != nil { - log.Error(err) - continue - } - } - return -} diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index d78aa1bc..bd824996 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -3,26 +3,24 @@ package repository import ( "fmt" - "github.com/google/uuid" "gorm.io/datatypes" "gorm.io/gorm" - "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAppGroupRepository interface { - Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (res []domain.AppGroup, err error) - Get(id domain.AppGroupId) (domain.AppGroup, error) - Create(dto domain.AppGroup) (id domain.AppGroupId, err error) - Update(dto domain.AppGroup) (err error) + Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (res []model.AppGroup, err error) + Get(id domain.AppGroupId) (model.AppGroup, error) + Create(dto model.AppGroup) (id domain.AppGroupId, err error) + Update(dto model.AppGroup) (err error) Delete(id domain.AppGroupId) error - GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (applications []domain.Application, err error) - UpsertApplication(dto domain.Application) error + GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (applications []model.Application, err error) + UpsertApplication(dto model.Application) error InitWorkflow(appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error InitWorkflowDescription(clusterId domain.ClusterId) error } @@ -37,76 +35,31 @@ func NewAppGroupRepository(db *gorm.DB) IAppGroupRepository { } } -// Models -type AppGroup struct { - gorm.Model - - ID domain.AppGroupId `gorm:"primarykey"` - AppGroupType domain.AppGroupType - ClusterId domain.ClusterId - Name string - Description string - WorkflowId string - Status domain.AppGroupStatus - StatusDesc string - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = domain.AppGroupId(helper.GenerateApplicaionGroupId()) - return nil -} - -type Application struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid"` - AppGroupId domain.AppGroupId - Endpoint string - Metadata datatypes.JSON - Type domain.ApplicationType -} - -func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (out []domain.AppGroup, err error) { - var appGroups []AppGroup +func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&AppGroup{}). - Where("cluster_id = ?", clusterId), &appGroups) + _, res := pg.Fetch(r.db.Model(&model.AppGroup{}). + Where("cluster_id = ?", clusterId), &out) if res.Error != nil { return nil, res.Error } - for _, appGroup := range appGroups { - outAppGroup := reflectAppGroup(appGroup) - out = append(out, outAppGroup) - } return out, nil } -func (r *AppGroupRepository) Get(id domain.AppGroupId) (domain.AppGroup, error) { - var appGroup AppGroup - res := r.db.First(&appGroup, "id = ?", id) +func (r *AppGroupRepository) Get(id domain.AppGroupId) (out model.AppGroup, err error) { + res := r.db.First(&out, "id = ?", id) if res.RowsAffected == 0 || res.Error != nil { - return domain.AppGroup{}, fmt.Errorf("Not found appGroup for %s", id) + return model.AppGroup{}, fmt.Errorf("Not found appGroup for %s", id) } - resAppGroup := reflectAppGroup(appGroup) - return resAppGroup, nil + return out, nil } -func (r *AppGroupRepository) Create(dto domain.AppGroup) (appGroupId domain.AppGroupId, err error) { - appGroup := AppGroup{ +func (r *AppGroupRepository) Create(dto model.AppGroup) (appGroupId domain.AppGroupId, err error) { + appGroup := model.AppGroup{ ClusterId: dto.ClusterId, AppGroupType: dto.AppGroupType, Name: dto.Name, @@ -124,8 +77,8 @@ func (r *AppGroupRepository) Create(dto domain.AppGroup) (appGroupId domain.AppG return appGroup.ID, nil } -func (r *AppGroupRepository) Update(dto domain.AppGroup) (err error) { - res := r.db.Model(&AppGroup{}). +func (r *AppGroupRepository) Update(dto model.AppGroup) (err error) { + res := r.db.Model(&model.AppGroup{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ "ClusterId": dto.ClusterId, @@ -141,35 +94,30 @@ func (r *AppGroupRepository) Update(dto domain.AppGroup) (err error) { } func (r *AppGroupRepository) Delete(id domain.AppGroupId) error { - res := r.db.Unscoped().Delete(&AppGroup{}, "id = ?", id) + res := r.db.Unscoped().Delete(&model.AppGroup{}, "id = ?", id) if res.Error != nil { return fmt.Errorf("could not delete appGroup %s", id) } return nil } -func (r *AppGroupRepository) GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) { - var applications []Application - res := r.db.Where("app_group_id = ? AND type = ?", id, applicationType).Find(&applications) +func (r *AppGroupRepository) GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { + res := r.db.Where("app_group_id = ? AND type = ?", id, applicationType).Find(&out) if res.Error != nil { return nil, res.Error } - for _, application := range applications { - outApplication := reflectApplication(application) - out = append(out, outApplication) - } return out, nil } -func (r *AppGroupRepository) UpsertApplication(dto domain.Application) error { - res := r.db.Where(Application{ +func (r *AppGroupRepository) UpsertApplication(dto model.Application) error { + res := r.db.Where(model.Application{ AppGroupId: dto.AppGroupId, - Type: dto.ApplicationType, + Type: dto.Type, }). - Assign(Application{ + Assign(model.Application{ Endpoint: dto.Endpoint, Metadata: datatypes.JSON([]byte(dto.Metadata))}). - FirstOrCreate(&Application{}) + FirstOrCreate(&model.Application{}) if res.Error != nil { return res.Error } @@ -178,7 +126,7 @@ func (r *AppGroupRepository) UpsertApplication(dto domain.Application) error { } func (r *AppGroupRepository) InitWorkflow(appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error { - res := r.db.Model(&AppGroup{}). + res := r.db.Model(&model.AppGroup{}). Where("ID = ?", appGroupId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId, "StatusDesc": ""}) @@ -190,7 +138,7 @@ func (r *AppGroupRepository) InitWorkflow(appGroupId domain.AppGroupId, workflow } func (r *AppGroupRepository) InitWorkflowDescription(clusterId domain.ClusterId) error { - res := r.db.Model(&AppGroup{}). + res := r.db.Model(&model.AppGroup{}). Where("cluster_id = ?", clusterId). Updates(map[string]interface{}{"WorkflowId": "", "StatusDesc": ""}) @@ -200,22 +148,3 @@ func (r *AppGroupRepository) InitWorkflowDescription(clusterId domain.ClusterId) return nil } - -func reflectAppGroup(appGroup AppGroup) (out domain.AppGroup) { - if err := serializer.Map(appGroup.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(appGroup, &out); err != nil { - log.Error(err) - } - return -} - -func reflectApplication(application Application) (out domain.Application) { - if err := serializer.Map(application, &out); err != nil { - log.Error(err) - } - out.Metadata = application.Metadata.String() - return - -} diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 479f4e77..a1d3e291 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" @@ -11,19 +12,19 @@ import ( ) type IAppServeAppRepository interface { - CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) - GetAppServeAppById(appId string) (*domain.AppServeApp, error) + CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) + GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) + GetAppServeAppById(appId string) (*model.AppServeApp, error) - GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) - GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) + GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) + GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) - GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) + GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) IsAppServeAppExist(appId string) (int64, error) IsAppServeAppNameExist(orgId string, appName string) (int64, error) - CreateTask(task *domain.AppServeAppTask) (taskId string, err error) + CreateTask(task *model.AppServeAppTask) (taskId string, err error) UpdateStatus(appId string, taskId string, status string, output string) error UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error GetTaskCountById(appId string) (int64, error) @@ -39,7 +40,7 @@ func NewAppServeAppRepository(db *gorm.DB) IAppServeAppRepository { } } -func (r *AppServeAppRepository) CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) { +func (r *AppServeAppRepository) CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) { res := r.db.Create(&app) if res.Error != nil { @@ -51,7 +52,7 @@ func (r *AppServeAppRepository) CreateAppServeApp(app *domain.AppServeApp) (appI // Update creates new appServeApp task for existing appServeApp. func (r *AppServeAppRepository) CreateTask( - task *domain.AppServeAppTask) (string, error) { + task *model.AppServeAppTask) (string, error) { res := r.db.Create(task) if res.Error != nil { return "", res.Error @@ -60,14 +61,14 @@ func (r *AppServeAppRepository) CreateTask( return task.ID, nil } -func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) (apps []domain.AppServeApp, err error) { - var clusters []Cluster +func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) (apps []model.AppServeApp, err error) { + var clusters []model.Cluster if pg == nil { pg = pagination.NewPagination(nil) } // TODO: should return different records based on showAll param - _, res := pg.Fetch(r.db.Model(&domain.AppServeApp{}). + _, res := pg.Fetch(r.db.Model(&model.AppServeApp{}). Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId), &apps) if res.Error != nil { return nil, fmt.Errorf("error while finding appServeApps with organizationId: %s", organizationId) @@ -97,9 +98,9 @@ func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll b return } -func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppServeApp, error) { - var app domain.AppServeApp - var cluster Cluster +func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*model.AppServeApp, error) { + var app model.AppServeApp + var cluster model.Cluster res := r.db.Where("id = ?", appId).First(&app) if res.Error != nil { @@ -123,12 +124,12 @@ func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppSer return &app, nil } -func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []domain.AppServeAppTask, err error) { +func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []model.AppServeAppTask, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&domain.AppServeAppTask{}). + _, res := pg.Fetch(r.db.Model(&model.AppServeAppTask{}). Where("app_serve_app_tasks.app_serve_app_id = ?", appId), &tasks) if res.Error != nil { return nil, fmt.Errorf("Error while finding tasks with appId: %s", appId) @@ -143,9 +144,9 @@ func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pag } // Return single task info along with its parent app info -func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) { - var task domain.AppServeAppTask - var app domain.AppServeApp +func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { + var task model.AppServeAppTask + var app model.AppServeApp // Retrieve task info res := r.db.Where("id = ?", taskId).First(&task) @@ -170,8 +171,8 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*domain.A return &task, &app, nil } -func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) { - var task domain.AppServeAppTask +func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) { + var task model.AppServeAppTask // TODO: Does this work?? where's app ID here? res := r.db.Order("created_at desc").First(&task) @@ -187,7 +188,7 @@ func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*domain. } func (r *AppServeAppRepository) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) { - var apps []domain.AppServeApp + var apps []model.AppServeApp queryStr := fmt.Sprintf("organization_id = '%s' AND target_cluster_id = '%s' AND status <> 'DELETE_SUCCESS'", organizationId, clusterId) res := r.db.Find(&apps, queryStr) @@ -227,7 +228,7 @@ func (r *AppServeAppRepository) IsAppServeAppNameExist(orgId string, appName str func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status string, output string) error { now := time.Now() - app := domain.AppServeApp{ + app := model.AppServeApp{ ID: appId, Status: status, UpdatedAt: &now, @@ -237,7 +238,7 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status return fmt.Errorf("UpdateStatus: nothing updated in AppServeApp with ID %s", appId) } - task := domain.AppServeAppTask{ + task := model.AppServeAppTask{ ID: taskId, Status: status, Output: output, @@ -249,16 +250,16 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status } //// Update task status - //res := r.db.Model(&domain.AppServeAppTask{}). + //res := r.db.Model(&model.AppServeAppTask{}). // Where("ID = ?", taskId). - // Updates(domain.AppServeAppTask{Status: status, Output: output}) + // Updates(model.AppServeAppTask{Status: status, Output: output}) // //if res.Error != nil || res.RowsAffected == 0 { // return fmt.Errorf("UpdateStatus: nothing updated in AppServeAppTask with ID %s", taskId) //} // //// Update status of the app. - //res = r.db.Model(&domain.AppServeApp{}). + //res = r.db.Model(&model.AppServeApp{}). // Where("ID = ?", appId). // Update("Status", status) //if res.Error != nil || res.RowsAffected == 0 { @@ -270,14 +271,14 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error { now := time.Now() - app := domain.AppServeApp{ + app := model.AppServeApp{ ID: appId, EndpointUrl: endpoint, PreviewEndpointUrl: previewEndpoint, UpdatedAt: &now, } - task := domain.AppServeAppTask{ + task := model.AppServeAppTask{ ID: taskId, HelmRevision: helmRevision, UpdatedAt: &now, @@ -316,7 +317,7 @@ func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endp func (r *AppServeAppRepository) GetTaskCountById(appId string) (int64, error) { var count int64 - if err := r.db.Model(&domain.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { + if err := r.db.Model(&model.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { return 0, fmt.Errorf("could not select count AppServeAppTask with ID: %s", appId) } return count, nil diff --git a/internal/repository/audit.go b/internal/repository/audit.go index bbee184c..c93de560 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -7,17 +7,15 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" - "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAuditRepository interface { - Get(auditId uuid.UUID) (domain.Audit, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]domain.Audit, error) - Create(dto domain.Audit) (auditId uuid.UUID, err error) + Get(auditId uuid.UUID) (model.Audit, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]model.Audit, error) + Create(dto model.Audit) (auditId uuid.UUID, err error) Delete(auditId uuid.UUID) (err error) } @@ -31,59 +29,30 @@ func NewAuditRepository(db *gorm.DB) IAuditRepository { } } -// Models -type Audit struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Group string - Message string - Description string - ClientIP string - UserId *uuid.UUID `gorm:"type:uuid"` - User domain.User `gorm:"foreignKey:UserId"` -} - -func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *AuditRepository) Get(auditId uuid.UUID) (out domain.Audit, err error) { - var audit Audit - res := r.db.Preload(clause.Associations).First(&audit, "id = ?", auditId) +func (r *AuditRepository) Get(auditId uuid.UUID) (out model.Audit, err error) { + res := r.db.Preload(clause.Associations).First(&out, "id = ?", auditId) if res.Error != nil { return } - out = reflectAudit(audit) return } -func (r *AuditRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.Audit, err error) { - var audits []Audit - +func (r *AuditRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.Audit, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - db := r.db.Model(&Audit{}).Preload(clause.Associations).Where("organization_id = ?", organizationId) - _, res := pg.Fetch(db, &audits) + db := r.db.Model(&model.Audit{}).Preload(clause.Associations).Where("audits.organization_id = ?", organizationId) + _, res := pg.Fetch(db, &out) if res.Error != nil { return nil, res.Error } - - for _, audit := range audits { - out = append(out, reflectAudit(audit)) - } - return } -func (r *AuditRepository) Create(dto domain.Audit) (auditId uuid.UUID, err error) { - audit := Audit{ +func (r *AuditRepository) Create(dto model.Audit) (auditId uuid.UUID, err error) { + audit := model.Audit{ OrganizationId: dto.OrganizationId, Group: dto.Group, Message: dto.Message, @@ -100,13 +69,3 @@ func (r *AuditRepository) Create(dto domain.Audit) (auditId uuid.UUID, err error func (r *AuditRepository) Delete(auditId uuid.UUID) (err error) { return fmt.Errorf("to be implemented") } - -func reflectAudit(audit Audit) (out domain.Audit) { - if err := serializer.Map(audit.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(audit, &out); err != nil { - log.Error(err) - } - return -} diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index 5d9a7de9..08f635c8 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -7,20 +7,19 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type ICloudAccountRepository interface { - Get(cloudAccountId uuid.UUID) (domain.CloudAccount, error) - GetByName(organizationId string, name string) (domain.CloudAccount, error) - GetByAwsAccountId(awsAccountId string) (domain.CloudAccount, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]domain.CloudAccount, error) - Create(dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) - Update(dto domain.CloudAccount) (err error) + Get(cloudAccountId uuid.UUID) (model.CloudAccount, error) + GetByName(organizationId string, name string) (model.CloudAccount, error) + GetByAwsAccountId(awsAccountId string) (model.CloudAccount, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) + Create(dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) + Update(dto model.CloudAccount) (err error) Delete(cloudAccountId uuid.UUID) (err error) InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) (err error) } @@ -35,86 +34,46 @@ func NewCloudAccountRepository(db *gorm.DB) ICloudAccountRepository { } } -// Models -type CloudAccount struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Name string `gorm:"index"` - Description string `gorm:"index"` - Resource string - CloudService string - WorkflowId string - Status domain.CloudAccountStatus - StatusDesc string - AwsAccountId string - CreatedIAM bool - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *CloudAccountRepository) Get(cloudAccountId uuid.UUID) (out domain.CloudAccount, err error) { - var cloudAccount CloudAccount - res := r.db.Preload(clause.Associations).First(&cloudAccount, "id = ?", cloudAccountId) +func (r *CloudAccountRepository) Get(cloudAccountId uuid.UUID) (out model.CloudAccount, err error) { + res := r.db.Preload(clause.Associations).First(&out, "id = ?", cloudAccountId) if res.Error != nil { - return domain.CloudAccount{}, res.Error + return model.CloudAccount{}, res.Error } - out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) GetByName(organizationId string, name string) (out domain.CloudAccount, err error) { - var cloudAccount CloudAccount - res := r.db.Preload(clause.Associations).First(&cloudAccount, "organization_id = ? AND name = ?", organizationId, name) - +func (r *CloudAccountRepository) GetByName(organizationId string, name string) (out model.CloudAccount, err error) { + res := r.db.Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { - return domain.CloudAccount{}, res.Error + return model.CloudAccount{}, res.Error } - out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) GetByAwsAccountId(awsAccountId string) (out domain.CloudAccount, err error) { - var cloudAccount CloudAccount - res := r.db.Preload(clause.Associations).First(&cloudAccount, "aws_account_id = ? AND status != ?", awsAccountId, domain.CloudAccountStatus_DELETED) - +func (r *CloudAccountRepository) GetByAwsAccountId(awsAccountId string) (out model.CloudAccount, err error) { + res := r.db.Preload(clause.Associations).First(&out, "aws_account_id = ? AND status != ?", awsAccountId, domain.CloudAccountStatus_DELETED) if res.Error != nil { - return domain.CloudAccount{}, res.Error + return model.CloudAccount{}, res.Error } - out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.CloudAccount, err error) { - var cloudAccounts []CloudAccount +func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.CloudAccount, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&CloudAccount{}). + _, res := pg.Fetch(r.db.Model(&model.CloudAccount{}). Preload(clause.Associations). - Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED), &cloudAccounts) + Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED), &out) if res.Error != nil { return nil, res.Error } - - for _, cloudAccount := range cloudAccounts { - out = append(out, reflectCloudAccount(cloudAccount)) - } return } -func (r *CloudAccountRepository) Create(dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) { - cloudAccount := CloudAccount{ +func (r *CloudAccountRepository) Create(dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { + cloudAccount := model.CloudAccount{ OrganizationId: dto.OrganizationId, Name: dto.Name, Description: dto.Description, @@ -123,7 +82,7 @@ func (r *CloudAccountRepository) Create(dto domain.CloudAccount) (cloudAccountId AwsAccountId: dto.AwsAccountId, CreatedIAM: false, Status: domain.CloudAccountStatus_PENDING, - CreatorId: &dto.CreatorId} + CreatorId: dto.CreatorId} res := r.db.Create(&cloudAccount) if res.Error != nil { return uuid.Nil, res.Error @@ -131,8 +90,8 @@ func (r *CloudAccountRepository) Create(dto domain.CloudAccount) (cloudAccountId return cloudAccount.ID, nil } -func (r *CloudAccountRepository) Update(dto domain.CloudAccount) (err error) { - res := r.db.Model(&CloudAccount{}). +func (r *CloudAccountRepository) Update(dto model.CloudAccount) (err error) { + res := r.db.Model(&model.CloudAccount{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description, "Resource": dto.Resource, "UpdatorId": dto.UpdatorId}) if res.Error != nil { @@ -142,7 +101,7 @@ func (r *CloudAccountRepository) Update(dto domain.CloudAccount) (err error) { } func (r *CloudAccountRepository) Delete(cloudAccountId uuid.UUID) (err error) { - res := r.db.Delete(&CloudAccount{}, "id = ?", cloudAccountId) + res := r.db.Delete(&model.CloudAccount{}, "id = ?", cloudAccountId) if res.Error != nil { return res.Error } @@ -150,7 +109,7 @@ func (r *CloudAccountRepository) Delete(cloudAccountId uuid.UUID) (err error) { } func (r *CloudAccountRepository) InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) error { - res := r.db.Model(&CloudAccount{}). + res := r.db.Model(&model.CloudAccount{}). Where("ID = ?", cloudAccountId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) @@ -160,13 +119,3 @@ func (r *CloudAccountRepository) InitWorkflow(cloudAccountId uuid.UUID, workflow return nil } - -func reflectCloudAccount(cloudAccount CloudAccount) (out domain.CloudAccount) { - if err := serializer.Map(cloudAccount.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(cloudAccount, &out); err != nil { - log.Error(err) - } - return -} diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index e637c040..05d2cb00 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -8,8 +8,8 @@ import ( "gorm.io/gorm/clause" "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) @@ -17,13 +17,13 @@ import ( // Interfaces type IClusterRepository interface { WithTrx(*gorm.DB) IClusterRepository - Fetch(pg *pagination.Pagination) (res []domain.Cluster, err error) - FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (res []domain.Cluster, err error) - FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (res []domain.Cluster, err error) - Get(id domain.ClusterId) (domain.Cluster, error) - GetByName(organizationId string, name string) (domain.Cluster, error) - Create(dto domain.Cluster) (clusterId domain.ClusterId, err error) - Update(dto domain.Cluster) (err error) + Fetch(pg *pagination.Pagination) (res []model.Cluster, err error) + FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) + FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) + Get(id domain.ClusterId) (model.Cluster, error) + GetByName(organizationId string, name string) (model.Cluster, error) + Create(dto model.Cluster) (clusterId domain.ClusterId, err error) + Update(dto model.Cluster) (err error) Delete(id domain.ClusterId) error InitWorkflow(clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error @@ -45,58 +45,6 @@ func NewClusterRepository(db *gorm.DB) IClusterRepository { } } -// Models -type Cluster struct { - gorm.Model - - ID domain.ClusterId `gorm:"primarykey"` - Name string `gorm:"index"` - CloudService string `gorm:"default:AWS"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Description string `gorm:"index"` - WorkflowId string - Status domain.ClusterStatus - StatusDesc string - CloudAccountId *uuid.UUID - CloudAccount CloudAccount `gorm:"foreignKey:CloudAccountId"` - StackTemplateId uuid.UUID - StackTemplate StackTemplate `gorm:"foreignKey:StackTemplateId"` - Favorites *[]ClusterFavorite - ClusterType domain.ClusterType `gorm:"default:0"` - ByoClusterEndpointHost string - ByoClusterEndpointPort int - IsStack bool `gorm:"default:false"` - TksCpNode int - TksCpNodeMax int - TksCpNodeType string - TksInfraNode int - TksInfraNodeMax int - TksInfraNodeType string - TksUserNode int - TksUserNodeMax int - TksUserNodeType string - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -type ClusterFavorite struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid"` - ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - UserId uuid.UUID `gorm:"type:uuid"` - User domain.User `gorm:"foreignKey:UserId"` -} - -func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { if trxHandle == nil { @@ -107,91 +55,70 @@ func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { return r } -func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []domain.Cluster, err error) { - var clusters []Cluster +func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db, &clusters) + _, res := pg.Fetch(r.db.Model(&model.Cluster{}).Preload(clause.Associations), &out) if res.Error != nil { return nil, res.Error } - for _, cluster := range clusters { - outCluster := reflectCluster(cluster) - out = append(out, outCluster) - } return } -func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { - var clusters []Cluster +func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&Cluster{}). + _, res := pg.Fetch(r.db.Model(&model.Cluster{}). Preload(clause.Associations). Joins("left outer join cluster_favorites on clusters.id = cluster_favorites.cluster_id AND cluster_favorites.user_id = ?", userId). Where("organization_id = ? AND status != ?", organizationId, domain.ClusterStatus_DELETED). - Order("cluster_favorites.cluster_id"), &clusters) - + Order("cluster_favorites.cluster_id"), &out) if res.Error != nil { return nil, res.Error } - for _, cluster := range clusters { - outCluster := reflectCluster(cluster) - out = append(out, outCluster) - } - return } -func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { - var clusters []Cluster +func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&Cluster{}).Preload("CloudAccount"). - Where("cloud_account_id = ?", cloudAccountId), &clusters) + _, res := pg.Fetch(r.db.Model(&model.Cluster{}).Preload("CloudAccount"). + Where("cloud_account_id = ?", cloudAccountId), &out) if res.Error != nil { return nil, res.Error } - for _, cluster := range clusters { - outCluster := reflectCluster(cluster) - out = append(out, outCluster) - } return } -func (r *ClusterRepository) Get(id domain.ClusterId) (out domain.Cluster, err error) { - var cluster Cluster - res := r.db.Preload(clause.Associations).First(&cluster, "id = ?", id) +func (r *ClusterRepository) Get(id domain.ClusterId) (out model.Cluster, err error) { + res := r.db.Preload(clause.Associations).First(&out, "id = ?", id) if res.Error != nil { - return domain.Cluster{}, res.Error + return model.Cluster{}, res.Error } - out = reflectCluster(cluster) return } -func (r *ClusterRepository) GetByName(organizationId string, name string) (out domain.Cluster, err error) { - var cluster Cluster - res := r.db.Preload(clause.Associations).First(&cluster, "organization_id = ? AND name = ?", organizationId, name) +func (r *ClusterRepository) GetByName(organizationId string, name string) (out model.Cluster, err error) { + res := r.db.Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { - return domain.Cluster{}, res.Error + return model.Cluster{}, res.Error } - out = reflectCluster(cluster) return } -func (r *ClusterRepository) Create(dto domain.Cluster) (clusterId domain.ClusterId, err error) { +func (r *ClusterRepository) Create(dto model.Cluster) (clusterId domain.ClusterId, err error) { var cloudAccountId *uuid.UUID - cloudAccountId = &dto.CloudAccountId - if dto.CloudService == domain.CloudService_BYOH || dto.CloudAccountId == uuid.Nil { + cloudAccountId = dto.CloudAccountId + if dto.CloudService == domain.CloudService_BYOH || *dto.CloudAccountId == uuid.Nil { cloudAccountId = nil } - cluster := Cluster{ + cluster := model.Cluster{ ID: domain.ClusterId(helper.GenerateClusterId()), OrganizationId: dto.OrganizationId, Name: dto.Name, @@ -206,15 +133,15 @@ func (r *ClusterRepository) Create(dto domain.Cluster) (clusterId domain.Cluster ByoClusterEndpointHost: dto.ByoClusterEndpointHost, ByoClusterEndpointPort: dto.ByoClusterEndpointPort, IsStack: dto.IsStack, - TksCpNode: dto.Conf.TksCpNode, - TksCpNodeMax: dto.Conf.TksCpNodeMax, - TksCpNodeType: dto.Conf.TksCpNodeType, - TksInfraNode: dto.Conf.TksInfraNode, - TksInfraNodeMax: dto.Conf.TksInfraNodeMax, - TksInfraNodeType: dto.Conf.TksInfraNodeType, - TksUserNode: dto.Conf.TksUserNode, - TksUserNodeMax: dto.Conf.TksUserNodeMax, - TksUserNodeType: dto.Conf.TksUserNodeType, + TksCpNode: dto.TksCpNode, + TksCpNodeMax: dto.TksCpNodeMax, + TksCpNodeType: dto.TksCpNodeType, + TksInfraNode: dto.TksInfraNode, + TksInfraNodeMax: dto.TksInfraNodeMax, + TksInfraNodeType: dto.TksInfraNodeType, + TksUserNode: dto.TksUserNode, + TksUserNodeMax: dto.TksUserNodeMax, + TksUserNodeType: dto.TksUserNodeType, } if dto.ID != "" { cluster.ID = dto.ID @@ -230,15 +157,15 @@ func (r *ClusterRepository) Create(dto domain.Cluster) (clusterId domain.Cluster } func (r *ClusterRepository) Delete(clusterId domain.ClusterId) error { - res := r.db.Unscoped().Delete(&Cluster{}, "id = ?", clusterId) + res := r.db.Unscoped().Delete(&model.Cluster{}, "id = ?", clusterId) if res.Error != nil { return fmt.Errorf("could not delete cluster for clusterId %s", clusterId) } return nil } -func (r *ClusterRepository) Update(dto domain.Cluster) error { - res := r.db.Model(&Cluster{}). +func (r *ClusterRepository) Update(dto model.Cluster) error { + res := r.db.Model(&model.Cluster{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description, "UpdatorId": dto.UpdatorId}) if res.Error != nil { @@ -248,7 +175,7 @@ func (r *ClusterRepository) Update(dto domain.Cluster) error { } func (r *ClusterRepository) InitWorkflow(clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error { - res := r.db.Model(&Cluster{}). + res := r.db.Model(&model.Cluster{}). Where("ID = ?", clusterId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId, "StatusDesc": ""}) @@ -260,7 +187,7 @@ func (r *ClusterRepository) InitWorkflow(clusterId domain.ClusterId, workflowId } func (r *ClusterRepository) InitWorkflowDescription(clusterId domain.ClusterId) error { - res := r.db.Model(&AppGroup{}). + res := r.db.Model(&model.AppGroup{}). Where("id = ?", clusterId). Updates(map[string]interface{}{"WorkflowId": "", "StatusDesc": ""}) @@ -272,7 +199,7 @@ func (r *ClusterRepository) InitWorkflowDescription(clusterId domain.ClusterId) } func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid.UUID) error { - var clusterFavorites []ClusterFavorite + var clusterFavorites []model.ClusterFavorite res := r.db.Where("cluster_id = ? AND user_id = ?", clusterId, userId).Find(&clusterFavorites) if res.Error != nil { log.Info(res.Error) @@ -283,7 +210,7 @@ func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid. return nil } - clusterFavorite := ClusterFavorite{ + clusterFavorite := model.ClusterFavorite{ ClusterId: clusterId, UserId: userId, } @@ -297,34 +224,10 @@ func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid. } func (r *ClusterRepository) DeleteFavorite(clusterId domain.ClusterId, userId uuid.UUID) error { - res := r.db.Unscoped().Delete(&ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) + res := r.db.Unscoped().Delete(&model.ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) if res.Error != nil { log.Error(res.Error) return fmt.Errorf("could not delete cluster favorite for clusterId %s, userId %s", clusterId, userId) } return nil } - -func reflectCluster(cluster Cluster) (out domain.Cluster) { - if err := serializer.Map(cluster.Model, &out); err != nil { - log.Error(err) - } - - if err := serializer.Map(cluster, &out); err != nil { - log.Error(err) - } - - if err := serializer.Map(cluster, &out.Conf); err != nil { - log.Error(err) - } - out.StackTemplate.Services = cluster.StackTemplate.Services - - if cluster.Favorites != nil && len(*cluster.Favorites) > 0 { - out.Favorited = true - - } else { - out.Favorited = false - } - - return -} diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go index 707d8d58..2b290779 100644 --- a/internal/repository/endpoint.go +++ b/internal/repository/endpoint.go @@ -2,16 +2,17 @@ package repository import ( "fmt" + "math" + + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" - "math" ) type IEndpointRepository interface { - Create(endpoint *domain.Endpoint) error - List(pg *pagination.Pagination) ([]*domain.Endpoint, error) - Get(id uint) (*domain.Endpoint, error) + Create(endpoint *model.Endpoint) error + List(pg *pagination.Pagination) ([]*model.Endpoint, error) + Get(id uint) (*model.Endpoint, error) } type EndpointRepository struct { @@ -24,8 +25,8 @@ func NewEndpointRepository(db *gorm.DB) *EndpointRepository { } } -func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { - obj := &domain.Endpoint{ +func (e *EndpointRepository) Create(endpoint *model.Endpoint) error { + obj := &model.Endpoint{ Name: endpoint.Name, Group: endpoint.Group, } @@ -37,14 +38,14 @@ func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { return nil } -func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint, error) { - var endpoints []*domain.Endpoint +func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*model.Endpoint, error) { + var endpoints []*model.Endpoint if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("endpoints", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(e.db.Model(&domain.Endpoint{})) + db := filterFunc(e.db.Model(&model.Endpoint{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -58,14 +59,14 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint return endpoints, nil } -func (e *EndpointRepository) Get(id uint) (*domain.Endpoint, error) { - var obj domain.Endpoint +func (e *EndpointRepository) Get(id uint) (*model.Endpoint, error) { + var obj model.Endpoint if err := e.db.Preload("Permission").First(&obj, "id = ?", id).Error; err != nil { return nil, err } - return &domain.Endpoint{ + return &model.Endpoint{ Name: obj.Name, Group: obj.Group, }, nil diff --git a/internal/repository/organization.go b/internal/repository/organization.go index a7839166..69ed3cce 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -2,8 +2,8 @@ package repository import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" @@ -11,10 +11,10 @@ import ( // Interfaces type IOrganizationRepository interface { - Create(organizationId string, name string, creator uuid.UUID, phone string, description string) (domain.Organization, error) - Fetch(pg *pagination.Pagination) (res *[]domain.Organization, err error) - Get(organizationId string) (res domain.Organization, err error) - Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) + Create(organizationId string, name string, creator uuid.UUID, phone string, description string) (model.Organization, error) + Fetch(pg *pagination.Pagination) (res *[]model.Organization, err error) + Get(organizationId string) (res model.Organization, err error) + Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error Delete(organizationId string) (err error) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error @@ -40,7 +40,7 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { // Description string // Phone string // WorkflowId string -// Status domain.OrganizationStatus +// Status model.OrganizationStatus // StatusDesc string // Creator uuid.UUID // PrimaryClusterId string // allow null @@ -52,8 +52,8 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { //} func (r *OrganizationRepository) Create(organizationId string, name string, creator uuid.UUID, phone string, - description string) (domain.Organization, error) { - organization := domain.Organization{ + description string) (model.Organization, error) { + organization := model.Organization{ ID: organizationId, Name: name, Creator: creator.String(), @@ -64,45 +64,36 @@ func (r *OrganizationRepository) Create(organizationId string, name string, crea res := r.db.Create(&organization) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Organization{}, res.Error + return model.Organization{}, res.Error } - return r.reflect(organization), nil + return organization, nil } -func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (*[]domain.Organization, error) { - var organizations []domain.Organization - var out []domain.Organization +func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (out *[]model.Organization, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db, &organizations) + _, res := pg.Fetch(r.db, &out) if res.Error != nil { return nil, res.Error } - - for _, organization := range organizations { - outOrganization := r.reflect(organization) - out = append(out, outOrganization) - } - return &out, nil + return } -func (r *OrganizationRepository) Get(id string) (domain.Organization, error) { - var organization domain.Organization - res := r.db.First(&organization, "id = ?", id) +func (r *OrganizationRepository) Get(id string) (out model.Organization, err error) { + res := r.db.First(&out, "id = ?", id) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Organization{}, res.Error + return model.Organization{}, res.Error } - return r.reflect(organization), nil + return } -func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) { - var organization domain.Organization - res := r.db.Model(&domain.Organization{}). +func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateOrganizationRequest) (out model.Organization, err error) { + res := r.db.Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "name": in.Name, @@ -112,19 +103,19 @@ func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateO if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Organization{}, res.Error + return model.Organization{}, res.Error } - res = r.db.Model(&domain.Organization{}).Where("id = ?", organizationId).Find(&organization) + res = r.db.Model(&model.Organization{}).Where("id = ?", organizationId).Find(&out) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Organization{}, res.Error + return model.Organization{}, res.Error } - return r.reflect(organization), nil + return } func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error { - res := r.db.Model(&domain.Organization{}). + res := r.db.Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "primary_cluster_id": primaryClusterId, @@ -138,7 +129,7 @@ func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, p } func (r *OrganizationRepository) Delete(organizationId string) error { - res := r.db.Delete(&domain.Organization{}, "id = ?", organizationId) + res := r.db.Delete(&model.Organization{}, "id = ?", organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -148,7 +139,7 @@ func (r *OrganizationRepository) Delete(organizationId string) error { } func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error { - res := r.db.Model(&domain.Organization{}). + res := r.db.Model(&model.Organization{}). Where("ID = ?", organizationId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) if res.Error != nil { @@ -157,15 +148,3 @@ func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId } return nil } - -func (r *OrganizationRepository) reflect(organization domain.Organization) (out domain.Organization) { - if err := serializer.Map(organization.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(organization, &out); err != nil { - log.Error(err) - } - out.Creator = organization.Creator - return - -} diff --git a/internal/repository/permission.go b/internal/repository/permission.go index db097922..ebed52e6 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -2,16 +2,16 @@ package repository import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/internal/model" "gorm.io/gorm" ) type IPermissionRepository interface { - Create(permission *domain.Permission) error - List(roleId string) ([]*domain.Permission, error) - Get(id uuid.UUID) (*domain.Permission, error) + Create(permission *model.Permission) error + List(roleId string) ([]*model.Permission, error) + Get(id uuid.UUID) (*model.Permission, error) Delete(id uuid.UUID) error - Update(permission *domain.Permission) error + Update(permission *model.Permission) error } type PermissionRepository struct { @@ -24,7 +24,7 @@ func NewPermissionRepository(db *gorm.DB) *PermissionRepository { } } -func (r PermissionRepository) Create(p *domain.Permission) error { +func (r PermissionRepository) Create(p *model.Permission) error { //var parent *Permission //var children []*Permission // @@ -49,8 +49,8 @@ func (r PermissionRepository) Create(p *domain.Permission) error { return r.db.Create(p).Error } -func (r PermissionRepository) List(roleId string) ([]*domain.Permission, error) { - var permissions []*domain.Permission +func (r PermissionRepository) List(roleId string) ([]*model.Permission, error) { + var permissions []*model.Permission err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL AND role_id = ?", roleId).Find(&permissions).Error if err != nil { @@ -60,8 +60,8 @@ func (r PermissionRepository) List(roleId string) ([]*domain.Permission, error) return permissions, nil } -func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { - permission := &domain.Permission{} +func (r PermissionRepository) Get(id uuid.UUID) (*model.Permission, error) { + permission := &model.Permission{} result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) if result.Error != nil { return nil, result.Error @@ -71,10 +71,10 @@ func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { } func (r PermissionRepository) Delete(id uuid.UUID) error { - return r.db.Delete(&domain.Permission{}, "id = ?", id).Error + return r.db.Delete(&model.Permission{}, "id = ?", id).Error } -func (r PermissionRepository) Update(p *domain.Permission) error { +func (r PermissionRepository) Update(p *model.Permission) error { // update on is_allowed - return r.db.Model(&domain.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error + return r.db.Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error } diff --git a/internal/repository/role.go b/internal/repository/role.go index d7bdb198..ab5c7f50 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -2,29 +2,30 @@ package repository import ( "fmt" + "math" + + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" - "math" ) type IRoleRepository interface { - Create(roleObj *domain.Role) (string, error) - List(pg *pagination.Pagination) ([]*domain.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) - Get(id string) (*domain.Role, error) - GetTksRole(id string) (*domain.Role, error) - GetTksRoleByRoleName(roleName string) (*domain.Role, error) + Create(roleObj *model.Role) (string, error) + List(pg *pagination.Pagination) ([]*model.Role, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) + Get(id string) (*model.Role, error) + GetTksRole(id string) (*model.Role, error) + GetTksRoleByRoleName(roleName string) (*model.Role, error) Delete(id string) error - Update(roleObj *domain.Role) error + Update(roleObj *model.Role) error } type RoleRepository struct { db *gorm.DB } -func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.Role, error) { - var role domain.Role +func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*model.Role, error) { + var role model.Role if err := r.db.Preload("Role").First(&role, "Role.name = ?", roleName).Error; err != nil { return nil, err } @@ -32,7 +33,7 @@ func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.Role, err return &role, nil } -func (r RoleRepository) Create(roleObj *domain.Role) (string, error) { +func (r RoleRepository) Create(roleObj *model.Role) (string, error) { if roleObj == nil { return "", fmt.Errorf("roleObj is nil") } @@ -43,14 +44,14 @@ func (r RoleRepository) Create(roleObj *domain.Role) (string, error) { return roleObj.ID, nil } -func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) { - var roles []*domain.Role +func (r RoleRepository) List(pg *pagination.Pagination) ([]*model.Role, error) { + var roles []*model.Role if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.Role{})) + db := filterFunc(r.db.Model(&model.Role{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -65,14 +66,14 @@ func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) return roles, nil } -func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) { - var roles []*domain.Role +func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { + var roles []*model.Role if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.Role{})) + db := filterFunc(r.db.Model(&model.Role{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -91,8 +92,8 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin return roles, nil } -func (r RoleRepository) Get(id string) (*domain.Role, error) { - var role domain.Role +func (r RoleRepository) Get(id string) (*model.Role, error) { + var role model.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } @@ -100,8 +101,8 @@ func (r RoleRepository) Get(id string) (*domain.Role, error) { return &role, nil } -func (r RoleRepository) GetTksRole(id string) (*domain.Role, error) { - var role domain.Role +func (r RoleRepository) GetTksRole(id string) (*model.Role, error) { + var role model.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } @@ -109,12 +110,12 @@ func (r RoleRepository) GetTksRole(id string) (*domain.Role, error) { return &role, nil } -func (r RoleRepository) Update(roleObj *domain.Role) error { +func (r RoleRepository) Update(roleObj *model.Role) error { if roleObj == nil { return fmt.Errorf("roleObj is nil") } - err := r.db.Model(&domain.Role{}).Where("id = ?", roleObj.ID).Updates(domain.Role{ + err := r.db.Model(&model.Role{}).Where("id = ?", roleObj.ID).Updates(model.Role{ Name: roleObj.Name, Description: roleObj.Description, }).Error @@ -127,7 +128,7 @@ func (r RoleRepository) Update(roleObj *domain.Role) error { } func (r RoleRepository) Delete(id string) error { - if err := r.db.Delete(&domain.Role{}, "id = ?", id).Error; err != nil { + if err := r.db.Delete(&model.Role{}, "id = ?", id).Error; err != nil { return err } diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 9c55df46..866df5cc 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -2,24 +2,21 @@ package repository import ( "github.com/google/uuid" - "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" - "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IStackTemplateRepository interface { - Get(stackTemplateId uuid.UUID) (domain.StackTemplate, error) - Fetch(pg *pagination.Pagination) ([]domain.StackTemplate, error) - Create(dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) - Update(dto domain.StackTemplate) (err error) - Delete(dto domain.StackTemplate) (err error) - UpdateOrganizations(stackTemplateId uuid.UUID, organizationIds []domain.Organization) (err error) + Get(stackTemplateId uuid.UUID) (model.StackTemplate, error) + Fetch(pg *pagination.Pagination) ([]model.StackTemplate, error) + Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) + Update(dto model.StackTemplate) (err error) + Delete(dto model.StackTemplate) (err error) + UpdateOrganizations(stackTemplateId uuid.UUID, organizationIds []model.Organization) (err error) } type StackTemplateRepository struct { @@ -32,87 +29,37 @@ func NewStackTemplateRepository(db *gorm.DB) IStackTemplateRepository { } } -// Models -type StackTemplate struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - Name string `gorm:"index"` - Description string `gorm:"index"` - Template string - TemplateType string - Version string - CloudService string - Platform string - KubeVersion string - KubeType string - Organizations []domain.Organization `gorm:"many2many:stack_template_organizations"` - Services datatypes.JSON - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out domain.StackTemplate, err error) { - var stackTemplate StackTemplate - res := r.db.Preload(clause.Associations).First(&stackTemplate, "id = ?", stackTemplateId) +func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out model.StackTemplate, err error) { + res := r.db.Preload(clause.Associations).First(&out, "id = ?", stackTemplateId) if res.Error != nil { - return domain.StackTemplate{}, res.Error + return model.StackTemplate{}, res.Error } - out = reflectStackTemplate(stackTemplate) return } -// [TODO] organizationId 별로 생성하지 않고, 하나의 stackTemplate 을 모든 organization 에서 재사용한다. ( 5월 한정, 추후 rearchitecture 필요) -func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain.StackTemplate, err error) { - var stackTemplates []StackTemplate - +func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.StackTemplate, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations), &stackTemplates) + _, res := pg.Fetch(r.db.Preload(clause.Associations), &out) if res.Error != nil { return nil, res.Error } - - for _, stackTemplate := range stackTemplates { - out = append(out, reflectStackTemplate(stackTemplate)) - } - return } -func (r *StackTemplateRepository) Create(dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) { - stackTemplate := StackTemplate{ - Name: dto.Name, - Description: dto.Description, - Template: dto.Template, - TemplateType: dto.TemplateType, - Version: dto.Version, - CloudService: dto.CloudService, - Platform: dto.Platform, - KubeVersion: dto.KubeVersion, - KubeType: dto.KubeType, - Services: dto.Services, - CreatorId: &dto.CreatorId, - UpdatorId: &dto.CreatorId} - res := r.db.Create(&stackTemplate) +func (r *StackTemplateRepository) Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { + res := r.db.Create(&dto) if res.Error != nil { return uuid.Nil, res.Error } - return stackTemplate.ID, nil + return dto.ID, nil } -func (r *StackTemplateRepository) Update(dto domain.StackTemplate) (err error) { - res := r.db.Model(&StackTemplate{}). +func (r *StackTemplateRepository) Update(dto model.StackTemplate) (err error) { + res := r.db.Model(&model.StackTemplate{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ "Template": dto.Template, @@ -131,16 +78,16 @@ func (r *StackTemplateRepository) Update(dto domain.StackTemplate) (err error) { return nil } -func (r *StackTemplateRepository) Delete(dto domain.StackTemplate) (err error) { - res := r.db.Delete(&StackTemplate{}, "id = ?", dto.ID) +func (r *StackTemplateRepository) Delete(dto model.StackTemplate) (err error) { + res := r.db.Delete(&model.StackTemplate{}, "id = ?", dto.ID) if res.Error != nil { return res.Error } return nil } -func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, organizations []domain.Organization) (err error) { - var stackTemplate = StackTemplate{} +func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, organizations []model.Organization) (err error) { + var stackTemplate = model.StackTemplate{} res := r.db.Preload("Organizations").First(&stackTemplate, "id = ?", stackTemplateId) if res.Error != nil { return res.Error @@ -152,15 +99,3 @@ func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, return nil } - -func reflectStackTemplate(stackTemplate StackTemplate) (out domain.StackTemplate) { - if err := serializer.Map(stackTemplate.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(stackTemplate, &out); err != nil { - log.Error(err) - } - - out.Services = stackTemplate.Services - return -} diff --git a/internal/repository/user.go b/internal/repository/user.go index 12ed1a50..fcfd4981 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -4,8 +4,8 @@ import ( "time" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" @@ -14,13 +14,13 @@ import ( // Interface type IUserRepository interface { CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, - department string, description string, organizationId string, roleId string) (domain.User, error) - List(filters ...FilterFunc) (out *[]domain.User, err error) - ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]domain.User, err error) - Get(accountId string, organizationId string) (domain.User, error) - GetByUuid(userId uuid.UUID) (domain.User, error) + department string, description string, organizationId string, roleId string) (model.User, error) + List(filters ...FilterFunc) (out *[]model.User, err error) + ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]model.User, err error) + Get(accountId string, organizationId string) (model.User, error) + GetByUuid(userId uuid.UUID) (model.User, error) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, email string, - department string, description string) (domain.User, error) + department string, description string) (model.User, error) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error DeleteWithUuid(uuid uuid.UUID) error Flush(organizationId string) error @@ -36,7 +36,7 @@ type UserRepository struct { } func (r *UserRepository) Flush(organizationId string) error { - res := r.db.Where("organization_id = ?", organizationId).Delete(&domain.User{}) + res := r.db.Where("organization_id = ?", organizationId).Delete(&model.User{}) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -77,9 +77,9 @@ func NewUserRepository(db *gorm.DB) IUserRepository { //} func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, - department string, description string, organizationId string, roleId string) (domain.User, error) { + department string, description string, organizationId string, roleId string) (model.User, error) { - newUser := domain.User{ + newUser := model.User{ ID: uuid, AccountId: accountId, Name: name, @@ -92,11 +92,11 @@ func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name s res := r.db.Create(&newUser) if res.Error != nil { log.Error(res.Error.Error()) - return domain.User{}, res.Error + return model.User{}, res.Error } user, err := r.getUserByAccountId(accountId, organizationId) if err != nil { - return domain.User{}, err + return model.User{}, err } return user, nil @@ -122,12 +122,12 @@ func (r *UserRepository) NameFilter(name string) FilterFunc { } } -func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { - var users []domain.User +func (r *UserRepository) List(filters ...FilterFunc) (*[]model.User, error) { + var users []model.User var res *gorm.DB if filters == nil { - res = r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Find(&users) + res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Find(&users) } else { combinedFilter := func(filters ...FilterFunc) FilterFunc { return func(user *gorm.DB) *gorm.DB { @@ -138,7 +138,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { } } cFunc := combinedFilter(filters...) - res = cFunc(r.db.Model(&domain.User{}).Preload("Organization").Preload("Role")).Find(&users) + res = cFunc(r.db.Model(&model.User{}).Preload("Organization").Preload("Role")).Find(&users) } if res.Error != nil { @@ -149,7 +149,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } - var out []domain.User + var out []model.User for _, user := range users { out = append(out, user) } @@ -157,20 +157,20 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { return &out, nil } -func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizationId string) (*[]domain.User, error) { - var users []domain.User +func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizationId string) (*[]model.User, error) { + var users []model.User if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&domain.User{}).Where("organization_id = ?", organizationId), &users) + _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&model.User{}).Where("organization_id = ?", organizationId), &users) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error } - var out []domain.User + var out []model.User for _, user := range users { out = append(out, user) } @@ -178,32 +178,32 @@ func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizat return &out, nil } -func (r *UserRepository) Get(accountId string, organizationId string) (domain.User, error) { +func (r *UserRepository) Get(accountId string, organizationId string) (model.User, error) { user, err := r.getUserByAccountId(accountId, organizationId) if err != nil { - return domain.User{}, err + return model.User{}, err } return user, nil } -func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser domain.User, err error) { - user := domain.User{} - res := r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) +func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser model.User, err error) { + user := model.User{} + res := r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.User{}, res.Error + return model.User{}, res.Error } if res.RowsAffected == 0 { - return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } return user, nil } func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, - email string, department string, description string) (domain.User, error) { - var user domain.User - res := r.db.Model(&domain.User{}).Where("id = ?", uuid).Updates(domain.User{ + email string, department string, description string) (model.User, error) { + var user model.User + res := r.db.Model(&model.User{}).Where("id = ?", uuid).Updates(model.User{ AccountId: accountId, Name: name, Email: email, @@ -212,26 +212,26 @@ func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name s RoleId: roleId, }) if res.RowsAffected == 0 || res.Error != nil { - return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.User{}, res.Error + return model.User{}, res.Error } - res = r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) + res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) if res.Error != nil { - return domain.User{}, res.Error + return model.User{}, res.Error } return user, nil } func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error { - var updateUser = domain.User{} + var updateUser = model.User{} if isTemporary { updateUser.PasswordUpdatedAt = time.Time{} } else { updateUser.PasswordUpdatedAt = time.Now() } - res := r.db.Model(&domain.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). + res := r.db.Model(&model.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). Select("password_updated_at").Updates(updateUser) if res.RowsAffected == 0 || res.Error != nil { @@ -245,7 +245,7 @@ func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId strin return nil } func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { - res := r.db.Unscoped().Delete(&domain.User{}, "id = ?", uuid) + res := r.db.Unscoped().Delete(&model.User{}, "id = ?", uuid) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -273,17 +273,17 @@ func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { // Creator uuid.UUID //} -func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { +func (r *UserRepository) GetRoleByName(roleName string) (model.Role, error) { role, err := r.getRoleByName(roleName) if err != nil { - return domain.Role{}, err + return model.Role{}, err } return role, nil } -//func (r *UserRepository) FetchRoles() (*[]domain.Role, error) { -// var roles []domain.Role +//func (r *UserRepository) FetchRoles() (*[]model.Role, error) { +// var roles []model.Role // res := r.db.Find(&roles) // // if res.Error != nil { @@ -295,7 +295,7 @@ func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { // return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") // } // -// var out []domain.Role +// var out []model.Role // for _, role := range roles { // outRole := r.reflectRole(role) // out = append(out, outRole) @@ -305,30 +305,30 @@ func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { //} // private members -func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (domain.User, error) { - user := domain.User{} - res := r.db.Model(&domain.User{}).Preload("Organization").Preload("Role"). +func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (model.User, error) { + user := model.User{} + res := r.db.Model(&model.User{}).Preload("Organization").Preload("Role"). Find(&user, "account_id = ? AND organization_id = ?", accountId, organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.User{}, res.Error + return model.User{}, res.Error } if res.RowsAffected == 0 { - return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } return user, nil } -func (r *UserRepository) getRoleByName(roleName string) (domain.Role, error) { - role := domain.Role{} +func (r *UserRepository) getRoleByName(roleName string) (model.Role, error) { + role := model.Role{} res := r.db.First(&role, "name = ?", roleName) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Role{}, res.Error + return model.Role{}, res.Error } if res.RowsAffected == 0 { - return domain.Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return model.Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } //if res.RowsAffected == 0 { diff --git a/internal/serializer/serializer.go b/internal/serializer/serializer.go index 70e96552..043a9ba4 100644 --- a/internal/serializer/serializer.go +++ b/internal/serializer/serializer.go @@ -5,7 +5,7 @@ import ( "reflect" "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/pkg/log" ) @@ -85,8 +85,14 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e } } */ - + } else { + if fieldName == "Model" { + if err := recursiveMap(srcField.Interface(), dst, converterMap); err != nil { + return err + } + } } + } return nil @@ -100,11 +106,11 @@ func Map(src interface{}, dst interface{}) error { val, _ := uuid.Parse(i.(string)) return val, nil }, - {srcType: reflect.TypeOf((*domain.Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(domain.Role).Name, nil + {srcType: reflect.TypeOf((*model.Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(model.Role).Name, nil }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*domain.Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return domain.Role{Name: i.(string)}, nil + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*model.Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return model.Role{Name: i.(string)}, nil }, }) } diff --git a/internal/usecase/alert.go b/internal/usecase/alert.go index 99fafa9c..de77595a 100644 --- a/internal/usecase/alert.go +++ b/internal/usecase/alert.go @@ -7,9 +7,9 @@ import ( "strings" "time" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" @@ -20,14 +20,14 @@ import ( ) type IAlertUsecase interface { - Get(ctx context.Context, alertId uuid.UUID) (domain.Alert, error) - GetByName(ctx context.Context, organizationId string, name string) (domain.Alert, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Alert, error) + Get(ctx context.Context, alertId uuid.UUID) (model.Alert, error) + GetByName(ctx context.Context, organizationId string, name string) (model.Alert, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Alert, error) Create(ctx context.Context, dto domain.CreateAlertRequest) (err error) - Update(ctx context.Context, dto domain.Alert) error - Delete(ctx context.Context, dto domain.Alert) error + Update(ctx context.Context, dto model.Alert) error + Delete(ctx context.Context, dto model.Alert) error - CreateAlertAction(ctx context.Context, dto domain.AlertAction) (alertActionId uuid.UUID, err error) + CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) } type AlertUsecase struct { @@ -101,7 +101,7 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque node = alert.Labels.Instance } - dto := domain.Alert{ + dto := model.Alert{ OrganizationId: organizationId, Name: alert.Labels.AlertName, Code: alert.Labels.AlertName, @@ -125,11 +125,11 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque return nil } -func (u *AlertUsecase) Update(ctx context.Context, dto domain.Alert) error { +func (u *AlertUsecase) Update(ctx context.Context, dto model.Alert) error { return nil } -func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert domain.Alert, err error) { +func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert model.Alert, err error) { alert, err = u.repo.Get(alertId) if err != nil { return alert, err @@ -139,7 +139,7 @@ func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert domain return } -func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, name string) (out domain.Alert, err error) { +func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Alert, err error) { out, err = u.repo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -150,7 +150,7 @@ func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, nam return } -func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (alerts []domain.Alert, err error) { +func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (alerts []model.Alert, err error) { alerts, err = u.repo.Fetch(organizationId, pg) if err != nil { return nil, err @@ -163,8 +163,8 @@ func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return alerts, nil } -func (u *AlertUsecase) Delete(ctx context.Context, dto domain.Alert) (err error) { - user, ok := request.UserFrom(ctx) +func (u *AlertUsecase) Delete(ctx context.Context, dto model.Alert) (err error) { + _, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") } @@ -174,8 +174,6 @@ func (u *AlertUsecase) Delete(ctx context.Context, dto domain.Alert) (err error) return httpErrors.NewNotFoundError(err, "AL_NOT_FOUND_ALERT", "") } - *dto.UpdatorId = user.GetUserId() - err = u.repo.Delete(dto) if err != nil { return err @@ -184,7 +182,7 @@ func (u *AlertUsecase) Delete(ctx context.Context, dto domain.Alert) (err error) return nil } -func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto domain.AlertAction) (alertActionId uuid.UUID, err error) { +func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -208,7 +206,7 @@ func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto domain.AlertAc return } -func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]domain.Cluster, strId string) (organizationId string, err error) { +func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]model.Cluster, strId string) (organizationId string, err error) { clusterId := domain.ClusterId(strId) if !clusterId.Validate() { return "", fmt.Errorf("Invalid clusterId %s", strId) @@ -223,9 +221,9 @@ func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]domain.Cluster, st return "", fmt.Errorf("No martched organization %s", strId) } -func (u *AlertUsecase) makeAdditionalInfo(alert *domain.Alert) { +func (u *AlertUsecase) makeAdditionalInfo(alert *model.Alert) { alert.FiredAt = &alert.CreatedAt - //alert.Status = domain.AlertActionStatus_CREATED + //alert.Status = model.AlertActionStatus_CREATED if len(alert.AlertActions) > 0 { alert.TakedAt = &alert.AlertActions[0].CreatedAt @@ -242,7 +240,7 @@ func (u *AlertUsecase) makeAdditionalInfo(alert *domain.Alert) { } } -func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster domain.Cluster, alert domain.CreateAlertRequestAlert, clusterId domain.ClusterId) (url string) { +func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, alert domain.CreateAlertRequestAlert, clusterId domain.ClusterId) (url string) { primaryGrafanaEndpoint := "" appGroups, err := u.appGroupRepo.Fetch(primaryCluster.ID, nil) if err == nil { diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index f6a2d7b4..a73c0e6b 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -17,12 +18,12 @@ import ( ) type IAppGroupUsecase interface { - Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) ([]domain.AppGroup, error) - Create(ctx context.Context, dto domain.AppGroup) (id domain.AppGroupId, err error) - Get(ctx context.Context, id domain.AppGroupId) (out domain.AppGroup, err error) + Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) ([]model.AppGroup, error) + Create(ctx context.Context, dto model.AppGroup) (id domain.AppGroupId, err error) + Get(ctx context.Context, id domain.AppGroupId) (out model.AppGroup, err error) Delete(ctx context.Context, id domain.AppGroupId) (err error) - GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) - UpdateApplication(ctx context.Context, dto domain.Application) (err error) + GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) + UpdateApplication(ctx context.Context, dto model.Application) (err error) } type AppGroupUsecase struct { @@ -41,7 +42,7 @@ func NewAppGroupUsecase(r repository.Repository, argoClient argowf.ArgoClient) I } } -func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (out []domain.AppGroup, err error) { +func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { out, err = u.repo.Fetch(clusterId, pg) if err != nil { return nil, err @@ -49,7 +50,7 @@ func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, return } -func (u *AppGroupUsecase) Create(ctx context.Context, dto domain.AppGroup) (id domain.AppGroupId, err error) { +func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id domain.AppGroupId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -158,10 +159,10 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto domain.AppGroup) (id d return dto.ID, nil } -func (u *AppGroupUsecase) Get(ctx context.Context, id domain.AppGroupId) (out domain.AppGroup, err error) { +func (u *AppGroupUsecase) Get(ctx context.Context, id domain.AppGroupId) (out model.AppGroup, err error) { appGroup, err := u.repo.Get(id) if err != nil { - return domain.AppGroup{}, err + return model.AppGroup{}, err } return appGroup, nil } @@ -255,7 +256,7 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err return nil } -func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) { +func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { out, err = u.repo.GetApplications(id, applicationType) if err != nil { return nil, err @@ -263,7 +264,7 @@ func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGrou return } -func (u *AppGroupUsecase) UpdateApplication(ctx context.Context, dto domain.Application) (err error) { +func (u *AppGroupUsecase) UpdateApplication(ctx context.Context, dto model.Application) (err error) { err = u.repo.UpsertApplication(dto) if err != nil { return err diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index b16163f1..198b31a3 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -14,6 +14,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -23,19 +24,19 @@ import ( ) type IAppServeAppUsecase interface { - CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) - GetAppServeAppById(appId string) (*domain.AppServeApp, error) - GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) - GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) - GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) + CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) + GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) + GetAppServeAppById(appId string) (*model.AppServeApp, error) + GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) + GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) + GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) IsAppServeAppExist(appId string) (bool, error) IsAppServeAppNameExist(orgId string, appName string) (bool, error) IsAppServeAppNamespaceExist(clusterId string, namespace string) (bool, error) UpdateAppServeAppStatus(appId string, taskId string, status string, output string) (ret string, err error) DeleteAppServeApp(appId string) (res string, err error) - UpdateAppServeApp(app *domain.AppServeApp, appTask *domain.AppServeAppTask) (ret string, err error) + UpdateAppServeApp(app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) UpdateAppServeAppEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) (string, error) PromoteAppServeApp(appId string) (ret string, err error) AbortAppServeApp(appId string) (ret string, err error) @@ -58,7 +59,7 @@ func NewAppServeAppUsecase(r repository.Repository, argoClient argowf.ArgoClient } } -func (u *AppServeAppUsecase) CreateAppServeApp(app *domain.AppServeApp) (string, string, error) { +func (u *AppServeAppUsecase) CreateAppServeApp(app *model.AppServeApp) (string, string, error) { if app == nil { return "", "", fmt.Errorf("invalid app obj") } @@ -179,7 +180,7 @@ func (u *AppServeAppUsecase) CreateAppServeApp(app *domain.AppServeApp) (string, return appId, app.Name, nil } -func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) { apps, err := u.repo.GetAppServeApps(organizationId, showAll, pg) if err != nil { fmt.Println(apps) @@ -188,7 +189,7 @@ func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool return apps, nil } -func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*domain.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*model.AppServeApp, error) { asa, err := u.repo.GetAppServeAppById(appId) if err != nil { return nil, err @@ -222,7 +223,7 @@ func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*domain.AppServeA return asa, nil } -func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) { +func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) { tasks, err := u.repo.GetAppServeAppTasksByAppId(appId, pg) if err != nil { log.Debugf("Tasks: %v", tasks) @@ -231,7 +232,7 @@ func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pa return tasks, nil } -func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { task, app, err := u.repo.GetAppServeAppTaskById(taskId) if err != nil { return nil, nil, err @@ -240,7 +241,7 @@ func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*domain.AppS return task, app, nil } -func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) { +func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) { task, err := u.repo.GetAppServeAppLatestTask(appId) if err != nil { return nil, err @@ -361,7 +362,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er * Start delete task * ********************/ - appTask := &domain.AppServeAppTask{ + appTask := &model.AppServeAppTask{ AppServeAppId: app.ID, Version: strconv.Itoa(len(app.AppServeAppTasks) + 1), ArtifactUrl: "", @@ -412,7 +413,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er "Confirm result by checking the app status after a while.", app.Name), nil } -func (u *AppServeAppUsecase) UpdateAppServeApp(app *domain.AppServeApp, appTask *domain.AppServeAppTask) (ret string, err error) { +func (u *AppServeAppUsecase) UpdateAppServeApp(app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) { if appTask == nil { return "", errors.New("invalid parameters. appTask is nil") } @@ -659,7 +660,7 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(appId string, taskId string) (r } // Find target(dest) task - var task domain.AppServeAppTask + var task model.AppServeAppTask for _, t := range app.AppServeAppTasks { if t.ID == taskId { task = t diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index 7461cf05..23744826 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -5,17 +5,17 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" ) type IAuditUsecase interface { - Get(ctx context.Context, auditId uuid.UUID) (domain.Audit, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Audit, error) - Create(ctx context.Context, dto domain.Audit) (auditId uuid.UUID, err error) - Delete(ctx context.Context, dto domain.Audit) error + Get(ctx context.Context, auditId uuid.UUID) (model.Audit, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Audit, error) + Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) + Delete(ctx context.Context, dto model.Audit) error } type AuditUsecase struct { @@ -28,7 +28,7 @@ func NewAuditUsecase(r repository.Repository) IAuditUsecase { } } -func (u *AuditUsecase) Create(ctx context.Context, dto domain.Audit) (auditId uuid.UUID, err error) { +func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { if dto.UserId == nil { user, ok := request.UserFrom(ctx) if ok { @@ -43,15 +43,15 @@ func (u *AuditUsecase) Create(ctx context.Context, dto domain.Audit) (auditId uu return auditId, nil } -func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res domain.Audit, err error) { +func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res model.Audit, err error) { res, err = u.repo.Get(auditId) if err != nil { - return domain.Audit{}, err + return model.Audit{}, err } return } -func (u *AuditUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (audits []domain.Audit, err error) { +func (u *AuditUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (audits []model.Audit, err error) { audits, err = u.repo.Fetch(organizationId, pg) if err != nil { return nil, err @@ -59,7 +59,7 @@ func (u *AuditUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return } -func (u *AuditUsecase) Delete(ctx context.Context, dto domain.Audit) (err error) { +func (u *AuditUsecase) Delete(ctx context.Context, dto model.Audit) (err error) { err = u.repo.Delete(dto.ID) if err != nil { return httpErrors.NewNotFoundError(err, "", "") diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 4fe4fd15..7213d1f2 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -24,13 +24,14 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/mail" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" ) type IAuthUsecase interface { - Login(accountId string, password string, organizationId string) (domain.User, error) + Login(accountId string, password string, organizationId string) (model.User, error) Logout(accessToken string, organizationId string) error PingToken(accessToken string, organizationId string) error FindId(code string, email string, userName string, organizationId string) (string, error) @@ -67,28 +68,28 @@ func NewAuthUsecase(r repository.Repository, kc keycloak.IKeycloak) IAuthUsecase } } -func (u *AuthUsecase) Login(accountId string, password string, organizationId string) (domain.User, error) { +func (u *AuthUsecase) Login(accountId string, password string, organizationId string) (model.User, error) { // Authentication with DB user, err := u.userRepository.Get(accountId, organizationId) if err != nil { - return domain.User{}, httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") + return model.User{}, httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") } - var accountToken *domain.User + var accountToken *model.User accountToken, err = u.kc.Login(accountId, password, organizationId) if err != nil { apiErr, ok := err.(*gocloak.APIError) if ok { if apiErr.Code == 401 { - return domain.User{}, httpErrors.NewBadRequestError(fmt.Errorf("Mismatch password"), "A_INVALID_PASSWORD", "") + return model.User{}, httpErrors.NewBadRequestError(fmt.Errorf("Mismatch password"), "A_INVALID_PASSWORD", "") } } - return domain.User{}, httpErrors.NewInternalServerError(err, "", "") + return model.User{}, httpErrors.NewInternalServerError(err, "", "") } log.Errorf("err: %v", err) if err != nil { //TODO: implement not found handling - return domain.User{}, err + return model.User{}, err } // Insert token @@ -254,7 +255,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, } func (u *AuthUsecase) VerifyIdentity(accountId string, email string, userName string, organizationId string) error { - var users *[]domain.User + var users *[]model.User var err error if accountId == "" { diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index a938066f..b6719bbb 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -15,10 +15,10 @@ import ( "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2" "github.com/aws/aws-sdk-go-v2/service/servicequotas" "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - - "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -32,14 +32,14 @@ import ( const MAX_WORKFLOW_TIME = 30 type ICloudAccountUsecase interface { - Get(ctx context.Context, cloudAccountId uuid.UUID) (domain.CloudAccount, error) - GetByName(ctx context.Context, organizationId string, name string) (domain.CloudAccount, error) - GetByAwsAccountId(ctx context.Context, awsAccountId string) (domain.CloudAccount, error) + Get(ctx context.Context, cloudAccountId uuid.UUID) (model.CloudAccount, error) + GetByName(ctx context.Context, organizationId string, name string) (model.CloudAccount, error) + GetByAwsAccountId(ctx context.Context, awsAccountId string) (model.CloudAccount, error) GetResourceQuota(ctx context.Context, cloudAccountId uuid.UUID) (available bool, out domain.ResourceQuota, err error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.CloudAccount, error) - Create(ctx context.Context, dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) - Update(ctx context.Context, dto domain.CloudAccount) error - Delete(ctx context.Context, dto domain.CloudAccount) error + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) + Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) + Update(ctx context.Context, dto model.CloudAccount) error + Delete(ctx context.Context, dto model.CloudAccount) error DeleteForce(ctx context.Context, cloudAccountId uuid.UUID) error } @@ -57,14 +57,15 @@ func NewCloudAccountUsecase(r repository.Repository, argoClient argowf.ArgoClien } } -func (u *CloudAccountUsecase) Create(ctx context.Context, dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) { +func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } + userId := user.GetUserId() dto.Resource = "TODO server result or additional information" - dto.CreatorId = user.GetUserId() + dto.CreatorId = &userId _, err = u.GetByName(ctx, dto.OrganizationId, dto.Name) if err == nil { @@ -114,14 +115,15 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto domain.CloudAccoun return cloudAccountId, nil } -func (u *CloudAccountUsecase) Update(ctx context.Context, dto domain.CloudAccount) error { +func (u *CloudAccountUsecase) Update(ctx context.Context, dto model.CloudAccount) error { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } + userId := user.GetUserId() dto.Resource = "TODO server result or additional information" - dto.UpdatorId = user.GetUserId() + dto.UpdatorId = &userId err := u.repo.Update(dto) if err != nil { return httpErrors.NewInternalServerError(err, "", "") @@ -129,10 +131,10 @@ func (u *CloudAccountUsecase) Update(ctx context.Context, dto domain.CloudAccoun return nil } -func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) (res domain.CloudAccount, err error) { +func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) (res model.CloudAccount, err error) { res, err = u.repo.Get(cloudAccountId) if err != nil { - return domain.CloudAccount{}, err + return model.CloudAccount{}, err } res.Clusters = u.getClusterCnt(cloudAccountId) @@ -140,31 +142,31 @@ func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) return } -func (u *CloudAccountUsecase) GetByName(ctx context.Context, organizationId string, name string) (res domain.CloudAccount, err error) { +func (u *CloudAccountUsecase) GetByName(ctx context.Context, organizationId string, name string) (res model.CloudAccount, err error) { res, err = u.repo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return domain.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") + return model.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") } - return domain.CloudAccount{}, err + return model.CloudAccount{}, err } res.Clusters = u.getClusterCnt(res.ID) return } -func (u *CloudAccountUsecase) GetByAwsAccountId(ctx context.Context, awsAccountId string) (res domain.CloudAccount, err error) { +func (u *CloudAccountUsecase) GetByAwsAccountId(ctx context.Context, awsAccountId string) (res model.CloudAccount, err error) { res, err = u.repo.GetByAwsAccountId(awsAccountId) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return domain.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") + return model.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") } - return domain.CloudAccount{}, err + return model.CloudAccount{}, err } res.Clusters = u.getClusterCnt(res.ID) return } -func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (cloudAccounts []domain.CloudAccount, err error) { +func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (cloudAccounts []model.CloudAccount, err error) { cloudAccounts, err = u.repo.Fetch(organizationId, pg) if err != nil { return nil, err @@ -176,17 +178,18 @@ func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, return } -func (u *CloudAccountUsecase) Delete(ctx context.Context, dto domain.CloudAccount) (err error) { +func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } + userId := user.GetUserId() cloudAccount, err := u.Get(ctx, dto.ID) if err != nil { return httpErrors.NewNotFoundError(err, "", "") } - dto.UpdatorId = user.GetUserId() + dto.UpdatorId = &userId if u.getClusterCnt(dto.ID) > 0 { return fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index f298fff7..e22233f3 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -8,13 +8,11 @@ import ( "strings" "time" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - byoh "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" @@ -25,19 +23,21 @@ import ( gcache "github.com/patrickmn/go-cache" "github.com/pkg/errors" "github.com/spf13/viper" + byoh "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1" "gopkg.in/yaml.v3" "gorm.io/gorm" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type IClusterUsecase interface { WithTrx(*gorm.DB) IClusterUsecase - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Cluster, error) - FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) - Create(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) - Import(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) - Bootstrap(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Cluster, error) + FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) + Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) + Import(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) + Bootstrap(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) Install(ctx context.Context, clusterId domain.ClusterId) (err error) - Get(ctx context.Context, clusterId domain.ClusterId) (out domain.Cluster, err error) + Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) GetClusterSiteValues(ctx context.Context, clusterId domain.ClusterId) (out domain.ClusterSiteValuesResponse, err error) Delete(ctx context.Context, clusterId domain.ClusterId) (err error) CreateBootstrapKubeconfig(ctx context.Context, clusterId domain.ClusterId) (out domain.BootstrapKubeconfig, err error) @@ -101,7 +101,7 @@ func (u *ClusterUsecase) WithTrx(trxHandle *gorm.DB) IClusterUsecase { return u } -func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []domain.Cluster, err error) { +func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.Cluster, err error) { user, ok := request.UserFrom(ctx) if !ok { return out, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -120,7 +120,7 @@ func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *p return out, nil } -func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { +func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { if cloudAccountId == uuid.Nil { return nil, fmt.Errorf("Invalid cloudAccountId") } @@ -133,7 +133,7 @@ func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccount return out, nil } -func (u *ClusterUsecase) Create(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -153,7 +153,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto domain.Cluster) (cluste tksCloudAccountId := dto.CloudAccountId.String() isExist := false for _, ca := range cloudAccounts { - if ca.ID == dto.CloudAccountId { + if ca.ID == *dto.CloudAccountId { // FOR TEST. ADD MAGIC KEYWORD if strings.Contains(ca.Name, domain.CLOUD_ACCOUNT_INCLUSTER) { @@ -213,7 +213,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto domain.Cluster) (cluste return clusterId, nil } -func (u *ClusterUsecase) Import(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -275,7 +275,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto domain.Cluster) (cluste return clusterId, nil } -func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -374,10 +374,10 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId return nil } -func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (out domain.Cluster, err error) { +func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) { cluster, err := u.repo.Get(clusterId) if err != nil { - return domain.Cluster{}, err + return model.Cluster{}, err } return cluster, nil @@ -453,13 +453,13 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom out.SshKeyName = "tks-seoul" out.ClusterRegion = "ap-northeast-2" - if err := serializer.Map(cluster.Conf, &out); err != nil { + if err := serializer.Map(cluster, &out); err != nil { log.ErrorWithContext(ctx, err) } if cluster.StackTemplate.CloudService == "AWS" && cluster.StackTemplate.KubeType == "AWS" { - out.TksUserNode = cluster.Conf.TksUserNode / domain.MAX_AZ_NUM - out.TksUserNodeMax = cluster.Conf.TksUserNodeMax / domain.MAX_AZ_NUM + out.TksUserNode = cluster.TksUserNode / domain.MAX_AZ_NUM + out.TksUserNodeMax = cluster.TksUserNodeMax / domain.MAX_AZ_NUM } if err := serializer.Map(cluster, &out); err != nil { @@ -712,30 +712,30 @@ func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterI out = []domain.ClusterNode{ { Type: "TKS_CP_NODE", - Targeted: cluster.Conf.TksCpNode, + Targeted: cluster.TksCpNode, Registered: tksCpNodeRegistered, Registering: tksCpNodeRegistering, - Status: clusterNodeStatus(cluster.Conf.TksCpNode, tksCpNodeRegistered), + Status: clusterNodeStatus(cluster.TksCpNode, tksCpNodeRegistered), Command: command + "control-plane", Validity: bootstrapKubeconfig.Expiration, Hosts: tksCpHosts, }, { Type: "TKS_INFRA_NODE", - Targeted: cluster.Conf.TksInfraNode, + Targeted: cluster.TksInfraNode, Registered: tksInfraNodeRegistered, Registering: tksInfraNodeRegistering, - Status: clusterNodeStatus(cluster.Conf.TksInfraNode, tksInfraNodeRegistered), + Status: clusterNodeStatus(cluster.TksInfraNode, tksInfraNodeRegistered), Command: command + "tks", Validity: bootstrapKubeconfig.Expiration, Hosts: tksInfraHosts, }, { Type: "TKS_USER_NODE", - Targeted: cluster.Conf.TksUserNode, + Targeted: cluster.TksUserNode, Registered: tksUserNodeRegistered, Registering: tksUserNodeRegistering, - Status: clusterNodeStatus(cluster.Conf.TksUserNode, tksUserNodeRegistered), + Status: clusterNodeStatus(cluster.TksUserNode, tksUserNodeRegistered), Command: command + "worker", Validity: bootstrapKubeconfig.Expiration, Hosts: tksUserHosts, @@ -779,7 +779,7 @@ func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterI } /* -func (u *ClusterUsecase) constructClusterConf(rawConf *domain.ClusterConf) (clusterConf *domain.ClusterConf, err error) { +func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clusterConf *model.ClusterConf, err error) { region := "ap-northeast-2" if rawConf != nil && rawConf.Region != "" { region = rawConf.Region @@ -857,7 +857,7 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *domain.ClusterConf) (clus } // Construct cluster conf - tempConf := domain.ClusterConf{ + tempConf := model.ClusterConf{ SshKeyName: sshKeyName, Region: region, NumOfAz: int(numOfAz), diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 18ceda50..e6e17c6f 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -26,8 +27,8 @@ import ( ) type IDashboardUsecase interface { - GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (res []domain.DashboardChart, err error) - GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) + GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (res []model.DashboardChart, err error) + GetStacks(ctx context.Context, organizationId string) (out []model.DashboardStack, err error) GetResources(ctx context.Context, organizationId string) (out domain.DashboardResource, err error) } @@ -49,7 +50,7 @@ func NewDashboardUsecase(r repository.Repository, cache *gcache.Cache) IDashboar } } -func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (out []domain.DashboardChart, err error) { +func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (out []model.DashboardChart, err error) { _, err = u.organizationRepo.Get(organizationId) if err != nil { return nil, errors.Wrap(err, "invalid organization") @@ -71,7 +72,7 @@ func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, return } -func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) { +func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) (out []model.DashboardStack, err error) { clusters, err := u.clusterRepo.FetchByOrganizationId(organizationId, uuid.Nil, nil) if err != nil { return out, err @@ -103,7 +104,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) return nil, err } stack := reflectClusterToStack(cluster, appGroups) - dashboardStack := domain.DashboardStack{} + dashboardStack := model.DashboardStack{} if err := serializer.Map(stack, &dashboardStack); err != nil { log.InfoWithContext(ctx, err) } @@ -153,11 +154,11 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri return out, err } - filteredClusters := funk.Filter(clusters, func(x domain.Cluster) bool { + filteredClusters := funk.Filter(clusters, func(x model.Cluster) bool { return x.Status != domain.ClusterStatus_DELETED }) if filteredClusters != nil { - out.Stack = fmt.Sprintf("%d 개", len(filteredClusters.([]domain.Cluster))) + out.Stack = fmt.Sprintf("%d 개", len(filteredClusters.([]model.Cluster))) } else { out.Stack = "0 개" } @@ -221,7 +222,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri return } -func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartType string, duration string, interval string, year string, month string) (res domain.DashboardChart, err error) { +func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartType string, duration string, interval string, year string, month string) (res model.DashboardChart, err error) { thanosUrl, err := u.getThanosUrl(organizationId) if err != nil { log.Error(err) @@ -326,7 +327,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy chartData.YAxis = nil chartData.PodCounts = podCounts - return domain.DashboardChart{ + return model.DashboardChart{ ChartType: domain.ChartType_POD_CALENDAR, OrganizationId: organizationId, Name: "POD 기동 현황", @@ -337,7 +338,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy UpdatedAt: time.Now(), }, nil default: - return domain.DashboardChart{}, fmt.Errorf("No data") + return model.DashboardChart{}, fmt.Errorf("No data") } result, err := thanosClient.FetchRange(query, int(now.Unix())-durationSec, int(now.Unix()), intervalSec) @@ -388,7 +389,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy chartData.XAxis = &domain.Axis{} chartData.XAxis.Data = xAxisData - return domain.DashboardChart{ + return model.DashboardChart{ ChartType: new(domain.ChartType).FromString(chartType), OrganizationId: organizationId, Name: chartType, diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 832430a1..dcc7bb60 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -19,10 +20,10 @@ import ( ) type IOrganizationUsecase interface { - Create(context.Context, *domain.Organization) (organizationId string, err error) - Fetch(pg *pagination.Pagination) (*[]domain.Organization, error) - Get(organizationId string) (domain.Organization, error) - Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) + Create(context.Context, *model.Organization) (organizationId string, err error) + Fetch(pg *pagination.Pagination) (*[]model.Organization, error) + Get(organizationId string) (model.Organization, error) + Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) UpdatePrimaryClusterId(organizationId string, clusterId string) (err error) Delete(organizationId string, accessToken string) error } @@ -43,7 +44,7 @@ func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClien } } -func (u *OrganizationUsecase) Create(ctx context.Context, in *domain.Organization) (organizationId string, err error) { +func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization) (organizationId string, err error) { creator := uuid.Nil if in.Creator != "" { creator, err = uuid.Parse(in.Creator) @@ -84,17 +85,17 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *domain.Organizatio return organizationId, nil } -func (u *OrganizationUsecase) Fetch(pg *pagination.Pagination) (out *[]domain.Organization, err error) { +func (u *OrganizationUsecase) Fetch(pg *pagination.Pagination) (out *[]model.Organization, err error) { organizations, err := u.repo.Fetch(pg) if err != nil { return nil, err } return organizations, nil } -func (u *OrganizationUsecase) Get(organizationId string) (res domain.Organization, err error) { +func (u *OrganizationUsecase) Get(organizationId string) (res model.Organization, err error) { res, err = u.repo.Get(organizationId) if err != nil { - return domain.Organization{}, httpErrors.NewNotFoundError(err, "", "") + return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") } return res, nil } @@ -130,15 +131,15 @@ func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) return nil } -func (u *OrganizationUsecase) Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) { +func (u *OrganizationUsecase) Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) { _, err := u.Get(organizationId) if err != nil { - return domain.Organization{}, httpErrors.NewNotFoundError(err, "", "") + return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") } res, err := u.repo.Update(organizationId, in) if err != nil { - return domain.Organization{}, err + return model.Organization{}, err } return res, nil diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index 4d38cca3..bcce7e95 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -2,21 +2,21 @@ package usecase import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" ) type IPermissionUsecase interface { - CreatePermissionSet(permissionSet *domain.PermissionSet) error - GetPermissionSetByRoleId(roleId string) (*domain.PermissionSet, error) - ListPermissions(roleId string) ([]*domain.Permission, error) - //GetPermission(id uuid.UUID) (*domain.Permission, error) + CreatePermissionSet(permissionSet *model.PermissionSet) error + GetPermissionSetByRoleId(roleId string) (*model.PermissionSet, error) + ListPermissions(roleId string) ([]*model.Permission, error) + //GetPermission(id uuid.UUID) (*model.Permission, error) //DeletePermission(id uuid.UUID) error - //UpdatePermission(permission *domain.Permission) error - SetRoleIdToPermissionSet(roleId string, permissionSet *domain.PermissionSet) - GetAllowedPermissionSet() *domain.PermissionSet - GetUserPermissionSet() *domain.PermissionSet - UpdatePermission(permission *domain.Permission) error + //UpdatePermission(permission *model.Permission) error + SetRoleIdToPermissionSet(roleId string, permissionSet *model.PermissionSet) + GetAllowedPermissionSet() *model.PermissionSet + GetUserPermissionSet() *model.PermissionSet + UpdatePermission(permission *model.Permission) error } type PermissionUsecase struct { @@ -29,7 +29,7 @@ func NewPermissionUsecase(repo repository.Repository) *PermissionUsecase { } } -func (p PermissionUsecase) CreatePermissionSet(permissionSet *domain.PermissionSet) error { +func (p PermissionUsecase) CreatePermissionSet(permissionSet *model.PermissionSet) error { var err error if err = p.repo.Create(permissionSet.Dashboard); err != nil { return err @@ -52,8 +52,8 @@ func (p PermissionUsecase) CreatePermissionSet(permissionSet *domain.PermissionS return nil } -func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*domain.PermissionSet, error) { - permissionSet := &domain.PermissionSet{ +func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*model.PermissionSet, error) { + permissionSet := &model.PermissionSet{ Dashboard: nil, Stack: nil, SecurityPolicy: nil, @@ -68,17 +68,17 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*domain.Perm } for _, permission := range permissionList { switch permission.Name { - case string(domain.DashBoardPermission): + case string(model.DashBoardPermission): permissionSet.Dashboard = permission - case string(domain.StackPermission): + case string(model.StackPermission): permissionSet.Stack = permission - case string(domain.SecurityPolicyPermission): + case string(model.SecurityPolicyPermission): permissionSet.SecurityPolicy = permission - case string(domain.ProjectManagementPermission): + case string(model.ProjectManagementPermission): permissionSet.ProjectManagement = permission - case string(domain.NotificationPermission): + case string(model.NotificationPermission): permissionSet.Notification = permission - case string(domain.ConfigurationPermission): + case string(model.ConfigurationPermission): permissionSet.Configuration = permission } } @@ -86,11 +86,11 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*domain.Perm return permissionSet, nil } -func (p PermissionUsecase) ListPermissions(roleId string) ([]*domain.Permission, error) { +func (p PermissionUsecase) ListPermissions(roleId string) ([]*model.Permission, error) { return p.repo.List(roleId) } -func (p PermissionUsecase) GetPermission(id uuid.UUID) (*domain.Permission, error) { +func (p PermissionUsecase) GetPermission(id uuid.UUID) (*model.Permission, error) { return p.repo.Get(id) } @@ -98,22 +98,22 @@ func (p PermissionUsecase) DeletePermission(id uuid.UUID) error { return p.repo.Delete(id) } -func (p PermissionUsecase) UpdatePermission(permission *domain.Permission) error { +func (p PermissionUsecase) UpdatePermission(permission *model.Permission) error { return p.repo.Update(permission) } -func (p PermissionUsecase) SetRoleIdToPermissionSet(roleId string, permissionSet *domain.PermissionSet) { +func (p PermissionUsecase) SetRoleIdToPermissionSet(roleId string, permissionSet *model.PermissionSet) { permissionSet.SetRoleId(roleId) } -func (p PermissionUsecase) GetAllowedPermissionSet() *domain.PermissionSet { - permissionSet := domain.NewDefaultPermissionSet() +func (p PermissionUsecase) GetAllowedPermissionSet() *model.PermissionSet { + permissionSet := model.NewDefaultPermissionSet() permissionSet.SetAllowedPermissionSet() return permissionSet } -func (p PermissionUsecase) GetUserPermissionSet() *domain.PermissionSet { - permissionSet := domain.NewDefaultPermissionSet() +func (p PermissionUsecase) GetUserPermissionSet() *model.PermissionSet { + permissionSet := model.NewDefaultPermissionSet() permissionSet.SetUserPermissionSet() return permissionSet } diff --git a/internal/usecase/role.go b/internal/usecase/role.go index 70d51081..bc5d3734 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -1,18 +1,18 @@ package usecase import ( + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" ) type IRoleUsecase interface { - CreateTksRole(role *domain.Role) (string, error) - ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) - GetTksRole(id string) (*domain.Role, error) + CreateTksRole(role *model.Role) (string, error) + ListRoles(pg *pagination.Pagination) ([]*model.Role, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) + GetTksRole(id string) (*model.Role, error) DeleteTksRole(id string) error - UpdateTksRole(role *domain.Role) error + UpdateTksRole(role *model.Role) error } type RoleUsecase struct { @@ -25,11 +25,11 @@ func NewRoleUsecase(repo repository.Repository) *RoleUsecase { } } -func (r RoleUsecase) CreateTksRole(role *domain.Role) (string, error) { +func (r RoleUsecase) CreateTksRole(role *model.Role) (string, error) { return r.repo.Create(role) } -func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) { +func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { roles, err := r.repo.ListTksRoles(organizationId, pg) if err != nil { return nil, err @@ -38,11 +38,11 @@ func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Paginati return roles, nil } -func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) { +func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*model.Role, error) { return r.repo.List(nil) } -func (r RoleUsecase) GetTksRole(id string) (*domain.Role, error) { +func (r RoleUsecase) GetTksRole(id string) (*model.Role, error) { role, err := r.repo.GetTksRole(id) if err != nil { return nil, err @@ -55,7 +55,7 @@ func (r RoleUsecase) DeleteTksRole(id string) error { return r.repo.Delete(id) } -func (r RoleUsecase) UpdateTksRole(role *domain.Role) error { +func (r RoleUsecase) UpdateTksRole(role *model.Role) error { err := r.repo.Update(role) if err != nil { return err diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 2a258d16..a7986497 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -7,20 +7,20 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" ) type IStackTemplateUsecase interface { - Get(ctx context.Context, stackTemplateId uuid.UUID) (domain.StackTemplate, error) - Fetch(ctx context.Context, pg *pagination.Pagination) ([]domain.StackTemplate, error) - Create(ctx context.Context, dto domain.StackTemplate) (stackTemplate uuid.UUID, err error) - Update(ctx context.Context, dto domain.StackTemplate) error - Delete(ctx context.Context, dto domain.StackTemplate) error - UpdateOrganizations(ctx context.Context, dto domain.StackTemplate) error + Get(ctx context.Context, stackTemplateId uuid.UUID) (model.StackTemplate, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.StackTemplate, error) + Create(ctx context.Context, dto model.StackTemplate) (stackTemplate uuid.UUID, err error) + Update(ctx context.Context, dto model.StackTemplate) error + Delete(ctx context.Context, dto model.StackTemplate) error + UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error } type StackTemplateUsecase struct { @@ -35,13 +35,14 @@ func NewStackTemplateUsecase(r repository.Repository) IStackTemplateUsecase { } } -func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) { +func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - dto.CreatorId = user.GetUserId() - dto.UpdatorId = user.GetUserId() + userId := user.GetUserId() + dto.CreatorId = &userId + dto.UpdatorId = &userId pg := pagination.NewPaginationWithFilter("name", "", "$eq", []string{dto.Name}) stackTemplates, _ := u.Fetch(ctx, pg) @@ -76,7 +77,7 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTempl return stackTemplateId, nil } -func (u *StackTemplateUsecase) Update(ctx context.Context, dto domain.StackTemplate) error { +func (u *StackTemplateUsecase) Update(ctx context.Context, dto model.StackTemplate) error { _, err := u.repo.Get(dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") @@ -89,15 +90,15 @@ func (u *StackTemplateUsecase) Update(ctx context.Context, dto domain.StackTempl return nil } -func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res domain.StackTemplate, err error) { +func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res model.StackTemplate, err error) { res, err = u.repo.Get(stackTemplateId) if err != nil { - return domain.StackTemplate{}, err + return model.StackTemplate{}, err } return } -func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (res []domain.StackTemplate, err error) { +func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (res []model.StackTemplate, err error) { res, err = u.repo.Fetch(pg) if err != nil { return nil, err @@ -105,17 +106,17 @@ func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Paginat return res, nil } -func (u *StackTemplateUsecase) Delete(ctx context.Context, dto domain.StackTemplate) (err error) { +func (u *StackTemplateUsecase) Delete(ctx context.Context, dto model.StackTemplate) (err error) { return nil } -func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto domain.StackTemplate) error { +func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error { _, err := u.repo.Get(dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") } - organizations := make([]domain.Organization, 0) + organizations := make([]model.Organization, 0) for _, organizationId := range dto.OrganizationIds { organization, err := u.organizationRepo.Get(organizationId) if err == nil { diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 3bb6f907..9daeea2a 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -11,6 +11,7 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" @@ -24,13 +25,13 @@ import ( ) type IStackUsecase interface { - Get(ctx context.Context, stackId domain.StackId) (domain.Stack, error) - GetByName(ctx context.Context, organizationId string, name string) (domain.Stack, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Stack, error) - Create(ctx context.Context, dto domain.Stack) (stackId domain.StackId, err error) + Get(ctx context.Context, stackId domain.StackId) (model.Stack, error) + GetByName(ctx context.Context, organizationId string, name string) (model.Stack, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Stack, error) + Create(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) Install(ctx context.Context, stackId domain.StackId) (err error) - Update(ctx context.Context, dto domain.Stack) error - Delete(ctx context.Context, dto domain.Stack) error + Update(ctx context.Context, dto model.Stack) error + Delete(ctx context.Context, dto model.Stack) error GetKubeConfig(ctx context.Context, stackId domain.StackId) (kubeConfig string, err error) GetStepStatus(ctx context.Context, stackId domain.StackId) (out []domain.StackStepStatus, stackStatus string, err error) SetFavorite(ctx context.Context, stackId domain.StackId) error @@ -61,7 +62,7 @@ func NewStackUsecase(r repository.Repository, argoClient argowf.ArgoClient, dash } } -func (u *StackUsecase) Create(ctx context.Context, dto domain.Stack) (stackId domain.StackId, err error) { +func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -103,7 +104,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto domain.Stack) (stackId do // Make stack nodes var stackConf domain.StackConfResponse - if err = domain.Map(dto.Conf, &stackConf); err != nil { + if err = serializer.Map(dto, &stackConf); err != nil { log.InfoWithContext(ctx, err) } if stackTemplate.CloudService == "AWS" && stackTemplate.KubeType == "AWS" { @@ -196,7 +197,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err // Make stack nodes var stackConf domain.StackConfResponse - if err = domain.Map(cluster.Conf, &stackConf); err != nil { + if err = serializer.Map(cluster, &stackConf); err != nil { log.InfoWithContext(ctx, err) } @@ -221,7 +222,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err return nil } -func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out domain.Stack, err error) { +func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out model.Stack, err error) { cluster, err := u.clusterRepo.Get(domain.ClusterId(stackId)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -275,7 +276,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out dom return } -func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, name string) (out domain.Stack, err error) { +func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Stack, err error) { cluster, err := u.clusterRepo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -293,7 +294,7 @@ func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, nam return } -func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []domain.Stack, err error) { +func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.Stack, err error) { user, ok := request.UserFrom(ctx) if !ok { return out, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -352,7 +353,7 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return } -func (u *StackUsecase) Update(ctx context.Context, dto domain.Stack) (err error) { +func (u *StackUsecase) Update(ctx context.Context, dto model.Stack) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -364,7 +365,7 @@ func (u *StackUsecase) Update(ctx context.Context, dto domain.Stack) (err error) } updatorId := user.GetUserId() - dtoCluster := domain.Cluster{ + dtoCluster := model.Cluster{ ID: domain.ClusterId(dto.ID), Description: dto.Description, UpdatorId: &updatorId, @@ -378,7 +379,7 @@ func (u *StackUsecase) Update(ctx context.Context, dto domain.Stack) (err error) return nil } -func (u *StackUsecase) Delete(ctx context.Context, dto domain.Stack) (err error) { +func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -617,7 +618,7 @@ func (u *StackUsecase) DeleteFavorite(ctx context.Context, stackId domain.StackI return nil } -func reflectClusterToStack(cluster domain.Cluster, appGroups []domain.AppGroup) (out domain.Stack) { +func reflectClusterToStack(cluster model.Cluster, appGroups []model.AppGroup) (out model.Stack) { if err := serializer.Map(cluster, &out); err != nil { log.Error(err) } @@ -629,7 +630,7 @@ func reflectClusterToStack(cluster domain.Cluster, appGroups []domain.AppGroup) out.StatusDesc = statusDesc /* - return domain.Stack{ + return model.Stack{ ID: domain.StackId(cluster.ID), OrganizationId: cluster.OrganizationId, Name: cluster.Name, @@ -663,7 +664,7 @@ func reflectClusterToStack(cluster domain.Cluster, appGroups []domain.AppGroup) } // [TODO] more pretty -func getStackStatus(cluster domain.Cluster, appGroups []domain.AppGroup) (domain.StackStatus, string) { +func getStackStatus(cluster model.Cluster, appGroups []model.AppGroup) (domain.StackStatus, string) { for _, appGroup := range appGroups { if appGroup.Status == domain.AppGroupStatus_PENDING && cluster.Status == domain.ClusterStatus_RUNNING { return domain.StackStatus_APPGROUP_INSTALLING, appGroup.StatusDesc diff --git a/internal/usecase/user.go b/internal/usecase/user.go index b851d2f5..0d3bd907 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -10,32 +10,32 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/mail" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" ) type IUserUsecase interface { - CreateAdmin(organizationId string, email string) (*domain.User, error) + CreateAdmin(organizationId string, email string) (*model.User, error) DeleteAdmin(organizationId string) error DeleteAll(ctx context.Context, organizationId string) error - Create(ctx context.Context, user *domain.User) (*domain.User, error) - List(ctx context.Context, organizationId string) (*[]domain.User, error) - ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]domain.User, error) - Get(userId uuid.UUID) (*domain.User, error) - Update(ctx context.Context, userId uuid.UUID, user *domain.User) (*domain.User, error) + Create(ctx context.Context, user *model.User) (*model.User, error) + List(ctx context.Context, organizationId string) (*[]model.User, error) + ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.User, error) + Get(userId uuid.UUID) (*model.User, error) + Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) ResetPassword(userId uuid.UUID) error ResetPasswordByAccountId(accountId string, organizationId string) error GenerateRandomPassword() string Delete(userId uuid.UUID, organizationId string) error - GetByAccountId(ctx context.Context, accountId string, organizationId string) (*domain.User, error) - GetByEmail(ctx context.Context, email string, organizationId string) (*domain.User, error) + GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) + GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error - UpdateByAccountId(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) + UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) UpdatePasswordByAccountId(ctx context.Context, accountId string, originPassword string, newPassword string, organizationId string) error RenewalPasswordExpiredTime(ctx context.Context, userId uuid.UUID) error RenewalPasswordExpiredTimeByAccountId(ctx context.Context, accountId string, organizationId string) error @@ -43,7 +43,7 @@ type IUserUsecase interface { ValidateAccount(userId uuid.UUID, password string, organizationId string) error ValidateAccountByAccountId(accountId string, password string, organizationId string) error - UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) + UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *model.User) (*model.User, error) } type UserUsecase struct { @@ -196,17 +196,17 @@ func (u *UserUsecase) DeleteAdmin(organizationId string) error { return nil } -func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*domain.User, error) { +func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*model.User, error) { // Generate Admin user object randomPassword := helper.GenerateRandomString(passwordLength) - user := domain.User{ + user := model.User{ AccountId: "admin", Password: randomPassword, Email: email, - Role: domain.Role{ + Role: model.Role{ Name: "admin", }, - Organization: domain.Organization{ + Organization: model.Organization{ ID: orgainzationId, }, Name: "admin", @@ -295,7 +295,7 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s return nil } -func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[]domain.User, err error) { +func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[]model.User, err error) { users, err = u.userRepository.List(u.userRepository.OrganizationFilter(organizationId)) if err != nil { return nil, err @@ -304,7 +304,7 @@ func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[ return } -func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (users *[]domain.User, err error) { +func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (users *[]model.User, err error) { users, err = u.userRepository.ListWithPagination(pg, organizationId) if err != nil { return nil, err @@ -313,7 +313,7 @@ func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId str return } -func (u *UserUsecase) Get(userId uuid.UUID) (*domain.User, error) { +func (u *UserUsecase) Get(userId uuid.UUID) (*model.User, error) { user, err := u.userRepository.GetByUuid(userId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -325,7 +325,7 @@ func (u *UserUsecase) Get(userId uuid.UUID) (*domain.User, error) { return &user, nil } -func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, organizationId string) (*domain.User, error) { +func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) { users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), u.userRepository.AccountIdFilter(accountId)) if err != nil { @@ -335,7 +335,7 @@ func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, orga return &(*users)[0], nil } -func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organizationId string) (*domain.User, error) { +func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) { users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), u.userRepository.EmailFilter(email)) if err != nil { @@ -345,7 +345,7 @@ func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organization return &(*users)[0], nil } -func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *domain.User) (*domain.User, error) { +func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) { storedUser, err := u.Get(userId) if err != nil { return nil, err @@ -355,8 +355,8 @@ func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *domain return u.UpdateByAccountId(ctx, storedUser.AccountId, user) } -func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) { - var out domain.User +func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) { + var out model.User originUser, err := u.kc.GetUser(user.Organization.ID, accountId) if err != nil { @@ -438,7 +438,7 @@ func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, o return nil } -func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.User, error) { +func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User, error) { // Create user in keycloak groups := []string{fmt.Sprintf("%s@%s", user.Role.Name, user.Organization.ID)} userUuidStr, err := u.kc.CreateUser(user.Organization.ID, &gocloak.User{ @@ -492,7 +492,7 @@ func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.Us return &resUser, nil } -func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *domain.User) (*domain.User, error) { +func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *model.User) (*model.User, error) { deepCopyUser := *newUser user, err := u.UpdateByAccountId(ctx, accountId, &deepCopyUser) if err != nil { diff --git a/pkg/domain/admin/user.go b/pkg/domain/admin/user.go index 7d53a51e..0a9e6820 100644 --- a/pkg/domain/admin/user.go +++ b/pkg/domain/admin/user.go @@ -1,8 +1,9 @@ package admin import ( - "github.com/openinfradev/tks-api/pkg/domain" "time" + + "github.com/openinfradev/tks-api/pkg/domain" ) type CreateUserRequest struct { @@ -26,17 +27,17 @@ type ListUserResponse struct { type GetUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role domain.Role `json:"role"` - Organization domain.Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role domain.RoleResponse `json:"role"` + Organization domain.OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } @@ -51,16 +52,16 @@ type UpdateUserRequest struct { type UpdateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role domain.Role `json:"role"` - Organization domain.Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role domain.RoleResponse `json:"role"` + Organization domain.OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } diff --git a/pkg/domain/alert.go b/pkg/domain/alert.go index 7201ef24..a60073bf 100644 --- a/pkg/domain/alert.go +++ b/pkg/domain/alert.go @@ -33,50 +33,6 @@ func (m AlertActionStatus) FromString(s string) AlertActionStatus { return AlertActionStatus_ERROR } -// 내부 -type Alert struct { - ID uuid.UUID - OrganizationId string - Organization Organization - Name string - Description string - Code string - Grade string - Message string - ClusterId ClusterId - Cluster Cluster - Node string - CheckPoint string - Summary string - GrafanaUrl string - FiredAt *time.Time - TakedAt *time.Time - ClosedAt *time.Time - TakedSec int - ProcessingSec int - Status AlertActionStatus - AlertActions []AlertAction - LastTaker User - RawData []byte - CreatorId *uuid.UUID - Creator User - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time -} - -type AlertAction struct { - ID uuid.UUID - AlertId uuid.UUID - Content string - Status AlertActionStatus - TakerId *uuid.UUID - Taker User - CreatedAt time.Time - UpdatedAt time.Time -} - type CreateAlertRequestAlert struct { Status string `json:"status"` GeneratorURL string `json:"generatorURL"` diff --git a/pkg/domain/app-group.go b/pkg/domain/app-group.go index d4e3211d..36dff144 100644 --- a/pkg/domain/app-group.go +++ b/pkg/domain/app-group.go @@ -114,33 +114,6 @@ func (m AppGroupType) FromString(s string) AppGroupType { return AppGroupType_UNSPECIFIED } -type AppGroup = struct { - ID AppGroupId - Name string - ClusterId ClusterId - AppGroupType AppGroupType - Description string - WorkflowId string - Status AppGroupStatus - StatusDesc string - CreatorId *uuid.UUID - Creator User - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time -} - -type Application = struct { - ID uuid.UUID - AppGroupId AppGroupId - Endpoint string - Metadata string - ApplicationType ApplicationType - CreatedAt time.Time - UpdatedAt time.Time -} - type AppGroupResponse = struct { ID AppGroupId `json:"id"` Name string `json:"name"` diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index 45239154..b1db60af 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -1,71 +1,56 @@ package domain -import ( - "time" - - "github.com/google/uuid" - "gorm.io/gorm" -) - -type AppServeApp struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - Name string `gorm:"index" json:"name,omitempty"` // application name - Namespace string `json:"namespace,omitempty"` // application namespace - OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to - ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to - Type string `json:"type,omitempty"` // type (build/deploy/all) - AppType string `json:"appType,omitempty"` // appType (spring/springboot) - EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app - PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment - TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed - TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name - Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app - GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` - AppServeAppTasks []AppServeAppTask `gorm:"foreignKey:AppServeAppId" json:"appServeAppTasks"` -} - -type AppServeAppTask struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - AppServeAppId string `gorm:"not null" json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to - Version string `json:"version,omitempty"` // application version - Status string `json:"status,omitempty"` // status is app status - Output string `json:"output,omitempty"` // output for task result - ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) - ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app - ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image - Profile string `json:"profile,omitempty"` // java app profile - AppConfig string `json:"appConfig,omitempty"` // java app config - AppSecret string `json:"appSecret,omitempty"` // java app secret - ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app - Port string `json:"port,omitempty"` // java app port - ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod - HelmRevision int32 `gorm:"default:0" json:"helmRevision,omitempty"` // revision of deployed helm release - Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) - RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version +import "time" + +type AppServeAppResponse struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` // application name + Namespace string `json:"namespace,omitempty"` // application namespace + OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to + Type string `json:"type,omitempty"` // type (build/deploy/all) + AppType string `json:"appType,omitempty"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed + TargetClusterName string `json:"targetClusterName,omitempty"` // target cluster name + Status string `json:"status,omitempty"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + CreatedAt time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` + AppServeAppTasks []AppServeAppTaskResponse `json:"appServeAppTasks"` +} + +type AppServeAppTaskResponse struct { + ID string `json:"id,omitempty"` + AppServeAppId string `json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to + Version string `json:"version,omitempty"` // application version + Status string `json:"status,omitempty"` // status is app status + Output string `json:"output,omitempty"` // output for task result + ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) + ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app + ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image + Profile string `json:"profile,omitempty"` // java app profile + AppConfig string `json:"appConfig,omitempty"` // java app config + AppSecret string `json:"appSecret,omitempty"` // java app secret + ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app + Port string `json:"port,omitempty"` // java app port + ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod + HelmRevision int32 `json:"helmRevision,omitempty"` // revision of deployed helm release + Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) + RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version PvEnabled bool `json:"pvEnabled"` PvStorageClass string `json:"pvStorageClass"` PvAccessMode string `json:"pvAccessMode"` PvSize string `json:"pvSize"` PvMountPath string `json:"pvMountPath"` - AvailableRollback bool `gorm:"-:all" json:"availableRollback"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` // createdAt is a creation timestamp for the application - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + AvailableRollback bool `json:"availableRollback"` + CreatedAt time.Time `json:"createdAt"` // createdAt is a creation timestamp for the application + UpdatedAt *time.Time `json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` } -func (a *AppServeApp) BeforeCreate(tx *gorm.DB) (err error) { - a.ID = uuid.New().String() - return nil -} - -func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} - type CreateAppServeAppRequest struct { // App Name string `json:"name" validate:"required,rfc1123,name"` @@ -158,25 +143,25 @@ type RollbackAppServeAppRequest struct { } type GetAppServeAppsResponse struct { - AppServeApps []AppServeApp `json:"appServeApps"` - Pagination PaginationResponse `json:"pagination"` + AppServeApps []AppServeAppResponse `json:"appServeApps"` + Pagination PaginationResponse `json:"pagination"` } // TODO: This will be deprecated later type GetAppServeAppResponse struct { - AppServeApp AppServeApp `json:"appServeApp"` - Stages []StageResponse `json:"stages"` + AppServeApp AppServeAppResponse `json:"appServeApp"` + Stages []StageResponse `json:"stages"` } type GetAppServeAppTasksResponse struct { - AppServeAppTasks []AppServeAppTask `json:"appServeAppTasks"` - Pagination PaginationResponse `json:"pagination"` + AppServeAppTasks []AppServeAppTaskResponse `json:"appServeAppTasks"` + Pagination PaginationResponse `json:"pagination"` } type GetAppServeAppTaskResponse struct { - AppServeApp AppServeApp `json:"appServeApp"` - AppServeAppTask AppServeAppTask `json:"appServeAppTask"` - Stages []StageResponse `json:"stages"` + AppServeApp AppServeAppResponse `json:"appServeApp"` + AppServeAppTask AppServeAppTaskResponse `json:"appServeAppTask"` + Stages []StageResponse `json:"stages"` } type StageResponse struct { diff --git a/pkg/domain/audit.go b/pkg/domain/audit.go index 9599ccae..6622aa40 100644 --- a/pkg/domain/audit.go +++ b/pkg/domain/audit.go @@ -2,25 +2,8 @@ package domain import ( "time" - - "github.com/google/uuid" ) -// 내부 -type Audit struct { - ID uuid.UUID - OrganizationId string - Organization Organization - Group string - Message string - Description string - ClientIP string - UserId *uuid.UUID - User User - CreatedAt time.Time - UpdatedAt time.Time -} - type AuditResponse struct { ID string `json:"id"` OrganizationId string `json:"organizationId"` @@ -29,7 +12,6 @@ type AuditResponse struct { Group string `json:"group"` Message string `json:"message"` ClientIP string `json:"clientIP"` - UserId string `json:"userId"` User SimpleUserResponse `json:"user"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` diff --git a/pkg/domain/auth.go b/pkg/domain/auth.go index abab6f97..4dbaeeef 100644 --- a/pkg/domain/auth.go +++ b/pkg/domain/auth.go @@ -13,13 +13,13 @@ type PingTokenRequest struct { type LoginResponse struct { User struct { - AccountId string `json:"accountId"` - Name string `json:"name"` - Token string `json:"token"` - Role Role `json:"role"` - Department string `json:"department"` - Organization Organization `json:"organization"` - PasswordExpired bool `json:"passwordExpired"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Token string `json:"token"` + Role RoleResponse `json:"role"` + Department string `json:"department"` + Organization OrganizationResponse `json:"organization"` + PasswordExpired bool `json:"passwordExpired"` } `json:"user"` } diff --git a/pkg/domain/cloud-account.go b/pkg/domain/cloud-account.go index 5e4720c8..3ec209e3 100644 --- a/pkg/domain/cloud-account.go +++ b/pkg/domain/cloud-account.go @@ -2,8 +2,6 @@ package domain import ( "time" - - "github.com/google/uuid" ) const CLOUD_ACCOUNT_INCLUSTER = "INCLUSTER" @@ -49,30 +47,6 @@ func (m CloudAccountStatus) FromString(s string) CloudAccountStatus { return CloudAccountStatus_PENDING } -// 내부 -type CloudAccount struct { - ID uuid.UUID - OrganizationId string - Name string - Description string - CloudService string - Resource string - Clusters int - AwsAccountId string - AccessKeyId string - SecretAccessKey string - SessionToken string - Status CloudAccountStatus - StatusDesc string - CreatedIAM bool - CreatorId uuid.UUID - Creator User - UpdatorId uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time -} - type ResourceQuotaAttr struct { Type string `json:"type"` Usage int `json:"usage"` diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index 6c2ea884..0d7c854b 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -3,7 +3,6 @@ package domain import ( "time" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" ) @@ -83,34 +82,6 @@ func (m ClusterType) FromString(s string) ClusterType { return ClusterType_USER } -// model -type Cluster struct { - ID ClusterId - CloudService string - OrganizationId string - Name string - Description string - CloudAccountId uuid.UUID - CloudAccount CloudAccount - StackTemplateId uuid.UUID - StackTemplate StackTemplate - Status ClusterStatus - StatusDesc string - Conf ClusterConf - Favorited bool - CreatorId *uuid.UUID - Creator User - ClusterType ClusterType - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time - ByoClusterEndpointHost string - ByoClusterEndpointPort int - IsStack bool - Kubeconfig []byte -} - type ClusterConf struct { TksCpNode int TksCpNodeMax int @@ -239,6 +210,7 @@ type ClusterResponse struct { ByoClusterEndpointHost string `json:"byoClusterEndpointHost,omitempty"` ByoClusterEndpointInt int `json:"byoClusterEndpointPort,omitempty"` IsStack bool `json:"isStack,omitempty"` + Favorited bool `json:"favorited,omitempty"` } type SimpleClusterResponse struct { diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index c7699fb7..3560838e 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -45,33 +45,6 @@ func (m ChartType) All() (out []string) { return } -// 내부 -type DashboardChart struct { - ChartType ChartType - OrganizationId string - Name string - Description string - Duration string // 1d, 7d, 30d ... - Interval string // 1h, 1d, ... - Year string - Month string - ChartData ChartData - UpdatedAt time.Time -} - -type DashboardStack struct { - ID StackId - Name string - Description string - Status string - StatusDesc string - Cpu string - Memory string - Storage string - CreatedAt time.Time - UpdatedAt time.Time -} - type Unit struct { Name string `json:"name"` Data []string `json:"data"` diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index c34a45ae..e2a2127d 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -1,11 +1,10 @@ package domain -import ( - "time" -) +import "time" -type Endpoint struct { - Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` - Group string `gorm:"type:text;" json:"group"` - CreatedAt time.Time +type EndpointResponse struct { + Name string `json:"name"` + Group string `json:"group"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } diff --git a/pkg/domain/mapper.go b/pkg/domain/mapper.go deleted file mode 100644 index e3fa80ac..00000000 --- a/pkg/domain/mapper.go +++ /dev/null @@ -1,140 +0,0 @@ -package domain - -import ( - "fmt" - "reflect" - - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/log" -) - -type ConverterMap map[compositeKey]func(interface{}) (interface{}, error) - -type compositeKey struct { - srcType reflect.Type - dstType reflect.Type -} - -func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) error { - srcVal := reflect.ValueOf(src) - srcType := srcVal.Type() - - dstVal := reflect.ValueOf(dst) - if dstVal.Kind() != reflect.Ptr || dstVal.IsNil() { - return fmt.Errorf("dst must be a non-nil pointer") - } - dstElem := dstVal.Elem() - - for i := 0; i < srcVal.NumField(); i++ { - fieldName := srcType.Field(i).Name - srcField := srcVal.Field(i) - dstField := dstElem.FieldByName(fieldName) - - if dstField.IsValid() && dstField.CanSet() { - if dstField.Type() == srcField.Type() { - dstField.Set(srcField) - continue - } else if srcField.Type().Kind() == reflect.Struct && dstField.Type().Kind() == reflect.Struct { - if err := recursiveMap(srcField.Interface(), dstField.Addr().Interface(), converterMap); err != nil { - return err - } - } else { - converterKey := compositeKey{srcType: srcField.Type(), dstType: dstField.Type()} - if converter, ok := converterMap[converterKey]; ok { - if converted, err := converter(srcField.Interface()); err != nil { - return err - } else { - dstField.Set(reflect.ValueOf(converted)) - } - } else { - log.Debugf("no converter found for %s -> %s", srcField.Type(), dstField.Type()) - continue - } - } - - /* - else if srcField.Type().Kind() == reflect.Ptr && dstField.Type().Kind() == reflect.Ptr { - log.Info("AAA ", dstField.Type()) - ptr := reflect.New(dstField.Elem().Type()) - if err := recursiveMap(srcField.Elem().Interface(), ptr.Elem().Interface(), converterMap); err != nil { - return err - } - } - */ - - } - } - - return nil -} -func Map(src interface{}, dst interface{}) error { - return recursiveMap(src, dst, ConverterMap{ - {srcType: reflect.TypeOf((*uuid.UUID)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(uuid.UUID).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*uuid.UUID)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - val, _ := uuid.Parse(i.(string)) - return val, nil - }, - {srcType: reflect.TypeOf((*OrganizationStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(OrganizationStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*OrganizationStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return organizationStatusMap[i.(string)], nil - }, - {srcType: reflect.TypeOf((*Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(Role).Name, nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return Role{Name: i.(string)}, nil - }, - {srcType: reflect.TypeOf((*ClusterStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(ClusterStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ClusterStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(ClusterStatus).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*AppGroupStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(AppGroupStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AppGroupStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(AppGroupStatus).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*AppGroupType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(AppGroupType).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AppGroupType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(AppGroupType).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*StackStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(StackStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*StackStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(StackStatus).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*ChartType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(ChartType).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ChartType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(ChartType).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*AlertActionStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(AlertActionStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AlertActionStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(AlertActionStatus).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*ApplicationType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(ApplicationType).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ApplicationType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(ApplicationType).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*CloudAccountStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(CloudAccountStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*CloudAccountStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(CloudAccountStatus).FromString(i.(string)), nil - }, - }) -} diff --git a/pkg/domain/mapper_test.go b/pkg/domain/mapper_test.go deleted file mode 100644 index c235e360..00000000 --- a/pkg/domain/mapper_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package domain - -import ( - "fmt" - "github.com/google/uuid" - "testing" - "time" -) - -// test case -func TestConvert(t *testing.T) { - type args struct { - src interface{} - dst interface{} - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "test case: CreateOrganizationRequest->Organization", - args: args{ - src: CreateOrganizationRequest{ - Name: "test", - Description: "test", - Phone: "test", - }, - dst: &Organization{}, - }, - wantErr: false, - }, - { - name: "test case Organization->CreateOrganizationResponse", - args: args{ - src: Organization{ - ID: "", - Name: "test", - Description: "test", - Phone: "test", - StatusDesc: "good", - Creator: "", - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - }, - dst: &CreateOrganizationResponse{}, - }, - wantErr: false, - }, - { - name: "test case Organization->GetOrganizationResponse", - args: args{ - src: Organization{ - ID: "", - Name: "test", - Description: "test", - Phone: "test", - Status: OrganizationStatus_CREATE, - StatusDesc: "good", - Creator: "", - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - }, - dst: &(&GetOrganizationResponse{}).Organization, - }, - wantErr: false, - }, - { - name: "test case CreateUserRequest->User", - args: args{ - src: CreateUserRequest{ - AccountId: "testAccount", - Password: "testPassword", - Name: "testName", - Email: "testEmail", - Department: "testDepartment", - Role: "testRole", - Description: "testDescription", - }, - dst: &User{}, - }, - wantErr: false, - }, - { - name: "test case User->GetUserResponse", - args: args{ - src: User{ - ID: uuid.New(), - AccountId: "testAccount", - Password: "testPassword", - Name: "testName", - Token: "testToken", - Role: Role{}, - Organization: Organization{}, - Creator: "", - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - Email: "", - Department: "", - Description: "", - }, - dst: &GetUserResponse{}, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := Map(tt.args.src, tt.args.dst); (err != nil) != tt.wantErr { - t.Errorf("Map() error = %v, wantErr %v", err, tt.wantErr) - } else { - fmt.Printf("Input: %+v\n", tt.args.src) - fmt.Printf("Output: %+v\n\n", tt.args.dst) - } - }) - } -} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index fed0cfe9..43fb524d 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -2,8 +2,6 @@ package domain import ( "time" - - "gorm.io/gorm" ) // enum @@ -50,18 +48,14 @@ func (m OrganizationStatus) FromString(s string) OrganizationStatus { return OrganizationStatus_ERROR } -type Organization struct { - gorm.Model - - ID string `gorm:"primarykey;type:varchar(36);not null" json:"id"` +type OrganizationResponse struct { + ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` Phone string `json:"phone"` PrimaryClusterId string `json:"primaryClusterId"` - WorkflowId string `json:"-"` Status OrganizationStatus `json:"status"` StatusDesc string `json:"statusDesc"` - Creator string `json:"creator"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index ad95656e..f7b69f40 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -2,626 +2,37 @@ package domain import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/delivery/api" - "github.com/openinfradev/tks-api/internal/helper" - "gorm.io/gorm" ) -type PermissionKind string - -const ( - DashBoardPermission PermissionKind = "대시보드" - StackPermission PermissionKind = "스택 관리" - SecurityPolicyPermission PermissionKind = "보안/정책 관리" - ProjectManagementPermission PermissionKind = "프로젝트 관리" - NotificationPermission PermissionKind = "알림" - ConfigurationPermission PermissionKind = "설정" -) - -type Permission struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` - Name string `json:"name"` - - IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` - RoleID *string `json:"role_id,omitempty"` - Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` - Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` - // omit empty - - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` - Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` +type PermissionResponse struct { + ID uuid.UUID `json:"ID"` + Name string `json:"name"` + IsAllowed *bool `json:"is_allowed,omitempty"` + RoleID *string `json:"role_id,omitempty"` + Role *RoleResponse `json:"role,omitempty"` + Endpoints []*EndpointResponse `json:"endpoints,omitempty"` + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Parent *PermissionResponse `json:"parent,omitempty"` + Children []*PermissionResponse `json:"children,omitempty"` } -func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { - if p.ID == uuid.Nil { - p.ID = uuid.New() - } - return nil -} - -type PermissionSet struct { - Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` - Stack *Permission `gorm:"-:all" json:"stack,omitempty"` - SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` - ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` - Notification *Permission `gorm:"-:all" json:"notification,omitempty"` - Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` -} - -func NewDefaultPermissionSet() *PermissionSet { - return &PermissionSet{ - Dashboard: newDashboard(), - Stack: newStack(), - SecurityPolicy: newSecurityPolicy(), - ProjectManagement: newProjectManagement(), - Notification: newNotification(), - Configuration: newConfiguration(), - } +type PermissionSetResponse struct { + Dashboard *PermissionResponse `json:"dashboard,omitempty"` + Stack *PermissionResponse `json:"stack,omitempty"` + SecurityPolicy *PermissionResponse `json:"security_policy,omitempty"` + ProjectManagement *PermissionResponse `json:"project_management,omitempty"` + Notification *PermissionResponse `json:"notification,omitempty"` + Configuration *PermissionResponse `json:"configuration,omitempty"` } type GetPermissionTemplatesResponse struct { - Permissions []*Permission `json:"permissions"` + Permissions []*PermissionResponse `json:"permissions"` } type GetPermissionsByRoleIdResponse struct { - Permissions []*Permission `json:"permissions"` + Permissions []*PermissionResponse `json:"permissions"` } type UpdatePermissionsByRoleIdRequest struct { - Permissions []*Permission `json:"permissions"` -} - -func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { - if root.Children == nil { - return append(edgePermissions, root) - } - - for _, child := range root.Children { - if f != nil && !(*f)(*child) { - continue - } - edgePermissions = GetEdgePermission(child, edgePermissions, f) - } - - return edgePermissions -} - -func SetRoleIDToPermission(roleID string, permission *Permission) { - permission.RoleID = helper.StringP(roleID) -} - -func endpointObjects(eps ...api.Endpoint) []*Endpoint { - var result []*Endpoint - for _, ep := range eps { - result = append(result, &Endpoint{ - Name: api.ApiMap[ep].Name, - Group: api.ApiMap[ep].Group, - }) - } - return result -} - -func newDashboard() *Permission { - dashboard := &Permission{ - Name: string(DashBoardPermission), - Children: []*Permission{ - { - Name: "대시보드", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetChartsDashboard, - api.GetChartDashboard, - api.GetStacksDashboard, - api.GetResourcesDashboard, - ), - }, - }, - }, - { - Name: "대시보드 설정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return dashboard -} - -func newStack() *Permission { - stack := &Permission{ - Name: string(StackPermission), - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetStacks, - api.GetStack, - api.CheckStackName, - api.GetStackStatus, - api.GetStackKubeConfig, - - api.SetFavoriteStack, - api.DeleteFavoriteStack, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateStack, - api.InstallStack, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateStack, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteStack, - ), - }, - }, - } - - return stack -} - -func newSecurityPolicy() *Permission { - security_policy := &Permission{ - Name: string(SecurityPolicyPermission), - Children: []*Permission{ - { - Name: "보안/정책", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return security_policy -} - -func newProjectManagement() *Permission { - projectManagement := &Permission{ - Name: string(ProjectManagementPermission), - Children: []*Permission{ - { - Name: "프로젝트", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateProject, - ), - }, - }, - }, - { - Name: "앱 서빙", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetAppServeApps, - api.GetAppServeApp, - api.GetNumOfAppsOnStack, - api.GetAppServeAppLatestTask, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - ), - }, - { - Name: "빌드", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), - }, - { - Name: "배포", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteAppServeApp, - ), - }, - }, - }, - { - Name: "설정-일반", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, - - api.GetProjectRoles, - api.GetProjectRole, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProject, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProject, - ), - }, - }, - }, - { - Name: "설정-멤버", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjectMembers, - api.GetProjectMember, - api.GetProjectRoles, - api.GetProjectRole, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.AddProjectMember, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProjectMemberRole, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.RemoveProjectMember, - ), - }, - }, - }, - { - Name: "설정-네임스페이스", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjectNamespaces, - api.GetProjectNamespace, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateProjectNamespace, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects(), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProjectNamespace, - ), - }, - }, - }, - }, - } - - return projectManagement -} - -func newNotification() *Permission { - notification := &Permission{ - Name: string(NotificationPermission), - Children: []*Permission{ - { - Name: "시스템 경고", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "보안/정책 감사로그", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return notification -} - -func newConfiguration() *Permission { - configuration := &Permission{ - Name: string(ConfigurationPermission), - Children: []*Permission{ - { - Name: "일반", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "클라우드 계정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "스택 템플릿", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "프로젝트 관리", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "사용자", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "사용자 권한 관리", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "알림 설정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return configuration -} - -func (p *PermissionSet) SetAllowedPermissionSet() { - edgePermissions := make([]*Permission, 0) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) - - for _, permission := range edgePermissions { - permission.IsAllowed = helper.BoolP(true) - } - - return -} - -func (p *PermissionSet) SetUserPermissionSet() { - f := func(permission Permission) bool { - return permission.Name == "조회" - } - edgePermissions := make([]*Permission, 0) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) - //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) - - for _, permission := range edgePermissions { - permission.IsAllowed = helper.BoolP(true) - } - - return -} - -func (p *PermissionSet) SetRoleId(roleId string) { - setRoleIdToPermission(p.Dashboard, roleId) - setRoleIdToPermission(p.Stack, roleId) - setRoleIdToPermission(p.SecurityPolicy, roleId) - setRoleIdToPermission(p.ProjectManagement, roleId) - setRoleIdToPermission(p.Notification, roleId) - setRoleIdToPermission(p.Configuration, roleId) -} - -func setRoleIdToPermission(root *Permission, roleId string) { - root.RoleID = helper.StringP(roleId) - - if root.Children == nil { - return - } - - for _, child := range root.Children { - setRoleIdToPermission(child, roleId) - } + Permissions []*PermissionResponse `json:"permissions"` } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 1007dd27..b63d6036 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -3,17 +3,18 @@ package domain import "time" type ProjectResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - IsMyProject string `json:"isMyProject"` - ProjectRoleId string `json:"projectRoleId"` - ProjectRoleName string `json:"projectRoleName"` - NamespaceCount int `json:"namespaceCount"` - AppCount int `json:"appCount"` - MemberCount int `json:"memberCount"` - CreatedAt time.Time `json:"createdAt"` + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + IsMyProject string `json:"isMyProject"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` + NamespaceCount int `json:"namespaceCount"` + AppCount int `json:"appCount"` + MemberCount int `json:"memberCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt *time.Time `json:"updatedAt"` } type GetProjectsResponse struct { diff --git a/pkg/domain/role.go b/pkg/domain/role.go index e177a76a..ab961b26 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -4,7 +4,6 @@ import ( "time" "github.com/google/uuid" - "gorm.io/gorm" ) type RoleType string @@ -15,23 +14,23 @@ const ( RoleTypeProject RoleType = "project" ) -func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { - r.ID = uuid.New().String() - return nil +type RoleResponse struct { + ID string `json:"id"` + Name string `json:"name"` + OrganizationID string `json:"organizationId"` + Organization OrganizationResponse `json:"organization"` + Type string `json:"type"` + Description string `json:"description"` + Creator uuid.UUID `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } -type Role struct { - gorm.Model - - ID string `gorm:"primarykey;" json:"id"` - Name string `json:"name"` - OrganizationID string `json:"organizationId"` - Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;" json:"organization"` - Type string `json:"type"` - Description string `json:"description"` - Creator uuid.UUID `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` +type SimpleRoleResponse = struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + OrganizationID string `json:"organizationId"` } type CreateTksRoleRequest struct { diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index 13b6e9da..122410d1 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -2,38 +2,11 @@ package domain import ( "time" - - "github.com/google/uuid" ) const STACK_TEMPLATE_TYPE_STANDARD = "STANDARD" const STACK_TEMPLATE_TYPE_MSA = "MSA" -// 내부 -type StackTemplate struct { - ID uuid.UUID - OrganizationId string - Name string - Description string - Template string - TemplateType string - CloudService string - Version string - Platform string - KubeVersion string - KubeType string - OrganizationIds []string - Organizations []Organization - ServiceIds []string - Services []byte - CreatorId uuid.UUID - Creator User - UpdatorId uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time -} - type StackTemplateServiceApplicationResponse struct { Name string `json:"name"` Description string `json:"description"` diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index b4935bcb..c56abc48 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -3,7 +3,6 @@ package domain import ( "time" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" ) @@ -74,45 +73,6 @@ const MAX_STEP_LMA_REMOVE = 12 const MAX_STEP_SM_CREATE = 22 const MAX_STEP_SM_REMOVE = 4 -// model -type Stack = struct { - ID StackId - Name string - Description string - ClusterId string - OrganizationId string - CloudService string - CloudAccountId uuid.UUID - CloudAccount CloudAccount - StackTemplateId uuid.UUID - StackTemplate StackTemplate - Status StackStatus - StatusDesc string - Conf StackConf - PrimaryCluster bool - GrafanaUrl string - CreatorId *uuid.UUID - Creator User - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time - Favorited bool - ClusterEndpoint string - Resource DashboardStackResponse -} - -type StackConf struct { - TksCpNode int - TksCpNodeMax int - TksCpNodeType string - TksInfraNode int - TksInfraNodeMax int - TksInfraNodeType string - TksUserNode int - TksUserNodeMax int - TksUserNodeType string -} type StackStepStatus struct { Status string `json:"status"` Stage string `json:"stage"` @@ -176,6 +136,19 @@ type StackResponse struct { UpdatedAt time.Time `json:"updatedAt"` } +type SimpleStackResponse struct { + ID StackId `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + OrganizationId string `json:"organizationId"` + StackTemplate SimpleStackTemplateResponse `json:"stackTemplate,omitempty"` + CloudAccount SimpleCloudAccountResponse `json:"cloudAccount,omitempty"` + Status string `json:"status"` + PrimaryCluster bool `json:"primaryCluster"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + type GetStacksResponse struct { Stacks []StackResponse `json:"stacks"` Pagination PaginationResponse `json:"pagination"` diff --git a/pkg/domain/user.go b/pkg/domain/user.go index d63b4605..a4833494 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -1,55 +1,49 @@ package domain import ( - "github.com/google/uuid" - "gorm.io/gorm" "time" + + "github.com/google/uuid" ) -type User struct { +// // Deprecated: Policy is deprecated, use Permission instead. +// +// type Policy = struct { +// ID string `json:"id"` +// Name string `json:"name"` +// Create bool `json:"create"` +// CreatePriviledge string `json:"createPriviledge"` +// Update bool `json:"update"` +// UpdatePriviledge string `json:"updatePriviledge"` +// Read bool `json:"read"` +// ReadPriviledge string `json:"readPriviledge"` +// Delete bool `json:"delete"` +// DeletePriviledge string `json:"deletePriviledge"` +// Creator string `json:"creator"` +// CreatedAt time.Time `json:"createdAt"` +// UpdatedAt time.Time `json:"updatedAt"` +// } +type UserResponse struct { ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` Password string `gorm:"-:all" json:"password"` Name string `json:"name"` Token string `json:"token"` RoleId string - Role Role `gorm:"foreignKey:RoleId;references:ID" json:"role"` + Role RoleResponse `gorm:"foreignKey:RoleId;references:ID" json:"role"` OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` - PasswordExpired bool `json:"passwordExpired"` + Organization OrganizationResponse `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` + PasswordExpired bool `json:"passwordExpired"` Email string `json:"email"` Department string `json:"department"` Description string `json:"description"` } -func (g *User) BeforeCreate(tx *gorm.DB) (err error) { - g.PasswordUpdatedAt = time.Now() - return nil -} - -// -//// Deprecated: Policy is deprecated, use Permission instead. -//type Policy = struct { -// ID string `json:"id"` -// Name string `json:"name"` -// Create bool `json:"create"` -// CreatePriviledge string `json:"createPriviledge"` -// Update bool `json:"update"` -// UpdatePriviledge string `json:"updatePriviledge"` -// Read bool `json:"read"` -// ReadPriviledge string `json:"readPriviledge"` -// Delete bool `json:"delete"` -// DeletePriviledge string `json:"deletePriviledge"` -// Creator string `json:"creator"` -// CreatedAt time.Time `json:"createdAt"` -// UpdatedAt time.Time `json:"updatedAt"` -//} - type CreateUserRequest struct { AccountId string `json:"accountId" validate:"required"` Password string `json:"password" validate:"required"` @@ -60,45 +54,38 @@ type CreateUserRequest struct { Description string `json:"description" validate:"min=0,max=100"` } -type SimpleRoleResponse = struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` -} - type SimpleUserResponse struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role SimpleRoleResponse `json:"role"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` } type CreateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` } `json:"user"` } type GetUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } @@ -107,17 +94,17 @@ type ListUserResponse struct { Pagination PaginationResponse `json:"pagination"` } type ListUserBody struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type UpdateUserRequest struct { @@ -130,28 +117,28 @@ type UpdateUserRequest struct { type UpdateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } type GetMyProfileResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` } `json:"user"` } type UpdateMyProfileRequest struct { @@ -163,13 +150,13 @@ type UpdateMyProfileRequest struct { type UpdateMyProfileResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` } `json:"user"` } From d61c4cb6aadba9e43025273220fcad5421daa3d3 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 13 Mar 2024 11:20:21 +0900 Subject: [PATCH 110/502] feature. workarround fixes for policy-template --- internal/database/database.go | 31 +++-- internal/delivery/http/policy-template.go | 3 +- internal/model/dashboard.go | 34 +----- internal/model/policy-template.go | 48 ++++++++ internal/model/stack.go | 2 +- internal/repository/policy-template.go | 135 +++++++++------------- internal/usecase/dashboard.go | 18 +-- internal/usecase/policy-template.go | 45 +++++--- pkg/domain/dashboard.go | 27 +++++ pkg/domain/policy-template.go | 2 + 10 files changed, 187 insertions(+), 158 deletions(-) create mode 100644 internal/model/policy-template.go diff --git a/internal/database/database.go b/internal/database/database.go index 6ed0af45..4c34a427 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -138,6 +138,20 @@ func migrateSchema(db *gorm.DB) error { return err } + // Audit + if err := db.AutoMigrate(&model.Audit{}); err != nil { + return err + } + + // PolicyTemplate + if err := db.AutoMigrate(&model.PolicyTemplateSupportedVersion{}); err != nil { + return err + } + + if err := db.AutoMigrate(&model.PolicyTemplate{}); err != nil { + return err + } + return nil } @@ -180,22 +194,5 @@ func EnsureDefaultRows(db *gorm.DB) error { } } -<<<<<<< Updated upstream - // Audit - if err := db.AutoMigrate(&repository.Audit{}); err != nil { - return err - } - - // PolicyTemplate - if err := db.AutoMigrate(&repository.PolicyTemplateSupportedVersion{}); err != nil { - return err - } - - if err := db.AutoMigrate(&repository.PolicyTemplate{}); err != nil { - return err - } - -======= ->>>>>>> Stashed changes return nil } diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 8126e00f..e747a98f 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -67,7 +68,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h return } - var dto domain.PolicyTemplate + var dto model.PolicyTemplate if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/model/dashboard.go b/internal/model/dashboard.go index 618f24be..3cb73ce4 100644 --- a/internal/model/dashboard.go +++ b/internal/model/dashboard.go @@ -1,34 +1,4 @@ package model -import ( - "time" - - "github.com/openinfradev/tks-api/pkg/domain" -) - -// 내부 -type DashboardChart struct { - ChartType domain.ChartType - OrganizationId string - Name string - Description string - Duration string // 1d, 7d, 30d ... - Interval string // 1h, 1d, ... - Year string - Month string - ChartData domain.ChartData - UpdatedAt time.Time -} - -type DashboardStack struct { - ID domain.StackId - Name string - Description string - Status string - StatusDesc string - Cpu string - Memory string - Storage string - CreatedAt time.Time - UpdatedAt time.Time -} +// Dashboard 는 DB repository 접근이 없이 외부 데이터만을 참조하므로, 일단 pkg/domain 의 model 을 사용하도록 해둡니다. +// 즉, usecase 에서 직접 pkg/domain 을 참조하도록 해 두었습니다. diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go new file mode 100644 index 00000000..430c4b7d --- /dev/null +++ b/internal/model/policy-template.go @@ -0,0 +1,48 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +type PolicyTemplateSupportedVersion struct { + gorm.Model + + PolicyTemplateId uuid.UUID `gorm:"index:template_version,unique"` + Version string `gorm:"index:template_version,unique"` + + ParameterSchema string `gorm:"type:text"` + Rego string `gorm:"type:text"` + Libs string `gorm:"type:text"` +} + +type PolicyTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` + Type string // Org or Tks + Name string + Version string + SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` + Description string + Kind string + Deprecated bool + Mandatory bool // Tks 인 경우에는 무시 + Severity string + PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organiations;"` + TemplateName string `gorm:"-:all" json:"templateName"` + ParametersSchema []domain.ParameterDef `gorm:"-:all" json:"parametersSchema,omitempty"` + Rego string `gorm:"-:all"` + Libs []string `gorm:"-:all"` + PermittedOrganizationIds []string `gorm:"-:all"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/stack.go b/internal/model/stack.go index 7d52f37a..72300ee5 100644 --- a/internal/model/stack.go +++ b/internal/model/stack.go @@ -29,7 +29,7 @@ type Stack = struct { Updator User Favorited bool ClusterEndpoint string - Resource DashboardStack + Resource domain.DashboardStack } type StackConf struct { diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index bc12f8fe..7500369b 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -16,18 +17,18 @@ import ( ) type IPolicyTemplateRepository interface { - Create(dto domain.PolicyTemplate) (policyTemplateId uuid.UUID, err error) + Create(dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) Update(dto domain.UpdatePolicyTemplateUpdate) (err error) - Fetch(pg *pagination.Pagination) (out []domain.PolicyTemplate, err error) - GetByName(policyTemplateName string) (out *domain.PolicyTemplate, err error) - GetByKind(policyTemplateKind string) (out *domain.PolicyTemplate, err error) - GetByID(policyTemplateId uuid.UUID) (out *domain.PolicyTemplate, err error) + Fetch(pg *pagination.Pagination) (out []model.PolicyTemplate, err error) + GetByName(policyTemplateName string) (out *model.PolicyTemplate, err error) + GetByKind(policyTemplateKind string) (out *model.PolicyTemplate, err error) + GetByID(policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) Delete(policyTemplateId uuid.UUID) (err error) ExistByName(policyTemplateName string) (exist bool, err error) ExistByKind(policyTemplateKind string) (exist bool, err error) ExistByID(policyTemplateId uuid.UUID) (exist bool, err error) ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) - GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) + GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) } @@ -42,54 +43,18 @@ func NewPolicyTemplateRepository(db *gorm.DB) IPolicyTemplateRepository { } } -type PolicyTemplateSupportedVersion struct { - gorm.Model - - PolicyTemplateId uuid.UUID `gorm:"index:template_version,unique"` - Version string `gorm:"index:template_version,unique"` - - ParameterSchema string `gorm:"type:text"` - Rego string `gorm:"type:text"` - Libs string `gorm:"type:text"` -} - -type PolicyTemplate struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` - Type string // Org or Tks - Name string - Version string - SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` - Description string - Kind string - Deprecated bool - Mandatory bool // Tks 인 경우에는 무시 - Severity string - PermittedOrganizations []domain.Organization `gorm:"many2many:policy_template_permitted_organiations;"` - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - -func (r *PolicyTemplateRepository) Create(dto domain.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { +func (r *PolicyTemplateRepository) Create(dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { jsonByte, err := json.Marshal(dto.ParametersSchema) if err != nil { return uuid.Nil, err } - policyTemplate := PolicyTemplate{ + policyTemplate := model.PolicyTemplate{ Type: "tks", Name: dto.TemplateName, Version: "v1.0.0", - SupportedVersions: []PolicyTemplateSupportedVersion{ + SupportedVersions: []model.PolicyTemplateSupportedVersion{ { Version: "v1.0.0", ParameterSchema: string(jsonByte), @@ -111,9 +76,9 @@ func (r *PolicyTemplateRepository) Create(dto domain.PolicyTemplate) (policyTemp } if dto.PermittedOrganizationIds != nil { - permittedOrganizations := make([]domain.Organization, len(dto.PermittedOrganizationIds)) + permittedOrganizations := make([]model.Organization, len(dto.PermittedOrganizationIds)) for i, permittedOrganizationId := range dto.PermittedOrganizationIds { - permittedOrganizations[i] = domain.Organization{ID: permittedOrganizationId} + permittedOrganizations[i] = model.Organization{ID: permittedOrganizationId} } err = tx.Model(&policyTemplate).Association("PermittedOrganizations").Replace(permittedOrganizations) @@ -156,14 +121,14 @@ func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) fmt.Printf("--updateMap=%+v\n--", updateMap) - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate policyTemplate.ID = dto.ID return r.db.Transaction(func(tx *gorm.DB) error { if dto.PermittedOrganizationIds != nil { - permittedOrganizations := make([]domain.Organization, len(*dto.PermittedOrganizationIds)) + permittedOrganizations := make([]model.Organization, len(*dto.PermittedOrganizationIds)) for i, permittedOrganizationId := range *dto.PermittedOrganizationIds { - permittedOrganizations[i] = domain.Organization{ID: permittedOrganizationId} + permittedOrganizations[i] = model.Organization{ID: permittedOrganizationId} } err = r.db.Model(&policyTemplate).Limit(1). @@ -189,20 +154,20 @@ func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) }) } -func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain.PolicyTemplate, err error) { - var policyTemplates []PolicyTemplate +func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.PolicyTemplate, err error) { + var policyTemplates []model.PolicyTemplate if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations).Model(&PolicyTemplate{}). + _, res := pg.Fetch(r.db.Preload(clause.Associations).Model(&model.PolicyTemplate{}). Where("type = 'tks'"), &policyTemplates) if res.Error != nil { return nil, res.Error } for _, policyTemplate := range policyTemplates { - var policyTemplateVersion PolicyTemplateSupportedVersion + var policyTemplateVersion model.PolicyTemplateSupportedVersion res = r.db. Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). First(&policyTemplateVersion) @@ -221,7 +186,7 @@ func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []domai return out, nil } -func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTemplate, policyTemplateVersion PolicyTemplateSupportedVersion) (out domain.PolicyTemplate) { +func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.PolicyTemplate, policyTemplateVersion model.PolicyTemplateSupportedVersion) (out model.PolicyTemplate) { if err := serializer.Map(policyTemplate.Model, &out); err != nil { log.Error(err) } @@ -229,7 +194,7 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTe log.Error(err) } out.TemplateName = policyTemplate.Name - out.ID = domain.PolicyTemplateId(policyTemplate.ID.String()) + out.ID = policyTemplate.ID var schemas []domain.ParameterDef @@ -241,14 +206,20 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTe } } - out.PermittedOrganizations = make([]domain.PermittedOrganization, len(policyTemplate.PermittedOrganizations)) - for i, org := range policyTemplate.PermittedOrganizations { - out.PermittedOrganizations[i] = domain.PermittedOrganization{ - OrganizationId: org.ID, - OrganizationName: org.Name, - Permitted: true, + // ktkfree : 이 부분은 재 구현 부탁 드립니다. + // PermittedOrganizations 필드가 model 과 response 를 위한 객체의 형이 다르네요. + // 아울러 reflect 는 repository 가 아닌 usecase 에 표현되는게 더 좋겠습니다. + + /* + out.PermittedOrganizations = make([]domain.PermittedOrganization, len(policyTemplate.PermittedOrganizations)) + for i, org := range policyTemplate.PermittedOrganizations { + out.PermittedOrganizations[i] = domain.PermittedOrganization{ + OrganizationId: org.ID, + OrganizationName: org.Name, + Permitted: true, + } } - } + */ out.Rego = policyTemplateVersion.Rego out.Libs = strings.Split(policyTemplateVersion.Libs, "---\n") @@ -259,7 +230,7 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTe func (r *PolicyTemplateRepository) ExistsBy(key string, value interface{}) (exists bool, err error) { query := fmt.Sprintf("%s = ?", key) - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate res := r.db.Where(query, value). First(&policyTemplate) @@ -288,10 +259,10 @@ func (r *PolicyTemplateRepository) ExistByID(policyTemplateId uuid.UUID) (exist return r.ExistsBy("id", policyTemplateId) } -func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *domain.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *model.PolicyTemplate, err error) { query := fmt.Sprintf("%s = ?", key) - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate res := r.db.Preload(clause.Associations).Where(query, value). First(&policyTemplate) @@ -305,7 +276,7 @@ func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *do } } - var policyTemplateVersion PolicyTemplateSupportedVersion + var policyTemplateVersion model.PolicyTemplateSupportedVersion res = r.db.Limit(1). Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). First(&policyTemplateVersion) @@ -327,7 +298,7 @@ func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *do return &result, nil } -func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *domain.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) { return r.GetBy("id", policyTemplateId) // var policyTemplate PolicyTemplate @@ -349,7 +320,7 @@ func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *dom // return &result, nil } -func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *domain.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *model.PolicyTemplate, err error) { return r.GetBy("name", policyTemplateName) // var policyTemplate PolicyTemplate @@ -371,21 +342,21 @@ func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *do // return &result, nil } -func (r *PolicyTemplateRepository) GetByKind(policyTemplateKind string) (out *domain.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByKind(policyTemplateKind string) (out *model.PolicyTemplate, err error) { return r.GetBy("kind", policyTemplateKind) } func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error) { return r.db.Transaction(func(tx *gorm.DB) error { - if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&PolicyTemplateSupportedVersion{}).Error; err != nil { + if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&model.PolicyTemplateSupportedVersion{}).Error; err != nil { return err } - if err := tx.Model(&PolicyTemplate{ID: policyTemplateId}).Association("PermittedOrganizations").Clear(); err != nil { + if err := tx.Model(&model.PolicyTemplate{ID: policyTemplateId}).Association("PermittedOrganizations").Clear(); err != nil { return err } - if err := tx.Where("id = ?", policyTemplateId).Delete(&PolicyTemplate{}).Error; err != nil { + if err := tx.Where("id = ?", policyTemplateId).Delete(&model.PolicyTemplate{}).Error; err != nil { return err } @@ -394,7 +365,7 @@ func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error } func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { - var supportedVersions []PolicyTemplateSupportedVersion + var supportedVersions []model.PolicyTemplateSupportedVersion res := r.db.Where("policy_template_id = ?", policyTemplateId).Find(&supportedVersions) if res.Error != nil { @@ -420,8 +391,8 @@ func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId u return result, nil } -func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) { - var policyTemplateVersion PolicyTemplateSupportedVersion +func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { + var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db. Where("policy_template_id = ? and version = ?", policyTemplateId, version). First(&policyTemplateVersion) @@ -435,7 +406,7 @@ func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uui } } - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate res = r.db. Where("id = ?", policyTemplateId). First(&policyTemplate) @@ -455,7 +426,7 @@ func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uui } func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) { - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate res := r.db.Select("version").First(&policyTemplate) if res.Error != nil { @@ -475,7 +446,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId // TODO: Operator에 현재 버전 사용중인 정책이 있는지 체크 필요 - var policyTemplateVersion PolicyTemplateSupportedVersion + var policyTemplateVersion model.PolicyTemplateSupportedVersion res = r.db.Where("policy_template_id = ? and version = ?", policyTemplateId, version). Delete(&policyTemplateVersion) if res.Error != nil { @@ -492,7 +463,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId } func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { - var policyTemplateVersion PolicyTemplateSupportedVersion + var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db.Limit(1). Where("policy_template_id = ? and version = ?", policyTemplateId, version). First(&policyTemplateVersion) @@ -525,7 +496,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId return "", parseErr } - newPolicyTemplateVersion := &PolicyTemplateSupportedVersion{ + newPolicyTemplateVersion := &model.PolicyTemplateSupportedVersion{ PolicyTemplateId: policyTemplateId, Version: newVersion, Rego: rego, @@ -538,7 +509,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId return err } - if err := tx.Model(&PolicyTemplate{}).Where("id = ?", policyTemplateId).Update("version", newVersion).Error; err != nil { + if err := tx.Model(&model.PolicyTemplate{}).Where("id = ?", policyTemplateId).Update("version", newVersion).Error; err != nil { return err } diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index e6e17c6f..a4f271a8 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -27,8 +27,8 @@ import ( ) type IDashboardUsecase interface { - GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (res []model.DashboardChart, err error) - GetStacks(ctx context.Context, organizationId string) (out []model.DashboardStack, err error) + GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (res []domain.DashboardChart, err error) + GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) GetResources(ctx context.Context, organizationId string) (out domain.DashboardResource, err error) } @@ -50,7 +50,7 @@ func NewDashboardUsecase(r repository.Repository, cache *gcache.Cache) IDashboar } } -func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (out []model.DashboardChart, err error) { +func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (out []domain.DashboardChart, err error) { _, err = u.organizationRepo.Get(organizationId) if err != nil { return nil, errors.Wrap(err, "invalid organization") @@ -72,7 +72,7 @@ func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, return } -func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) (out []model.DashboardStack, err error) { +func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) { clusters, err := u.clusterRepo.FetchByOrganizationId(organizationId, uuid.Nil, nil) if err != nil { return out, err @@ -104,7 +104,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) return nil, err } stack := reflectClusterToStack(cluster, appGroups) - dashboardStack := model.DashboardStack{} + dashboardStack := domain.DashboardStack{} if err := serializer.Map(stack, &dashboardStack); err != nil { log.InfoWithContext(ctx, err) } @@ -222,7 +222,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri return } -func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartType string, duration string, interval string, year string, month string) (res model.DashboardChart, err error) { +func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartType string, duration string, interval string, year string, month string) (res domain.DashboardChart, err error) { thanosUrl, err := u.getThanosUrl(organizationId) if err != nil { log.Error(err) @@ -327,7 +327,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy chartData.YAxis = nil chartData.PodCounts = podCounts - return model.DashboardChart{ + return domain.DashboardChart{ ChartType: domain.ChartType_POD_CALENDAR, OrganizationId: organizationId, Name: "POD 기동 현황", @@ -338,7 +338,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy UpdatedAt: time.Now(), }, nil default: - return model.DashboardChart{}, fmt.Errorf("No data") + return domain.DashboardChart{}, fmt.Errorf("No data") } result, err := thanosClient.FetchRange(query, int(now.Unix())-durationSec, int(now.Unix()), intervalSec) @@ -389,7 +389,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy chartData.XAxis = &domain.Axis{} chartData.XAxis.Data = xAxisData - return model.DashboardChart{ + return domain.DashboardChart{ ChartType: new(domain.ChartType).FromString(chartType), OrganizationId: organizationId, Name: chartType, diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 9f1b8263..7c76a846 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -9,21 +9,23 @@ import ( "github.com/google/uuid" "github.com/open-policy-agent/opa/ast" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" ) type IPolicyTemplateUsecase interface { - Create(ctx context.Context, policyTemplate domain.PolicyTemplate) (policyTemplateId string, err error) - Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []domain.PolicyTemplate, err error) + Create(ctx context.Context, policyTemplate model.PolicyTemplate) (policyTemplateId string, err error) + Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) Update(ctx context.Context, policyTemplateId uuid.UUID, update domain.UpdatePolicyTemplateRequest) (err error) - Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *domain.PolicyTemplate, err error) + Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) IsPolicyTemplateKindExist(ctx context.Context, policyTemplateKind string) (bool, error) - GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) + GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) @@ -45,7 +47,7 @@ func NewPolicyTemplateUsecase(r repository.Repository) IPolicyTemplateUsecase { } } -func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto domain.PolicyTemplate) (policyTemplateId string, err error) { +func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId string, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") @@ -79,7 +81,7 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto domain.PolicyTem return id.String(), nil } -func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []domain.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) { policyTemplates, err = u.repo.Fetch(pg) if err != nil { @@ -99,7 +101,7 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagina } -func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *domain.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetByID(policyTemplateID) if err != nil { @@ -173,7 +175,7 @@ func (u *PolicyTemplateUsecase) IsPolicyTemplateKindExist(ctx context.Context, p return u.repo.ExistByKind(policyTemplateKind) } -func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetPolicyTemplateVersion(policyTemplateId, version) if err != nil { @@ -190,10 +192,12 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, po return policyTemplate, nil } -func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]domain.Organization, permittedOrgIdSet map[string]string, policyTemplate *domain.PolicyTemplate) { +func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]model.Organization, permittedOrgIdSet map[string]string, policyTemplate *model.PolicyTemplate) { // 허용리스트가 비어있으면 모든 Org에 대해서 허용 permitted := len(permittedOrgIdSet) == 0 + log.Info("CHECK HERE ", permitted) + for _, organization := range *organizations { _, ok := permittedOrgIdSet[organization.ID] @@ -201,21 +205,30 @@ func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]doma if !ok { policyTemplate.PermittedOrganizations = append( policyTemplate.PermittedOrganizations, - domain.PermittedOrganization{ - OrganizationId: organization.ID, - OrganizationName: organization.Name, - Permitted: permitted, - }) + + // ktkfree : 역시 이부분 확인 부탁 드립니다. + /* + domain.PermittedOrganization{ + OrganizationId: organization.ID, + OrganizationName: organization.Name, + Permitted: permitted, + } + */ + ) } } } -func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *domain.PolicyTemplate) map[string]string { +func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *model.PolicyTemplate) map[string]string { permittedOrgIdSet := make(map[string]string) for _, permittedOrg := range policyTemplate.PermittedOrganizations { // Set 처리를 위해서 키만 사용, 값은 아무거나 - permittedOrgIdSet[permittedOrg.OrganizationId] = "1" + + // ktkfree : 이부분 확인 부탁 드립니다. + // + //permittedOrgIdSet[permittedOrg.OrganizationId] = "1" + log.Info("CHECK HERE ", permittedOrg) } return permittedOrgIdSet } diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 3560838e..6f3e18e2 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -37,6 +37,33 @@ func (m ChartType) FromString(s string) ChartType { return ChartType_ERROR } +// 내부 +type DashboardChart struct { + ChartType ChartType + OrganizationId string + Name string + Description string + Duration string // 1d, 7d, 30d ... + Interval string // 1h, 1d, ... + Year string + Month string + ChartData ChartData + UpdatedAt time.Time +} + +type DashboardStack struct { + ID StackId + Name string + Description string + Status string + StatusDesc string + Cpu string + Memory string + Storage string + CreatedAt time.Time + UpdatedAt time.Time +} + // [TODO] func (m ChartType) All() (out []string) { for _, v := range chartType { diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index baf8990f..e2dd0810 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -73,6 +73,7 @@ type PolicyTemplateResponse struct { PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` } +/* type PolicyTemplate struct { ID PolicyTemplateId Type string @@ -97,6 +98,7 @@ type PolicyTemplate struct { PermittedOrganizationIds []string // 생성 시에만 사용 PermittedOrganizations []PermittedOrganization } +*/ type CreateCommonPolicyTemplateRequest struct { TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` From b74b9a5b1745d35f8ac0df2d88be2e5eb0596b81 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 13 Mar 2024 14:51:47 +0900 Subject: [PATCH 111/502] feature. add stackTemplate API for user --- api/swagger/docs.go | 27 ----- api/swagger/swagger.json | 27 ----- api/swagger/swagger.yaml | 19 --- internal/delivery/api/endpoint.go | 2 + .../delivery/api/generated_endpoints.go.go | 16 +++ internal/delivery/http/stack-template.go | 114 ++++++++++++++++++ internal/filter/settings.go | 1 + internal/model/stack-template.go | 5 + internal/pagination/pagination.go | 10 +- internal/repository/stack-template.go | 16 +++ internal/route/route.go | 2 + internal/usecase/stack-template.go | 9 ++ 12 files changed, 173 insertions(+), 75 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index b6f5d90f..c4d02ad8 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -9281,9 +9281,6 @@ const docTemplate = `{ "createdAt": { "type": "string" }, - "creator": { - "type": "string" - }, "description": { "type": "string" }, @@ -9307,9 +9304,6 @@ const docTemplate = `{ }, "updatedAt": { "type": "string" - }, - "workflowId": { - "type": "string" } } }, @@ -9365,7 +9359,6 @@ const docTemplate = `{ } } }, -<<<<<<< Updated upstream "github_com_openinfradev_tks-api_pkg_domain.ParameterDef": { "type": "object", "properties": { @@ -9389,10 +9382,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Permission": { -======= "github_com_openinfradev_tks-api_pkg_domain.PermissionResponse": { ->>>>>>> Stashed changes "type": "object", "properties": { "ID": { @@ -10022,20 +10012,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -10079,9 +10055,6 @@ const docTemplate = `{ }, "name": { "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 15aaf32b..5b5e092f 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -9275,9 +9275,6 @@ "createdAt": { "type": "string" }, - "creator": { - "type": "string" - }, "description": { "type": "string" }, @@ -9301,9 +9298,6 @@ }, "updatedAt": { "type": "string" - }, - "workflowId": { - "type": "string" } } }, @@ -9359,7 +9353,6 @@ } } }, -<<<<<<< Updated upstream "github_com_openinfradev_tks-api_pkg_domain.ParameterDef": { "type": "object", "properties": { @@ -9383,10 +9376,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Permission": { -======= "github_com_openinfradev_tks-api_pkg_domain.PermissionResponse": { ->>>>>>> Stashed changes "type": "object", "properties": { "ID": { @@ -10016,20 +10006,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -10073,9 +10049,6 @@ }, "name": { "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 11ad7868..eaeae4bc 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1802,8 +1802,6 @@ definitions: properties: createdAt: type: string - creator: - type: string description: type: string id: @@ -1820,8 +1818,6 @@ definitions: type: string updatedAt: type: string - workflowId: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus: enum: @@ -1862,7 +1858,6 @@ definitions: totalRows: type: integer type: object -<<<<<<< Updated upstream github_com_openinfradev_tks-api_pkg_domain.ParameterDef: properties: children: @@ -1878,10 +1873,7 @@ definitions: type: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.Permission: -======= github_com_openinfradev_tks-api_pkg_domain.PermissionResponse: ->>>>>>> Stashed changes properties: ID: type: string @@ -2302,15 +2294,6 @@ definitions: name: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse: - properties: - description: - type: string - id: - type: string - name: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse: properties: cloudService: @@ -2340,8 +2323,6 @@ definitions: type: string name: type: string - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' type: object github_com_openinfradev_tks-api_pkg_domain.StackConfResponse: properties: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 9d7c0966..c4d1a85b 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -102,6 +102,8 @@ const ( Admin_UpdateStackTemplate Admin_DeleteStackTemplate Admin_UpdateStackTemplateOrganizations + GetOrganizationStackTemplates + GetOrganizationStackTemplate // Dashboard GetChartsDashboard // 대시보드/대시보드/조회 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index aeea2305..32a81fb6 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -303,6 +303,14 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, + GetOrganizationStackTemplates: { + Name: "GetOrganizationStackTemplates", + Group: "StackTemplate", + }, + GetOrganizationStackTemplate: { + Name: "GetOrganizationStackTemplate", + Group: "StackTemplate", + }, GetChartsDashboard: { Name: "GetChartsDashboard", Group: "Dashboard", @@ -880,6 +888,10 @@ func (e Endpoint) String() string { return "Admin_DeleteStackTemplate" case Admin_UpdateStackTemplateOrganizations: return "Admin_UpdateStackTemplateOrganizations" + case GetOrganizationStackTemplates: + return "GetOrganizationStackTemplates" + case GetOrganizationStackTemplate: + return "GetOrganizationStackTemplate" case GetChartsDashboard: return "GetChartsDashboard" case GetChartDashboard: @@ -1248,6 +1260,10 @@ func GetEndpoint(name string) Endpoint { return Admin_DeleteStackTemplate case "Admin_UpdateStackTemplateOrganizations": return Admin_UpdateStackTemplateOrganizations + case "GetOrganizationStackTemplates": + return GetOrganizationStackTemplates + case "GetOrganizationStackTemplate": + return GetOrganizationStackTemplate case "GetChartsDashboard": return GetChartsDashboard case "GetChartDashboard": diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 1bbb42ce..4fbb4a7c 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -301,3 +301,117 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW } ResponseJSON(w, r, http.StatusOK, nil) } + +// GetOrganizationStackTemplates godoc +// +// @Tags StackTemplates +// @Summary Get Organization StackTemplates +// @Description Get Organization StackTemplates +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetStackTemplatesResponse +// @Router /organizations/{organizationId}/stack-templates [get] +// @Security JWT +func (h *StackTemplateHandler) GetOrganizationStackTemplates(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + stackTemplates, err := h.usecase.FetchWithOrganization(r.Context(), organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetStackTemplatesResponse + out.StackTemplates = make([]domain.StackTemplateResponse, len(stackTemplates)) + for i, stackTemplate := range stackTemplates { + if err := serializer.Map(stackTemplate, &out.StackTemplates[i]); err != nil { + log.InfoWithContext(r.Context(), err) + } + + out.StackTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) + for j, organization := range stackTemplate.Organizations { + if err := serializer.Map(organization, &out.StackTemplates[i].Organizations[j]); err != nil { + log.InfoWithContext(r.Context(), err) + } + } + + err := json.Unmarshal(stackTemplate.Services, &out.StackTemplates[i].Services) + if err != nil { + log.ErrorWithContext(r.Context(), err) + } + } + + if out.Pagination, err = pg.Response(); err != nil { + log.InfoWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetOrganizationStackTemplate godoc +// +// @Tags StackTemplates +// @Summary Get Organization StackTemplate +// @Description Get Organization StackTemplate +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetStackTemplateResponse +// @Router /organizations/{organizationId}/stack-templates/{stackTemplateId} [get] +// @Security JWT +func (h *StackTemplateHandler) GetOrganizationStackTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + _, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + strId, ok := vars["stackTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + stackTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + stackTemplate, err := h.usecase.Get(r.Context(), stackTemplateId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetStackTemplateResponse + if err := serializer.Map(stackTemplate, &out.StackTemplate); err != nil { + log.InfoWithContext(r.Context(), err) + } + + out.StackTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) + for i, organization := range stackTemplate.Organizations { + if err := serializer.Map(organization, &out.StackTemplate.Organizations[i]); err != nil { + log.InfoWithContext(r.Context(), err) + } + } + + err = json.Unmarshal(stackTemplate.Services, &out.StackTemplate.Services) + if err != nil { + log.ErrorWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/filter/settings.go b/internal/filter/settings.go index 6634545d..4e06fc48 100644 --- a/internal/filter/settings.go +++ b/internal/filter/settings.go @@ -316,6 +316,7 @@ func getField(field string, sch *schema.Schema, blacklist *Blacklist) (*schema.F if !ok || (relation.Type != schema.HasOne && relation.Type != schema.BelongsTo) { return nil, nil, "" } + s = relation.FieldSchema if blacklist != nil { blacklist = blacklist.Relations[v] diff --git a/internal/model/stack-template.go b/internal/model/stack-template.go index 3bdda2f8..c74cad06 100644 --- a/internal/model/stack-template.go +++ b/internal/model/stack-template.go @@ -33,3 +33,8 @@ func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { c.ID = uuid.New() return nil } + +type StackTemplateOrganization struct { + StackTemplateId uuid.UUID `gorm:"primarykey"` + OrganizationId string `gorm:"primarykey"` +} diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 4b32fc39..591a498c 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -86,6 +86,10 @@ func (p *Pagination) GetFilters() []Filter { return p.Filters } +func (p *Pagination) AddFilter(f Filter) { + p.Filters = append(p.Filters, f) +} + func (p *Pagination) MakePaginationRequest() { if p.PaginationRequest == nil { p.PaginationRequest = &goyave.Request{} @@ -116,9 +120,11 @@ func (p *Pagination) MakePaginationRequest() { } pgSorts = append(pgSorts, &pgSort) + pgJoins := filter.Join{} + p.PaginationRequest.Data = map[string]interface{}{ - "filter": pgFilters, - //"join": pgJoins, + "filter": pgFilters, + "join": pgJoins, "page": p.Page, "per_page": p.Limit, "sort": pgSorts, diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 866df5cc..103aec44 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -13,6 +13,7 @@ import ( type IStackTemplateRepository interface { Get(stackTemplateId uuid.UUID) (model.StackTemplate, error) Fetch(pg *pagination.Pagination) ([]model.StackTemplate, error) + FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) Update(dto model.StackTemplate) (err error) Delete(dto model.StackTemplate) (err error) @@ -50,6 +51,21 @@ func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []model. return } +func (r *StackTemplateRepository) FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch( + r.db.Preload(clause.Associations). + Joins("JOIN stack_template_organizations ON stack_template_organizations.stack_template_id = stack_templates.id AND stack_template_organizations.organization_id = ?", organizationId), + &out) + if res.Error != nil { + return nil, res.Error + } + return +} + func (r *StackTemplateRepository) Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { res := r.db.Create(&dto) if res.Error != nil { diff --git a/internal/route/route.go b/internal/route/route.go index c28e1da8..573ca3a1 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -187,6 +187,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}/organizations", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplateOrganizations, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplateOrganizations))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.GetOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetOrganizationStackTemplate, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplate))).Methods(http.MethodGet) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index a7986497..4c672e7a 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -17,6 +17,7 @@ import ( type IStackTemplateUsecase interface { Get(ctx context.Context, stackTemplateId uuid.UUID) (model.StackTemplate, error) Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.StackTemplate, error) + FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.StackTemplate, error) Create(ctx context.Context, dto model.StackTemplate) (stackTemplate uuid.UUID, err error) Update(ctx context.Context, dto model.StackTemplate) error Delete(ctx context.Context, dto model.StackTemplate) error @@ -106,6 +107,14 @@ func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Paginat return res, nil } +func (u *StackTemplateUsecase) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (res []model.StackTemplate, err error) { + res, err = u.repo.FetchWithOrganization(organizationId, pg) + if err != nil { + return nil, err + } + return res, nil +} + func (u *StackTemplateUsecase) Delete(ctx context.Context, dto model.StackTemplate) (err error) { return nil } From e30947c92a3d41efb378bfecfb931df0ae83c9d7 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 13 Mar 2024 16:14:09 +0900 Subject: [PATCH 112/502] feature. add api to audits --- internal/delivery/api/endpoint.go | 2 +- internal/delivery/http/cloud-account.go | 6 +- internal/delivery/http/handler.go | 2 + internal/delivery/http/organization.go | 7 +- internal/middleware/audit/audit-map.go | 88 +++++++++++++++++++++++-- pkg/domain/cloud-account.go | 4 ++ pkg/domain/organization.go | 4 ++ 7 files changed, 104 insertions(+), 9 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index c4d1a85b..4c6a3bdd 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -121,7 +121,7 @@ const ( // Stack GetStacks // 스택관리/조회 - CreateStack // // 스택관리/생성 + CreateStack // 스택관리/생성 CheckStackName // 스택관리/조회 GetStack // 스택관리/조회 UpdateStack // 스택관리/수정 diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index d27fa317..5c29a04d 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -296,7 +296,11 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * return } - ResponseJSON(w, r, http.StatusOK, nil) + out := domain.DeleteCloudAccountResponse{ + ID: cloudAccountId, + } + + ResponseJSON(w, r, http.StatusOK, out) } // CheckCloudAccountName godoc diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index 680c338d..d2b6e180 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -1,6 +1,7 @@ package http import ( + "bytes" "encoding/json" "errors" "io" @@ -49,6 +50,7 @@ func UnmarshalRequestInput(r *http.Request, in any) error { if err != nil { return err } + r.Body = io.NopCloser(bytes.NewBuffer(body)) err = json.Unmarshal(body, &in) if err != nil { diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index e2d9068d..5f1b2c7f 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -217,7 +217,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Success 200 {object} nil +// @Success 200 {object} DeleteOrganizationResponse // @Router /organizations/{organizationId} [delete] // @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { @@ -254,7 +254,10 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. return } - ResponseJSON(w, r, http.StatusOK, nil) + out := domain.DeleteOrganizationResponse{ + ID: organizationId, + } + ResponseJSON(w, r, http.StatusOK, out) } // UpdateOrganization godoc diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index 85a80d9d..863b71fd 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -19,7 +19,6 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } - if isSuccess(statusCode) { return fmt.Sprintf("스택 [%s]을 생성하였습니다.", input.Name), "" } else { @@ -30,22 +29,101 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } - if isSuccess(statusCode) { return fmt.Sprintf("프로젝트 [%s]를 생성하였습니다.", input.Name), "" } else { - return "프로젝트 [%s]를 생성하는데 실패하였습니다. ", errorText(out) + return fmt.Sprintf("프로젝트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) } }, internalApi.CreateCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateCloudAccountRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } - if isSuccess(statusCode) { return fmt.Sprintf("클라우드 어카운트 [%s]를 생성하였습니다.", input.Name), "" } else { - return "프로젝트 [%s]를 생성하는데 실패하였습니다. ", errorText(out) + return fmt.Sprintf("클라우드 어카운트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.DeleteCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + if isSuccess(statusCode) { + output := domain.DeleteCloudAccountResponse{} + if err := json.Unmarshal(in, &output); err != nil { + log.Error(err) + } + return fmt.Sprintf("클라우드어카운트 [ID:%s]를 삭제하였습니다.", output.ID), "" + } else { + return "클라우드어카운트 [%s]를 삭제하는데 실패하였습니다. ", errorText(out) + } + }, internalApi.CreateUser: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateUserRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("사용자 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("사용자 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.CreateOrganization: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateOrganizationRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("조직 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("조직 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.DeleteOrganization: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + if isSuccess(statusCode) { + output := domain.DeleteOrganizationResponse{} + if err := json.Unmarshal(in, &output); err != nil { + log.Error(err) + } + return fmt.Sprintf("조직 [ID:%s]를 삭제하였습니다.", output.ID), "" + } else { + return "조직 [%s]를 삭제하는데 실패하였습니다. ", errorText(out) + } + }, internalApi.CreateAppServeApp: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateAppServeAppRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("앱서빙 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("앱서빙 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.Admin_CreateStackTemplate: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateStackTemplateRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + log.Info(input) + if isSuccess(statusCode) { + return fmt.Sprintf("스택 템플릿 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("스택 템플릿 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.Admin_CreateUser: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateUserRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("어드민 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.CreatePolicyTemplate: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreatePolicyTemplateRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("폴리시템플릿 [%s]를 생성하였습니다.", input.TemplateName), "" + } else { + return fmt.Sprintf("폴리시템플릿 [%s]을 생성하는데 실패하였습니다.", input.TemplateName), errorText(out) } }, } diff --git a/pkg/domain/cloud-account.go b/pkg/domain/cloud-account.go index 3ec209e3..591356ac 100644 --- a/pkg/domain/cloud-account.go +++ b/pkg/domain/cloud-account.go @@ -131,3 +131,7 @@ type GetCloudAccountResourceQuotaResponse struct { Available bool `json:"available"` ResourceQuota ResourceQuota `json:"resourceQuota"` } + +type DeleteCloudAccountResponse struct { + ID string `json:"id"` +} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 43fb524d..efe7e5e3 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -123,3 +123,7 @@ type UpdateOrganizationResponse struct { type UpdatePrimaryClusterRequest struct { PrimaryClusterId string `json:"primaryClusterId"` } + +type DeleteOrganizationResponse struct { + ID string `json:"id"` +} From ceb699c8d30cf21621f8f2aefaeb91544b7265a4 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 13 Mar 2024 16:19:54 +0900 Subject: [PATCH 113/502] trivial. resolve swagger build error --- api/swagger/docs.go | 105 ++++++++++++++++++++++- api/swagger/swagger.json | 105 ++++++++++++++++++++++- api/swagger/swagger.yaml | 65 ++++++++++++++ internal/delivery/http/organization.go | 2 +- internal/delivery/http/stack-template.go | 2 +- 5 files changed, 275 insertions(+), 4 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index c4d02ad8..0832751f 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -2100,7 +2100,10 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse" + } } } } @@ -5668,6 +5671,98 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/stack-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization StackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization StackTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization StackTemplate", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -8362,6 +8457,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 5b5e092f..c02a7f9a 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -2094,7 +2094,10 @@ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse" + } } } } @@ -5662,6 +5665,98 @@ } } }, + "/organizations/{organizationId}/stack-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization StackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization StackTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization StackTemplate", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks": { "get": { "security": [ @@ -8356,6 +8451,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index eaeae4bc..166168a6 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1207,6 +1207,11 @@ definitions: - accessKeyId - secretAccessKey type: object + github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse: + properties: + id: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.EndpointResponse: properties: createdAt: @@ -4189,6 +4194,8 @@ paths: responses: "200": description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse' security: - JWT: [] summary: Delete organization @@ -6535,6 +6542,64 @@ paths: summary: Update Permissions By Role ID tags: - Permission + /organizations/{organizationId}/stack-templates: + get: + consumes: + - application/json + description: Get Organization StackTemplates + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' + security: + - JWT: [] + summary: Get Organization StackTemplates + tags: + - StackTemplates + /organizations/{organizationId}/stack-templates/{stackTemplateId}: + get: + consumes: + - application/json + description: Get Organization StackTemplate + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse' + security: + - JWT: [] + summary: Get Organization StackTemplate + tags: + - StackTemplates /organizations/{organizationId}/stacks: get: consumes: diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 5f1b2c7f..264a3611 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -217,7 +217,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Success 200 {object} DeleteOrganizationResponse +// @Success 200 {object} domain.DeleteOrganizationResponse // @Router /organizations/{organizationId} [delete] // @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 4fbb4a7c..fdfded2a 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -367,7 +367,7 @@ func (h *StackTemplateHandler) GetOrganizationStackTemplates(w http.ResponseWrit // @Description Get Organization StackTemplate // @Accept json // @Produce json -// @Success 200 {object} domain.GetStackTemplateResponse +// @Success 200 {object} domain.GetStackTemplateResponse // @Router /organizations/{organizationId}/stack-templates/{stackTemplateId} [get] // @Security JWT func (h *StackTemplateHandler) GetOrganizationStackTemplate(w http.ResponseWriter, r *http.Request) { From 24d7d229c373ed455eb25385bed681e48ee4f47d Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 13 Mar 2024 16:34:05 +0900 Subject: [PATCH 114/502] feature. change audit api path "/organizations/" to "/admin" --- api/swagger/docs.go | 366 +++++++++++------------ api/swagger/swagger.json | 366 +++++++++++------------ api/swagger/swagger.yaml | 234 +++++++-------- internal/delivery/http/audit.go | 17 +- internal/delivery/http/stack-template.go | 6 +- internal/repository/audit.go | 6 +- internal/route/route.go | 8 +- internal/usecase/audit.go | 6 +- 8 files changed, 501 insertions(+), 508 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0832751f..4a544877 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -22,6 +22,186 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/admin/audits": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audits", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audits", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filter", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "or", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Create Audit", + "parameters": [ + { + "description": "create audit request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" + } + } + } + } + }, + "/admin/audits/{auditId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audit", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Delete Audit 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -816,7 +996,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "summary": "Create StackTemplate", "parameters": [ { "description": "create stack template request", @@ -918,7 +1098,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "summary": "Update StackTemplate", "parameters": [ { "description": "Update stack template request", @@ -952,7 +1132,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "summary": "Delete StackTemplate", "parameters": [ { "type": "string", @@ -2337,186 +2517,6 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/audits": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Audits", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Get Audits", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filter", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "or", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Create Audit", - "parameters": [ - { - "description": "create audit request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" - } - } - } - } - }, - "/organizations/{organizationId}/audits/{auditId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Get Audit", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Delete Audit 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index c02a7f9a..8872bcf7 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -16,6 +16,186 @@ "host": "tks-api-dev.taco-cat.xyz", "basePath": "/api/1.0/", "paths": { + "/admin/audits": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audits", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audits", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filter", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "or", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Create Audit", + "parameters": [ + { + "description": "create audit request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" + } + } + } + } + }, + "/admin/audits/{auditId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audit", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Delete Audit 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -810,7 +990,7 @@ "tags": [ "StackTemplates" ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "summary": "Create StackTemplate", "parameters": [ { "description": "create stack template request", @@ -912,7 +1092,7 @@ "tags": [ "StackTemplates" ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "summary": "Update StackTemplate", "parameters": [ { "description": "Update stack template request", @@ -946,7 +1126,7 @@ "tags": [ "StackTemplates" ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "summary": "Delete StackTemplate", "parameters": [ { "type": "string", @@ -2331,186 +2511,6 @@ } } }, - "/organizations/{organizationId}/audits": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Audits", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Get Audits", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filter", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "or", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Create Audit", - "parameters": [ - { - "description": "create audit request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" - } - } - } - } - }, - "/organizations/{organizationId}/audits/{auditId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Get Audit", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Delete Audit 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 166168a6..a94fa389 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2925,6 +2925,120 @@ info: title: tks-api service version: "1.0" paths: + /admin/audits: + get: + consumes: + - application/json + description: Get Audits + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filter + type: array + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: or + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse' + security: + - JWT: [] + summary: Get Audits + tags: + - Audits + post: + consumes: + - application/json + description: Create Audit + parameters: + - description: create audit request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse' + security: + - JWT: [] + summary: Create Audit + tags: + - Audits + /admin/audits/{auditId}: + delete: + consumes: + - application/json + description: Delete Audit + parameters: + - description: auditId + in: path + name: auditId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete Audit 'NOT IMPLEMENTED' + tags: + - Audits + get: + consumes: + - application/json + description: Get Audit + parameters: + - description: auditId + in: path + name: auditId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse' + security: + - JWT: [] + summary: Get Audit + tags: + - Audits /admin/organizations/{organizationId}/projects: get: consumes: @@ -3441,7 +3555,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse' security: - JWT: [] - summary: Create StackTemplate 'NOT IMPLEMENTED' + summary: Create StackTemplate tags: - StackTemplates /admin/stack-templates/{stackTemplateId}: @@ -3462,7 +3576,7 @@ paths: description: OK security: - JWT: [] - summary: Delete StackTemplate 'NOT IMPLEMENTED' + summary: Delete StackTemplate tags: - StackTemplates get: @@ -3505,7 +3619,7 @@ paths: description: OK security: - JWT: [] - summary: Update StackTemplate 'NOT IMPLEMENTED' + summary: Update StackTemplate tags: - StackTemplates /admin/stack-templates/{stackTemplateId}/organizations: @@ -4397,120 +4511,6 @@ paths: summary: Create alert action tags: - Alerts - /organizations/{organizationId}/audits: - get: - consumes: - - application/json - description: Get Audits - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filter - type: array - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: or - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse' - security: - - JWT: [] - summary: Get Audits - tags: - - Audits - post: - consumes: - - application/json - description: Create Audit - parameters: - - description: create audit request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse' - security: - - JWT: [] - summary: Create Audit - tags: - - Audits - /organizations/{organizationId}/audits/{auditId}: - delete: - consumes: - - application/json - description: Delete Audit - parameters: - - description: auditId - in: path - name: auditId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete Audit 'NOT IMPLEMENTED' - tags: - - Audits - get: - consumes: - - application/json - description: Get Audit - parameters: - - description: auditId - in: path - name: auditId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse' - security: - - JWT: [] - summary: Get Audit - tags: - - Audits /organizations/{organizationId}/cloud-accounts: get: consumes: diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 395d9112..2a7b2b99 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -34,7 +34,7 @@ func NewAuditHandler(h usecase.Usecase) *AuditHandler { // @Produce json // @Param body body domain.CreateAuditRequest true "create audit request" // @Success 200 {object} domain.CreateAuditResponse -// @Router /organizations/{organizationId}/audits [post] +// @Router /admin/audits [post] // @Security JWT func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) @@ -54,19 +54,12 @@ func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { // @Param filter query []string false "filters" // @Param or query []string false "filters" // @Success 200 {object} domain.GetAuditsResponse -// @Router /organizations/{organizationId}/audits [get] +// @Router /admin/audits [get] // @Security JWT func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) - return - } - urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - audits, err := h.usecase.Fetch(r.Context(), organizationId, pg) + audits, err := h.usecase.Fetch(r.Context(), pg) if err != nil { ErrorJSON(w, r, err) return @@ -96,7 +89,7 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} domain.GetAuditResponse -// @Router /organizations/{organizationId}/audits/{auditId} [get] +// @Router /admin/audits/{auditId} [get] // @Security JWT func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -137,7 +130,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/audits/{auditId} [delete] +// @Router /admin/audits/{auditId} [delete] // @Security JWT func (h *AuditHandler) DeleteAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index fdfded2a..60cad92a 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -31,7 +31,7 @@ func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { // CreateStackTemplate godoc // // @Tags StackTemplates -// @Summary Create StackTemplate 'NOT IMPLEMENTED' +// @Summary Create StackTemplate // @Description Create StackTemplate // @Accept json // @Produce json @@ -171,7 +171,7 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R // UpdateStackTemplate godoc // // @Tags StackTemplates -// @Summary Update StackTemplate 'NOT IMPLEMENTED' +// @Summary Update StackTemplate // @Description Update StackTemplate // @Accept json // @Produce json @@ -210,7 +210,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt // DeleteStackTemplate godoc // // @Tags StackTemplates -// @Summary Delete StackTemplate 'NOT IMPLEMENTED' +// @Summary Delete StackTemplate // @Description Delete StackTemplate // @Accept json // @Produce json diff --git a/internal/repository/audit.go b/internal/repository/audit.go index c93de560..f7e0c5dd 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -14,7 +14,7 @@ import ( // Interfaces type IAuditRepository interface { Get(auditId uuid.UUID) (model.Audit, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]model.Audit, error) + Fetch(pg *pagination.Pagination) ([]model.Audit, error) Create(dto model.Audit) (auditId uuid.UUID, err error) Delete(auditId uuid.UUID) (err error) } @@ -38,12 +38,12 @@ func (r *AuditRepository) Get(auditId uuid.UUID) (out model.Audit, err error) { return } -func (r *AuditRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.Audit, err error) { +func (r *AuditRepository) Fetch(pg *pagination.Pagination) (out []model.Audit, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - db := r.db.Model(&model.Audit{}).Preload(clause.Associations).Where("audits.organization_id = ?", organizationId) + db := r.db.Model(&model.Audit{}).Preload(clause.Associations) _, res := pg.Fetch(db, &out) if res.Error != nil { return nil, res.Error diff --git a/internal/route/route.go b/internal/route/route.go index 573ca3a1..0346e233 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -181,9 +181,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa stackTemplateHandler := delivery.NewStackTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}/organizations", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplateOrganizations, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplateOrganizations))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) @@ -246,9 +246,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) auditHandler := delivery.NewAuditHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/admin/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/admin/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/admin/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) roleHandler := delivery.NewRoleHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.CreateTksRole, http.HandlerFunc(roleHandler.CreateTksRole))).Methods(http.MethodPost) diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index 23744826..0e3e5165 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -13,7 +13,7 @@ import ( type IAuditUsecase interface { Get(ctx context.Context, auditId uuid.UUID) (model.Audit, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Audit, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.Audit, error) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) Delete(ctx context.Context, dto model.Audit) error } @@ -51,8 +51,8 @@ func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res model.Au return } -func (u *AuditUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (audits []model.Audit, err error) { - audits, err = u.repo.Fetch(organizationId, pg) +func (u *AuditUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (audits []model.Audit, err error) { + audits, err = u.repo.Fetch(pg) if err != nil { return nil, err } From 7b39056bdfbd1c95935107f38c89dd20d649dfba Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 14 Mar 2024 09:28:47 +0900 Subject: [PATCH 115/502] Revert "Merge pull request #275 from openinfradev/refact_pkg" This reverts commit 92dc48e12cba948799c857fd600b1ecf8f61d90e, reversing changes made to 65c56afb3b612e84f4f558380558113094d4fe41. --- api/swagger/docs.go | 1350 +++++++++-------- api/swagger/swagger.json | 1350 +++++++++-------- api/swagger/swagger.yaml | 923 ++++++----- internal/database/database.go | 63 +- internal/delivery/api/endpoint.go | 4 +- .../delivery/api/generated_endpoints.go.go | 16 - internal/delivery/http/alert.go | 3 +- internal/delivery/http/app-group.go | 5 +- internal/delivery/http/app-serve-app.go | 51 +- internal/delivery/http/audit.go | 17 +- internal/delivery/http/auth.go | 5 +- internal/delivery/http/cloud-account.go | 13 +- internal/delivery/http/cluster.go | 34 +- internal/delivery/http/handler.go | 2 - internal/delivery/http/organization.go | 14 +- internal/delivery/http/permission.go | 57 +- internal/delivery/http/policy-template.go | 3 +- internal/delivery/http/role.go | 10 +- internal/delivery/http/stack-template.go | 127 +- internal/delivery/http/stack.go | 15 +- internal/delivery/http/user.go | 21 +- internal/filter/settings.go | 2 - internal/keycloak/keycloak.go | 34 +- internal/middleware/audit/audit-map.go | 88 +- internal/middleware/audit/audit.go | 4 +- internal/model/alert.go | 60 - internal/model/app-group.go | 47 - internal/model/app-serve-app.go | 67 - internal/model/audit.go | 26 - internal/model/cloud-account.go | 38 - internal/model/cluster.go | 84 - internal/model/dashboard.go | 4 - internal/model/end-point.go | 11 - internal/model/organization.go | 21 - internal/model/permission.go | 615 -------- internal/model/policy-template.go | 48 - internal/model/role.go | 27 - internal/model/stack-template.go | 40 - internal/model/stack.go | 45 - internal/model/user.go | 34 - internal/pagination/pagination.go | 14 +- internal/repository/alert.go | 143 +- internal/repository/app-group.go | 127 +- internal/repository/app-serve-app.go | 63 +- internal/repository/audit.go | 63 +- internal/repository/cloud-account.go | 103 +- internal/repository/cluster.go | 183 ++- internal/repository/endpoint.go | 27 +- internal/repository/organization.go | 73 +- internal/repository/permission.go | 26 +- internal/repository/policy-template.go | 135 +- internal/repository/role.go | 51 +- internal/repository/stack-template.go | 117 +- internal/repository/user.go | 104 +- internal/route/route.go | 10 +- internal/serializer/serializer.go | 18 +- internal/usecase/alert.go | 42 +- internal/usecase/app-group.go | 23 +- internal/usecase/app-serve-app.go | 33 +- internal/usecase/audit.go | 22 +- internal/usecase/auth.go | 17 +- internal/usecase/cloud-account.go | 51 +- internal/usecase/cluster.go | 58 +- internal/usecase/dashboard.go | 5 +- internal/usecase/organization.go | 23 +- internal/usecase/permission.go | 54 +- internal/usecase/policy-template.go | 45 +- internal/usecase/role.go | 22 +- internal/usecase/stack-template.go | 44 +- internal/usecase/stack.go | 37 +- internal/usecase/user.go | 50 +- pkg/domain/admin/user.go | 45 +- pkg/domain/alert.go | 44 + pkg/domain/app-group.go | 27 + pkg/domain/app-serve-app.go | 119 +- pkg/domain/audit.go | 18 + pkg/domain/auth.go | 14 +- pkg/domain/cloud-account.go | 30 +- pkg/domain/cluster.go | 30 +- pkg/domain/dashboard.go | 16 +- pkg/domain/endpoint.go | 13 +- pkg/domain/mapper.go | 140 ++ pkg/domain/mapper_test.go | 117 ++ pkg/domain/organization.go | 14 +- pkg/domain/permission.go | 629 +++++++- pkg/domain/policy-template.go | 2 - pkg/domain/project.go | 23 +- pkg/domain/role.go | 31 +- pkg/domain/stack-template.go | 27 + pkg/domain/stack.go | 53 +- pkg/domain/user.go | 181 ++- 91 files changed, 4560 insertions(+), 4174 deletions(-) delete mode 100644 internal/model/alert.go delete mode 100644 internal/model/app-group.go delete mode 100644 internal/model/app-serve-app.go delete mode 100644 internal/model/audit.go delete mode 100644 internal/model/cloud-account.go delete mode 100644 internal/model/cluster.go delete mode 100644 internal/model/dashboard.go delete mode 100644 internal/model/end-point.go delete mode 100644 internal/model/organization.go delete mode 100644 internal/model/permission.go delete mode 100644 internal/model/policy-template.go delete mode 100644 internal/model/role.go delete mode 100644 internal/model/stack-template.go delete mode 100644 internal/model/stack.go delete mode 100644 internal/model/user.go create mode 100644 pkg/domain/mapper.go create mode 100644 pkg/domain/mapper_test.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 4a544877..4464bf58 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -22,186 +22,6 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/admin/audits": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Audits", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Get Audits", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filter", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "or", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Create Audit", - "parameters": [ - { - "description": "create audit request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" - } - } - } - } - }, - "/admin/audits/{auditId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Get Audit", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Delete Audit 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -996,7 +816,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Create StackTemplate", + "summary": "Create StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { "description": "create stack template request", @@ -1098,7 +918,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Update StackTemplate", + "summary": "Update StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { "description": "Update stack template request", @@ -1132,7 +952,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Delete StackTemplate", + "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { "type": "string", @@ -1868,7 +1688,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" } } } @@ -1901,7 +1721,10 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" + } } } } @@ -2282,7 +2105,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" } } } @@ -2517,14 +2340,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/cloud-accounts": { + "/organizations/{organizationId}/audits": { "get": { "security": [ { "JWT": [] } ], - "description": "Get CloudAccounts", + "description": "Get Audits", "consumes": [ "application/json" ], @@ -2532,17 +2355,10 @@ const docTemplate = `{ "application/json" ], "tags": [ - "CloudAccounts" + "Audits" ], - "summary": "Get CloudAccounts", + "summary": "Get Audits", "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, { "type": "string", "description": "pageSize", @@ -2574,7 +2390,17 @@ const docTemplate = `{ }, "collectionFormat": "csv", "description": "filters", - "name": "filters", + "name": "filter", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "or", "in": "query" } ], @@ -2582,7 +2408,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" } } } @@ -2593,7 +2419,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Create CloudAccount", + "description": "Create Audit", "consumes": [ "application/json" ], @@ -2601,24 +2427,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "CloudAccounts" + "Audits" ], - "summary": "Create CloudAccount", + "summary": "Create Audit", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", + "description": "create audit request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" } } ], @@ -2626,20 +2445,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" } } } } }, - "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "/organizations/{organizationId}/audits/{auditId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Check awsAccountId for cloudAccount", + "description": "Get Audit", "consumes": [ "application/json" ], @@ -2647,21 +2466,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "CloudAccounts" + "Audits" ], - "summary": "Check awsAccountId for cloudAccount", + "summary": "Get Audit", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "awsAccountId", - "name": "awsAccountId", + "description": "auditId", + "name": "auditId", "in": "path", "required": true } @@ -2670,20 +2482,211 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" } } } - } - }, - "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Check name for cloudAccount", + "description": "Delete Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Delete Audit 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get CloudAccounts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Get CloudAccounts", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Create CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check awsAccountId for cloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Check awsAccountId for cloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "awsAccountId", + "name": "awsAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for cloudAccount", "consumes": [ "application/json" ], @@ -3768,7 +3771,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" } } } @@ -4435,7 +4438,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" } } } @@ -5624,7 +5627,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" } } } @@ -5671,14 +5674,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stack-templates": { + "/organizations/{organizationId}/stacks": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplates", + "description": "Get Stacks", "consumes": [ "application/json" ], @@ -5686,10 +5689,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "Stacks" ], - "summary": "Get Organization StackTemplates", + "summary": "Get Stacks", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -5715,13 +5725,9 @@ const docTemplate = `{ "in": "query" }, { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", + "type": "string", + "description": "combinedFilter", + "name": "combinedFilter", "in": "query" } ], @@ -5729,20 +5735,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" } } } - } - }, - "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplate", + "description": "Create Stack", "consumes": [ "application/json" ], @@ -5750,27 +5754,45 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "Stacks" + ], + "summary": "Create Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" + } + } ], - "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" } } } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", + "description": "Check name for stack", "consumes": [ "application/json" ], @@ -5780,118 +5802,7 @@ const docTemplate = `{ "tags": [ "Stacks" ], - "summary": "Get Stacks", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Create Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" - } - } - } - } - }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check name for stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Check name for stack", + "summary": "Check name for stack", "parameters": [ { "type": "string", @@ -6550,7 +6461,10 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + } } } } @@ -6618,7 +6532,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" } } } @@ -6706,177 +6620,6 @@ const docTemplate = `{ } }, "definitions": { - "github_com_openinfradev_tks-api_internal_model.AppServeApp": { - "type": "object", - "properties": { - "appServeAppTasks": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask" - } - }, - "appType": { - "description": "appType (spring/springboot)", - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "endpointUrl": { - "description": "endpoint URL of deployed app", - "type": "string" - }, - "grafanaUrl": { - "description": "grafana dashboard URL for deployed app", - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "description": "application name", - "type": "string" - }, - "namespace": { - "description": "application namespace", - "type": "string" - }, - "organizationId": { - "description": "contractId is a contract ID which this app belongs to", - "type": "string" - }, - "previewEndpointUrl": { - "description": "preview svc endpoint URL in B/G deployment", - "type": "string" - }, - "projectId": { - "description": "project ID which this app belongs to", - "type": "string" - }, - "status": { - "description": "status is status of deployed app", - "type": "string" - }, - "targetClusterId": { - "description": "target cluster to which the app is deployed", - "type": "string" - }, - "targetClusterName": { - "description": "target cluster name", - "type": "string" - }, - "type": { - "description": "type (build/deploy/all)", - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_internal_model.AppServeAppTask": { - "type": "object", - "properties": { - "appConfig": { - "description": "java app config", - "type": "string" - }, - "appSecret": { - "description": "java app secret", - "type": "string" - }, - "appServeAppId": { - "description": "ID for appServeApp that this task belongs to", - "type": "string" - }, - "artifactUrl": { - "description": "URL of java app artifact (Eg, Jar)", - "type": "string" - }, - "availableRollback": { - "type": "boolean" - }, - "createdAt": { - "description": "createdAt is a creation timestamp for the application", - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "executablePath": { - "description": "Executable path of app image", - "type": "string" - }, - "extraEnv": { - "description": "env variable list for java app", - "type": "string" - }, - "helmRevision": { - "description": "revision of deployed helm release", - "type": "integer" - }, - "id": { - "type": "string" - }, - "imageUrl": { - "description": "URL of built image for app", - "type": "string" - }, - "output": { - "description": "output for task result", - "type": "string" - }, - "port": { - "description": "java app port", - "type": "string" - }, - "profile": { - "description": "java app profile", - "type": "string" - }, - "pvAccessMode": { - "type": "string" - }, - "pvEnabled": { - "type": "boolean" - }, - "pvMountPath": { - "type": "string" - }, - "pvSize": { - "type": "string" - }, - "pvStorageClass": { - "type": "string" - }, - "resourceSpec": { - "description": "resource spec of app pod", - "type": "string" - }, - "rollbackVersion": { - "description": "rollback target version", - "type": "string" - }, - "status": { - "description": "status is app status", - "type": "string" - }, - "strategy": { - "description": "deployment strategy (eg, rolling-update)", - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "description": "application version", - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { @@ -7085,13 +6828,13 @@ const docTemplate = `{ "AppGroupType_SERVICE_MESH" ] }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeApp": { "type": "object", "properties": { "appServeAppTasks": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" } }, "appType": { @@ -7156,7 +6899,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask": { "type": "object", "properties": { "appConfig": { @@ -7343,6 +7086,9 @@ const docTemplate = `{ }, "user": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "userId": { + "type": "string" } } }, @@ -7412,6 +7158,71 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CloudAccount": { + "type": "object", + "properties": { + "accessKeyId": { + "type": "string" + }, + "awsAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusters": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "createdIAM": { + "type": "boolean" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "secretAccessKey": { + "type": "string" + }, + "sessionToken": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "updatorId": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { @@ -7445,17 +7256,150 @@ const docTemplate = `{ "organizationId": { "type": "string" }, - "resource": { + "resource": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "x-enum-varnames": [ + "CloudAccountStatus_PENDING", + "CloudAccountStatus_CREATING", + "CloudAccountStatus_CREATED", + "CloudAccountStatus_DELETING", + "CloudAccountStatus_DELETED", + "CloudAccountStatus_CREATE_ERROR", + "CloudAccountStatus_DELETE_ERROR" + ] + }, + "github_com_openinfradev_tks-api_pkg_domain.Cluster": { + "type": "object", + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "cloudAccount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount" + }, + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusterType": { + "type": "integer" + }, + "conf": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "favorited": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "isStack": { + "type": "boolean" + }, + "kubeconfig": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate" + }, + "stackTemplateId": { "type": "string" }, "status": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus" + }, + "statusDesc": { "type": "string" }, "updatedAt": { "type": "string" }, "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "updatorId": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterConf": { + "type": "object", + "properties": { + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" } } }, @@ -7564,9 +7508,6 @@ const docTemplate = `{ "description": { "type": "string" }, - "favorited": { - "type": "boolean" - }, "id": { "type": "string" }, @@ -7643,6 +7584,33 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "x-enum-varnames": [ + "ClusterStatus_PENDING", + "ClusterStatus_INSTALLING", + "ClusterStatus_RUNNING", + "ClusterStatus_DELETING", + "ClusterStatus_DELETED", + "ClusterStatus_INSTALL_ERROR", + "ClusterStatus_DELETE_ERROR", + "ClusterStatus_BOOTSTRAPPING", + "ClusterStatus_BOOTSTRAPPED", + "ClusterStatus_BOOTSTRAP_ERROR" + ] + }, "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { @@ -8338,10 +8306,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } @@ -8457,15 +8425,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { "type": "object", "properties": { "createdAt": { @@ -8476,9 +8436,6 @@ const docTemplate = `{ }, "name": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, @@ -8611,7 +8568,7 @@ const docTemplate = `{ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" }, "stages": { "type": "array", @@ -8625,10 +8582,10 @@ const docTemplate = `{ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" }, "appServeAppTask": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" }, "stages": { "type": "array", @@ -8723,14 +8680,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { - "type": "object", - "properties": { - "cluster": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse": { "type": "object", "properties": { @@ -8805,10 +8754,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } @@ -9138,10 +9087,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -9304,10 +9253,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -9349,13 +9298,13 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "passwordExpired": { "type": "boolean" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "token": { "type": "string" @@ -9378,12 +9327,18 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Organization": { "type": "object", "properties": { "createdAt": { "type": "string" }, + "creator": { + "type": "string" + }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "description": { "type": "string" }, @@ -9485,7 +9440,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Permission": { "type": "object", "properties": { "ID": { @@ -9494,15 +9449,24 @@ const docTemplate = `{ "children": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" } }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "endpoints": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" } }, + "id": { + "type": "integer" + }, "is_allowed": { "type": "boolean" }, @@ -9510,39 +9474,42 @@ const docTemplate = `{ "type": "string" }, "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "parent_id": { "type": "string" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "role_id": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse": { + "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { "type": "object", "properties": { "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "security_policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" } } }, @@ -9894,9 +9861,6 @@ const docTemplate = `{ }, "projectRoleName": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, @@ -10018,7 +9982,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Role": { "type": "object", "properties": { "createdAt": { @@ -10027,6 +9991,9 @@ const docTemplate = `{ "creator": { "type": "string" }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "description": { "type": "string" }, @@ -10037,7 +10004,7 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "organizationId": { "type": "string" @@ -10115,6 +10082,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -10158,6 +10139,9 @@ const docTemplate = `{ }, "name": { "type": "string" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" } } }, @@ -10277,6 +10261,86 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackTemplate": { + "type": "object", + "properties": { + "cloudService": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + } + }, + "platform": { + "type": "string" + }, + "serviceIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "services": { + "type": "array", + "items": { + "type": "integer" + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "updatorId": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse": { "type": "object", "properties": { @@ -10542,10 +10606,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } @@ -10613,7 +10677,7 @@ const docTemplate = `{ "permissions": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" } } } @@ -10837,10 +10901,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -10849,6 +10913,62 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.User": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "organizationId": { + "type": "string" + }, + "password": { + "type": "string" + }, + "passwordExpired": { + "type": "boolean" + }, + "passwordUpdatedAt": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "roleId": { + "type": "string" + }, + "token": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ @@ -10938,10 +11058,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -11009,10 +11129,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -11037,6 +11157,18 @@ const docTemplate = `{ "type": "string" } } + }, + "gorm.DeletedAt": { + "type": "object", + "properties": { + "time": { + "type": "string" + }, + "valid": { + "description": "Valid is true if Time is not NULL", + "type": "boolean" + } + } } }, "securityDefinitions": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 8872bcf7..86d8b058 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -16,186 +16,6 @@ "host": "tks-api-dev.taco-cat.xyz", "basePath": "/api/1.0/", "paths": { - "/admin/audits": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Audits", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Get Audits", - "parameters": [ - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filter", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "or", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Create Audit", - "parameters": [ - { - "description": "create audit request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" - } - } - } - } - }, - "/admin/audits/{auditId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Get Audit", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" - } - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Delete Audit 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -990,7 +810,7 @@ "tags": [ "StackTemplates" ], - "summary": "Create StackTemplate", + "summary": "Create StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { "description": "create stack template request", @@ -1092,7 +912,7 @@ "tags": [ "StackTemplates" ], - "summary": "Update StackTemplate", + "summary": "Update StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { "description": "Update stack template request", @@ -1126,7 +946,7 @@ "tags": [ "StackTemplates" ], - "summary": "Delete StackTemplate", + "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", "parameters": [ { "type": "string", @@ -1862,7 +1682,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" } } } @@ -1895,7 +1715,10 @@ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" + } } } } @@ -2276,7 +2099,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" } } } @@ -2511,14 +2334,14 @@ } } }, - "/organizations/{organizationId}/cloud-accounts": { + "/organizations/{organizationId}/audits": { "get": { "security": [ { "JWT": [] } ], - "description": "Get CloudAccounts", + "description": "Get Audits", "consumes": [ "application/json" ], @@ -2526,17 +2349,10 @@ "application/json" ], "tags": [ - "CloudAccounts" + "Audits" ], - "summary": "Get CloudAccounts", + "summary": "Get Audits", "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, { "type": "string", "description": "pageSize", @@ -2568,7 +2384,17 @@ }, "collectionFormat": "csv", "description": "filters", - "name": "filters", + "name": "filter", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "or", "in": "query" } ], @@ -2576,7 +2402,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" } } } @@ -2587,7 +2413,7 @@ "JWT": [] } ], - "description": "Create CloudAccount", + "description": "Create Audit", "consumes": [ "application/json" ], @@ -2595,24 +2421,17 @@ "application/json" ], "tags": [ - "CloudAccounts" + "Audits" ], - "summary": "Create CloudAccount", + "summary": "Create Audit", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", + "description": "create audit request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" } } ], @@ -2620,20 +2439,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" } } } } }, - "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "/organizations/{organizationId}/audits/{auditId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Check awsAccountId for cloudAccount", + "description": "Get Audit", "consumes": [ "application/json" ], @@ -2641,21 +2460,14 @@ "application/json" ], "tags": [ - "CloudAccounts" + "Audits" ], - "summary": "Check awsAccountId for cloudAccount", + "summary": "Get Audit", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "awsAccountId", - "name": "awsAccountId", + "description": "auditId", + "name": "auditId", "in": "path", "required": true } @@ -2664,20 +2476,211 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" } } } - } - }, - "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Check name for cloudAccount", + "description": "Delete Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Delete Audit 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get CloudAccounts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Get CloudAccounts", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create CloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Create CloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check awsAccountId for cloudAccount", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CloudAccounts" + ], + "summary": "Check awsAccountId for cloudAccount", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "awsAccountId", + "name": "awsAccountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" + } + } + } + } + }, + "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for cloudAccount", "consumes": [ "application/json" ], @@ -3762,7 +3765,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" } } } @@ -4429,7 +4432,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" } } } @@ -5618,7 +5621,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" } } } @@ -5665,14 +5668,14 @@ } } }, - "/organizations/{organizationId}/stack-templates": { + "/organizations/{organizationId}/stacks": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplates", + "description": "Get Stacks", "consumes": [ "application/json" ], @@ -5680,10 +5683,17 @@ "application/json" ], "tags": [ - "StackTemplates" + "Stacks" ], - "summary": "Get Organization StackTemplates", + "summary": "Get Stacks", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -5709,13 +5719,9 @@ "in": "query" }, { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", + "type": "string", + "description": "combinedFilter", + "name": "combinedFilter", "in": "query" } ], @@ -5723,20 +5729,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" } } } - } - }, - "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplate", + "description": "Create Stack", "consumes": [ "application/json" ], @@ -5744,27 +5748,45 @@ "application/json" ], "tags": [ - "StackTemplates" + "Stacks" + ], + "summary": "Create Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" + } + } ], - "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" } } } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", + "description": "Check name for stack", "consumes": [ "application/json" ], @@ -5774,118 +5796,7 @@ "tags": [ "Stacks" ], - "summary": "Get Stacks", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Create Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" - } - } - } - } - }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check name for stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Check name for stack", + "summary": "Check name for stack", "parameters": [ { "type": "string", @@ -6544,7 +6455,10 @@ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + } } } } @@ -6612,7 +6526,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" } } } @@ -6700,177 +6614,6 @@ } }, "definitions": { - "github_com_openinfradev_tks-api_internal_model.AppServeApp": { - "type": "object", - "properties": { - "appServeAppTasks": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask" - } - }, - "appType": { - "description": "appType (spring/springboot)", - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "endpointUrl": { - "description": "endpoint URL of deployed app", - "type": "string" - }, - "grafanaUrl": { - "description": "grafana dashboard URL for deployed app", - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "description": "application name", - "type": "string" - }, - "namespace": { - "description": "application namespace", - "type": "string" - }, - "organizationId": { - "description": "contractId is a contract ID which this app belongs to", - "type": "string" - }, - "previewEndpointUrl": { - "description": "preview svc endpoint URL in B/G deployment", - "type": "string" - }, - "projectId": { - "description": "project ID which this app belongs to", - "type": "string" - }, - "status": { - "description": "status is status of deployed app", - "type": "string" - }, - "targetClusterId": { - "description": "target cluster to which the app is deployed", - "type": "string" - }, - "targetClusterName": { - "description": "target cluster name", - "type": "string" - }, - "type": { - "description": "type (build/deploy/all)", - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_internal_model.AppServeAppTask": { - "type": "object", - "properties": { - "appConfig": { - "description": "java app config", - "type": "string" - }, - "appSecret": { - "description": "java app secret", - "type": "string" - }, - "appServeAppId": { - "description": "ID for appServeApp that this task belongs to", - "type": "string" - }, - "artifactUrl": { - "description": "URL of java app artifact (Eg, Jar)", - "type": "string" - }, - "availableRollback": { - "type": "boolean" - }, - "createdAt": { - "description": "createdAt is a creation timestamp for the application", - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "executablePath": { - "description": "Executable path of app image", - "type": "string" - }, - "extraEnv": { - "description": "env variable list for java app", - "type": "string" - }, - "helmRevision": { - "description": "revision of deployed helm release", - "type": "integer" - }, - "id": { - "type": "string" - }, - "imageUrl": { - "description": "URL of built image for app", - "type": "string" - }, - "output": { - "description": "output for task result", - "type": "string" - }, - "port": { - "description": "java app port", - "type": "string" - }, - "profile": { - "description": "java app profile", - "type": "string" - }, - "pvAccessMode": { - "type": "string" - }, - "pvEnabled": { - "type": "boolean" - }, - "pvMountPath": { - "type": "string" - }, - "pvSize": { - "type": "string" - }, - "pvStorageClass": { - "type": "string" - }, - "resourceSpec": { - "description": "resource spec of app pod", - "type": "string" - }, - "rollbackVersion": { - "description": "rollback target version", - "type": "string" - }, - "status": { - "description": "status is app status", - "type": "string" - }, - "strategy": { - "description": "deployment strategy (eg, rolling-update)", - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "description": "application version", - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { @@ -7079,13 +6822,13 @@ "AppGroupType_SERVICE_MESH" ] }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeApp": { "type": "object", "properties": { "appServeAppTasks": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" } }, "appType": { @@ -7150,7 +6893,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask": { "type": "object", "properties": { "appConfig": { @@ -7337,6 +7080,9 @@ }, "user": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "userId": { + "type": "string" } } }, @@ -7406,6 +7152,71 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CloudAccount": { + "type": "object", + "properties": { + "accessKeyId": { + "type": "string" + }, + "awsAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusters": { + "type": "integer" + }, + "createdAt": { + "type": "string" + }, + "createdIAM": { + "type": "boolean" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "secretAccessKey": { + "type": "string" + }, + "sessionToken": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus" + }, + "statusDesc": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "updatorId": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { @@ -7439,17 +7250,150 @@ "organizationId": { "type": "string" }, - "resource": { + "resource": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "x-enum-varnames": [ + "CloudAccountStatus_PENDING", + "CloudAccountStatus_CREATING", + "CloudAccountStatus_CREATED", + "CloudAccountStatus_DELETING", + "CloudAccountStatus_DELETED", + "CloudAccountStatus_CREATE_ERROR", + "CloudAccountStatus_DELETE_ERROR" + ] + }, + "github_com_openinfradev_tks-api_pkg_domain.Cluster": { + "type": "object", + "properties": { + "byoClusterEndpointHost": { + "type": "string" + }, + "byoClusterEndpointPort": { + "type": "integer" + }, + "cloudAccount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount" + }, + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string" + }, + "clusterType": { + "type": "integer" + }, + "conf": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "favorited": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "isStack": { + "type": "boolean" + }, + "kubeconfig": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "stackTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate" + }, + "stackTemplateId": { "type": "string" }, "status": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus" + }, + "statusDesc": { "type": "string" }, "updatedAt": { "type": "string" }, "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "updatorId": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterConf": { + "type": "object", + "properties": { + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" } } }, @@ -7558,9 +7502,6 @@ "description": { "type": "string" }, - "favorited": { - "type": "boolean" - }, "id": { "type": "string" }, @@ -7637,6 +7578,33 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterStatus": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "x-enum-varnames": [ + "ClusterStatus_PENDING", + "ClusterStatus_INSTALLING", + "ClusterStatus_RUNNING", + "ClusterStatus_DELETING", + "ClusterStatus_DELETED", + "ClusterStatus_INSTALL_ERROR", + "ClusterStatus_DELETE_ERROR", + "ClusterStatus_BOOTSTRAPPING", + "ClusterStatus_BOOTSTRAPPED", + "ClusterStatus_BOOTSTRAP_ERROR" + ] + }, "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { @@ -8332,10 +8300,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } @@ -8451,15 +8419,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { "type": "object", "properties": { "createdAt": { @@ -8470,9 +8430,6 @@ }, "name": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, @@ -8605,7 +8562,7 @@ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" }, "stages": { "type": "array", @@ -8619,10 +8576,10 @@ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" }, "appServeAppTask": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" }, "stages": { "type": "array", @@ -8717,14 +8674,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { - "type": "object", - "properties": { - "cluster": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse": { "type": "object", "properties": { @@ -8799,10 +8748,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } @@ -9132,10 +9081,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -9298,10 +9247,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -9343,13 +9292,13 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "passwordExpired": { "type": "boolean" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "token": { "type": "string" @@ -9372,12 +9321,18 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Organization": { "type": "object", "properties": { "createdAt": { "type": "string" }, + "creator": { + "type": "string" + }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "description": { "type": "string" }, @@ -9479,7 +9434,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Permission": { "type": "object", "properties": { "ID": { @@ -9488,15 +9443,24 @@ "children": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" } }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "endpoints": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" } }, + "id": { + "type": "integer" + }, "is_allowed": { "type": "boolean" }, @@ -9504,39 +9468,42 @@ "type": "string" }, "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "parent_id": { "type": "string" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "role_id": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse": { + "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { "type": "object", "properties": { "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "security_policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" }, "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" } } }, @@ -9888,9 +9855,6 @@ }, "projectRoleName": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, @@ -10012,7 +9976,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { + "github_com_openinfradev_tks-api_pkg_domain.Role": { "type": "object", "properties": { "createdAt": { @@ -10021,6 +9985,9 @@ "creator": { "type": "string" }, + "deletedAt": { + "$ref": "#/definitions/gorm.DeletedAt" + }, "description": { "type": "string" }, @@ -10031,7 +9998,7 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "organizationId": { "type": "string" @@ -10109,6 +10076,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -10152,6 +10133,9 @@ }, "name": { "type": "string" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" } } }, @@ -10271,6 +10255,86 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackTemplate": { + "type": "object", + "properties": { + "cloudService": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "creatorId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + } + }, + "platform": { + "type": "string" + }, + "serviceIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "services": { + "type": "array", + "items": { + "type": "integer" + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" + }, + "updatorId": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse": { "type": "object", "properties": { @@ -10536,10 +10600,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" } } } @@ -10607,7 +10671,7 @@ "permissions": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" } } } @@ -10831,10 +10895,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -10843,6 +10907,62 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.User": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "creator": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + }, + "organizationId": { + "type": "string" + }, + "password": { + "type": "string" + }, + "passwordExpired": { + "type": "boolean" + }, + "passwordUpdatedAt": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + }, + "roleId": { + "type": "string" + }, + "token": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ @@ -10932,10 +11052,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -11003,10 +11123,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" }, "updatedAt": { "type": "string" @@ -11031,6 +11151,18 @@ "type": "string" } } + }, + "gorm.DeletedAt": { + "type": "object", + "properties": { + "time": { + "type": "string" + }, + "valid": { + "description": "Valid is true if Time is not NULL", + "type": "boolean" + } + } } }, "securityDefinitions": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index a94fa389..188af9fd 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1,128 +1,5 @@ basePath: /api/1.0/ definitions: - github_com_openinfradev_tks-api_internal_model.AppServeApp: - properties: - appServeAppTasks: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask' - type: array - appType: - description: appType (spring/springboot) - type: string - createdAt: - type: string - deletedAt: - type: string - endpointUrl: - description: endpoint URL of deployed app - type: string - grafanaUrl: - description: grafana dashboard URL for deployed app - type: string - id: - type: string - name: - description: application name - type: string - namespace: - description: application namespace - type: string - organizationId: - description: contractId is a contract ID which this app belongs to - type: string - previewEndpointUrl: - description: preview svc endpoint URL in B/G deployment - type: string - projectId: - description: project ID which this app belongs to - type: string - status: - description: status is status of deployed app - type: string - targetClusterId: - description: target cluster to which the app is deployed - type: string - targetClusterName: - description: target cluster name - type: string - type: - description: type (build/deploy/all) - type: string - updatedAt: - type: string - type: object - github_com_openinfradev_tks-api_internal_model.AppServeAppTask: - properties: - appConfig: - description: java app config - type: string - appSecret: - description: java app secret - type: string - appServeAppId: - description: ID for appServeApp that this task belongs to - type: string - artifactUrl: - description: URL of java app artifact (Eg, Jar) - type: string - availableRollback: - type: boolean - createdAt: - description: createdAt is a creation timestamp for the application - type: string - deletedAt: - type: string - executablePath: - description: Executable path of app image - type: string - extraEnv: - description: env variable list for java app - type: string - helmRevision: - description: revision of deployed helm release - type: integer - id: - type: string - imageUrl: - description: URL of built image for app - type: string - output: - description: output for task result - type: string - port: - description: java app port - type: string - profile: - description: java app profile - type: string - pvAccessMode: - type: string - pvEnabled: - type: boolean - pvMountPath: - type: string - pvSize: - type: string - pvStorageClass: - type: string - resourceSpec: - description: resource spec of app pod - type: string - rollbackVersion: - description: rollback target version - type: string - status: - description: status is app status - type: string - strategy: - description: deployment strategy (eg, rolling-update) - type: string - updatedAt: - type: string - version: - description: application version - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.ActionResponse: properties: body: @@ -266,11 +143,11 @@ definitions: - AppGroupType_UNSPECIFIED - AppGroupType_LMA - AppGroupType_SERVICE_MESH - github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse: + github_com_openinfradev_tks-api_pkg_domain.AppServeApp: properties: appServeAppTasks: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask' type: array appType: description: appType (spring/springboot) @@ -317,7 +194,7 @@ definitions: updatedAt: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse: + github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask: properties: appConfig: description: java app config @@ -454,6 +331,8 @@ definitions: type: string user: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + userId: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.Axis: properties: @@ -497,6 +376,49 @@ definitions: existed: type: boolean type: object + github_com_openinfradev_tks-api_pkg_domain.CloudAccount: + properties: + accessKeyId: + type: string + awsAccountId: + type: string + cloudService: + type: string + clusters: + type: integer + createdAt: + type: string + createdIAM: + type: boolean + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' + creatorId: + type: string + description: + type: string + id: + type: string + name: + type: string + organizationId: + type: string + resource: + type: string + secretAccessKey: + type: string + sessionToken: + type: string + status: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus' + statusDesc: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' + updatorId: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse: properties: awsAccountId: @@ -528,6 +450,98 @@ definitions: updator: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus: + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + type: integer + x-enum-varnames: + - CloudAccountStatus_PENDING + - CloudAccountStatus_CREATING + - CloudAccountStatus_CREATED + - CloudAccountStatus_DELETING + - CloudAccountStatus_DELETED + - CloudAccountStatus_CREATE_ERROR + - CloudAccountStatus_DELETE_ERROR + github_com_openinfradev_tks-api_pkg_domain.Cluster: + properties: + byoClusterEndpointHost: + type: string + byoClusterEndpointPort: + type: integer + cloudAccount: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount' + cloudAccountId: + type: string + cloudService: + type: string + clusterType: + type: integer + conf: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf' + createdAt: + type: string + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' + creatorId: + type: string + description: + type: string + favorited: + type: boolean + id: + type: string + isStack: + type: boolean + kubeconfig: + items: + type: integer + type: array + name: + type: string + organizationId: + type: string + stackTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate' + stackTemplateId: + type: string + status: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus' + statusDesc: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' + updatorId: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.ClusterConf: + properties: + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse: properties: tksCpNode: @@ -597,8 +611,6 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string - favorited: - type: boolean id: type: string isStack: @@ -649,6 +661,30 @@ definitions: tksUserNodeType: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ClusterStatus: + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + type: integer + x-enum-varnames: + - ClusterStatus_PENDING + - ClusterStatus_INSTALLING + - ClusterStatus_RUNNING + - ClusterStatus_DELETING + - ClusterStatus_DELETED + - ClusterStatus_INSTALL_ERROR + - ClusterStatus_DELETE_ERROR + - ClusterStatus_BOOTSTRAPPING + - ClusterStatus_BOOTSTRAPPED + - ClusterStatus_BOOTSTRAP_ERROR github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse: properties: result: @@ -1128,9 +1164,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' type: object type: object github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse: @@ -1207,12 +1243,7 @@ definitions: - accessKeyId - secretAccessKey type: object - github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse: - properties: - id: - type: string - type: object - github_com_openinfradev_tks-api_pkg_domain.EndpointResponse: + github_com_openinfradev_tks-api_pkg_domain.Endpoint: properties: createdAt: type: string @@ -1220,8 +1251,6 @@ definitions: type: string name: type: string - updatedAt: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse: type: object @@ -1309,7 +1338,7 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse: properties: appServeApp: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' stages: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' @@ -1318,9 +1347,9 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse: properties: appServeApp: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' appServeAppTask: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask' stages: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' @@ -1380,11 +1409,6 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode' type: array type: object - github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse: - properties: - cluster: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse' - type: object github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse: properties: clusters: @@ -1433,9 +1457,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' type: object type: object github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse: @@ -1646,9 +1670,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' updatedAt: type: string type: object @@ -1755,9 +1779,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' updatedAt: type: string type: object @@ -1785,11 +1809,11 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' passwordExpired: type: boolean role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' token: type: string type: object @@ -1803,10 +1827,14 @@ definitions: type: array type: object type: object - github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse: + github_com_openinfradev_tks-api_pkg_domain.Organization: properties: createdAt: type: string + creator: + type: string + deletedAt: + $ref: '#/definitions/gorm.DeletedAt' description: type: string id: @@ -1878,45 +1906,53 @@ definitions: type: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.PermissionResponse: + github_com_openinfradev_tks-api_pkg_domain.Permission: properties: ID: type: string children: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' type: array + createdAt: + type: string + deletedAt: + $ref: '#/definitions/gorm.DeletedAt' endpoints: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint' type: array + id: + type: integer is_allowed: type: boolean name: type: string parent: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' parent_id: type: string role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' role_id: type: string + updatedAt: + type: string type: object - github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse: + github_com_openinfradev_tks-api_pkg_domain.PermissionSet: properties: configuration: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' dashboard: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' notification: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' project_management: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' security_policy: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' stack: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' type: object github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization: properties: @@ -2155,8 +2191,6 @@ definitions: type: string projectRoleName: type: string - updatedAt: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse: properties: @@ -2236,12 +2270,14 @@ definitions: usage: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.RoleResponse: + github_com_openinfradev_tks-api_pkg_domain.Role: properties: createdAt: type: string creator: type: string + deletedAt: + $ref: '#/definitions/gorm.DeletedAt' description: type: string id: @@ -2249,7 +2285,7 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' organizationId: type: string type: @@ -2299,6 +2335,15 @@ definitions: name: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse: + properties: + description: + type: string + id: + type: string + name: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse: properties: cloudService: @@ -2328,6 +2373,8 @@ definitions: type: string name: type: string + role: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' type: object github_com_openinfradev_tks-api_pkg_domain.StackConfResponse: properties: @@ -2407,6 +2454,59 @@ definitions: step: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.StackTemplate: + properties: + cloudService: + type: string + createdAt: + type: string + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' + creatorId: + type: string + description: + type: string + id: + type: string + kubeType: + type: string + kubeVersion: + type: string + name: + type: string + organizationId: + type: string + organizationIds: + items: + type: string + type: array + organizations: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + type: array + platform: + type: string + serviceIds: + items: + type: string + type: array + services: + items: + type: integer + type: array + template: + type: string + templateType: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' + updatorId: + type: string + version: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse: properties: cloudService: @@ -2583,9 +2683,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' type: object type: object github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest: @@ -2630,7 +2730,7 @@ definitions: properties: permissions: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' type: array type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest: @@ -2780,13 +2880,50 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' updatedAt: type: string type: object type: object + github_com_openinfradev_tks-api_pkg_domain.User: + properties: + accountId: + type: string + createdAt: + type: string + creator: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + organizationId: + type: string + password: + type: string + passwordExpired: + type: boolean + passwordUpdatedAt: + type: string + role: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + roleId: + type: string + token: + type: string + updatedAt: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest: properties: email: @@ -2847,9 +2984,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' updatedAt: type: string type: object @@ -2866,179 +3003,73 @@ definitions: maxLength: 100 minLength: 0 type: string - email: - type: string - name: - type: string - role: - type: string - required: - - email - - role - type: object - github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse: - properties: - user: - properties: - accountId: - type: string - createdAt: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' - updatedAt: - type: string - type: object - type: object - github_com_openinfradev_tks-api_pkg_httpErrors.RestError: - properties: - code: - type: string - message: - type: string - status: - type: integer - text: - type: string - type: object -host: tks-api-dev.taco-cat.xyz -info: - contact: - email: taekyu.kang@sk.com - name: taekyu.kang@sk.com - description: This is backend api service for tks platform - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - title: tks-api service - version: "1.0" -paths: - /admin/audits: - get: - consumes: - - application/json - description: Get Audits - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filter - type: array - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: or - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse' - security: - - JWT: [] - summary: Get Audits - tags: - - Audits - post: - consumes: - - application/json - description: Create Audit - parameters: - - description: create audit request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse' - security: - - JWT: [] - summary: Create Audit - tags: - - Audits - /admin/audits/{auditId}: - delete: - consumes: - - application/json - description: Delete Audit - parameters: - - description: auditId - in: path - name: auditId - required: true + email: type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete Audit 'NOT IMPLEMENTED' - tags: - - Audits - get: - consumes: - - application/json - description: Get Audit - parameters: - - description: auditId - in: path - name: auditId - required: true + name: type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse' - security: - - JWT: [] - summary: Get Audit - tags: - - Audits + role: + type: string + required: + - email + - role + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse: + properties: + user: + properties: + accountId: + type: string + createdAt: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + role: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + updatedAt: + type: string + type: object + type: object + github_com_openinfradev_tks-api_pkg_httpErrors.RestError: + properties: + code: + type: string + message: + type: string + status: + type: integer + text: + type: string + type: object + gorm.DeletedAt: + properties: + time: + type: string + valid: + description: Valid is true if Time is not NULL + type: boolean + type: object +host: tks-api-dev.taco-cat.xyz +info: + contact: + email: taekyu.kang@sk.com + name: taekyu.kang@sk.com + description: This is backend api service for tks platform + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + title: tks-api service + version: "1.0" +paths: /admin/organizations/{organizationId}/projects: get: consumes: @@ -3555,7 +3586,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse' security: - JWT: [] - summary: Create StackTemplate + summary: Create StackTemplate 'NOT IMPLEMENTED' tags: - StackTemplates /admin/stack-templates/{stackTemplateId}: @@ -3576,7 +3607,7 @@ paths: description: OK security: - JWT: [] - summary: Delete StackTemplate + summary: Delete StackTemplate 'NOT IMPLEMENTED' tags: - StackTemplates get: @@ -3619,7 +3650,7 @@ paths: description: OK security: - JWT: [] - summary: Update StackTemplate + summary: Update StackTemplate 'NOT IMPLEMENTED' tags: - StackTemplates /admin/stack-templates/{stackTemplateId}/organizations: @@ -4075,6 +4106,8 @@ paths: responses: "200": description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster' security: - JWT: [] summary: Delete cluster @@ -4096,7 +4129,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster' security: - JWT: [] summary: Get cluster @@ -4309,7 +4342,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' security: - JWT: [] summary: Delete organization @@ -4511,6 +4544,120 @@ paths: summary: Create alert action tags: - Alerts + /organizations/{organizationId}/audits: + get: + consumes: + - application/json + description: Get Audits + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filter + type: array + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: or + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse' + security: + - JWT: [] + summary: Get Audits + tags: + - Audits + post: + consumes: + - application/json + description: Create Audit + parameters: + - description: create audit request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse' + security: + - JWT: [] + summary: Create Audit + tags: + - Audits + /organizations/{organizationId}/audits/{auditId}: + delete: + consumes: + - application/json + description: Delete Audit + parameters: + - description: auditId + in: path + name: auditId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete Audit 'NOT IMPLEMENTED' + tags: + - Audits + get: + consumes: + - application/json + description: Get Audit + parameters: + - description: auditId + in: path + name: auditId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse' + security: + - JWT: [] + summary: Get Audit + tags: + - Audits /organizations/{organizationId}/cloud-accounts: get: consumes: @@ -5219,7 +5366,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' type: array security: - JWT: [] @@ -5586,7 +5733,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' type: array security: - JWT: [] @@ -6510,7 +6657,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' security: - JWT: [] summary: Get Permissions By Role ID @@ -6542,64 +6689,6 @@ paths: summary: Update Permissions By Role ID tags: - Permission - /organizations/{organizationId}/stack-templates: - get: - consumes: - - application/json - description: Get Organization StackTemplates - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' - security: - - JWT: [] - summary: Get Organization StackTemplates - tags: - - StackTemplates - /organizations/{organizationId}/stack-templates/{stackTemplateId}: - get: - consumes: - - application/json - description: Get Organization StackTemplate - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse' - security: - - JWT: [] - summary: Get Organization StackTemplate - tags: - - StackTemplates /organizations/{organizationId}/stacks: get: consumes: @@ -6990,6 +7079,8 @@ paths: responses: "200": description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' security: - JWT: [] summary: Delete user @@ -7145,7 +7236,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' security: - JWT: [] summary: Get Permission Templates diff --git a/internal/database/database.go b/internal/database/database.go index 4c34a427..1fd29171 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -14,6 +14,7 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" ) func InitDB() (*gorm.DB, error) { @@ -59,68 +60,68 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&repository.CacheEmailCode{}); err != nil { return err } - if err := db.AutoMigrate(&model.User{}); err != nil { + if err := db.AutoMigrate(&domain.User{}); err != nil { return err } - if err := db.AutoMigrate(&model.Role{}); err != nil { + if err := db.AutoMigrate(&domain.Role{}); err != nil { return err } // Organization - if err := db.AutoMigrate(&model.Organization{}); err != nil { + if err := db.AutoMigrate(&domain.Organization{}); err != nil { return err } // CloudAccount - if err := db.AutoMigrate(&model.CloudAccount{}); err != nil { + if err := db.AutoMigrate(&repository.CloudAccount{}); err != nil { return err } // StackTemplate - if err := db.AutoMigrate(&model.StackTemplate{}); err != nil { + if err := db.AutoMigrate(&repository.StackTemplate{}); err != nil { return err } // Cluster - if err := db.AutoMigrate(&model.Cluster{}); err != nil { + if err := db.AutoMigrate(&repository.Cluster{}); err != nil { return err } - if err := db.AutoMigrate(&model.ClusterFavorite{}); err != nil { + if err := db.AutoMigrate(&repository.ClusterFavorite{}); err != nil { return err } // Services - if err := db.AutoMigrate(&model.AppGroup{}); err != nil { + if err := db.AutoMigrate(&repository.AppGroup{}); err != nil { return err } - if err := db.AutoMigrate(&model.Application{}); err != nil { + if err := db.AutoMigrate(&repository.Application{}); err != nil { return err } // AppServe - if err := db.AutoMigrate(&model.AppServeApp{}); err != nil { + if err := db.AutoMigrate(&domain.AppServeApp{}); err != nil { return err } - if err := db.AutoMigrate(&model.AppServeAppTask{}); err != nil { + if err := db.AutoMigrate(&domain.AppServeAppTask{}); err != nil { return err } // Alert - if err := db.AutoMigrate(&model.Alert{}); err != nil { + if err := db.AutoMigrate(&repository.Alert{}); err != nil { return err } - if err := db.AutoMigrate(&model.AlertAction{}); err != nil { + if err := db.AutoMigrate(&repository.AlertAction{}); err != nil { return err } // Role - if err := db.AutoMigrate(&model.Role{}); err != nil { + if err := db.AutoMigrate(&domain.Role{}); err != nil { return err } - if err := db.AutoMigrate(&model.Permission{}); err != nil { + if err := db.AutoMigrate(&domain.Permission{}); err != nil { return err } - if err := db.AutoMigrate(&model.Endpoint{}); err != nil { + if err := db.AutoMigrate(&domain.Endpoint{}); err != nil { return err } @@ -138,20 +139,6 @@ func migrateSchema(db *gorm.DB) error { return err } - // Audit - if err := db.AutoMigrate(&model.Audit{}); err != nil { - return err - } - - // PolicyTemplate - if err := db.AutoMigrate(&model.PolicyTemplateSupportedVersion{}); err != nil { - return err - } - - if err := db.AutoMigrate(&model.PolicyTemplate{}); err != nil { - return err - } - return nil } @@ -185,7 +172,7 @@ func EnsureDefaultRows(db *gorm.DB) error { } for _, ep := range api.ApiMap { if _, ok := storedEps[ep.Name]; !ok { - if err := repoFactory.Endpoint.Create(&model.Endpoint{ + if err := repoFactory.Endpoint.Create(&domain.Endpoint{ Name: ep.Name, Group: ep.Group, }); err != nil { @@ -194,5 +181,19 @@ func EnsureDefaultRows(db *gorm.DB) error { } } + // Audit + if err := db.AutoMigrate(&repository.Audit{}); err != nil { + return err + } + + // PolicyTemplate + if err := db.AutoMigrate(&repository.PolicyTemplateSupportedVersion{}); err != nil { + return err + } + + if err := db.AutoMigrate(&repository.PolicyTemplate{}); err != nil { + return err + } + return nil } diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 4c6a3bdd..9d7c0966 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -102,8 +102,6 @@ const ( Admin_UpdateStackTemplate Admin_DeleteStackTemplate Admin_UpdateStackTemplateOrganizations - GetOrganizationStackTemplates - GetOrganizationStackTemplate // Dashboard GetChartsDashboard // 대시보드/대시보드/조회 @@ -121,7 +119,7 @@ const ( // Stack GetStacks // 스택관리/조회 - CreateStack // 스택관리/생성 + CreateStack // // 스택관리/생성 CheckStackName // 스택관리/조회 GetStack // 스택관리/조회 UpdateStack // 스택관리/수정 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 32a81fb6..aeea2305 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -303,14 +303,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, - GetOrganizationStackTemplates: { - Name: "GetOrganizationStackTemplates", - Group: "StackTemplate", - }, - GetOrganizationStackTemplate: { - Name: "GetOrganizationStackTemplate", - Group: "StackTemplate", - }, GetChartsDashboard: { Name: "GetChartsDashboard", Group: "Dashboard", @@ -888,10 +880,6 @@ func (e Endpoint) String() string { return "Admin_DeleteStackTemplate" case Admin_UpdateStackTemplateOrganizations: return "Admin_UpdateStackTemplateOrganizations" - case GetOrganizationStackTemplates: - return "GetOrganizationStackTemplates" - case GetOrganizationStackTemplate: - return "GetOrganizationStackTemplate" case GetChartsDashboard: return "GetChartsDashboard" case GetChartDashboard: @@ -1260,10 +1248,6 @@ func GetEndpoint(name string) Endpoint { return Admin_DeleteStackTemplate case "Admin_UpdateStackTemplateOrganizations": return Admin_UpdateStackTemplateOrganizations - case "GetOrganizationStackTemplates": - return GetOrganizationStackTemplates - case "GetOrganizationStackTemplate": - return GetOrganizationStackTemplate case "GetChartsDashboard": return GetChartsDashboard case "GetChartDashboard": diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index bf878aef..5b03746f 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -8,7 +8,6 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -273,7 +272,7 @@ func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) log.InfoWithContext(r.Context(), "alert : ", helper.ModelToJson(input)) - var dto model.AlertAction + var dto domain.AlertAction if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 27543035..26dbb840 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -6,7 +6,6 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -44,7 +43,7 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) return } - var dto model.AppGroup + var dto domain.AppGroup if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -265,7 +264,7 @@ func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Reque return } - var dto model.Application + var dto domain.Application if err := serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index aa6f92b1..d738685f 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -12,7 +12,6 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -116,7 +115,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re (appReq).SetDefaultValue() - var app model.AppServeApp + var app domain.AppServeApp if err = serializer.Map(appReq, &app); err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -132,7 +131,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re app.Status = "PREPARING" app.CreatedAt = now - var task model.AppServeAppTask + var task domain.AppServeAppTask if err = serializer.Map(appReq, &task); err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -231,7 +230,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} []model.AppServeApp +// @Success 200 {object} []domain.AppServeApp // @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { @@ -265,13 +264,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ } var out domain.GetAppServeAppsResponse - out.AppServeApps = make([]domain.AppServeAppResponse, len(apps)) - for i, app := range apps { - if err := serializer.Map(app, &out.AppServeApps[i]); err != nil { - log.InfoWithContext(r.Context(), err) - continue - } - } + out.AppServeApps = apps if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) @@ -324,7 +317,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque return } - newTasks := make([]model.AppServeAppTask, 0) + newTasks := make([]domain.AppServeAppTask, 0) for idx, t := range app.AppServeAppTasks { // Rollbacking to latest task should be blocked. @@ -337,10 +330,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque app.AppServeAppTasks = newTasks var out domain.GetAppServeAppResponse - if err := serializer.Map(app, &out.AppServeApp); err != nil { - log.InfoWithContext(r.Context(), err) - } - + out.AppServeApp = *app // NOTE: makeStages function's been changed to use task instead of app //out.Stages = makeStages(app) @@ -387,9 +377,7 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - if err := serializer.Map(task, &out.AppServeAppTask); err != nil { - log.InfoWithContext(r.Context(), err) - } + out.AppServeAppTask = *task ResponseJSON(w, r, http.StatusOK, out) } @@ -447,7 +435,7 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. // @Param sortColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} []model.AppServeApp +// @Success 200 {object} []domain.AppServeApp // @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r *http.Request) { @@ -475,13 +463,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r } var out domain.GetAppServeAppTasksResponse - out.AppServeAppTasks = make([]domain.AppServeAppTaskResponse, len(tasks)) - for i, task := range tasks { - if err := serializer.Map(task, &out.AppServeAppTasks[i]); err != nil { - log.InfoWithContext(r.Context(), err) - continue - } - } + out.AppServeAppTasks = tasks if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) @@ -551,19 +533,14 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - if err := serializer.Map(app, &out.AppServeApp); err != nil { - log.InfoWithContext(r.Context(), err) - } - if err := serializer.Map(task, &out.AppServeAppTask); err != nil { - log.InfoWithContext(r.Context(), err) - } - + out.AppServeApp = *app + out.AppServeAppTask = *task out.Stages = makeStages(task, app) ResponseJSON(w, r, http.StatusOK, out) } -func makeStages(task *model.AppServeAppTask, app *model.AppServeApp) []domain.StageResponse { +func makeStages(task *domain.AppServeAppTask, app *domain.AppServeApp) []domain.StageResponse { stages := make([]domain.StageResponse, 0) var stage domain.StageResponse @@ -605,7 +582,7 @@ func makeStages(task *model.AppServeAppTask, app *model.AppServeApp) []domain.St return stages } -func makeStage(task *model.AppServeAppTask, app *model.AppServeApp, pl string) domain.StageResponse { +func makeStage(task *domain.AppServeAppTask, app *domain.AppServeApp, pl string) domain.StageResponse { taskStatus := task.Status strategy := task.Strategy @@ -797,7 +774,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re // from existing app config. //appReq.SetDefaultValue() - var task model.AppServeAppTask + var task domain.AppServeAppTask //tasks := app.AppServeAppTasks //sort.Slice(tasks, func(i, j int) bool { // return tasks[i].CreatedAt.String() > tasks[j].CreatedAt.String() diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 2a7b2b99..395d9112 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -34,7 +34,7 @@ func NewAuditHandler(h usecase.Usecase) *AuditHandler { // @Produce json // @Param body body domain.CreateAuditRequest true "create audit request" // @Success 200 {object} domain.CreateAuditResponse -// @Router /admin/audits [post] +// @Router /organizations/{organizationId}/audits [post] // @Security JWT func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) @@ -54,12 +54,19 @@ func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { // @Param filter query []string false "filters" // @Param or query []string false "filters" // @Success 200 {object} domain.GetAuditsResponse -// @Router /admin/audits [get] +// @Router /organizations/{organizationId}/audits [get] // @Security JWT func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - audits, err := h.usecase.Fetch(r.Context(), pg) + audits, err := h.usecase.Fetch(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) return @@ -89,7 +96,7 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} domain.GetAuditResponse -// @Router /admin/audits/{auditId} [get] +// @Router /organizations/{organizationId}/audits/{auditId} [get] // @Security JWT func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -130,7 +137,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} nil -// @Router /admin/audits/{auditId} [delete] +// @Router /organizations/{organizationId}/audits/{auditId} [delete] // @Security JWT func (h *AuditHandler) DeleteAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index d2fea4d3..72a56812 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -7,7 +7,6 @@ import ( "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" @@ -62,7 +61,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { user, err := h.usecase.Login(input.AccountId, input.Password, input.OrganizationId) if err != nil { errorResponse, _ := httpErrors.ErrorResponse(err) - _, _ = h.auditUsecase.Create(r.Context(), model.Audit{ + _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ OrganizationId: input.OrganizationId, Group: "Auth", Message: fmt.Sprintf("[%s]님이 로그인에 실패하였습니다.", input.AccountId), @@ -74,7 +73,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } else { - _, _ = h.auditUsecase.Create(r.Context(), model.Audit{ + _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ OrganizationId: input.OrganizationId, Group: "Auth", Message: fmt.Sprintf("[%s]님이 로그인 하였습니다.", input.AccountId), diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 5c29a04d..15b4f6a1 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -7,7 +7,6 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -54,7 +53,7 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. return } - var dto model.CloudAccount + var dto domain.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -199,7 +198,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. return } - var dto model.CloudAccount + var dto domain.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -249,7 +248,7 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. return } - var dto model.CloudAccount + var dto domain.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -296,11 +295,7 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * return } - out := domain.DeleteCloudAccountResponse{ - ID: cloudAccountId, - } - - ResponseJSON(w, r, http.StatusOK, out) + ResponseJSON(w, r, http.StatusOK, nil) } // CheckCloudAccountName godoc diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index d0811b04..1f8fb6a9 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -4,8 +4,8 @@ import ( "fmt" "net/http" + "github.com/google/uuid" "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -58,13 +58,6 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { log.InfoWithContext(r.Context(), err) continue } - - if cluster.Favorites != nil && len(*cluster.Favorites) > 0 { - out.Clusters[i].Favorited = true - } else { - out.Clusters[i].Favorited = false - } - } if out.Pagination, err = pg.Response(); err != nil { @@ -82,7 +75,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.GetClusterResponse +// @Success 200 {object} domain.Cluster // @Router /clusters/{clusterId} [get] // @Security JWT func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { @@ -157,13 +150,19 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { return } - var dto model.Cluster + var dto domain.Cluster if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } + if err = serializer.Map(input, &dto.Conf); err != nil { + log.InfoWithContext(r.Context(), err) + } + + // [TODO] set default value dto.ClusterType = domain.ClusterType_USER - dto.SetDefaultConf() + dto.Conf.SetDefault() + log.InfoWithContext(r.Context(), dto.Conf) //txHandle := r.Context().Value("txHandle").(*gorm.DB) clusterId := domain.ClusterId("") @@ -211,13 +210,18 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { return } - var dto model.Cluster + var dto domain.Cluster if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } - dto.SetDefaultConf() - dto.CloudAccountId = nil + if err = serializer.Map(input, &dto.Conf); err != nil { + log.InfoWithContext(r.Context(), err) + } + dto.Conf.SetDefault() + log.InfoWithContext(r.Context(), dto.Conf) + + dto.CloudAccountId = uuid.Nil clusterId, err := h.usecase.Import(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) @@ -266,7 +270,7 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) // @Accept json // @Produce json // @Param clusterId path string true "clusterId" -// @Success 200 {object} nil +// @Success 200 {object} domain.Cluster // @Router /clusters/{clusterId} [delete] // @Security JWT func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index d2b6e180..680c338d 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -1,7 +1,6 @@ package http import ( - "bytes" "encoding/json" "errors" "io" @@ -50,7 +49,6 @@ func UnmarshalRequestInput(r *http.Request, in any) error { if err != nil { return err } - r.Body = io.NopCloser(bytes.NewBuffer(body)) err = json.Unmarshal(body, &in) if err != nil { diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 264a3611..26bbb8d7 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -6,7 +6,6 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -53,7 +52,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } ctx := r.Context() - var organization model.Organization + var organization domain.Organization if err = serializer.Map(input, &organization); err != nil { log.ErrorWithContext(r.Context(), err) } @@ -67,7 +66,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. organization.ID = organizationId // Role 생성 - adminRole := model.Role{ + adminRole := domain.Role{ OrganizationID: organizationId, Name: "admin", Description: "admin", @@ -79,7 +78,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. ErrorJSON(w, r, err) return } - userRole := model.Role{ + userRole := domain.Role{ OrganizationID: organizationId, Name: "user", Description: "user", @@ -217,7 +216,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.DeleteOrganizationResponse +// @Success 200 {object} domain.Organization // @Router /organizations/{organizationId} [delete] // @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { @@ -254,10 +253,7 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. return } - out := domain.DeleteOrganizationResponse{ - ID: organizationId, - } - ResponseJSON(w, r, http.StatusOK, out) + ResponseJSON(w, r, http.StatusOK, nil) } // UpdateOrganization godoc diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index d7ca79d9..22bdfb64 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -1,15 +1,12 @@ package http import ( - "net/http" - "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal/model" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" + "net/http" ) type IPermissionHandler interface { @@ -35,24 +32,19 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { // @Description Get Permission Templates // @Accept json // @Produce json -// @Success 200 {object} domain.PermissionSetResponse +// @Success 200 {object} domain.PermissionSet // @Router /permissions/templates [get] // @Security JWT func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { - permissionSet := model.NewDefaultPermissionSet() - - var premissionSetResponse domain.PermissionSetResponse - if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { - log.InfoWithContext(r.Context(), err) - } + permissionSet := domain.NewDefaultPermissionSet() var out domain.GetPermissionTemplatesResponse - out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) - out.Permissions = append(out.Permissions, premissionSetResponse.Stack) - out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) - out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) - out.Permissions = append(out.Permissions, premissionSetResponse.Notification) - out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) + out.Permissions = append(out.Permissions, permissionSet.Dashboard) + out.Permissions = append(out.Permissions, permissionSet.Stack) + out.Permissions = append(out.Permissions, permissionSet.SecurityPolicy) + out.Permissions = append(out.Permissions, permissionSet.ProjectManagement) + out.Permissions = append(out.Permissions, permissionSet.Notification) + out.Permissions = append(out.Permissions, permissionSet.Configuration) ResponseJSON(w, r, http.StatusOK, out) } @@ -64,7 +56,7 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http // @Description Get Permissions By Role ID // @Accept json // @Produce json -// @Success 200 {object} domain.PermissionSetResponse +// @Success 200 {object} domain.PermissionSet // @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] // @Security JWT func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { @@ -85,18 +77,13 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http return } - var premissionSetResponse domain.PermissionSetResponse - if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { - log.InfoWithContext(r.Context(), err) - } - var out domain.GetPermissionsByRoleIdResponse - out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) - out.Permissions = append(out.Permissions, premissionSetResponse.Stack) - out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) - out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) - out.Permissions = append(out.Permissions, premissionSetResponse.Notification) - out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) + out.Permissions = append(out.Permissions, permissionSet.Dashboard) + out.Permissions = append(out.Permissions, permissionSet.Stack) + out.Permissions = append(out.Permissions, permissionSet.SecurityPolicy) + out.Permissions = append(out.Permissions, permissionSet.ProjectManagement) + out.Permissions = append(out.Permissions, permissionSet.Notification) + out.Permissions = append(out.Permissions, permissionSet.Configuration) ResponseJSON(w, r, http.StatusOK, out) } @@ -135,15 +122,9 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h } log.Debugf("input: %+v", input) - for _, permissionResponse := range input.Permissions { - log.Debugf("permissionResponse: %+v", permissionResponse) - - var permission model.Permission - if err := serializer.Map(permissionResponse, &permission); err != nil { - log.InfoWithContext(r.Context(), err) - } - - if err := h.permissionUsecase.UpdatePermission(&permission); err != nil { + for _, permission := range input.Permissions { + log.Debugf("permission: %+v", permission) + if err := h.permissionUsecase.UpdatePermission(permission); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index e747a98f..8126e00f 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -8,7 +8,6 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -68,7 +67,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h return } - var dto model.PolicyTemplate + var dto domain.PolicyTemplate if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 7fdb1157..1ad67b29 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -1,16 +1,14 @@ package http import ( - "net/http" - "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" + "net/http" ) type IRoleHandler interface { @@ -69,7 +67,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - dto := model.Role{ + dto := domain.Role{ OrganizationID: organizationId, Name: input.Name, Description: input.Description, @@ -84,7 +82,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // create permission - defaultPermissionSet := model.NewDefaultPermissionSet() + defaultPermissionSet := domain.NewDefaultPermissionSet() h.permissionUsecase.SetRoleIdToPermissionSet(roleId, defaultPermissionSet) err = h.permissionUsecase.CreatePermissionSet(defaultPermissionSet) if err != nil { @@ -258,7 +256,7 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - dto := model.Role{ + dto := domain.Role{ ID: roleId, Description: input.Description, } diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 60cad92a..107e621b 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -8,7 +8,6 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -31,7 +30,7 @@ func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { // CreateStackTemplate godoc // // @Tags StackTemplates -// @Summary Create StackTemplate +// @Summary Create StackTemplate 'NOT IMPLEMENTED' // @Description Create StackTemplate // @Accept json // @Produce json @@ -47,7 +46,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt return } - var dto model.StackTemplate + var dto domain.StackTemplate if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -171,7 +170,7 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R // UpdateStackTemplate godoc // // @Tags StackTemplates -// @Summary Update StackTemplate +// @Summary Update StackTemplate 'NOT IMPLEMENTED' // @Description Update StackTemplate // @Accept json // @Produce json @@ -193,7 +192,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt return } - var dto model.StackTemplate + var dto domain.StackTemplate if err := serializer.Map(r, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -210,7 +209,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt // DeleteStackTemplate godoc // // @Tags StackTemplates -// @Summary Delete StackTemplate +// @Summary Delete StackTemplate 'NOT IMPLEMENTED' // @Description Delete StackTemplate // @Accept json // @Produce json @@ -288,7 +287,7 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW return } - var dto model.StackTemplate + var dto domain.StackTemplate if err := serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -301,117 +300,3 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW } ResponseJSON(w, r, http.StatusOK, nil) } - -// GetOrganizationStackTemplates godoc -// -// @Tags StackTemplates -// @Summary Get Organization StackTemplates -// @Description Get Organization StackTemplates -// @Accept json -// @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetStackTemplatesResponse -// @Router /organizations/{organizationId}/stack-templates [get] -// @Security JWT -func (h *StackTemplateHandler) GetOrganizationStackTemplates(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) - return - } - - urlParams := r.URL.Query() - pg := pagination.NewPagination(&urlParams) - stackTemplates, err := h.usecase.FetchWithOrganization(r.Context(), organizationId, pg) - if err != nil { - ErrorJSON(w, r, err) - return - } - - var out domain.GetStackTemplatesResponse - out.StackTemplates = make([]domain.StackTemplateResponse, len(stackTemplates)) - for i, stackTemplate := range stackTemplates { - if err := serializer.Map(stackTemplate, &out.StackTemplates[i]); err != nil { - log.InfoWithContext(r.Context(), err) - } - - out.StackTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) - for j, organization := range stackTemplate.Organizations { - if err := serializer.Map(organization, &out.StackTemplates[i].Organizations[j]); err != nil { - log.InfoWithContext(r.Context(), err) - } - } - - err := json.Unmarshal(stackTemplate.Services, &out.StackTemplates[i].Services) - if err != nil { - log.ErrorWithContext(r.Context(), err) - } - } - - if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) - } - - ResponseJSON(w, r, http.StatusOK, out) -} - -// GetOrganizationStackTemplate godoc -// -// @Tags StackTemplates -// @Summary Get Organization StackTemplate -// @Description Get Organization StackTemplate -// @Accept json -// @Produce json -// @Success 200 {object} domain.GetStackTemplateResponse -// @Router /organizations/{organizationId}/stack-templates/{stackTemplateId} [get] -// @Security JWT -func (h *StackTemplateHandler) GetOrganizationStackTemplate(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - _, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) - return - } - - strId, ok := vars["stackTemplateId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) - return - } - - stackTemplateId, err := uuid.Parse(strId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) - return - } - - stackTemplate, err := h.usecase.Get(r.Context(), stackTemplateId) - if err != nil { - ErrorJSON(w, r, err) - return - } - - var out domain.GetStackTemplateResponse - if err := serializer.Map(stackTemplate, &out.StackTemplate); err != nil { - log.InfoWithContext(r.Context(), err) - } - - out.StackTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) - for i, organization := range stackTemplate.Organizations { - if err := serializer.Map(organization, &out.StackTemplate.Organizations[i]); err != nil { - log.InfoWithContext(r.Context(), err) - } - } - - err = json.Unmarshal(stackTemplate.Services, &out.StackTemplate.Services) - if err != nil { - log.ErrorWithContext(r.Context(), err) - } - - ResponseJSON(w, r, http.StatusOK, out) -} diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 9a40cf22..fd84da4e 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -6,7 +6,6 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -52,10 +51,13 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { return } - var dto model.Stack + var dto domain.Stack if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } + if err = serializer.Map(input, &dto.Conf); err != nil { + log.InfoWithContext(r.Context(), err) + } dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -124,10 +126,7 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { for i, stack := range stacks { if err := serializer.Map(stack, &out.Stacks[i]); err != nil { log.InfoWithContext(r.Context(), err) - } - - if err := serializer.Map(stack.CreatedAt, &out.Stacks[i].CreatedAt); err != nil { - log.InfoWithContext(r.Context(), err) + continue } err = json.Unmarshal(stack.StackTemplate.Services, &out.Stacks[i].StackTemplate.Services) @@ -260,7 +259,7 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { return } - var dto model.Stack + var dto domain.Stack if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -303,7 +302,7 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { return } - var dto model.Stack + var dto domain.Stack dto.ID = domain.StackId(strId) dto.OrganizationId = organizationId diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 9fa3b8b7..7df3a3bc 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -9,7 +9,6 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -87,11 +86,11 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user model.User + var user domain.User if err = serializer.Map(input, &user); err != nil { log.ErrorWithContext(r.Context(), err) } - user.Organization = model.Organization{ + user.Organization = domain.Organization{ ID: organizationId, } @@ -232,7 +231,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Success 200 {object} nil +// @Success 200 {object} domain.User // @Router /organizations/{organizationId}/users/{accountId} [delete] // @Security JWT func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { @@ -299,12 +298,12 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user model.User + var user domain.User if err = serializer.Map(input, &user); err != nil { ErrorJSON(w, r, err) return } - user.Organization = model.Organization{ + user.Organization = domain.Organization{ ID: organizationId, } user.AccountId = accountId @@ -452,7 +451,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user model.User + var user domain.User if err = serializer.Map(input, &user); err != nil { log.ErrorWithContext(r.Context(), err) ErrorJSON(w, r, err) @@ -711,7 +710,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } } - user := model.User{ + user := domain.User{ Name: input.Name, AccountId: input.AccountId, Email: input.Email, @@ -733,7 +732,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } } - user.Organization = model.Organization{ + user.Organization = domain.Organization{ ID: organizationId, } @@ -974,14 +973,14 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - user := model.User{ + user := domain.User{ AccountId: accountId, Name: input.Name, Email: input.Email, Department: input.Department, Description: input.Description, } - user.Organization = model.Organization{ + user.Organization = domain.Organization{ ID: organizationId, } diff --git a/internal/filter/settings.go b/internal/filter/settings.go index 4e06fc48..ac2a31a8 100644 --- a/internal/filter/settings.go +++ b/internal/filter/settings.go @@ -316,7 +316,6 @@ func getField(field string, sch *schema.Schema, blacklist *Blacklist) (*schema.F if !ok || (relation.Type != schema.HasOne && relation.Type != schema.BelongsTo) { return nil, nil, "" } - s = relation.FieldSchema if blacklist != nil { blacklist = blacklist.Relations[v] @@ -331,7 +330,6 @@ func getField(field string, sch *schema.Schema, blacklist *Blacklist) (*schema.F if !ok { return nil, nil, "" } - return col, s, joinName } diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 610d59ad..8d2252f5 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -10,7 +10,7 @@ import ( "time" "github.com/Nerzal/gocloak/v13" - "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" ) @@ -18,15 +18,15 @@ import ( type IKeycloak interface { InitializeKeycloak() error - LoginAdmin(accountId string, password string) (*model.User, error) - Login(accountId string, password string, organizationId string) (*model.User, error) + LoginAdmin(accountId string, password string) (*domain.User, error) + Login(accountId string, password string, organizationId string) (*domain.User, error) Logout(sessionId string, organizationId string) error CreateRealm(organizationId string) (string, error) - GetRealm(organizationId string) (*model.Organization, error) - GetRealms() ([]*model.Organization, error) + GetRealm(organizationId string) (*domain.Organization, error) + GetRealms() ([]*domain.Organization, error) DeleteRealm(organizationId string) error - UpdateRealm(organizationId string, organizationConfig model.Organization) error + UpdateRealm(organizationId string, organizationConfig domain.Organization) error CreateUser(organizationId string, user *gocloak.User) (string, error) GetUser(organizationId string, userAccountId string) (*gocloak.User, error) @@ -51,7 +51,7 @@ type Keycloak struct { adminCliToken *gocloak.JWT } -func (k *Keycloak) LoginAdmin(accountId string, password string) (*model.User, error) { +func (k *Keycloak) LoginAdmin(accountId string, password string) (*domain.User, error) { ctx := context.Background() JWTToken, err := k.client.LoginAdmin(ctx, accountId, password, DefaultMasterRealm) if err != nil { @@ -59,17 +59,17 @@ func (k *Keycloak) LoginAdmin(accountId string, password string) (*model.User, e return nil, err } - return &model.User{Token: JWTToken.AccessToken}, nil + return &domain.User{Token: JWTToken.AccessToken}, nil } -func (k *Keycloak) Login(accountId string, password string, organizationId string) (*model.User, error) { +func (k *Keycloak) Login(accountId string, password string, organizationId string) (*domain.User, error) { ctx := context.Background() JWTToken, err := k.client.Login(ctx, DefaultClientID, k.config.ClientSecret, organizationId, accountId, password) if err != nil { log.Error(err) return nil, err } - return &model.User{Token: JWTToken.AccessToken}, nil + return &domain.User{Token: JWTToken.AccessToken}, nil } func New(config *Config) IKeycloak { @@ -249,7 +249,7 @@ func (k *Keycloak) CreateRealm(organizationId string) (string, error) { return realmUUID, nil } -func (k *Keycloak) GetRealm(organizationId string) (*model.Organization, error) { +func (k *Keycloak) GetRealm(organizationId string) (*domain.Organization, error) { ctx := context.Background() token := k.adminCliToken realm, err := k.client.GetRealm(ctx, token.AccessToken, organizationId) @@ -260,14 +260,14 @@ func (k *Keycloak) GetRealm(organizationId string) (*model.Organization, error) return k.reflectOrganization(*realm), nil } -func (k *Keycloak) GetRealms() ([]*model.Organization, error) { +func (k *Keycloak) GetRealms() ([]*domain.Organization, error) { ctx := context.Background() token := k.adminCliToken realms, err := k.client.GetRealms(ctx, token.AccessToken) if err != nil { return nil, err } - organization := make([]*model.Organization, 0) + organization := make([]*domain.Organization, 0) for _, realm := range realms { organization = append(organization, k.reflectOrganization(*realm)) } @@ -275,7 +275,7 @@ func (k *Keycloak) GetRealms() ([]*model.Organization, error) { return organization, nil } -func (k *Keycloak) UpdateRealm(organizationId string, organizationConfig model.Organization) error { +func (k *Keycloak) UpdateRealm(organizationId string, organizationConfig domain.Organization) error { ctx := context.Background() token := k.adminCliToken realm := k.reflectRealmRepresentation(organizationConfig) @@ -844,14 +844,14 @@ func (k *Keycloak) createDefaultClient(ctx context.Context, accessToken string, return id, nil } -func (k *Keycloak) reflectOrganization(org gocloak.RealmRepresentation) *model.Organization { - return &model.Organization{ +func (k *Keycloak) reflectOrganization(org gocloak.RealmRepresentation) *domain.Organization { + return &domain.Organization{ ID: *org.ID, Name: *org.Realm, } } -func (k *Keycloak) reflectRealmRepresentation(org model.Organization) *gocloak.RealmRepresentation { +func (k *Keycloak) reflectRealmRepresentation(org domain.Organization) *gocloak.RealmRepresentation { return &gocloak.RealmRepresentation{ Realm: gocloak.StringP(org.Name), } diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index 863b71fd..85a80d9d 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -19,6 +19,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } + if isSuccess(statusCode) { return fmt.Sprintf("스택 [%s]을 생성하였습니다.", input.Name), "" } else { @@ -29,101 +30,22 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } + if isSuccess(statusCode) { return fmt.Sprintf("프로젝트 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("프로젝트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return "프로젝트 [%s]를 생성하는데 실패하였습니다. ", errorText(out) } }, internalApi.CreateCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateCloudAccountRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } + if isSuccess(statusCode) { return fmt.Sprintf("클라우드 어카운트 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("클라우드 어카운트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) - } - }, internalApi.DeleteCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { - if isSuccess(statusCode) { - output := domain.DeleteCloudAccountResponse{} - if err := json.Unmarshal(in, &output); err != nil { - log.Error(err) - } - return fmt.Sprintf("클라우드어카운트 [ID:%s]를 삭제하였습니다.", output.ID), "" - } else { - return "클라우드어카운트 [%s]를 삭제하는데 실패하였습니다. ", errorText(out) - } - }, internalApi.CreateUser: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { - input := domain.CreateUserRequest{} - if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) - } - if isSuccess(statusCode) { - return fmt.Sprintf("사용자 [%s]를 생성하였습니다.", input.Name), "" - } else { - return fmt.Sprintf("사용자 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) - } - }, internalApi.CreateOrganization: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { - input := domain.CreateOrganizationRequest{} - if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) - } - if isSuccess(statusCode) { - return fmt.Sprintf("조직 [%s]를 생성하였습니다.", input.Name), "" - } else { - return fmt.Sprintf("조직 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) - } - }, internalApi.DeleteOrganization: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { - if isSuccess(statusCode) { - output := domain.DeleteOrganizationResponse{} - if err := json.Unmarshal(in, &output); err != nil { - log.Error(err) - } - return fmt.Sprintf("조직 [ID:%s]를 삭제하였습니다.", output.ID), "" - } else { - return "조직 [%s]를 삭제하는데 실패하였습니다. ", errorText(out) - } - }, internalApi.CreateAppServeApp: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { - input := domain.CreateAppServeAppRequest{} - if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) - } - if isSuccess(statusCode) { - return fmt.Sprintf("앱서빙 [%s]를 생성하였습니다.", input.Name), "" - } else { - return fmt.Sprintf("앱서빙 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) - } - }, internalApi.Admin_CreateStackTemplate: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { - input := domain.CreateStackTemplateRequest{} - if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) - } - log.Info(input) - if isSuccess(statusCode) { - return fmt.Sprintf("스택 템플릿 [%s]를 생성하였습니다.", input.Name), "" - } else { - return fmt.Sprintf("스택 템플릿 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) - } - }, internalApi.Admin_CreateUser: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { - input := domain.CreateUserRequest{} - if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) - } - if isSuccess(statusCode) { - return fmt.Sprintf("어드민 [%s]를 생성하였습니다.", input.Name), "" - } else { - return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) - } - }, internalApi.CreatePolicyTemplate: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { - input := domain.CreatePolicyTemplateRequest{} - if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) - } - if isSuccess(statusCode) { - return fmt.Sprintf("폴리시템플릿 [%s]를 생성하였습니다.", input.TemplateName), "" - } else { - return fmt.Sprintf("폴리시템플릿 [%s]을 생성하는데 실패하였습니다.", input.TemplateName), errorText(out) + return "프로젝트 [%s]를 생성하는데 실패하였습니다. ", errorText(out) } }, } diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 12360269..428f8d35 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -10,8 +10,8 @@ import ( internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/middleware/logging" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) @@ -59,7 +59,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han message, description = fn(lrw.GetBody(), body, statusCode) r.Body = io.NopCloser(bytes.NewBuffer(body)) - dto := model.Audit{ + dto := domain.Audit{ OrganizationId: organizationId, Group: internalApi.ApiMap[endpoint].Group, Message: message, diff --git a/internal/model/alert.go b/internal/model/alert.go deleted file mode 100644 index 5d360781..00000000 --- a/internal/model/alert.go +++ /dev/null @@ -1,60 +0,0 @@ -package model - -import ( - "time" - - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/datatypes" - "gorm.io/gorm" -) - -// Models -type Alert struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - Name string - Code string - Description string - Grade string - Message string - ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - Node string - CheckPoint string - GrafanaUrl string - FiredAt *time.Time `gorm:"-:all"` - TakedAt *time.Time `gorm:"-:all"` - ClosedAt *time.Time `gorm:"-:all"` - TakedSec int `gorm:"-:all"` - ProcessingSec int `gorm:"-:all"` - LastTaker User `gorm:"-:all"` - AlertActions []AlertAction - Summary string - RawData datatypes.JSON - Status domain.AlertActionStatus `gorm:"index"` -} - -func (c *Alert) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - -type AlertAction struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - AlertId uuid.UUID - Content string - Status domain.AlertActionStatus - TakerId *uuid.UUID `gorm:"type:uuid"` - Taker User `gorm:"foreignKey:TakerId"` -} - -func (c *AlertAction) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/app-group.go b/internal/model/app-group.go deleted file mode 100644 index fea48726..00000000 --- a/internal/model/app-group.go +++ /dev/null @@ -1,47 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/datatypes" - "gorm.io/gorm" -) - -// Models -type AppGroup struct { - gorm.Model - - ID domain.AppGroupId `gorm:"primarykey"` - AppGroupType domain.AppGroupType - ClusterId domain.ClusterId - Name string - Description string - WorkflowId string - Status domain.AppGroupStatus - StatusDesc string - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` -} - -func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = domain.AppGroupId(helper.GenerateApplicaionGroupId()) - return nil -} - -type Application struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid"` - AppGroupId domain.AppGroupId - Endpoint string - Metadata datatypes.JSON - Type domain.ApplicationType -} - -func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go deleted file mode 100644 index 4b6e779e..00000000 --- a/internal/model/app-serve-app.go +++ /dev/null @@ -1,67 +0,0 @@ -package model - -import ( - "time" - - "github.com/google/uuid" - "gorm.io/gorm" -) - -type AppServeApp struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - Name string `gorm:"index" json:"name,omitempty"` // application name - Namespace string `json:"namespace,omitempty"` // application namespace - OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to - ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to - Type string `json:"type,omitempty"` // type (build/deploy/all) - AppType string `json:"appType,omitempty"` // appType (spring/springboot) - EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app - PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment - TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed - TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name - Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app - GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` - AppServeAppTasks []AppServeAppTask `gorm:"foreignKey:AppServeAppId" json:"appServeAppTasks"` -} - -type AppServeAppTask struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - AppServeAppId string `gorm:"not null" json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to - Version string `json:"version,omitempty"` // application version - Status string `json:"status,omitempty"` // status is app status - Output string `json:"output,omitempty"` // output for task result - ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) - ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app - ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image - Profile string `json:"profile,omitempty"` // java app profile - AppConfig string `json:"appConfig,omitempty"` // java app config - AppSecret string `json:"appSecret,omitempty"` // java app secret - ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app - Port string `json:"port,omitempty"` // java app port - ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod - HelmRevision int32 `gorm:"default:0" json:"helmRevision,omitempty"` // revision of deployed helm release - Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) - RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version - PvEnabled bool `json:"pvEnabled"` - PvStorageClass string `json:"pvStorageClass"` - PvAccessMode string `json:"pvAccessMode"` - PvSize string `json:"pvSize"` - PvMountPath string `json:"pvMountPath"` - AvailableRollback bool `gorm:"-:all" json:"availableRollback"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` // createdAt is a creation timestamp for the application - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` -} - -func (a *AppServeApp) BeforeCreate(tx *gorm.DB) (err error) { - a.ID = uuid.New().String() - return nil -} - -func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} diff --git a/internal/model/audit.go b/internal/model/audit.go deleted file mode 100644 index bfa853c1..00000000 --- a/internal/model/audit.go +++ /dev/null @@ -1,26 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - "gorm.io/gorm" -) - -// Models -type Audit struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - Group string - Message string - Description string - ClientIP string - UserId *uuid.UUID `gorm:"type:uuid"` - User User `gorm:"foreignKey:UserId"` -} - -func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/cloud-account.go b/internal/model/cloud-account.go deleted file mode 100644 index 33d3a14b..00000000 --- a/internal/model/cloud-account.go +++ /dev/null @@ -1,38 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/gorm" -) - -// Models -type CloudAccount struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - Name string `gorm:"index"` - Description string `gorm:"index"` - Resource string - CloudService string - WorkflowId string - Status domain.CloudAccountStatus - StatusDesc string - AwsAccountId string - AccessKeyId string `gorm:"-:all"` - SecretAccessKey string `gorm:"-:all"` - SessionToken string `gorm:"-:all"` - Clusters int `gorm:"-:all"` - CreatedIAM bool - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` -} - -func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/cluster.go b/internal/model/cluster.go deleted file mode 100644 index 8ca4b764..00000000 --- a/internal/model/cluster.go +++ /dev/null @@ -1,84 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/gorm" -) - -// Models -type Cluster struct { - gorm.Model - - ID domain.ClusterId `gorm:"primarykey"` - Name string `gorm:"index"` - CloudService string `gorm:"default:AWS"` - OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - Description string `gorm:"index"` - WorkflowId string - Status domain.ClusterStatus - StatusDesc string - CloudAccountId *uuid.UUID - CloudAccount CloudAccount `gorm:"foreignKey:CloudAccountId"` - StackTemplateId uuid.UUID - StackTemplate StackTemplate `gorm:"foreignKey:StackTemplateId"` - Favorites *[]ClusterFavorite - ClusterType domain.ClusterType `gorm:"default:0"` - ByoClusterEndpointHost string - ByoClusterEndpointPort int - IsStack bool `gorm:"default:false"` - TksCpNode int - TksCpNodeMax int - TksCpNodeType string - TksInfraNode int - TksInfraNodeMax int - TksInfraNodeType string - TksUserNode int - TksUserNodeMax int - TksUserNodeType string - Kubeconfig []byte `gorm:"-:all"` - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` -} - -func (m *Cluster) SetDefaultConf() { - m.TksCpNodeMax = m.TksCpNode - - if m.TksInfraNode == 0 { - m.TksInfraNode = 3 - } - m.TksInfraNodeMax = m.TksInfraNode - - if m.TksUserNode == 0 { - m.TksUserNode = 1 - } - m.TksUserNodeMax = m.TksUserNode - - if m.TksCpNodeType == "" { - m.TksCpNodeType = "t3.xlarge" - } - if m.TksInfraNodeType == "" { - m.TksInfraNodeType = "t3.2xlarge" - } - if m.TksUserNodeType == "" { - m.TksUserNodeType = "t3.large" - } -} - -type ClusterFavorite struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid"` - ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - UserId uuid.UUID `gorm:"type:uuid"` - User User `gorm:"foreignKey:UserId"` -} - -func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/dashboard.go b/internal/model/dashboard.go deleted file mode 100644 index 3cb73ce4..00000000 --- a/internal/model/dashboard.go +++ /dev/null @@ -1,4 +0,0 @@ -package model - -// Dashboard 는 DB repository 접근이 없이 외부 데이터만을 참조하므로, 일단 pkg/domain 의 model 을 사용하도록 해둡니다. -// 즉, usecase 에서 직접 pkg/domain 을 참조하도록 해 두었습니다. diff --git a/internal/model/end-point.go b/internal/model/end-point.go deleted file mode 100644 index 912fa0ce..00000000 --- a/internal/model/end-point.go +++ /dev/null @@ -1,11 +0,0 @@ -package model - -import ( - "time" -) - -type Endpoint struct { - Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` - Group string `gorm:"type:text;" json:"group"` - CreatedAt time.Time -} diff --git a/internal/model/organization.go b/internal/model/organization.go deleted file mode 100644 index 74264c16..00000000 --- a/internal/model/organization.go +++ /dev/null @@ -1,21 +0,0 @@ -package model - -import ( - "gorm.io/gorm" - - "github.com/openinfradev/tks-api/pkg/domain" -) - -type Organization struct { - gorm.Model - - ID string `gorm:"primarykey;type:varchar(36);not null"` - Name string - Description string - Phone string - PrimaryClusterId string - WorkflowId string - Status domain.OrganizationStatus - StatusDesc string - Creator string -} diff --git a/internal/model/permission.go b/internal/model/permission.go deleted file mode 100644 index b83824af..00000000 --- a/internal/model/permission.go +++ /dev/null @@ -1,615 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/delivery/api" - "github.com/openinfradev/tks-api/internal/helper" - "gorm.io/gorm" -) - -type PermissionKind string - -const ( - DashBoardPermission PermissionKind = "대시보드" - StackPermission PermissionKind = "스택 관리" - SecurityPolicyPermission PermissionKind = "보안/정책 관리" - ProjectManagementPermission PermissionKind = "프로젝트 관리" - NotificationPermission PermissionKind = "알림" - ConfigurationPermission PermissionKind = "설정" -) - -type Permission struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` - Name string `json:"name"` - - IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` - RoleID *string `json:"role_id,omitempty"` - Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` - Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` - // omit empty - - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` - Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` -} - -func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { - if p.ID == uuid.Nil { - p.ID = uuid.New() - } - return nil -} - -type PermissionSet struct { - Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` - Stack *Permission `gorm:"-:all" json:"stack,omitempty"` - SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` - ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` - Notification *Permission `gorm:"-:all" json:"notification,omitempty"` - Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` -} - -func NewDefaultPermissionSet() *PermissionSet { - return &PermissionSet{ - Dashboard: newDashboard(), - Stack: newStack(), - SecurityPolicy: newSecurityPolicy(), - ProjectManagement: newProjectManagement(), - Notification: newNotification(), - Configuration: newConfiguration(), - } -} - -func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { - if root.Children == nil { - return append(edgePermissions, root) - } - - for _, child := range root.Children { - if f != nil && !(*f)(*child) { - continue - } - edgePermissions = GetEdgePermission(child, edgePermissions, f) - } - - return edgePermissions -} - -func SetRoleIDToPermission(roleID string, permission *Permission) { - permission.RoleID = helper.StringP(roleID) -} - -func endpointObjects(eps ...api.Endpoint) []*Endpoint { - var result []*Endpoint - for _, ep := range eps { - result = append(result, &Endpoint{ - Name: api.ApiMap[ep].Name, - Group: api.ApiMap[ep].Group, - }) - } - return result -} - -func newDashboard() *Permission { - dashboard := &Permission{ - Name: string(DashBoardPermission), - Children: []*Permission{ - { - Name: "대시보드", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetChartsDashboard, - api.GetChartDashboard, - api.GetStacksDashboard, - api.GetResourcesDashboard, - ), - }, - }, - }, - { - Name: "대시보드 설정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return dashboard -} - -func newStack() *Permission { - stack := &Permission{ - Name: string(StackPermission), - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetStacks, - api.GetStack, - api.CheckStackName, - api.GetStackStatus, - api.GetStackKubeConfig, - - api.SetFavoriteStack, - api.DeleteFavoriteStack, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateStack, - api.InstallStack, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateStack, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteStack, - ), - }, - }, - } - - return stack -} - -func newSecurityPolicy() *Permission { - security_policy := &Permission{ - Name: string(SecurityPolicyPermission), - Children: []*Permission{ - { - Name: "보안/정책", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return security_policy -} - -func newProjectManagement() *Permission { - projectManagement := &Permission{ - Name: string(ProjectManagementPermission), - Children: []*Permission{ - { - Name: "프로젝트", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateProject, - ), - }, - }, - }, - { - Name: "앱 서빙", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetAppServeApps, - api.GetAppServeApp, - api.GetNumOfAppsOnStack, - api.GetAppServeAppLatestTask, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - ), - }, - { - Name: "빌드", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), - }, - { - Name: "배포", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteAppServeApp, - ), - }, - }, - }, - { - Name: "설정-일반", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, - - api.GetProjectRoles, - api.GetProjectRole, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProject, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProject, - ), - }, - }, - }, - { - Name: "설정-멤버", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjectMembers, - api.GetProjectMember, - api.GetProjectRoles, - api.GetProjectRole, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.AddProjectMember, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProjectMemberRole, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.RemoveProjectMember, - ), - }, - }, - }, - { - Name: "설정-네임스페이스", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjectNamespaces, - api.GetProjectNamespace, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateProjectNamespace, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects(), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProjectNamespace, - ), - }, - }, - }, - }, - } - - return projectManagement -} - -func newNotification() *Permission { - notification := &Permission{ - Name: string(NotificationPermission), - Children: []*Permission{ - { - Name: "시스템 경고", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "보안/정책 감사로그", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return notification -} - -func newConfiguration() *Permission { - configuration := &Permission{ - Name: string(ConfigurationPermission), - Children: []*Permission{ - { - Name: "일반", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "클라우드 계정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "스택 템플릿", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "프로젝트 관리", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "사용자", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "사용자 권한 관리", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "알림 설정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return configuration -} - -func (p *PermissionSet) SetAllowedPermissionSet() { - edgePermissions := make([]*Permission, 0) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) - - for _, permission := range edgePermissions { - permission.IsAllowed = helper.BoolP(true) - } - - return -} - -func (p *PermissionSet) SetUserPermissionSet() { - f := func(permission Permission) bool { - return permission.Name == "조회" - } - edgePermissions := make([]*Permission, 0) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) - //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) - - for _, permission := range edgePermissions { - permission.IsAllowed = helper.BoolP(true) - } - - return -} - -func (p *PermissionSet) SetRoleId(roleId string) { - setRoleIdToPermission(p.Dashboard, roleId) - setRoleIdToPermission(p.Stack, roleId) - setRoleIdToPermission(p.SecurityPolicy, roleId) - setRoleIdToPermission(p.ProjectManagement, roleId) - setRoleIdToPermission(p.Notification, roleId) - setRoleIdToPermission(p.Configuration, roleId) -} - -func setRoleIdToPermission(root *Permission, roleId string) { - root.RoleID = helper.StringP(roleId) - - if root.Children == nil { - return - } - - for _, child := range root.Children { - setRoleIdToPermission(child, roleId) - } -} diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go deleted file mode 100644 index 430c4b7d..00000000 --- a/internal/model/policy-template.go +++ /dev/null @@ -1,48 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/gorm" -) - -type PolicyTemplateSupportedVersion struct { - gorm.Model - - PolicyTemplateId uuid.UUID `gorm:"index:template_version,unique"` - Version string `gorm:"index:template_version,unique"` - - ParameterSchema string `gorm:"type:text"` - Rego string `gorm:"type:text"` - Libs string `gorm:"type:text"` -} - -type PolicyTemplate struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` - Type string // Org or Tks - Name string - Version string - SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` - Description string - Kind string - Deprecated bool - Mandatory bool // Tks 인 경우에는 무시 - Severity string - PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organiations;"` - TemplateName string `gorm:"-:all" json:"templateName"` - ParametersSchema []domain.ParameterDef `gorm:"-:all" json:"parametersSchema,omitempty"` - Rego string `gorm:"-:all"` - Libs []string `gorm:"-:all"` - PermittedOrganizationIds []string `gorm:"-:all"` - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` -} - -func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/role.go b/internal/model/role.go deleted file mode 100644 index 01f6497a..00000000 --- a/internal/model/role.go +++ /dev/null @@ -1,27 +0,0 @@ -package model - -import ( - "time" - - "github.com/google/uuid" - "gorm.io/gorm" -) - -func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { - r.ID = uuid.New().String() - return nil -} - -type Role struct { - gorm.Model - - ID string `gorm:"primarykey;" json:"id"` - Name string `json:"name"` - OrganizationID string `json:"organizationId"` - Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;" json:"organization"` - Type string `json:"type"` - Description string `json:"description"` - Creator uuid.UUID `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} diff --git a/internal/model/stack-template.go b/internal/model/stack-template.go deleted file mode 100644 index c74cad06..00000000 --- a/internal/model/stack-template.go +++ /dev/null @@ -1,40 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - "gorm.io/datatypes" - "gorm.io/gorm" -) - -type StackTemplate struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - Name string `gorm:"index"` - Description string `gorm:"index"` - Template string - TemplateType string - Version string - CloudService string - Platform string - KubeVersion string - KubeType string - Organizations []Organization `gorm:"many2many:stack_template_organizations"` - Services datatypes.JSON - ServiceIds []string `gorm:"-:all"` - OrganizationIds []string `gorm:"-:all"` - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` -} - -func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - -type StackTemplateOrganization struct { - StackTemplateId uuid.UUID `gorm:"primarykey"` - OrganizationId string `gorm:"primarykey"` -} diff --git a/internal/model/stack.go b/internal/model/stack.go deleted file mode 100644 index 72300ee5..00000000 --- a/internal/model/stack.go +++ /dev/null @@ -1,45 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/gorm" -) - -type Stack = struct { - gorm.Model - - ID domain.StackId - Name string - Description string - ClusterId string - OrganizationId string - CloudService string - CloudAccountId uuid.UUID - CloudAccount CloudAccount - StackTemplateId uuid.UUID - StackTemplate StackTemplate - Status domain.StackStatus - StatusDesc string - PrimaryCluster bool - GrafanaUrl string - CreatorId *uuid.UUID - Creator User - UpdatorId *uuid.UUID - Updator User - Favorited bool - ClusterEndpoint string - Resource domain.DashboardStack -} - -type StackConf struct { - TksCpNode int - TksCpNodeMax int - TksCpNodeType string - TksInfraNode int - TksInfraNodeMax int - TksInfraNodeType string - TksUserNode int - TksUserNodeMax int - TksUserNodeType string -} diff --git a/internal/model/user.go b/internal/model/user.go deleted file mode 100644 index 96303110..00000000 --- a/internal/model/user.go +++ /dev/null @@ -1,34 +0,0 @@ -package model - -import ( - "time" - - "github.com/google/uuid" - "gorm.io/gorm" -) - -type User struct { - ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` - AccountId string `json:"accountId"` - Password string `gorm:"-:all" json:"password"` - Name string `json:"name"` - Token string `json:"token"` - RoleId string - Role Role `gorm:"foreignKey:RoleId;references:ID" json:"role"` - OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` - PasswordExpired bool `json:"passwordExpired"` - - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` -} - -func (g *User) BeforeCreate(tx *gorm.DB) (err error) { - g.PasswordUpdatedAt = time.Now() - return nil -} diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 591a498c..0de16f10 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -9,8 +9,6 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" - "golang.org/x/text/cases" - "golang.org/x/text/language" "gorm.io/gorm" "goyave.dev/goyave/v4" @@ -86,10 +84,6 @@ func (p *Pagination) GetFilters() []Filter { return p.Filters } -func (p *Pagination) AddFilter(f Filter) { - p.Filters = append(p.Filters, f) -} - func (p *Pagination) MakePaginationRequest() { if p.PaginationRequest == nil { p.PaginationRequest = &goyave.Request{} @@ -120,11 +114,9 @@ func (p *Pagination) MakePaginationRequest() { } pgSorts = append(pgSorts, &pgSort) - pgJoins := filter.Join{} - p.PaginationRequest.Data = map[string]interface{}{ - "filter": pgFilters, - "join": pgJoins, + "filter": pgFilters, + //"join": pgJoins, "page": p.Page, "per_page": p.Limit, "sort": pgSorts, @@ -220,7 +212,7 @@ func NewPagination(urlParams *url.Values) *Pagination { releation := "" arrColumns := strings.Split(column, ".") if len(arrColumns) > 1 { - releation = cases.Title(language.English, cases.Compact).String(arrColumns[0]) + releation = arrColumns[0] column = arrColumns[1] } diff --git a/internal/repository/alert.go b/internal/repository/alert.go index 2d35f536..4e8c8575 100644 --- a/internal/repository/alert.go +++ b/internal/repository/alert.go @@ -4,25 +4,27 @@ import ( "time" "github.com/google/uuid" + "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAlertRepository interface { - Get(alertId uuid.UUID) (model.Alert, error) - GetByName(organizationId string, name string) (model.Alert, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]model.Alert, error) - FetchPodRestart(organizationId string, start time.Time, end time.Time) ([]model.Alert, error) - Create(dto model.Alert) (alertId uuid.UUID, err error) - Update(dto model.Alert) (err error) - Delete(dto model.Alert) (err error) - - CreateAlertAction(dto model.AlertAction) (alertActionId uuid.UUID, err error) + Get(alertId uuid.UUID) (domain.Alert, error) + GetByName(organizationId string, name string) (domain.Alert, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]domain.Alert, error) + FetchPodRestart(organizationId string, start time.Time, end time.Time) ([]domain.Alert, error) + Create(dto domain.Alert) (alertId uuid.UUID, err error) + Update(dto domain.Alert) (err error) + Delete(dto domain.Alert) (err error) + + CreateAlertAction(dto domain.AlertAction) (alertActionId uuid.UUID, err error) } type AlertRepository struct { @@ -35,55 +37,114 @@ func NewAlertRepository(db *gorm.DB) IAlertRepository { } } +// Models +type Alert struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` + Name string + Code string + Description string + Grade string + Message string + ClusterId domain.ClusterId + Cluster Cluster `gorm:"foreignKey:ClusterId"` + Node string + CheckPoint string + GrafanaUrl string + Summary string + AlertActions []AlertAction + RawData datatypes.JSON + Status domain.AlertActionStatus `gorm:"index"` +} + +func (c *Alert) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + +type AlertAction struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + AlertId uuid.UUID + Content string + Status domain.AlertActionStatus + TakerId *uuid.UUID `gorm:"type:uuid"` + Taker domain.User `gorm:"foreignKey:TakerId"` +} + +func (c *AlertAction) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + // Logics -func (r *AlertRepository) Get(alertId uuid.UUID) (out model.Alert, err error) { - res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "id = ?", alertId) +func (r *AlertRepository) Get(alertId uuid.UUID) (out domain.Alert, err error) { + var alert Alert + res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&alert, "id = ?", alertId) if res.Error != nil { - return model.Alert{}, res.Error + return domain.Alert{}, res.Error } + out = reflectAlert(alert) return } -func (r *AlertRepository) GetByName(organizationId string, name string) (out model.Alert, err error) { - res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) +func (r *AlertRepository) GetByName(organizationId string, name string) (out domain.Alert, err error) { + var alert Alert + res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&alert, "organization_id = ? AND name = ?", organizationId, name) + if res.Error != nil { - return model.Alert{}, res.Error + return domain.Alert{}, res.Error } + out = reflectAlert(alert) return } -func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.Alert, err error) { +func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.Alert, err error) { + var alerts []Alert if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.Alert{}). + _, res := pg.Fetch(r.db.Model(&Alert{}). Preload("AlertActions", func(db *gorm.DB) *gorm.DB { return db.Order("created_at ASC") }).Preload("AlertActions.Taker"). Preload("Cluster", "status = 2"). Preload("Organization"). Joins("join clusters on clusters.id = alerts.cluster_id AND clusters.status = 2"). - Where("alerts.organization_id = ?", organizationId), &out) + Where("alerts.organization_id = ?", organizationId), &alerts) if res.Error != nil { return nil, res.Error } + + for _, alert := range alerts { + out = append(out, reflectAlert(alert)) + } return } -func (r *AlertRepository) FetchPodRestart(organizationId string, start time.Time, end time.Time) (out []model.Alert, err error) { +func (r *AlertRepository) FetchPodRestart(organizationId string, start time.Time, end time.Time) (out []domain.Alert, err error) { + var alerts []Alert res := r.db.Preload(clause.Associations).Order("created_at DESC"). Where("organization_id = ? AND name = 'pod-restart-frequently' AND created_at BETWEEN ? AND ?", organizationId, start, end). - Find(&out) + Find(&alerts) if res.Error != nil { return nil, res.Error } + + for _, alert := range alerts { + out = append(out, reflectAlert(alert)) + } return } -func (r *AlertRepository) Create(dto model.Alert) (alertId uuid.UUID, err error) { - alert := model.Alert{ +func (r *AlertRepository) Create(dto domain.Alert) (alertId uuid.UUID, err error) { + alert := Alert{ OrganizationId: dto.OrganizationId, Name: dto.Name, Code: dto.Code, @@ -105,8 +166,8 @@ func (r *AlertRepository) Create(dto model.Alert) (alertId uuid.UUID, err error) return alert.ID, nil } -func (r *AlertRepository) Update(dto model.Alert) (err error) { - res := r.db.Model(&model.Alert{}). +func (r *AlertRepository) Update(dto domain.Alert) (err error) { + res := r.db.Model(&Alert{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description}) if res.Error != nil { @@ -115,16 +176,16 @@ func (r *AlertRepository) Update(dto model.Alert) (err error) { return nil } -func (r *AlertRepository) Delete(dto model.Alert) (err error) { - res := r.db.Delete(&model.Alert{}, "id = ?", dto.ID) +func (r *AlertRepository) Delete(dto domain.Alert) (err error) { + res := r.db.Delete(&Alert{}, "id = ?", dto.ID) if res.Error != nil { return res.Error } return nil } -func (r *AlertRepository) CreateAlertAction(dto model.AlertAction) (alertActionId uuid.UUID, err error) { - alert := model.AlertAction{ +func (r *AlertRepository) CreateAlertAction(dto domain.AlertAction) (alertActionId uuid.UUID, err error) { + alert := AlertAction{ AlertId: dto.AlertId, Content: dto.Content, Status: dto.Status, @@ -134,7 +195,7 @@ func (r *AlertRepository) CreateAlertAction(dto model.AlertAction) (alertActionI if res.Error != nil { return uuid.Nil, res.Error } - res = r.db.Model(&model.Alert{}). + res = r.db.Model(&Alert{}). Where("id = ?", dto.AlertId). Update("status", dto.Status) if res.Error != nil { @@ -143,3 +204,25 @@ func (r *AlertRepository) CreateAlertAction(dto model.AlertAction) (alertActionI return alert.ID, nil } + +func reflectAlert(alert Alert) (out domain.Alert) { + if err := serializer.Map(alert.Model, &out); err != nil { + log.Error(err) + } + if err := serializer.Map(alert, &out); err != nil { + log.Error(err) + } + + out.AlertActions = make([]domain.AlertAction, len(alert.AlertActions)) + for i, alertAction := range alert.AlertActions { + if err := serializer.Map(alertAction.Model, &out.AlertActions[i]); err != nil { + log.Error(err) + continue + } + if err := serializer.Map(alertAction, &out.AlertActions[i]); err != nil { + log.Error(err) + continue + } + } + return +} diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index bd824996..d78aa1bc 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -3,24 +3,26 @@ package repository import ( "fmt" + "github.com/google/uuid" "gorm.io/datatypes" "gorm.io/gorm" - "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAppGroupRepository interface { - Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (res []model.AppGroup, err error) - Get(id domain.AppGroupId) (model.AppGroup, error) - Create(dto model.AppGroup) (id domain.AppGroupId, err error) - Update(dto model.AppGroup) (err error) + Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (res []domain.AppGroup, err error) + Get(id domain.AppGroupId) (domain.AppGroup, error) + Create(dto domain.AppGroup) (id domain.AppGroupId, err error) + Update(dto domain.AppGroup) (err error) Delete(id domain.AppGroupId) error - GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (applications []model.Application, err error) - UpsertApplication(dto model.Application) error + GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (applications []domain.Application, err error) + UpsertApplication(dto domain.Application) error InitWorkflow(appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error InitWorkflowDescription(clusterId domain.ClusterId) error } @@ -35,31 +37,76 @@ func NewAppGroupRepository(db *gorm.DB) IAppGroupRepository { } } +// Models +type AppGroup struct { + gorm.Model + + ID domain.AppGroupId `gorm:"primarykey"` + AppGroupType domain.AppGroupType + ClusterId domain.ClusterId + Name string + Description string + WorkflowId string + Status domain.AppGroupStatus + StatusDesc string + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` +} + +func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = domain.AppGroupId(helper.GenerateApplicaionGroupId()) + return nil +} + +type Application struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid"` + AppGroupId domain.AppGroupId + Endpoint string + Metadata datatypes.JSON + Type domain.ApplicationType +} + +func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + // Logics -func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { +func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (out []domain.AppGroup, err error) { + var appGroups []AppGroup if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.AppGroup{}). - Where("cluster_id = ?", clusterId), &out) + _, res := pg.Fetch(r.db.Model(&AppGroup{}). + Where("cluster_id = ?", clusterId), &appGroups) if res.Error != nil { return nil, res.Error } + for _, appGroup := range appGroups { + outAppGroup := reflectAppGroup(appGroup) + out = append(out, outAppGroup) + } return out, nil } -func (r *AppGroupRepository) Get(id domain.AppGroupId) (out model.AppGroup, err error) { - res := r.db.First(&out, "id = ?", id) +func (r *AppGroupRepository) Get(id domain.AppGroupId) (domain.AppGroup, error) { + var appGroup AppGroup + res := r.db.First(&appGroup, "id = ?", id) if res.RowsAffected == 0 || res.Error != nil { - return model.AppGroup{}, fmt.Errorf("Not found appGroup for %s", id) + return domain.AppGroup{}, fmt.Errorf("Not found appGroup for %s", id) } - return out, nil + resAppGroup := reflectAppGroup(appGroup) + return resAppGroup, nil } -func (r *AppGroupRepository) Create(dto model.AppGroup) (appGroupId domain.AppGroupId, err error) { - appGroup := model.AppGroup{ +func (r *AppGroupRepository) Create(dto domain.AppGroup) (appGroupId domain.AppGroupId, err error) { + appGroup := AppGroup{ ClusterId: dto.ClusterId, AppGroupType: dto.AppGroupType, Name: dto.Name, @@ -77,8 +124,8 @@ func (r *AppGroupRepository) Create(dto model.AppGroup) (appGroupId domain.AppGr return appGroup.ID, nil } -func (r *AppGroupRepository) Update(dto model.AppGroup) (err error) { - res := r.db.Model(&model.AppGroup{}). +func (r *AppGroupRepository) Update(dto domain.AppGroup) (err error) { + res := r.db.Model(&AppGroup{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ "ClusterId": dto.ClusterId, @@ -94,30 +141,35 @@ func (r *AppGroupRepository) Update(dto model.AppGroup) (err error) { } func (r *AppGroupRepository) Delete(id domain.AppGroupId) error { - res := r.db.Unscoped().Delete(&model.AppGroup{}, "id = ?", id) + res := r.db.Unscoped().Delete(&AppGroup{}, "id = ?", id) if res.Error != nil { return fmt.Errorf("could not delete appGroup %s", id) } return nil } -func (r *AppGroupRepository) GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { - res := r.db.Where("app_group_id = ? AND type = ?", id, applicationType).Find(&out) +func (r *AppGroupRepository) GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) { + var applications []Application + res := r.db.Where("app_group_id = ? AND type = ?", id, applicationType).Find(&applications) if res.Error != nil { return nil, res.Error } + for _, application := range applications { + outApplication := reflectApplication(application) + out = append(out, outApplication) + } return out, nil } -func (r *AppGroupRepository) UpsertApplication(dto model.Application) error { - res := r.db.Where(model.Application{ +func (r *AppGroupRepository) UpsertApplication(dto domain.Application) error { + res := r.db.Where(Application{ AppGroupId: dto.AppGroupId, - Type: dto.Type, + Type: dto.ApplicationType, }). - Assign(model.Application{ + Assign(Application{ Endpoint: dto.Endpoint, Metadata: datatypes.JSON([]byte(dto.Metadata))}). - FirstOrCreate(&model.Application{}) + FirstOrCreate(&Application{}) if res.Error != nil { return res.Error } @@ -126,7 +178,7 @@ func (r *AppGroupRepository) UpsertApplication(dto model.Application) error { } func (r *AppGroupRepository) InitWorkflow(appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error { - res := r.db.Model(&model.AppGroup{}). + res := r.db.Model(&AppGroup{}). Where("ID = ?", appGroupId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId, "StatusDesc": ""}) @@ -138,7 +190,7 @@ func (r *AppGroupRepository) InitWorkflow(appGroupId domain.AppGroupId, workflow } func (r *AppGroupRepository) InitWorkflowDescription(clusterId domain.ClusterId) error { - res := r.db.Model(&model.AppGroup{}). + res := r.db.Model(&AppGroup{}). Where("cluster_id = ?", clusterId). Updates(map[string]interface{}{"WorkflowId": "", "StatusDesc": ""}) @@ -148,3 +200,22 @@ func (r *AppGroupRepository) InitWorkflowDescription(clusterId domain.ClusterId) return nil } + +func reflectAppGroup(appGroup AppGroup) (out domain.AppGroup) { + if err := serializer.Map(appGroup.Model, &out); err != nil { + log.Error(err) + } + if err := serializer.Map(appGroup, &out); err != nil { + log.Error(err) + } + return +} + +func reflectApplication(application Application) (out domain.Application) { + if err := serializer.Map(application, &out); err != nil { + log.Error(err) + } + out.Metadata = application.Metadata.String() + return + +} diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index a1d3e291..479f4e77 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -4,7 +4,6 @@ import ( "fmt" "time" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" @@ -12,19 +11,19 @@ import ( ) type IAppServeAppRepository interface { - CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) - GetAppServeAppById(appId string) (*model.AppServeApp, error) + CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) + GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) + GetAppServeAppById(appId string) (*domain.AppServeApp, error) - GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) - GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) + GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) + GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) - GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) + GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) IsAppServeAppExist(appId string) (int64, error) IsAppServeAppNameExist(orgId string, appName string) (int64, error) - CreateTask(task *model.AppServeAppTask) (taskId string, err error) + CreateTask(task *domain.AppServeAppTask) (taskId string, err error) UpdateStatus(appId string, taskId string, status string, output string) error UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error GetTaskCountById(appId string) (int64, error) @@ -40,7 +39,7 @@ func NewAppServeAppRepository(db *gorm.DB) IAppServeAppRepository { } } -func (r *AppServeAppRepository) CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) { +func (r *AppServeAppRepository) CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) { res := r.db.Create(&app) if res.Error != nil { @@ -52,7 +51,7 @@ func (r *AppServeAppRepository) CreateAppServeApp(app *model.AppServeApp) (appId // Update creates new appServeApp task for existing appServeApp. func (r *AppServeAppRepository) CreateTask( - task *model.AppServeAppTask) (string, error) { + task *domain.AppServeAppTask) (string, error) { res := r.db.Create(task) if res.Error != nil { return "", res.Error @@ -61,14 +60,14 @@ func (r *AppServeAppRepository) CreateTask( return task.ID, nil } -func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) (apps []model.AppServeApp, err error) { - var clusters []model.Cluster +func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) (apps []domain.AppServeApp, err error) { + var clusters []Cluster if pg == nil { pg = pagination.NewPagination(nil) } // TODO: should return different records based on showAll param - _, res := pg.Fetch(r.db.Model(&model.AppServeApp{}). + _, res := pg.Fetch(r.db.Model(&domain.AppServeApp{}). Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId), &apps) if res.Error != nil { return nil, fmt.Errorf("error while finding appServeApps with organizationId: %s", organizationId) @@ -98,9 +97,9 @@ func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll b return } -func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*model.AppServeApp, error) { - var app model.AppServeApp - var cluster model.Cluster +func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppServeApp, error) { + var app domain.AppServeApp + var cluster Cluster res := r.db.Where("id = ?", appId).First(&app) if res.Error != nil { @@ -124,12 +123,12 @@ func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*model.AppServ return &app, nil } -func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []model.AppServeAppTask, err error) { +func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []domain.AppServeAppTask, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.AppServeAppTask{}). + _, res := pg.Fetch(r.db.Model(&domain.AppServeAppTask{}). Where("app_serve_app_tasks.app_serve_app_id = ?", appId), &tasks) if res.Error != nil { return nil, fmt.Errorf("Error while finding tasks with appId: %s", appId) @@ -144,9 +143,9 @@ func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pag } // Return single task info along with its parent app info -func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { - var task model.AppServeAppTask - var app model.AppServeApp +func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) { + var task domain.AppServeAppTask + var app domain.AppServeApp // Retrieve task info res := r.db.Where("id = ?", taskId).First(&task) @@ -171,8 +170,8 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*model.Ap return &task, &app, nil } -func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) { - var task model.AppServeAppTask +func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) { + var task domain.AppServeAppTask // TODO: Does this work?? where's app ID here? res := r.db.Order("created_at desc").First(&task) @@ -188,7 +187,7 @@ func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*model.A } func (r *AppServeAppRepository) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) { - var apps []model.AppServeApp + var apps []domain.AppServeApp queryStr := fmt.Sprintf("organization_id = '%s' AND target_cluster_id = '%s' AND status <> 'DELETE_SUCCESS'", organizationId, clusterId) res := r.db.Find(&apps, queryStr) @@ -228,7 +227,7 @@ func (r *AppServeAppRepository) IsAppServeAppNameExist(orgId string, appName str func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status string, output string) error { now := time.Now() - app := model.AppServeApp{ + app := domain.AppServeApp{ ID: appId, Status: status, UpdatedAt: &now, @@ -238,7 +237,7 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status return fmt.Errorf("UpdateStatus: nothing updated in AppServeApp with ID %s", appId) } - task := model.AppServeAppTask{ + task := domain.AppServeAppTask{ ID: taskId, Status: status, Output: output, @@ -250,16 +249,16 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status } //// Update task status - //res := r.db.Model(&model.AppServeAppTask{}). + //res := r.db.Model(&domain.AppServeAppTask{}). // Where("ID = ?", taskId). - // Updates(model.AppServeAppTask{Status: status, Output: output}) + // Updates(domain.AppServeAppTask{Status: status, Output: output}) // //if res.Error != nil || res.RowsAffected == 0 { // return fmt.Errorf("UpdateStatus: nothing updated in AppServeAppTask with ID %s", taskId) //} // //// Update status of the app. - //res = r.db.Model(&model.AppServeApp{}). + //res = r.db.Model(&domain.AppServeApp{}). // Where("ID = ?", appId). // Update("Status", status) //if res.Error != nil || res.RowsAffected == 0 { @@ -271,14 +270,14 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error { now := time.Now() - app := model.AppServeApp{ + app := domain.AppServeApp{ ID: appId, EndpointUrl: endpoint, PreviewEndpointUrl: previewEndpoint, UpdatedAt: &now, } - task := model.AppServeAppTask{ + task := domain.AppServeAppTask{ ID: taskId, HelmRevision: helmRevision, UpdatedAt: &now, @@ -317,7 +316,7 @@ func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endp func (r *AppServeAppRepository) GetTaskCountById(appId string) (int64, error) { var count int64 - if err := r.db.Model(&model.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { + if err := r.db.Model(&domain.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { return 0, fmt.Errorf("could not select count AppServeAppTask with ID: %s", appId) } return count, nil diff --git a/internal/repository/audit.go b/internal/repository/audit.go index f7e0c5dd..bbee184c 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -7,15 +7,17 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAuditRepository interface { - Get(auditId uuid.UUID) (model.Audit, error) - Fetch(pg *pagination.Pagination) ([]model.Audit, error) - Create(dto model.Audit) (auditId uuid.UUID, err error) + Get(auditId uuid.UUID) (domain.Audit, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]domain.Audit, error) + Create(dto domain.Audit) (auditId uuid.UUID, err error) Delete(auditId uuid.UUID) (err error) } @@ -29,30 +31,59 @@ func NewAuditRepository(db *gorm.DB) IAuditRepository { } } +// Models +type Audit struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` + Group string + Message string + Description string + ClientIP string + UserId *uuid.UUID `gorm:"type:uuid"` + User domain.User `gorm:"foreignKey:UserId"` +} + +func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + // Logics -func (r *AuditRepository) Get(auditId uuid.UUID) (out model.Audit, err error) { - res := r.db.Preload(clause.Associations).First(&out, "id = ?", auditId) +func (r *AuditRepository) Get(auditId uuid.UUID) (out domain.Audit, err error) { + var audit Audit + res := r.db.Preload(clause.Associations).First(&audit, "id = ?", auditId) if res.Error != nil { return } + out = reflectAudit(audit) return } -func (r *AuditRepository) Fetch(pg *pagination.Pagination) (out []model.Audit, err error) { +func (r *AuditRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.Audit, err error) { + var audits []Audit + if pg == nil { pg = pagination.NewPagination(nil) } - db := r.db.Model(&model.Audit{}).Preload(clause.Associations) - _, res := pg.Fetch(db, &out) + db := r.db.Model(&Audit{}).Preload(clause.Associations).Where("organization_id = ?", organizationId) + _, res := pg.Fetch(db, &audits) if res.Error != nil { return nil, res.Error } + + for _, audit := range audits { + out = append(out, reflectAudit(audit)) + } + return } -func (r *AuditRepository) Create(dto model.Audit) (auditId uuid.UUID, err error) { - audit := model.Audit{ +func (r *AuditRepository) Create(dto domain.Audit) (auditId uuid.UUID, err error) { + audit := Audit{ OrganizationId: dto.OrganizationId, Group: dto.Group, Message: dto.Message, @@ -69,3 +100,13 @@ func (r *AuditRepository) Create(dto model.Audit) (auditId uuid.UUID, err error) func (r *AuditRepository) Delete(auditId uuid.UUID) (err error) { return fmt.Errorf("to be implemented") } + +func reflectAudit(audit Audit) (out domain.Audit) { + if err := serializer.Map(audit.Model, &out); err != nil { + log.Error(err) + } + if err := serializer.Map(audit, &out); err != nil { + log.Error(err) + } + return +} diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index 08f635c8..5d9a7de9 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -7,19 +7,20 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type ICloudAccountRepository interface { - Get(cloudAccountId uuid.UUID) (model.CloudAccount, error) - GetByName(organizationId string, name string) (model.CloudAccount, error) - GetByAwsAccountId(awsAccountId string) (model.CloudAccount, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) - Create(dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) - Update(dto model.CloudAccount) (err error) + Get(cloudAccountId uuid.UUID) (domain.CloudAccount, error) + GetByName(organizationId string, name string) (domain.CloudAccount, error) + GetByAwsAccountId(awsAccountId string) (domain.CloudAccount, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]domain.CloudAccount, error) + Create(dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) + Update(dto domain.CloudAccount) (err error) Delete(cloudAccountId uuid.UUID) (err error) InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) (err error) } @@ -34,46 +35,86 @@ func NewCloudAccountRepository(db *gorm.DB) ICloudAccountRepository { } } +// Models +type CloudAccount struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` + Name string `gorm:"index"` + Description string `gorm:"index"` + Resource string + CloudService string + WorkflowId string + Status domain.CloudAccountStatus + StatusDesc string + AwsAccountId string + CreatedIAM bool + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` +} + +func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + // Logics -func (r *CloudAccountRepository) Get(cloudAccountId uuid.UUID) (out model.CloudAccount, err error) { - res := r.db.Preload(clause.Associations).First(&out, "id = ?", cloudAccountId) +func (r *CloudAccountRepository) Get(cloudAccountId uuid.UUID) (out domain.CloudAccount, err error) { + var cloudAccount CloudAccount + res := r.db.Preload(clause.Associations).First(&cloudAccount, "id = ?", cloudAccountId) if res.Error != nil { - return model.CloudAccount{}, res.Error + return domain.CloudAccount{}, res.Error } + out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) GetByName(organizationId string, name string) (out model.CloudAccount, err error) { - res := r.db.Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) +func (r *CloudAccountRepository) GetByName(organizationId string, name string) (out domain.CloudAccount, err error) { + var cloudAccount CloudAccount + res := r.db.Preload(clause.Associations).First(&cloudAccount, "organization_id = ? AND name = ?", organizationId, name) + if res.Error != nil { - return model.CloudAccount{}, res.Error + return domain.CloudAccount{}, res.Error } + out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) GetByAwsAccountId(awsAccountId string) (out model.CloudAccount, err error) { - res := r.db.Preload(clause.Associations).First(&out, "aws_account_id = ? AND status != ?", awsAccountId, domain.CloudAccountStatus_DELETED) +func (r *CloudAccountRepository) GetByAwsAccountId(awsAccountId string) (out domain.CloudAccount, err error) { + var cloudAccount CloudAccount + res := r.db.Preload(clause.Associations).First(&cloudAccount, "aws_account_id = ? AND status != ?", awsAccountId, domain.CloudAccountStatus_DELETED) + if res.Error != nil { - return model.CloudAccount{}, res.Error + return domain.CloudAccount{}, res.Error } + out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.CloudAccount, err error) { +func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.CloudAccount, err error) { + var cloudAccounts []CloudAccount if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.CloudAccount{}). + _, res := pg.Fetch(r.db.Model(&CloudAccount{}). Preload(clause.Associations). - Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED), &out) + Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED), &cloudAccounts) if res.Error != nil { return nil, res.Error } + + for _, cloudAccount := range cloudAccounts { + out = append(out, reflectCloudAccount(cloudAccount)) + } return } -func (r *CloudAccountRepository) Create(dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { - cloudAccount := model.CloudAccount{ +func (r *CloudAccountRepository) Create(dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) { + cloudAccount := CloudAccount{ OrganizationId: dto.OrganizationId, Name: dto.Name, Description: dto.Description, @@ -82,7 +123,7 @@ func (r *CloudAccountRepository) Create(dto model.CloudAccount) (cloudAccountId AwsAccountId: dto.AwsAccountId, CreatedIAM: false, Status: domain.CloudAccountStatus_PENDING, - CreatorId: dto.CreatorId} + CreatorId: &dto.CreatorId} res := r.db.Create(&cloudAccount) if res.Error != nil { return uuid.Nil, res.Error @@ -90,8 +131,8 @@ func (r *CloudAccountRepository) Create(dto model.CloudAccount) (cloudAccountId return cloudAccount.ID, nil } -func (r *CloudAccountRepository) Update(dto model.CloudAccount) (err error) { - res := r.db.Model(&model.CloudAccount{}). +func (r *CloudAccountRepository) Update(dto domain.CloudAccount) (err error) { + res := r.db.Model(&CloudAccount{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description, "Resource": dto.Resource, "UpdatorId": dto.UpdatorId}) if res.Error != nil { @@ -101,7 +142,7 @@ func (r *CloudAccountRepository) Update(dto model.CloudAccount) (err error) { } func (r *CloudAccountRepository) Delete(cloudAccountId uuid.UUID) (err error) { - res := r.db.Delete(&model.CloudAccount{}, "id = ?", cloudAccountId) + res := r.db.Delete(&CloudAccount{}, "id = ?", cloudAccountId) if res.Error != nil { return res.Error } @@ -109,7 +150,7 @@ func (r *CloudAccountRepository) Delete(cloudAccountId uuid.UUID) (err error) { } func (r *CloudAccountRepository) InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) error { - res := r.db.Model(&model.CloudAccount{}). + res := r.db.Model(&CloudAccount{}). Where("ID = ?", cloudAccountId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) @@ -119,3 +160,13 @@ func (r *CloudAccountRepository) InitWorkflow(cloudAccountId uuid.UUID, workflow return nil } + +func reflectCloudAccount(cloudAccount CloudAccount) (out domain.CloudAccount) { + if err := serializer.Map(cloudAccount.Model, &out); err != nil { + log.Error(err) + } + if err := serializer.Map(cloudAccount, &out); err != nil { + log.Error(err) + } + return +} diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 05d2cb00..e637c040 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -8,8 +8,8 @@ import ( "gorm.io/gorm/clause" "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) @@ -17,13 +17,13 @@ import ( // Interfaces type IClusterRepository interface { WithTrx(*gorm.DB) IClusterRepository - Fetch(pg *pagination.Pagination) (res []model.Cluster, err error) - FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) - FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) - Get(id domain.ClusterId) (model.Cluster, error) - GetByName(organizationId string, name string) (model.Cluster, error) - Create(dto model.Cluster) (clusterId domain.ClusterId, err error) - Update(dto model.Cluster) (err error) + Fetch(pg *pagination.Pagination) (res []domain.Cluster, err error) + FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (res []domain.Cluster, err error) + FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (res []domain.Cluster, err error) + Get(id domain.ClusterId) (domain.Cluster, error) + GetByName(organizationId string, name string) (domain.Cluster, error) + Create(dto domain.Cluster) (clusterId domain.ClusterId, err error) + Update(dto domain.Cluster) (err error) Delete(id domain.ClusterId) error InitWorkflow(clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error @@ -45,6 +45,58 @@ func NewClusterRepository(db *gorm.DB) IClusterRepository { } } +// Models +type Cluster struct { + gorm.Model + + ID domain.ClusterId `gorm:"primarykey"` + Name string `gorm:"index"` + CloudService string `gorm:"default:AWS"` + OrganizationId string + Organization domain.Organization `gorm:"foreignKey:OrganizationId"` + Description string `gorm:"index"` + WorkflowId string + Status domain.ClusterStatus + StatusDesc string + CloudAccountId *uuid.UUID + CloudAccount CloudAccount `gorm:"foreignKey:CloudAccountId"` + StackTemplateId uuid.UUID + StackTemplate StackTemplate `gorm:"foreignKey:StackTemplateId"` + Favorites *[]ClusterFavorite + ClusterType domain.ClusterType `gorm:"default:0"` + ByoClusterEndpointHost string + ByoClusterEndpointPort int + IsStack bool `gorm:"default:false"` + TksCpNode int + TksCpNodeMax int + TksCpNodeType string + TksInfraNode int + TksInfraNodeMax int + TksInfraNodeType string + TksUserNode int + TksUserNodeMax int + TksUserNodeType string + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` +} + +type ClusterFavorite struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid"` + ClusterId domain.ClusterId + Cluster Cluster `gorm:"foreignKey:ClusterId"` + UserId uuid.UUID `gorm:"type:uuid"` + User domain.User `gorm:"foreignKey:UserId"` +} + +func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + // Logics func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { if trxHandle == nil { @@ -55,70 +107,91 @@ func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { return r } -func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []model.Cluster, err error) { +func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []domain.Cluster, err error) { + var clusters []Cluster if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.Cluster{}).Preload(clause.Associations), &out) + _, res := pg.Fetch(r.db, &clusters) if res.Error != nil { return nil, res.Error } + for _, cluster := range clusters { + outCluster := reflectCluster(cluster) + out = append(out, outCluster) + } return } -func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { +func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { + var clusters []Cluster if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.Cluster{}). + _, res := pg.Fetch(r.db.Model(&Cluster{}). Preload(clause.Associations). Joins("left outer join cluster_favorites on clusters.id = cluster_favorites.cluster_id AND cluster_favorites.user_id = ?", userId). Where("organization_id = ? AND status != ?", organizationId, domain.ClusterStatus_DELETED). - Order("cluster_favorites.cluster_id"), &out) + Order("cluster_favorites.cluster_id"), &clusters) + if res.Error != nil { return nil, res.Error } + for _, cluster := range clusters { + outCluster := reflectCluster(cluster) + out = append(out, outCluster) + } + return } -func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { +func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { + var clusters []Cluster if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.Cluster{}).Preload("CloudAccount"). - Where("cloud_account_id = ?", cloudAccountId), &out) + _, res := pg.Fetch(r.db.Model(&Cluster{}).Preload("CloudAccount"). + Where("cloud_account_id = ?", cloudAccountId), &clusters) if res.Error != nil { return nil, res.Error } + for _, cluster := range clusters { + outCluster := reflectCluster(cluster) + out = append(out, outCluster) + } return } -func (r *ClusterRepository) Get(id domain.ClusterId) (out model.Cluster, err error) { - res := r.db.Preload(clause.Associations).First(&out, "id = ?", id) +func (r *ClusterRepository) Get(id domain.ClusterId) (out domain.Cluster, err error) { + var cluster Cluster + res := r.db.Preload(clause.Associations).First(&cluster, "id = ?", id) if res.Error != nil { - return model.Cluster{}, res.Error + return domain.Cluster{}, res.Error } + out = reflectCluster(cluster) return } -func (r *ClusterRepository) GetByName(organizationId string, name string) (out model.Cluster, err error) { - res := r.db.Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) +func (r *ClusterRepository) GetByName(organizationId string, name string) (out domain.Cluster, err error) { + var cluster Cluster + res := r.db.Preload(clause.Associations).First(&cluster, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { - return model.Cluster{}, res.Error + return domain.Cluster{}, res.Error } + out = reflectCluster(cluster) return } -func (r *ClusterRepository) Create(dto model.Cluster) (clusterId domain.ClusterId, err error) { +func (r *ClusterRepository) Create(dto domain.Cluster) (clusterId domain.ClusterId, err error) { var cloudAccountId *uuid.UUID - cloudAccountId = dto.CloudAccountId - if dto.CloudService == domain.CloudService_BYOH || *dto.CloudAccountId == uuid.Nil { + cloudAccountId = &dto.CloudAccountId + if dto.CloudService == domain.CloudService_BYOH || dto.CloudAccountId == uuid.Nil { cloudAccountId = nil } - cluster := model.Cluster{ + cluster := Cluster{ ID: domain.ClusterId(helper.GenerateClusterId()), OrganizationId: dto.OrganizationId, Name: dto.Name, @@ -133,15 +206,15 @@ func (r *ClusterRepository) Create(dto model.Cluster) (clusterId domain.ClusterI ByoClusterEndpointHost: dto.ByoClusterEndpointHost, ByoClusterEndpointPort: dto.ByoClusterEndpointPort, IsStack: dto.IsStack, - TksCpNode: dto.TksCpNode, - TksCpNodeMax: dto.TksCpNodeMax, - TksCpNodeType: dto.TksCpNodeType, - TksInfraNode: dto.TksInfraNode, - TksInfraNodeMax: dto.TksInfraNodeMax, - TksInfraNodeType: dto.TksInfraNodeType, - TksUserNode: dto.TksUserNode, - TksUserNodeMax: dto.TksUserNodeMax, - TksUserNodeType: dto.TksUserNodeType, + TksCpNode: dto.Conf.TksCpNode, + TksCpNodeMax: dto.Conf.TksCpNodeMax, + TksCpNodeType: dto.Conf.TksCpNodeType, + TksInfraNode: dto.Conf.TksInfraNode, + TksInfraNodeMax: dto.Conf.TksInfraNodeMax, + TksInfraNodeType: dto.Conf.TksInfraNodeType, + TksUserNode: dto.Conf.TksUserNode, + TksUserNodeMax: dto.Conf.TksUserNodeMax, + TksUserNodeType: dto.Conf.TksUserNodeType, } if dto.ID != "" { cluster.ID = dto.ID @@ -157,15 +230,15 @@ func (r *ClusterRepository) Create(dto model.Cluster) (clusterId domain.ClusterI } func (r *ClusterRepository) Delete(clusterId domain.ClusterId) error { - res := r.db.Unscoped().Delete(&model.Cluster{}, "id = ?", clusterId) + res := r.db.Unscoped().Delete(&Cluster{}, "id = ?", clusterId) if res.Error != nil { return fmt.Errorf("could not delete cluster for clusterId %s", clusterId) } return nil } -func (r *ClusterRepository) Update(dto model.Cluster) error { - res := r.db.Model(&model.Cluster{}). +func (r *ClusterRepository) Update(dto domain.Cluster) error { + res := r.db.Model(&Cluster{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description, "UpdatorId": dto.UpdatorId}) if res.Error != nil { @@ -175,7 +248,7 @@ func (r *ClusterRepository) Update(dto model.Cluster) error { } func (r *ClusterRepository) InitWorkflow(clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error { - res := r.db.Model(&model.Cluster{}). + res := r.db.Model(&Cluster{}). Where("ID = ?", clusterId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId, "StatusDesc": ""}) @@ -187,7 +260,7 @@ func (r *ClusterRepository) InitWorkflow(clusterId domain.ClusterId, workflowId } func (r *ClusterRepository) InitWorkflowDescription(clusterId domain.ClusterId) error { - res := r.db.Model(&model.AppGroup{}). + res := r.db.Model(&AppGroup{}). Where("id = ?", clusterId). Updates(map[string]interface{}{"WorkflowId": "", "StatusDesc": ""}) @@ -199,7 +272,7 @@ func (r *ClusterRepository) InitWorkflowDescription(clusterId domain.ClusterId) } func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid.UUID) error { - var clusterFavorites []model.ClusterFavorite + var clusterFavorites []ClusterFavorite res := r.db.Where("cluster_id = ? AND user_id = ?", clusterId, userId).Find(&clusterFavorites) if res.Error != nil { log.Info(res.Error) @@ -210,7 +283,7 @@ func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid. return nil } - clusterFavorite := model.ClusterFavorite{ + clusterFavorite := ClusterFavorite{ ClusterId: clusterId, UserId: userId, } @@ -224,10 +297,34 @@ func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid. } func (r *ClusterRepository) DeleteFavorite(clusterId domain.ClusterId, userId uuid.UUID) error { - res := r.db.Unscoped().Delete(&model.ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) + res := r.db.Unscoped().Delete(&ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) if res.Error != nil { log.Error(res.Error) return fmt.Errorf("could not delete cluster favorite for clusterId %s, userId %s", clusterId, userId) } return nil } + +func reflectCluster(cluster Cluster) (out domain.Cluster) { + if err := serializer.Map(cluster.Model, &out); err != nil { + log.Error(err) + } + + if err := serializer.Map(cluster, &out); err != nil { + log.Error(err) + } + + if err := serializer.Map(cluster, &out.Conf); err != nil { + log.Error(err) + } + out.StackTemplate.Services = cluster.StackTemplate.Services + + if cluster.Favorites != nil && len(*cluster.Favorites) > 0 { + out.Favorited = true + + } else { + out.Favorited = false + } + + return +} diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go index 2b290779..707d8d58 100644 --- a/internal/repository/endpoint.go +++ b/internal/repository/endpoint.go @@ -2,17 +2,16 @@ package repository import ( "fmt" - "math" - - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" + "math" ) type IEndpointRepository interface { - Create(endpoint *model.Endpoint) error - List(pg *pagination.Pagination) ([]*model.Endpoint, error) - Get(id uint) (*model.Endpoint, error) + Create(endpoint *domain.Endpoint) error + List(pg *pagination.Pagination) ([]*domain.Endpoint, error) + Get(id uint) (*domain.Endpoint, error) } type EndpointRepository struct { @@ -25,8 +24,8 @@ func NewEndpointRepository(db *gorm.DB) *EndpointRepository { } } -func (e *EndpointRepository) Create(endpoint *model.Endpoint) error { - obj := &model.Endpoint{ +func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { + obj := &domain.Endpoint{ Name: endpoint.Name, Group: endpoint.Group, } @@ -38,14 +37,14 @@ func (e *EndpointRepository) Create(endpoint *model.Endpoint) error { return nil } -func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*model.Endpoint, error) { - var endpoints []*model.Endpoint +func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint, error) { + var endpoints []*domain.Endpoint if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("endpoints", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(e.db.Model(&model.Endpoint{})) + db := filterFunc(e.db.Model(&domain.Endpoint{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -59,14 +58,14 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*model.Endpoint, return endpoints, nil } -func (e *EndpointRepository) Get(id uint) (*model.Endpoint, error) { - var obj model.Endpoint +func (e *EndpointRepository) Get(id uint) (*domain.Endpoint, error) { + var obj domain.Endpoint if err := e.db.Preload("Permission").First(&obj, "id = ?", id).Error; err != nil { return nil, err } - return &model.Endpoint{ + return &domain.Endpoint{ Name: obj.Name, Group: obj.Group, }, nil diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 69ed3cce..a7839166 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -2,8 +2,8 @@ package repository import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" @@ -11,10 +11,10 @@ import ( // Interfaces type IOrganizationRepository interface { - Create(organizationId string, name string, creator uuid.UUID, phone string, description string) (model.Organization, error) - Fetch(pg *pagination.Pagination) (res *[]model.Organization, err error) - Get(organizationId string) (res model.Organization, err error) - Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) + Create(organizationId string, name string, creator uuid.UUID, phone string, description string) (domain.Organization, error) + Fetch(pg *pagination.Pagination) (res *[]domain.Organization, err error) + Get(organizationId string) (res domain.Organization, err error) + Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error Delete(organizationId string) (err error) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error @@ -40,7 +40,7 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { // Description string // Phone string // WorkflowId string -// Status model.OrganizationStatus +// Status domain.OrganizationStatus // StatusDesc string // Creator uuid.UUID // PrimaryClusterId string // allow null @@ -52,8 +52,8 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { //} func (r *OrganizationRepository) Create(organizationId string, name string, creator uuid.UUID, phone string, - description string) (model.Organization, error) { - organization := model.Organization{ + description string) (domain.Organization, error) { + organization := domain.Organization{ ID: organizationId, Name: name, Creator: creator.String(), @@ -64,36 +64,45 @@ func (r *OrganizationRepository) Create(organizationId string, name string, crea res := r.db.Create(&organization) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return model.Organization{}, res.Error + return domain.Organization{}, res.Error } - return organization, nil + return r.reflect(organization), nil } -func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (out *[]model.Organization, err error) { +func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (*[]domain.Organization, error) { + var organizations []domain.Organization + var out []domain.Organization if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db, &out) + _, res := pg.Fetch(r.db, &organizations) if res.Error != nil { return nil, res.Error } - return + + for _, organization := range organizations { + outOrganization := r.reflect(organization) + out = append(out, outOrganization) + } + return &out, nil } -func (r *OrganizationRepository) Get(id string) (out model.Organization, err error) { - res := r.db.First(&out, "id = ?", id) +func (r *OrganizationRepository) Get(id string) (domain.Organization, error) { + var organization domain.Organization + res := r.db.First(&organization, "id = ?", id) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return model.Organization{}, res.Error + return domain.Organization{}, res.Error } - return + return r.reflect(organization), nil } -func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateOrganizationRequest) (out model.Organization, err error) { - res := r.db.Model(&model.Organization{}). +func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) { + var organization domain.Organization + res := r.db.Model(&domain.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "name": in.Name, @@ -103,19 +112,19 @@ func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateO if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return model.Organization{}, res.Error + return domain.Organization{}, res.Error } - res = r.db.Model(&model.Organization{}).Where("id = ?", organizationId).Find(&out) + res = r.db.Model(&domain.Organization{}).Where("id = ?", organizationId).Find(&organization) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return model.Organization{}, res.Error + return domain.Organization{}, res.Error } - return + return r.reflect(organization), nil } func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error { - res := r.db.Model(&model.Organization{}). + res := r.db.Model(&domain.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "primary_cluster_id": primaryClusterId, @@ -129,7 +138,7 @@ func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, p } func (r *OrganizationRepository) Delete(organizationId string) error { - res := r.db.Delete(&model.Organization{}, "id = ?", organizationId) + res := r.db.Delete(&domain.Organization{}, "id = ?", organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -139,7 +148,7 @@ func (r *OrganizationRepository) Delete(organizationId string) error { } func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error { - res := r.db.Model(&model.Organization{}). + res := r.db.Model(&domain.Organization{}). Where("ID = ?", organizationId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) if res.Error != nil { @@ -148,3 +157,15 @@ func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId } return nil } + +func (r *OrganizationRepository) reflect(organization domain.Organization) (out domain.Organization) { + if err := serializer.Map(organization.Model, &out); err != nil { + log.Error(err) + } + if err := serializer.Map(organization, &out); err != nil { + log.Error(err) + } + out.Creator = organization.Creator + return + +} diff --git a/internal/repository/permission.go b/internal/repository/permission.go index ebed52e6..db097922 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -2,16 +2,16 @@ package repository import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" ) type IPermissionRepository interface { - Create(permission *model.Permission) error - List(roleId string) ([]*model.Permission, error) - Get(id uuid.UUID) (*model.Permission, error) + Create(permission *domain.Permission) error + List(roleId string) ([]*domain.Permission, error) + Get(id uuid.UUID) (*domain.Permission, error) Delete(id uuid.UUID) error - Update(permission *model.Permission) error + Update(permission *domain.Permission) error } type PermissionRepository struct { @@ -24,7 +24,7 @@ func NewPermissionRepository(db *gorm.DB) *PermissionRepository { } } -func (r PermissionRepository) Create(p *model.Permission) error { +func (r PermissionRepository) Create(p *domain.Permission) error { //var parent *Permission //var children []*Permission // @@ -49,8 +49,8 @@ func (r PermissionRepository) Create(p *model.Permission) error { return r.db.Create(p).Error } -func (r PermissionRepository) List(roleId string) ([]*model.Permission, error) { - var permissions []*model.Permission +func (r PermissionRepository) List(roleId string) ([]*domain.Permission, error) { + var permissions []*domain.Permission err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL AND role_id = ?", roleId).Find(&permissions).Error if err != nil { @@ -60,8 +60,8 @@ func (r PermissionRepository) List(roleId string) ([]*model.Permission, error) { return permissions, nil } -func (r PermissionRepository) Get(id uuid.UUID) (*model.Permission, error) { - permission := &model.Permission{} +func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { + permission := &domain.Permission{} result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) if result.Error != nil { return nil, result.Error @@ -71,10 +71,10 @@ func (r PermissionRepository) Get(id uuid.UUID) (*model.Permission, error) { } func (r PermissionRepository) Delete(id uuid.UUID) error { - return r.db.Delete(&model.Permission{}, "id = ?", id).Error + return r.db.Delete(&domain.Permission{}, "id = ?", id).Error } -func (r PermissionRepository) Update(p *model.Permission) error { +func (r PermissionRepository) Update(p *domain.Permission) error { // update on is_allowed - return r.db.Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error + return r.db.Model(&domain.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error } diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 7500369b..bc12f8fe 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -17,18 +16,18 @@ import ( ) type IPolicyTemplateRepository interface { - Create(dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) + Create(dto domain.PolicyTemplate) (policyTemplateId uuid.UUID, err error) Update(dto domain.UpdatePolicyTemplateUpdate) (err error) - Fetch(pg *pagination.Pagination) (out []model.PolicyTemplate, err error) - GetByName(policyTemplateName string) (out *model.PolicyTemplate, err error) - GetByKind(policyTemplateKind string) (out *model.PolicyTemplate, err error) - GetByID(policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) + Fetch(pg *pagination.Pagination) (out []domain.PolicyTemplate, err error) + GetByName(policyTemplateName string) (out *domain.PolicyTemplate, err error) + GetByKind(policyTemplateKind string) (out *domain.PolicyTemplate, err error) + GetByID(policyTemplateId uuid.UUID) (out *domain.PolicyTemplate, err error) Delete(policyTemplateId uuid.UUID) (err error) ExistByName(policyTemplateName string) (exist bool, err error) ExistByKind(policyTemplateKind string) (exist bool, err error) ExistByID(policyTemplateId uuid.UUID) (exist bool, err error) ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) - GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) + GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) } @@ -43,18 +42,54 @@ func NewPolicyTemplateRepository(db *gorm.DB) IPolicyTemplateRepository { } } -func (r *PolicyTemplateRepository) Create(dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { +type PolicyTemplateSupportedVersion struct { + gorm.Model + + PolicyTemplateId uuid.UUID `gorm:"index:template_version,unique"` + Version string `gorm:"index:template_version,unique"` + + ParameterSchema string `gorm:"type:text"` + Rego string `gorm:"type:text"` + Libs string `gorm:"type:text"` +} + +type PolicyTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` + Type string // Org or Tks + Name string + Version string + SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` + Description string + Kind string + Deprecated bool + Mandatory bool // Tks 인 경우에는 무시 + Severity string + PermittedOrganizations []domain.Organization `gorm:"many2many:policy_template_permitted_organiations;"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` +} + +func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + +func (r *PolicyTemplateRepository) Create(dto domain.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { jsonByte, err := json.Marshal(dto.ParametersSchema) if err != nil { return uuid.Nil, err } - policyTemplate := model.PolicyTemplate{ + policyTemplate := PolicyTemplate{ Type: "tks", Name: dto.TemplateName, Version: "v1.0.0", - SupportedVersions: []model.PolicyTemplateSupportedVersion{ + SupportedVersions: []PolicyTemplateSupportedVersion{ { Version: "v1.0.0", ParameterSchema: string(jsonByte), @@ -76,9 +111,9 @@ func (r *PolicyTemplateRepository) Create(dto model.PolicyTemplate) (policyTempl } if dto.PermittedOrganizationIds != nil { - permittedOrganizations := make([]model.Organization, len(dto.PermittedOrganizationIds)) + permittedOrganizations := make([]domain.Organization, len(dto.PermittedOrganizationIds)) for i, permittedOrganizationId := range dto.PermittedOrganizationIds { - permittedOrganizations[i] = model.Organization{ID: permittedOrganizationId} + permittedOrganizations[i] = domain.Organization{ID: permittedOrganizationId} } err = tx.Model(&policyTemplate).Association("PermittedOrganizations").Replace(permittedOrganizations) @@ -121,14 +156,14 @@ func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) fmt.Printf("--updateMap=%+v\n--", updateMap) - var policyTemplate model.PolicyTemplate + var policyTemplate PolicyTemplate policyTemplate.ID = dto.ID return r.db.Transaction(func(tx *gorm.DB) error { if dto.PermittedOrganizationIds != nil { - permittedOrganizations := make([]model.Organization, len(*dto.PermittedOrganizationIds)) + permittedOrganizations := make([]domain.Organization, len(*dto.PermittedOrganizationIds)) for i, permittedOrganizationId := range *dto.PermittedOrganizationIds { - permittedOrganizations[i] = model.Organization{ID: permittedOrganizationId} + permittedOrganizations[i] = domain.Organization{ID: permittedOrganizationId} } err = r.db.Model(&policyTemplate).Limit(1). @@ -154,20 +189,20 @@ func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) }) } -func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.PolicyTemplate, err error) { - var policyTemplates []model.PolicyTemplate +func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain.PolicyTemplate, err error) { + var policyTemplates []PolicyTemplate if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations).Model(&model.PolicyTemplate{}). + _, res := pg.Fetch(r.db.Preload(clause.Associations).Model(&PolicyTemplate{}). Where("type = 'tks'"), &policyTemplates) if res.Error != nil { return nil, res.Error } for _, policyTemplate := range policyTemplates { - var policyTemplateVersion model.PolicyTemplateSupportedVersion + var policyTemplateVersion PolicyTemplateSupportedVersion res = r.db. Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). First(&policyTemplateVersion) @@ -186,7 +221,7 @@ func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []model return out, nil } -func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.PolicyTemplate, policyTemplateVersion model.PolicyTemplateSupportedVersion) (out model.PolicyTemplate) { +func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTemplate, policyTemplateVersion PolicyTemplateSupportedVersion) (out domain.PolicyTemplate) { if err := serializer.Map(policyTemplate.Model, &out); err != nil { log.Error(err) } @@ -194,7 +229,7 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.Po log.Error(err) } out.TemplateName = policyTemplate.Name - out.ID = policyTemplate.ID + out.ID = domain.PolicyTemplateId(policyTemplate.ID.String()) var schemas []domain.ParameterDef @@ -206,20 +241,14 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.Po } } - // ktkfree : 이 부분은 재 구현 부탁 드립니다. - // PermittedOrganizations 필드가 model 과 response 를 위한 객체의 형이 다르네요. - // 아울러 reflect 는 repository 가 아닌 usecase 에 표현되는게 더 좋겠습니다. - - /* - out.PermittedOrganizations = make([]domain.PermittedOrganization, len(policyTemplate.PermittedOrganizations)) - for i, org := range policyTemplate.PermittedOrganizations { - out.PermittedOrganizations[i] = domain.PermittedOrganization{ - OrganizationId: org.ID, - OrganizationName: org.Name, - Permitted: true, - } + out.PermittedOrganizations = make([]domain.PermittedOrganization, len(policyTemplate.PermittedOrganizations)) + for i, org := range policyTemplate.PermittedOrganizations { + out.PermittedOrganizations[i] = domain.PermittedOrganization{ + OrganizationId: org.ID, + OrganizationName: org.Name, + Permitted: true, } - */ + } out.Rego = policyTemplateVersion.Rego out.Libs = strings.Split(policyTemplateVersion.Libs, "---\n") @@ -230,7 +259,7 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.Po func (r *PolicyTemplateRepository) ExistsBy(key string, value interface{}) (exists bool, err error) { query := fmt.Sprintf("%s = ?", key) - var policyTemplate model.PolicyTemplate + var policyTemplate PolicyTemplate res := r.db.Where(query, value). First(&policyTemplate) @@ -259,10 +288,10 @@ func (r *PolicyTemplateRepository) ExistByID(policyTemplateId uuid.UUID) (exist return r.ExistsBy("id", policyTemplateId) } -func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *model.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *domain.PolicyTemplate, err error) { query := fmt.Sprintf("%s = ?", key) - var policyTemplate model.PolicyTemplate + var policyTemplate PolicyTemplate res := r.db.Preload(clause.Associations).Where(query, value). First(&policyTemplate) @@ -276,7 +305,7 @@ func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *mo } } - var policyTemplateVersion model.PolicyTemplateSupportedVersion + var policyTemplateVersion PolicyTemplateSupportedVersion res = r.db.Limit(1). Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). First(&policyTemplateVersion) @@ -298,7 +327,7 @@ func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *mo return &result, nil } -func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *domain.PolicyTemplate, err error) { return r.GetBy("id", policyTemplateId) // var policyTemplate PolicyTemplate @@ -320,7 +349,7 @@ func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *mod // return &result, nil } -func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *model.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *domain.PolicyTemplate, err error) { return r.GetBy("name", policyTemplateName) // var policyTemplate PolicyTemplate @@ -342,21 +371,21 @@ func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *mo // return &result, nil } -func (r *PolicyTemplateRepository) GetByKind(policyTemplateKind string) (out *model.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByKind(policyTemplateKind string) (out *domain.PolicyTemplate, err error) { return r.GetBy("kind", policyTemplateKind) } func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error) { return r.db.Transaction(func(tx *gorm.DB) error { - if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&model.PolicyTemplateSupportedVersion{}).Error; err != nil { + if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&PolicyTemplateSupportedVersion{}).Error; err != nil { return err } - if err := tx.Model(&model.PolicyTemplate{ID: policyTemplateId}).Association("PermittedOrganizations").Clear(); err != nil { + if err := tx.Model(&PolicyTemplate{ID: policyTemplateId}).Association("PermittedOrganizations").Clear(); err != nil { return err } - if err := tx.Where("id = ?", policyTemplateId).Delete(&model.PolicyTemplate{}).Error; err != nil { + if err := tx.Where("id = ?", policyTemplateId).Delete(&PolicyTemplate{}).Error; err != nil { return err } @@ -365,7 +394,7 @@ func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error } func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { - var supportedVersions []model.PolicyTemplateSupportedVersion + var supportedVersions []PolicyTemplateSupportedVersion res := r.db.Where("policy_template_id = ?", policyTemplateId).Find(&supportedVersions) if res.Error != nil { @@ -391,8 +420,8 @@ func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId u return result, nil } -func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { - var policyTemplateVersion model.PolicyTemplateSupportedVersion +func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) { + var policyTemplateVersion PolicyTemplateSupportedVersion res := r.db. Where("policy_template_id = ? and version = ?", policyTemplateId, version). First(&policyTemplateVersion) @@ -406,7 +435,7 @@ func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uui } } - var policyTemplate model.PolicyTemplate + var policyTemplate PolicyTemplate res = r.db. Where("id = ?", policyTemplateId). First(&policyTemplate) @@ -426,7 +455,7 @@ func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uui } func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) { - var policyTemplate model.PolicyTemplate + var policyTemplate PolicyTemplate res := r.db.Select("version").First(&policyTemplate) if res.Error != nil { @@ -446,7 +475,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId // TODO: Operator에 현재 버전 사용중인 정책이 있는지 체크 필요 - var policyTemplateVersion model.PolicyTemplateSupportedVersion + var policyTemplateVersion PolicyTemplateSupportedVersion res = r.db.Where("policy_template_id = ? and version = ?", policyTemplateId, version). Delete(&policyTemplateVersion) if res.Error != nil { @@ -463,7 +492,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId } func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { - var policyTemplateVersion model.PolicyTemplateSupportedVersion + var policyTemplateVersion PolicyTemplateSupportedVersion res := r.db.Limit(1). Where("policy_template_id = ? and version = ?", policyTemplateId, version). First(&policyTemplateVersion) @@ -496,7 +525,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId return "", parseErr } - newPolicyTemplateVersion := &model.PolicyTemplateSupportedVersion{ + newPolicyTemplateVersion := &PolicyTemplateSupportedVersion{ PolicyTemplateId: policyTemplateId, Version: newVersion, Rego: rego, @@ -509,7 +538,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId return err } - if err := tx.Model(&model.PolicyTemplate{}).Where("id = ?", policyTemplateId).Update("version", newVersion).Error; err != nil { + if err := tx.Model(&PolicyTemplate{}).Where("id = ?", policyTemplateId).Update("version", newVersion).Error; err != nil { return err } diff --git a/internal/repository/role.go b/internal/repository/role.go index ab5c7f50..d7bdb198 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -2,30 +2,29 @@ package repository import ( "fmt" - "math" - - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" + "math" ) type IRoleRepository interface { - Create(roleObj *model.Role) (string, error) - List(pg *pagination.Pagination) ([]*model.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) - Get(id string) (*model.Role, error) - GetTksRole(id string) (*model.Role, error) - GetTksRoleByRoleName(roleName string) (*model.Role, error) + Create(roleObj *domain.Role) (string, error) + List(pg *pagination.Pagination) ([]*domain.Role, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) + Get(id string) (*domain.Role, error) + GetTksRole(id string) (*domain.Role, error) + GetTksRoleByRoleName(roleName string) (*domain.Role, error) Delete(id string) error - Update(roleObj *model.Role) error + Update(roleObj *domain.Role) error } type RoleRepository struct { db *gorm.DB } -func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*model.Role, error) { - var role model.Role +func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.Role, error) { + var role domain.Role if err := r.db.Preload("Role").First(&role, "Role.name = ?", roleName).Error; err != nil { return nil, err } @@ -33,7 +32,7 @@ func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*model.Role, erro return &role, nil } -func (r RoleRepository) Create(roleObj *model.Role) (string, error) { +func (r RoleRepository) Create(roleObj *domain.Role) (string, error) { if roleObj == nil { return "", fmt.Errorf("roleObj is nil") } @@ -44,14 +43,14 @@ func (r RoleRepository) Create(roleObj *model.Role) (string, error) { return roleObj.ID, nil } -func (r RoleRepository) List(pg *pagination.Pagination) ([]*model.Role, error) { - var roles []*model.Role +func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) { + var roles []*domain.Role if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&model.Role{})) + db := filterFunc(r.db.Model(&domain.Role{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -66,14 +65,14 @@ func (r RoleRepository) List(pg *pagination.Pagination) ([]*model.Role, error) { return roles, nil } -func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { - var roles []*model.Role +func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) { + var roles []*domain.Role if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&model.Role{})) + db := filterFunc(r.db.Model(&domain.Role{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -92,8 +91,8 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin return roles, nil } -func (r RoleRepository) Get(id string) (*model.Role, error) { - var role model.Role +func (r RoleRepository) Get(id string) (*domain.Role, error) { + var role domain.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } @@ -101,8 +100,8 @@ func (r RoleRepository) Get(id string) (*model.Role, error) { return &role, nil } -func (r RoleRepository) GetTksRole(id string) (*model.Role, error) { - var role model.Role +func (r RoleRepository) GetTksRole(id string) (*domain.Role, error) { + var role domain.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } @@ -110,12 +109,12 @@ func (r RoleRepository) GetTksRole(id string) (*model.Role, error) { return &role, nil } -func (r RoleRepository) Update(roleObj *model.Role) error { +func (r RoleRepository) Update(roleObj *domain.Role) error { if roleObj == nil { return fmt.Errorf("roleObj is nil") } - err := r.db.Model(&model.Role{}).Where("id = ?", roleObj.ID).Updates(model.Role{ + err := r.db.Model(&domain.Role{}).Where("id = ?", roleObj.ID).Updates(domain.Role{ Name: roleObj.Name, Description: roleObj.Description, }).Error @@ -128,7 +127,7 @@ func (r RoleRepository) Update(roleObj *model.Role) error { } func (r RoleRepository) Delete(id string) error { - if err := r.db.Delete(&model.Role{}, "id = ?", id).Error; err != nil { + if err := r.db.Delete(&domain.Role{}, "id = ?", id).Error; err != nil { return err } diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 103aec44..9c55df46 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -2,22 +2,24 @@ package repository import ( "github.com/google/uuid" + "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IStackTemplateRepository interface { - Get(stackTemplateId uuid.UUID) (model.StackTemplate, error) - Fetch(pg *pagination.Pagination) ([]model.StackTemplate, error) - FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) - Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) - Update(dto model.StackTemplate) (err error) - Delete(dto model.StackTemplate) (err error) - UpdateOrganizations(stackTemplateId uuid.UUID, organizationIds []model.Organization) (err error) + Get(stackTemplateId uuid.UUID) (domain.StackTemplate, error) + Fetch(pg *pagination.Pagination) ([]domain.StackTemplate, error) + Create(dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) + Update(dto domain.StackTemplate) (err error) + Delete(dto domain.StackTemplate) (err error) + UpdateOrganizations(stackTemplateId uuid.UUID, organizationIds []domain.Organization) (err error) } type StackTemplateRepository struct { @@ -30,52 +32,87 @@ func NewStackTemplateRepository(db *gorm.DB) IStackTemplateRepository { } } +// Models +type StackTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index"` + Description string `gorm:"index"` + Template string + TemplateType string + Version string + CloudService string + Platform string + KubeVersion string + KubeType string + Organizations []domain.Organization `gorm:"many2many:stack_template_organizations"` + Services datatypes.JSON + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator domain.User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator domain.User `gorm:"foreignKey:UpdatorId"` +} + +func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + // Logics -func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out model.StackTemplate, err error) { - res := r.db.Preload(clause.Associations).First(&out, "id = ?", stackTemplateId) +func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out domain.StackTemplate, err error) { + var stackTemplate StackTemplate + res := r.db.Preload(clause.Associations).First(&stackTemplate, "id = ?", stackTemplateId) if res.Error != nil { - return model.StackTemplate{}, res.Error + return domain.StackTemplate{}, res.Error } + out = reflectStackTemplate(stackTemplate) return } -func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.StackTemplate, err error) { +// [TODO] organizationId 별로 생성하지 않고, 하나의 stackTemplate 을 모든 organization 에서 재사용한다. ( 5월 한정, 추후 rearchitecture 필요) +func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain.StackTemplate, err error) { + var stackTemplates []StackTemplate + if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations), &out) + _, res := pg.Fetch(r.db.Preload(clause.Associations), &stackTemplates) if res.Error != nil { return nil, res.Error } - return -} -func (r *StackTemplateRepository) FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) { - if pg == nil { - pg = pagination.NewPagination(nil) + for _, stackTemplate := range stackTemplates { + out = append(out, reflectStackTemplate(stackTemplate)) } - _, res := pg.Fetch( - r.db.Preload(clause.Associations). - Joins("JOIN stack_template_organizations ON stack_template_organizations.stack_template_id = stack_templates.id AND stack_template_organizations.organization_id = ?", organizationId), - &out) - if res.Error != nil { - return nil, res.Error - } return } -func (r *StackTemplateRepository) Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { - res := r.db.Create(&dto) +func (r *StackTemplateRepository) Create(dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) { + stackTemplate := StackTemplate{ + Name: dto.Name, + Description: dto.Description, + Template: dto.Template, + TemplateType: dto.TemplateType, + Version: dto.Version, + CloudService: dto.CloudService, + Platform: dto.Platform, + KubeVersion: dto.KubeVersion, + KubeType: dto.KubeType, + Services: dto.Services, + CreatorId: &dto.CreatorId, + UpdatorId: &dto.CreatorId} + res := r.db.Create(&stackTemplate) if res.Error != nil { return uuid.Nil, res.Error } - return dto.ID, nil + return stackTemplate.ID, nil } -func (r *StackTemplateRepository) Update(dto model.StackTemplate) (err error) { - res := r.db.Model(&model.StackTemplate{}). +func (r *StackTemplateRepository) Update(dto domain.StackTemplate) (err error) { + res := r.db.Model(&StackTemplate{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ "Template": dto.Template, @@ -94,16 +131,16 @@ func (r *StackTemplateRepository) Update(dto model.StackTemplate) (err error) { return nil } -func (r *StackTemplateRepository) Delete(dto model.StackTemplate) (err error) { - res := r.db.Delete(&model.StackTemplate{}, "id = ?", dto.ID) +func (r *StackTemplateRepository) Delete(dto domain.StackTemplate) (err error) { + res := r.db.Delete(&StackTemplate{}, "id = ?", dto.ID) if res.Error != nil { return res.Error } return nil } -func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, organizations []model.Organization) (err error) { - var stackTemplate = model.StackTemplate{} +func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, organizations []domain.Organization) (err error) { + var stackTemplate = StackTemplate{} res := r.db.Preload("Organizations").First(&stackTemplate, "id = ?", stackTemplateId) if res.Error != nil { return res.Error @@ -115,3 +152,15 @@ func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, return nil } + +func reflectStackTemplate(stackTemplate StackTemplate) (out domain.StackTemplate) { + if err := serializer.Map(stackTemplate.Model, &out); err != nil { + log.Error(err) + } + if err := serializer.Map(stackTemplate, &out); err != nil { + log.Error(err) + } + + out.Services = stackTemplate.Services + return +} diff --git a/internal/repository/user.go b/internal/repository/user.go index fcfd4981..12ed1a50 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -4,8 +4,8 @@ import ( "time" "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" @@ -14,13 +14,13 @@ import ( // Interface type IUserRepository interface { CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, - department string, description string, organizationId string, roleId string) (model.User, error) - List(filters ...FilterFunc) (out *[]model.User, err error) - ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]model.User, err error) - Get(accountId string, organizationId string) (model.User, error) - GetByUuid(userId uuid.UUID) (model.User, error) + department string, description string, organizationId string, roleId string) (domain.User, error) + List(filters ...FilterFunc) (out *[]domain.User, err error) + ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]domain.User, err error) + Get(accountId string, organizationId string) (domain.User, error) + GetByUuid(userId uuid.UUID) (domain.User, error) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, email string, - department string, description string) (model.User, error) + department string, description string) (domain.User, error) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error DeleteWithUuid(uuid uuid.UUID) error Flush(organizationId string) error @@ -36,7 +36,7 @@ type UserRepository struct { } func (r *UserRepository) Flush(organizationId string) error { - res := r.db.Where("organization_id = ?", organizationId).Delete(&model.User{}) + res := r.db.Where("organization_id = ?", organizationId).Delete(&domain.User{}) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -77,9 +77,9 @@ func NewUserRepository(db *gorm.DB) IUserRepository { //} func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, - department string, description string, organizationId string, roleId string) (model.User, error) { + department string, description string, organizationId string, roleId string) (domain.User, error) { - newUser := model.User{ + newUser := domain.User{ ID: uuid, AccountId: accountId, Name: name, @@ -92,11 +92,11 @@ func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name s res := r.db.Create(&newUser) if res.Error != nil { log.Error(res.Error.Error()) - return model.User{}, res.Error + return domain.User{}, res.Error } user, err := r.getUserByAccountId(accountId, organizationId) if err != nil { - return model.User{}, err + return domain.User{}, err } return user, nil @@ -122,12 +122,12 @@ func (r *UserRepository) NameFilter(name string) FilterFunc { } } -func (r *UserRepository) List(filters ...FilterFunc) (*[]model.User, error) { - var users []model.User +func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { + var users []domain.User var res *gorm.DB if filters == nil { - res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Find(&users) + res = r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Find(&users) } else { combinedFilter := func(filters ...FilterFunc) FilterFunc { return func(user *gorm.DB) *gorm.DB { @@ -138,7 +138,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]model.User, error) { } } cFunc := combinedFilter(filters...) - res = cFunc(r.db.Model(&model.User{}).Preload("Organization").Preload("Role")).Find(&users) + res = cFunc(r.db.Model(&domain.User{}).Preload("Organization").Preload("Role")).Find(&users) } if res.Error != nil { @@ -149,7 +149,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]model.User, error) { return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } - var out []model.User + var out []domain.User for _, user := range users { out = append(out, user) } @@ -157,20 +157,20 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]model.User, error) { return &out, nil } -func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizationId string) (*[]model.User, error) { - var users []model.User +func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizationId string) (*[]domain.User, error) { + var users []domain.User if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&model.User{}).Where("organization_id = ?", organizationId), &users) + _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&domain.User{}).Where("organization_id = ?", organizationId), &users) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error } - var out []model.User + var out []domain.User for _, user := range users { out = append(out, user) } @@ -178,32 +178,32 @@ func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizat return &out, nil } -func (r *UserRepository) Get(accountId string, organizationId string) (model.User, error) { +func (r *UserRepository) Get(accountId string, organizationId string) (domain.User, error) { user, err := r.getUserByAccountId(accountId, organizationId) if err != nil { - return model.User{}, err + return domain.User{}, err } return user, nil } -func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser model.User, err error) { - user := model.User{} - res := r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) +func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser domain.User, err error) { + user := domain.User{} + res := r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return model.User{}, res.Error + return domain.User{}, res.Error } if res.RowsAffected == 0 { - return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } return user, nil } func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, - email string, department string, description string) (model.User, error) { - var user model.User - res := r.db.Model(&model.User{}).Where("id = ?", uuid).Updates(model.User{ + email string, department string, description string) (domain.User, error) { + var user domain.User + res := r.db.Model(&domain.User{}).Where("id = ?", uuid).Updates(domain.User{ AccountId: accountId, Name: name, Email: email, @@ -212,26 +212,26 @@ func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name s RoleId: roleId, }) if res.RowsAffected == 0 || res.Error != nil { - return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return model.User{}, res.Error + return domain.User{}, res.Error } - res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) + res = r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) if res.Error != nil { - return model.User{}, res.Error + return domain.User{}, res.Error } return user, nil } func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error { - var updateUser = model.User{} + var updateUser = domain.User{} if isTemporary { updateUser.PasswordUpdatedAt = time.Time{} } else { updateUser.PasswordUpdatedAt = time.Now() } - res := r.db.Model(&model.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). + res := r.db.Model(&domain.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). Select("password_updated_at").Updates(updateUser) if res.RowsAffected == 0 || res.Error != nil { @@ -245,7 +245,7 @@ func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId strin return nil } func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { - res := r.db.Unscoped().Delete(&model.User{}, "id = ?", uuid) + res := r.db.Unscoped().Delete(&domain.User{}, "id = ?", uuid) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -273,17 +273,17 @@ func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { // Creator uuid.UUID //} -func (r *UserRepository) GetRoleByName(roleName string) (model.Role, error) { +func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { role, err := r.getRoleByName(roleName) if err != nil { - return model.Role{}, err + return domain.Role{}, err } return role, nil } -//func (r *UserRepository) FetchRoles() (*[]model.Role, error) { -// var roles []model.Role +//func (r *UserRepository) FetchRoles() (*[]domain.Role, error) { +// var roles []domain.Role // res := r.db.Find(&roles) // // if res.Error != nil { @@ -295,7 +295,7 @@ func (r *UserRepository) GetRoleByName(roleName string) (model.Role, error) { // return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") // } // -// var out []model.Role +// var out []domain.Role // for _, role := range roles { // outRole := r.reflectRole(role) // out = append(out, outRole) @@ -305,30 +305,30 @@ func (r *UserRepository) GetRoleByName(roleName string) (model.Role, error) { //} // private members -func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (model.User, error) { - user := model.User{} - res := r.db.Model(&model.User{}).Preload("Organization").Preload("Role"). +func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (domain.User, error) { + user := domain.User{} + res := r.db.Model(&domain.User{}).Preload("Organization").Preload("Role"). Find(&user, "account_id = ? AND organization_id = ?", accountId, organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return model.User{}, res.Error + return domain.User{}, res.Error } if res.RowsAffected == 0 { - return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } return user, nil } -func (r *UserRepository) getRoleByName(roleName string) (model.Role, error) { - role := model.Role{} +func (r *UserRepository) getRoleByName(roleName string) (domain.Role, error) { + role := domain.Role{} res := r.db.First(&role, "name = ?", roleName) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return model.Role{}, res.Error + return domain.Role{}, res.Error } if res.RowsAffected == 0 { - return model.Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return domain.Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } //if res.RowsAffected == 0 { diff --git a/internal/route/route.go b/internal/route/route.go index 0346e233..c28e1da8 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -181,14 +181,12 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa stackTemplateHandler := delivery.NewStackTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}/organizations", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplateOrganizations, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplateOrganizations))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.GetOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplates))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetOrganizationStackTemplate, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplate))).Methods(http.MethodGet) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) @@ -246,9 +244,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) auditHandler := delivery.NewAuditHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/admin/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/admin/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/admin/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) roleHandler := delivery.NewRoleHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.CreateTksRole, http.HandlerFunc(roleHandler.CreateTksRole))).Methods(http.MethodPost) diff --git a/internal/serializer/serializer.go b/internal/serializer/serializer.go index 043a9ba4..70e96552 100644 --- a/internal/serializer/serializer.go +++ b/internal/serializer/serializer.go @@ -5,7 +5,7 @@ import ( "reflect" "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) @@ -85,14 +85,8 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e } } */ - } else { - if fieldName == "Model" { - if err := recursiveMap(srcField.Interface(), dst, converterMap); err != nil { - return err - } - } - } + } } return nil @@ -106,11 +100,11 @@ func Map(src interface{}, dst interface{}) error { val, _ := uuid.Parse(i.(string)) return val, nil }, - {srcType: reflect.TypeOf((*model.Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(model.Role).Name, nil + {srcType: reflect.TypeOf((*domain.Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(domain.Role).Name, nil }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*model.Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return model.Role{Name: i.(string)}, nil + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*domain.Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return domain.Role{Name: i.(string)}, nil }, }) } diff --git a/internal/usecase/alert.go b/internal/usecase/alert.go index de77595a..99fafa9c 100644 --- a/internal/usecase/alert.go +++ b/internal/usecase/alert.go @@ -7,9 +7,9 @@ import ( "strings" "time" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" + + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" @@ -20,14 +20,14 @@ import ( ) type IAlertUsecase interface { - Get(ctx context.Context, alertId uuid.UUID) (model.Alert, error) - GetByName(ctx context.Context, organizationId string, name string) (model.Alert, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Alert, error) + Get(ctx context.Context, alertId uuid.UUID) (domain.Alert, error) + GetByName(ctx context.Context, organizationId string, name string) (domain.Alert, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Alert, error) Create(ctx context.Context, dto domain.CreateAlertRequest) (err error) - Update(ctx context.Context, dto model.Alert) error - Delete(ctx context.Context, dto model.Alert) error + Update(ctx context.Context, dto domain.Alert) error + Delete(ctx context.Context, dto domain.Alert) error - CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) + CreateAlertAction(ctx context.Context, dto domain.AlertAction) (alertActionId uuid.UUID, err error) } type AlertUsecase struct { @@ -101,7 +101,7 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque node = alert.Labels.Instance } - dto := model.Alert{ + dto := domain.Alert{ OrganizationId: organizationId, Name: alert.Labels.AlertName, Code: alert.Labels.AlertName, @@ -125,11 +125,11 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque return nil } -func (u *AlertUsecase) Update(ctx context.Context, dto model.Alert) error { +func (u *AlertUsecase) Update(ctx context.Context, dto domain.Alert) error { return nil } -func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert model.Alert, err error) { +func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert domain.Alert, err error) { alert, err = u.repo.Get(alertId) if err != nil { return alert, err @@ -139,7 +139,7 @@ func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert model. return } -func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Alert, err error) { +func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, name string) (out domain.Alert, err error) { out, err = u.repo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -150,7 +150,7 @@ func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, nam return } -func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (alerts []model.Alert, err error) { +func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (alerts []domain.Alert, err error) { alerts, err = u.repo.Fetch(organizationId, pg) if err != nil { return nil, err @@ -163,8 +163,8 @@ func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return alerts, nil } -func (u *AlertUsecase) Delete(ctx context.Context, dto model.Alert) (err error) { - _, ok := request.UserFrom(ctx) +func (u *AlertUsecase) Delete(ctx context.Context, dto domain.Alert) (err error) { + user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") } @@ -174,6 +174,8 @@ func (u *AlertUsecase) Delete(ctx context.Context, dto model.Alert) (err error) return httpErrors.NewNotFoundError(err, "AL_NOT_FOUND_ALERT", "") } + *dto.UpdatorId = user.GetUserId() + err = u.repo.Delete(dto) if err != nil { return err @@ -182,7 +184,7 @@ func (u *AlertUsecase) Delete(ctx context.Context, dto model.Alert) (err error) return nil } -func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) { +func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto domain.AlertAction) (alertActionId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -206,7 +208,7 @@ func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto model.AlertAct return } -func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]model.Cluster, strId string) (organizationId string, err error) { +func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]domain.Cluster, strId string) (organizationId string, err error) { clusterId := domain.ClusterId(strId) if !clusterId.Validate() { return "", fmt.Errorf("Invalid clusterId %s", strId) @@ -221,9 +223,9 @@ func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]model.Cluster, str return "", fmt.Errorf("No martched organization %s", strId) } -func (u *AlertUsecase) makeAdditionalInfo(alert *model.Alert) { +func (u *AlertUsecase) makeAdditionalInfo(alert *domain.Alert) { alert.FiredAt = &alert.CreatedAt - //alert.Status = model.AlertActionStatus_CREATED + //alert.Status = domain.AlertActionStatus_CREATED if len(alert.AlertActions) > 0 { alert.TakedAt = &alert.AlertActions[0].CreatedAt @@ -240,7 +242,7 @@ func (u *AlertUsecase) makeAdditionalInfo(alert *model.Alert) { } } -func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, alert domain.CreateAlertRequestAlert, clusterId domain.ClusterId) (url string) { +func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster domain.Cluster, alert domain.CreateAlertRequestAlert, clusterId domain.ClusterId) (url string) { primaryGrafanaEndpoint := "" appGroups, err := u.appGroupRepo.Fetch(primaryCluster.ID, nil) if err == nil { diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index a73c0e6b..f6a2d7b4 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -18,12 +17,12 @@ import ( ) type IAppGroupUsecase interface { - Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) ([]model.AppGroup, error) - Create(ctx context.Context, dto model.AppGroup) (id domain.AppGroupId, err error) - Get(ctx context.Context, id domain.AppGroupId) (out model.AppGroup, err error) + Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) ([]domain.AppGroup, error) + Create(ctx context.Context, dto domain.AppGroup) (id domain.AppGroupId, err error) + Get(ctx context.Context, id domain.AppGroupId) (out domain.AppGroup, err error) Delete(ctx context.Context, id domain.AppGroupId) (err error) - GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) - UpdateApplication(ctx context.Context, dto model.Application) (err error) + GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) + UpdateApplication(ctx context.Context, dto domain.Application) (err error) } type AppGroupUsecase struct { @@ -42,7 +41,7 @@ func NewAppGroupUsecase(r repository.Repository, argoClient argowf.ArgoClient) I } } -func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { +func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (out []domain.AppGroup, err error) { out, err = u.repo.Fetch(clusterId, pg) if err != nil { return nil, err @@ -50,7 +49,7 @@ func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, return } -func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id domain.AppGroupId, err error) { +func (u *AppGroupUsecase) Create(ctx context.Context, dto domain.AppGroup) (id domain.AppGroupId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -159,10 +158,10 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do return dto.ID, nil } -func (u *AppGroupUsecase) Get(ctx context.Context, id domain.AppGroupId) (out model.AppGroup, err error) { +func (u *AppGroupUsecase) Get(ctx context.Context, id domain.AppGroupId) (out domain.AppGroup, err error) { appGroup, err := u.repo.Get(id) if err != nil { - return model.AppGroup{}, err + return domain.AppGroup{}, err } return appGroup, nil } @@ -256,7 +255,7 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err return nil } -func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { +func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) { out, err = u.repo.GetApplications(id, applicationType) if err != nil { return nil, err @@ -264,7 +263,7 @@ func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGrou return } -func (u *AppGroupUsecase) UpdateApplication(ctx context.Context, dto model.Application) (err error) { +func (u *AppGroupUsecase) UpdateApplication(ctx context.Context, dto domain.Application) (err error) { err = u.repo.UpsertApplication(dto) if err != nil { return err diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 198b31a3..b16163f1 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -14,7 +14,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/openinfradev/tks-api/internal/kubernetes" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -24,19 +23,19 @@ import ( ) type IAppServeAppUsecase interface { - CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) - GetAppServeAppById(appId string) (*model.AppServeApp, error) - GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) - GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) - GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) + CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) + GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) + GetAppServeAppById(appId string) (*domain.AppServeApp, error) + GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) + GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) + GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) IsAppServeAppExist(appId string) (bool, error) IsAppServeAppNameExist(orgId string, appName string) (bool, error) IsAppServeAppNamespaceExist(clusterId string, namespace string) (bool, error) UpdateAppServeAppStatus(appId string, taskId string, status string, output string) (ret string, err error) DeleteAppServeApp(appId string) (res string, err error) - UpdateAppServeApp(app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) + UpdateAppServeApp(app *domain.AppServeApp, appTask *domain.AppServeAppTask) (ret string, err error) UpdateAppServeAppEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) (string, error) PromoteAppServeApp(appId string) (ret string, err error) AbortAppServeApp(appId string) (ret string, err error) @@ -59,7 +58,7 @@ func NewAppServeAppUsecase(r repository.Repository, argoClient argowf.ArgoClient } } -func (u *AppServeAppUsecase) CreateAppServeApp(app *model.AppServeApp) (string, string, error) { +func (u *AppServeAppUsecase) CreateAppServeApp(app *domain.AppServeApp) (string, string, error) { if app == nil { return "", "", fmt.Errorf("invalid app obj") } @@ -180,7 +179,7 @@ func (u *AppServeAppUsecase) CreateAppServeApp(app *model.AppServeApp) (string, return appId, app.Name, nil } -func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) { apps, err := u.repo.GetAppServeApps(organizationId, showAll, pg) if err != nil { fmt.Println(apps) @@ -189,7 +188,7 @@ func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool return apps, nil } -func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*model.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*domain.AppServeApp, error) { asa, err := u.repo.GetAppServeAppById(appId) if err != nil { return nil, err @@ -223,7 +222,7 @@ func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*model.AppServeAp return asa, nil } -func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) { +func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) { tasks, err := u.repo.GetAppServeAppTasksByAppId(appId, pg) if err != nil { log.Debugf("Tasks: %v", tasks) @@ -232,7 +231,7 @@ func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pa return tasks, nil } -func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) { task, app, err := u.repo.GetAppServeAppTaskById(taskId) if err != nil { return nil, nil, err @@ -241,7 +240,7 @@ func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*model.AppSe return task, app, nil } -func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) { +func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) { task, err := u.repo.GetAppServeAppLatestTask(appId) if err != nil { return nil, err @@ -362,7 +361,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er * Start delete task * ********************/ - appTask := &model.AppServeAppTask{ + appTask := &domain.AppServeAppTask{ AppServeAppId: app.ID, Version: strconv.Itoa(len(app.AppServeAppTasks) + 1), ArtifactUrl: "", @@ -413,7 +412,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er "Confirm result by checking the app status after a while.", app.Name), nil } -func (u *AppServeAppUsecase) UpdateAppServeApp(app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) { +func (u *AppServeAppUsecase) UpdateAppServeApp(app *domain.AppServeApp, appTask *domain.AppServeAppTask) (ret string, err error) { if appTask == nil { return "", errors.New("invalid parameters. appTask is nil") } @@ -660,7 +659,7 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(appId string, taskId string) (r } // Find target(dest) task - var task model.AppServeAppTask + var task domain.AppServeAppTask for _, t := range app.AppServeAppTasks { if t.ID == taskId { task = t diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index 0e3e5165..7461cf05 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -5,17 +5,17 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" ) type IAuditUsecase interface { - Get(ctx context.Context, auditId uuid.UUID) (model.Audit, error) - Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.Audit, error) - Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) - Delete(ctx context.Context, dto model.Audit) error + Get(ctx context.Context, auditId uuid.UUID) (domain.Audit, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Audit, error) + Create(ctx context.Context, dto domain.Audit) (auditId uuid.UUID, err error) + Delete(ctx context.Context, dto domain.Audit) error } type AuditUsecase struct { @@ -28,7 +28,7 @@ func NewAuditUsecase(r repository.Repository) IAuditUsecase { } } -func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { +func (u *AuditUsecase) Create(ctx context.Context, dto domain.Audit) (auditId uuid.UUID, err error) { if dto.UserId == nil { user, ok := request.UserFrom(ctx) if ok { @@ -43,23 +43,23 @@ func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uui return auditId, nil } -func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res model.Audit, err error) { +func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res domain.Audit, err error) { res, err = u.repo.Get(auditId) if err != nil { - return model.Audit{}, err + return domain.Audit{}, err } return } -func (u *AuditUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (audits []model.Audit, err error) { - audits, err = u.repo.Fetch(pg) +func (u *AuditUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (audits []domain.Audit, err error) { + audits, err = u.repo.Fetch(organizationId, pg) if err != nil { return nil, err } return } -func (u *AuditUsecase) Delete(ctx context.Context, dto model.Audit) (err error) { +func (u *AuditUsecase) Delete(ctx context.Context, dto domain.Audit) (err error) { err = u.repo.Delete(dto.ID) if err != nil { return httpErrors.NewNotFoundError(err, "", "") diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 7213d1f2..4fe4fd15 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -24,14 +24,13 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/mail" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" ) type IAuthUsecase interface { - Login(accountId string, password string, organizationId string) (model.User, error) + Login(accountId string, password string, organizationId string) (domain.User, error) Logout(accessToken string, organizationId string) error PingToken(accessToken string, organizationId string) error FindId(code string, email string, userName string, organizationId string) (string, error) @@ -68,28 +67,28 @@ func NewAuthUsecase(r repository.Repository, kc keycloak.IKeycloak) IAuthUsecase } } -func (u *AuthUsecase) Login(accountId string, password string, organizationId string) (model.User, error) { +func (u *AuthUsecase) Login(accountId string, password string, organizationId string) (domain.User, error) { // Authentication with DB user, err := u.userRepository.Get(accountId, organizationId) if err != nil { - return model.User{}, httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") + return domain.User{}, httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") } - var accountToken *model.User + var accountToken *domain.User accountToken, err = u.kc.Login(accountId, password, organizationId) if err != nil { apiErr, ok := err.(*gocloak.APIError) if ok { if apiErr.Code == 401 { - return model.User{}, httpErrors.NewBadRequestError(fmt.Errorf("Mismatch password"), "A_INVALID_PASSWORD", "") + return domain.User{}, httpErrors.NewBadRequestError(fmt.Errorf("Mismatch password"), "A_INVALID_PASSWORD", "") } } - return model.User{}, httpErrors.NewInternalServerError(err, "", "") + return domain.User{}, httpErrors.NewInternalServerError(err, "", "") } log.Errorf("err: %v", err) if err != nil { //TODO: implement not found handling - return model.User{}, err + return domain.User{}, err } // Insert token @@ -255,7 +254,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, } func (u *AuthUsecase) VerifyIdentity(accountId string, email string, userName string, organizationId string) error { - var users *[]model.User + var users *[]domain.User var err error if accountId == "" { diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index b6719bbb..a938066f 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -15,10 +15,10 @@ import ( "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2" "github.com/aws/aws-sdk-go-v2/service/servicequotas" "github.com/aws/aws-sdk-go-v2/service/sts" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" + + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -32,14 +32,14 @@ import ( const MAX_WORKFLOW_TIME = 30 type ICloudAccountUsecase interface { - Get(ctx context.Context, cloudAccountId uuid.UUID) (model.CloudAccount, error) - GetByName(ctx context.Context, organizationId string, name string) (model.CloudAccount, error) - GetByAwsAccountId(ctx context.Context, awsAccountId string) (model.CloudAccount, error) + Get(ctx context.Context, cloudAccountId uuid.UUID) (domain.CloudAccount, error) + GetByName(ctx context.Context, organizationId string, name string) (domain.CloudAccount, error) + GetByAwsAccountId(ctx context.Context, awsAccountId string) (domain.CloudAccount, error) GetResourceQuota(ctx context.Context, cloudAccountId uuid.UUID) (available bool, out domain.ResourceQuota, err error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) - Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) - Update(ctx context.Context, dto model.CloudAccount) error - Delete(ctx context.Context, dto model.CloudAccount) error + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.CloudAccount, error) + Create(ctx context.Context, dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) + Update(ctx context.Context, dto domain.CloudAccount) error + Delete(ctx context.Context, dto domain.CloudAccount) error DeleteForce(ctx context.Context, cloudAccountId uuid.UUID) error } @@ -57,15 +57,14 @@ func NewCloudAccountUsecase(r repository.Repository, argoClient argowf.ArgoClien } } -func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { +func (u *CloudAccountUsecase) Create(ctx context.Context, dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - userId := user.GetUserId() dto.Resource = "TODO server result or additional information" - dto.CreatorId = &userId + dto.CreatorId = user.GetUserId() _, err = u.GetByName(ctx, dto.OrganizationId, dto.Name) if err == nil { @@ -115,15 +114,14 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount return cloudAccountId, nil } -func (u *CloudAccountUsecase) Update(ctx context.Context, dto model.CloudAccount) error { +func (u *CloudAccountUsecase) Update(ctx context.Context, dto domain.CloudAccount) error { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - userId := user.GetUserId() dto.Resource = "TODO server result or additional information" - dto.UpdatorId = &userId + dto.UpdatorId = user.GetUserId() err := u.repo.Update(dto) if err != nil { return httpErrors.NewInternalServerError(err, "", "") @@ -131,10 +129,10 @@ func (u *CloudAccountUsecase) Update(ctx context.Context, dto model.CloudAccount return nil } -func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) (res model.CloudAccount, err error) { +func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) (res domain.CloudAccount, err error) { res, err = u.repo.Get(cloudAccountId) if err != nil { - return model.CloudAccount{}, err + return domain.CloudAccount{}, err } res.Clusters = u.getClusterCnt(cloudAccountId) @@ -142,31 +140,31 @@ func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) return } -func (u *CloudAccountUsecase) GetByName(ctx context.Context, organizationId string, name string) (res model.CloudAccount, err error) { +func (u *CloudAccountUsecase) GetByName(ctx context.Context, organizationId string, name string) (res domain.CloudAccount, err error) { res, err = u.repo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return model.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") + return domain.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") } - return model.CloudAccount{}, err + return domain.CloudAccount{}, err } res.Clusters = u.getClusterCnt(res.ID) return } -func (u *CloudAccountUsecase) GetByAwsAccountId(ctx context.Context, awsAccountId string) (res model.CloudAccount, err error) { +func (u *CloudAccountUsecase) GetByAwsAccountId(ctx context.Context, awsAccountId string) (res domain.CloudAccount, err error) { res, err = u.repo.GetByAwsAccountId(awsAccountId) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return model.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") + return domain.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") } - return model.CloudAccount{}, err + return domain.CloudAccount{}, err } res.Clusters = u.getClusterCnt(res.ID) return } -func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (cloudAccounts []model.CloudAccount, err error) { +func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (cloudAccounts []domain.CloudAccount, err error) { cloudAccounts, err = u.repo.Fetch(organizationId, pg) if err != nil { return nil, err @@ -178,18 +176,17 @@ func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, return } -func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount) (err error) { +func (u *CloudAccountUsecase) Delete(ctx context.Context, dto domain.CloudAccount) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - userId := user.GetUserId() cloudAccount, err := u.Get(ctx, dto.ID) if err != nil { return httpErrors.NewNotFoundError(err, "", "") } - dto.UpdatorId = &userId + dto.UpdatorId = user.GetUserId() if u.getClusterCnt(dto.ID) > 0 { return fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index e22233f3..f298fff7 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -8,11 +8,13 @@ import ( "strings" "time" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" + byoh "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" @@ -23,21 +25,19 @@ import ( gcache "github.com/patrickmn/go-cache" "github.com/pkg/errors" "github.com/spf13/viper" - byoh "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1" "gopkg.in/yaml.v3" "gorm.io/gorm" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type IClusterUsecase interface { WithTrx(*gorm.DB) IClusterUsecase - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Cluster, error) - FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) - Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) - Import(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) - Bootstrap(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Cluster, error) + FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) + Create(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) + Import(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) + Bootstrap(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) Install(ctx context.Context, clusterId domain.ClusterId) (err error) - Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) + Get(ctx context.Context, clusterId domain.ClusterId) (out domain.Cluster, err error) GetClusterSiteValues(ctx context.Context, clusterId domain.ClusterId) (out domain.ClusterSiteValuesResponse, err error) Delete(ctx context.Context, clusterId domain.ClusterId) (err error) CreateBootstrapKubeconfig(ctx context.Context, clusterId domain.ClusterId) (out domain.BootstrapKubeconfig, err error) @@ -101,7 +101,7 @@ func (u *ClusterUsecase) WithTrx(trxHandle *gorm.DB) IClusterUsecase { return u } -func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.Cluster, err error) { +func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []domain.Cluster, err error) { user, ok := request.UserFrom(ctx) if !ok { return out, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -120,7 +120,7 @@ func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *p return out, nil } -func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { +func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { if cloudAccountId == uuid.Nil { return nil, fmt.Errorf("Invalid cloudAccountId") } @@ -133,7 +133,7 @@ func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccount return out, nil } -func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Create(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -153,7 +153,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster tksCloudAccountId := dto.CloudAccountId.String() isExist := false for _, ca := range cloudAccounts { - if ca.ID == *dto.CloudAccountId { + if ca.ID == dto.CloudAccountId { // FOR TEST. ADD MAGIC KEYWORD if strings.Contains(ca.Name, domain.CLOUD_ACCOUNT_INCLUSTER) { @@ -213,7 +213,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster return clusterId, nil } -func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Import(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -275,7 +275,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster return clusterId, nil } -func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -374,10 +374,10 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId return nil } -func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) { +func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (out domain.Cluster, err error) { cluster, err := u.repo.Get(clusterId) if err != nil { - return model.Cluster{}, err + return domain.Cluster{}, err } return cluster, nil @@ -453,13 +453,13 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom out.SshKeyName = "tks-seoul" out.ClusterRegion = "ap-northeast-2" - if err := serializer.Map(cluster, &out); err != nil { + if err := serializer.Map(cluster.Conf, &out); err != nil { log.ErrorWithContext(ctx, err) } if cluster.StackTemplate.CloudService == "AWS" && cluster.StackTemplate.KubeType == "AWS" { - out.TksUserNode = cluster.TksUserNode / domain.MAX_AZ_NUM - out.TksUserNodeMax = cluster.TksUserNodeMax / domain.MAX_AZ_NUM + out.TksUserNode = cluster.Conf.TksUserNode / domain.MAX_AZ_NUM + out.TksUserNodeMax = cluster.Conf.TksUserNodeMax / domain.MAX_AZ_NUM } if err := serializer.Map(cluster, &out); err != nil { @@ -712,30 +712,30 @@ func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterI out = []domain.ClusterNode{ { Type: "TKS_CP_NODE", - Targeted: cluster.TksCpNode, + Targeted: cluster.Conf.TksCpNode, Registered: tksCpNodeRegistered, Registering: tksCpNodeRegistering, - Status: clusterNodeStatus(cluster.TksCpNode, tksCpNodeRegistered), + Status: clusterNodeStatus(cluster.Conf.TksCpNode, tksCpNodeRegistered), Command: command + "control-plane", Validity: bootstrapKubeconfig.Expiration, Hosts: tksCpHosts, }, { Type: "TKS_INFRA_NODE", - Targeted: cluster.TksInfraNode, + Targeted: cluster.Conf.TksInfraNode, Registered: tksInfraNodeRegistered, Registering: tksInfraNodeRegistering, - Status: clusterNodeStatus(cluster.TksInfraNode, tksInfraNodeRegistered), + Status: clusterNodeStatus(cluster.Conf.TksInfraNode, tksInfraNodeRegistered), Command: command + "tks", Validity: bootstrapKubeconfig.Expiration, Hosts: tksInfraHosts, }, { Type: "TKS_USER_NODE", - Targeted: cluster.TksUserNode, + Targeted: cluster.Conf.TksUserNode, Registered: tksUserNodeRegistered, Registering: tksUserNodeRegistering, - Status: clusterNodeStatus(cluster.TksUserNode, tksUserNodeRegistered), + Status: clusterNodeStatus(cluster.Conf.TksUserNode, tksUserNodeRegistered), Command: command + "worker", Validity: bootstrapKubeconfig.Expiration, Hosts: tksUserHosts, @@ -779,7 +779,7 @@ func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterI } /* -func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clusterConf *model.ClusterConf, err error) { +func (u *ClusterUsecase) constructClusterConf(rawConf *domain.ClusterConf) (clusterConf *domain.ClusterConf, err error) { region := "ap-northeast-2" if rawConf != nil && rawConf.Region != "" { region = rawConf.Region @@ -857,7 +857,7 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clust } // Construct cluster conf - tempConf := model.ClusterConf{ + tempConf := domain.ClusterConf{ SshKeyName: sshKeyName, Region: region, NumOfAz: int(numOfAz), diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index a4f271a8..18ceda50 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -11,7 +11,6 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -154,11 +153,11 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri return out, err } - filteredClusters := funk.Filter(clusters, func(x model.Cluster) bool { + filteredClusters := funk.Filter(clusters, func(x domain.Cluster) bool { return x.Status != domain.ClusterStatus_DELETED }) if filteredClusters != nil { - out.Stack = fmt.Sprintf("%d 개", len(filteredClusters.([]model.Cluster))) + out.Stack = fmt.Sprintf("%d 개", len(filteredClusters.([]domain.Cluster))) } else { out.Stack = "0 개" } diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index dcc7bb60..832430a1 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -8,7 +8,6 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -20,10 +19,10 @@ import ( ) type IOrganizationUsecase interface { - Create(context.Context, *model.Organization) (organizationId string, err error) - Fetch(pg *pagination.Pagination) (*[]model.Organization, error) - Get(organizationId string) (model.Organization, error) - Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) + Create(context.Context, *domain.Organization) (organizationId string, err error) + Fetch(pg *pagination.Pagination) (*[]domain.Organization, error) + Get(organizationId string) (domain.Organization, error) + Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) UpdatePrimaryClusterId(organizationId string, clusterId string) (err error) Delete(organizationId string, accessToken string) error } @@ -44,7 +43,7 @@ func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClien } } -func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization) (organizationId string, err error) { +func (u *OrganizationUsecase) Create(ctx context.Context, in *domain.Organization) (organizationId string, err error) { creator := uuid.Nil if in.Creator != "" { creator, err = uuid.Parse(in.Creator) @@ -85,17 +84,17 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization return organizationId, nil } -func (u *OrganizationUsecase) Fetch(pg *pagination.Pagination) (out *[]model.Organization, err error) { +func (u *OrganizationUsecase) Fetch(pg *pagination.Pagination) (out *[]domain.Organization, err error) { organizations, err := u.repo.Fetch(pg) if err != nil { return nil, err } return organizations, nil } -func (u *OrganizationUsecase) Get(organizationId string) (res model.Organization, err error) { +func (u *OrganizationUsecase) Get(organizationId string) (res domain.Organization, err error) { res, err = u.repo.Get(organizationId) if err != nil { - return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") + return domain.Organization{}, httpErrors.NewNotFoundError(err, "", "") } return res, nil } @@ -131,15 +130,15 @@ func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) return nil } -func (u *OrganizationUsecase) Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) { +func (u *OrganizationUsecase) Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) { _, err := u.Get(organizationId) if err != nil { - return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") + return domain.Organization{}, httpErrors.NewNotFoundError(err, "", "") } res, err := u.repo.Update(organizationId, in) if err != nil { - return model.Organization{}, err + return domain.Organization{}, err } return res, nil diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index bcce7e95..4d38cca3 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -2,21 +2,21 @@ package usecase import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" ) type IPermissionUsecase interface { - CreatePermissionSet(permissionSet *model.PermissionSet) error - GetPermissionSetByRoleId(roleId string) (*model.PermissionSet, error) - ListPermissions(roleId string) ([]*model.Permission, error) - //GetPermission(id uuid.UUID) (*model.Permission, error) + CreatePermissionSet(permissionSet *domain.PermissionSet) error + GetPermissionSetByRoleId(roleId string) (*domain.PermissionSet, error) + ListPermissions(roleId string) ([]*domain.Permission, error) + //GetPermission(id uuid.UUID) (*domain.Permission, error) //DeletePermission(id uuid.UUID) error - //UpdatePermission(permission *model.Permission) error - SetRoleIdToPermissionSet(roleId string, permissionSet *model.PermissionSet) - GetAllowedPermissionSet() *model.PermissionSet - GetUserPermissionSet() *model.PermissionSet - UpdatePermission(permission *model.Permission) error + //UpdatePermission(permission *domain.Permission) error + SetRoleIdToPermissionSet(roleId string, permissionSet *domain.PermissionSet) + GetAllowedPermissionSet() *domain.PermissionSet + GetUserPermissionSet() *domain.PermissionSet + UpdatePermission(permission *domain.Permission) error } type PermissionUsecase struct { @@ -29,7 +29,7 @@ func NewPermissionUsecase(repo repository.Repository) *PermissionUsecase { } } -func (p PermissionUsecase) CreatePermissionSet(permissionSet *model.PermissionSet) error { +func (p PermissionUsecase) CreatePermissionSet(permissionSet *domain.PermissionSet) error { var err error if err = p.repo.Create(permissionSet.Dashboard); err != nil { return err @@ -52,8 +52,8 @@ func (p PermissionUsecase) CreatePermissionSet(permissionSet *model.PermissionSe return nil } -func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*model.PermissionSet, error) { - permissionSet := &model.PermissionSet{ +func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*domain.PermissionSet, error) { + permissionSet := &domain.PermissionSet{ Dashboard: nil, Stack: nil, SecurityPolicy: nil, @@ -68,17 +68,17 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*model.Permi } for _, permission := range permissionList { switch permission.Name { - case string(model.DashBoardPermission): + case string(domain.DashBoardPermission): permissionSet.Dashboard = permission - case string(model.StackPermission): + case string(domain.StackPermission): permissionSet.Stack = permission - case string(model.SecurityPolicyPermission): + case string(domain.SecurityPolicyPermission): permissionSet.SecurityPolicy = permission - case string(model.ProjectManagementPermission): + case string(domain.ProjectManagementPermission): permissionSet.ProjectManagement = permission - case string(model.NotificationPermission): + case string(domain.NotificationPermission): permissionSet.Notification = permission - case string(model.ConfigurationPermission): + case string(domain.ConfigurationPermission): permissionSet.Configuration = permission } } @@ -86,11 +86,11 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*model.Permi return permissionSet, nil } -func (p PermissionUsecase) ListPermissions(roleId string) ([]*model.Permission, error) { +func (p PermissionUsecase) ListPermissions(roleId string) ([]*domain.Permission, error) { return p.repo.List(roleId) } -func (p PermissionUsecase) GetPermission(id uuid.UUID) (*model.Permission, error) { +func (p PermissionUsecase) GetPermission(id uuid.UUID) (*domain.Permission, error) { return p.repo.Get(id) } @@ -98,22 +98,22 @@ func (p PermissionUsecase) DeletePermission(id uuid.UUID) error { return p.repo.Delete(id) } -func (p PermissionUsecase) UpdatePermission(permission *model.Permission) error { +func (p PermissionUsecase) UpdatePermission(permission *domain.Permission) error { return p.repo.Update(permission) } -func (p PermissionUsecase) SetRoleIdToPermissionSet(roleId string, permissionSet *model.PermissionSet) { +func (p PermissionUsecase) SetRoleIdToPermissionSet(roleId string, permissionSet *domain.PermissionSet) { permissionSet.SetRoleId(roleId) } -func (p PermissionUsecase) GetAllowedPermissionSet() *model.PermissionSet { - permissionSet := model.NewDefaultPermissionSet() +func (p PermissionUsecase) GetAllowedPermissionSet() *domain.PermissionSet { + permissionSet := domain.NewDefaultPermissionSet() permissionSet.SetAllowedPermissionSet() return permissionSet } -func (p PermissionUsecase) GetUserPermissionSet() *model.PermissionSet { - permissionSet := model.NewDefaultPermissionSet() +func (p PermissionUsecase) GetUserPermissionSet() *domain.PermissionSet { + permissionSet := domain.NewDefaultPermissionSet() permissionSet.SetUserPermissionSet() return permissionSet } diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 7c76a846..9f1b8263 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -9,23 +9,21 @@ import ( "github.com/google/uuid" "github.com/open-policy-agent/opa/ast" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" ) type IPolicyTemplateUsecase interface { - Create(ctx context.Context, policyTemplate model.PolicyTemplate) (policyTemplateId string, err error) - Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) + Create(ctx context.Context, policyTemplate domain.PolicyTemplate) (policyTemplateId string, err error) + Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []domain.PolicyTemplate, err error) Update(ctx context.Context, policyTemplateId uuid.UUID, update domain.UpdatePolicyTemplateRequest) (err error) - Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) + Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *domain.PolicyTemplate, err error) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) IsPolicyTemplateKindExist(ctx context.Context, policyTemplateKind string) (bool, error) - GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) + GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) @@ -47,7 +45,7 @@ func NewPolicyTemplateUsecase(r repository.Repository) IPolicyTemplateUsecase { } } -func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId string, err error) { +func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto domain.PolicyTemplate) (policyTemplateId string, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") @@ -81,7 +79,7 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp return id.String(), nil } -func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []domain.PolicyTemplate, err error) { policyTemplates, err = u.repo.Fetch(pg) if err != nil { @@ -101,7 +99,7 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagina } -func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *domain.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetByID(policyTemplateID) if err != nil { @@ -175,7 +173,7 @@ func (u *PolicyTemplateUsecase) IsPolicyTemplateKindExist(ctx context.Context, p return u.repo.ExistByKind(policyTemplateKind) } -func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetPolicyTemplateVersion(policyTemplateId, version) if err != nil { @@ -192,12 +190,10 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, po return policyTemplate, nil } -func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]model.Organization, permittedOrgIdSet map[string]string, policyTemplate *model.PolicyTemplate) { +func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]domain.Organization, permittedOrgIdSet map[string]string, policyTemplate *domain.PolicyTemplate) { // 허용리스트가 비어있으면 모든 Org에 대해서 허용 permitted := len(permittedOrgIdSet) == 0 - log.Info("CHECK HERE ", permitted) - for _, organization := range *organizations { _, ok := permittedOrgIdSet[organization.ID] @@ -205,30 +201,21 @@ func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]mode if !ok { policyTemplate.PermittedOrganizations = append( policyTemplate.PermittedOrganizations, - - // ktkfree : 역시 이부분 확인 부탁 드립니다. - /* - domain.PermittedOrganization{ - OrganizationId: organization.ID, - OrganizationName: organization.Name, - Permitted: permitted, - } - */ - ) + domain.PermittedOrganization{ + OrganizationId: organization.ID, + OrganizationName: organization.Name, + Permitted: permitted, + }) } } } -func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *model.PolicyTemplate) map[string]string { +func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *domain.PolicyTemplate) map[string]string { permittedOrgIdSet := make(map[string]string) for _, permittedOrg := range policyTemplate.PermittedOrganizations { // Set 처리를 위해서 키만 사용, 값은 아무거나 - - // ktkfree : 이부분 확인 부탁 드립니다. - // - //permittedOrgIdSet[permittedOrg.OrganizationId] = "1" - log.Info("CHECK HERE ", permittedOrg) + permittedOrgIdSet[permittedOrg.OrganizationId] = "1" } return permittedOrgIdSet } diff --git a/internal/usecase/role.go b/internal/usecase/role.go index bc5d3734..70d51081 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -1,18 +1,18 @@ package usecase import ( - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" ) type IRoleUsecase interface { - CreateTksRole(role *model.Role) (string, error) - ListRoles(pg *pagination.Pagination) ([]*model.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) - GetTksRole(id string) (*model.Role, error) + CreateTksRole(role *domain.Role) (string, error) + ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) + GetTksRole(id string) (*domain.Role, error) DeleteTksRole(id string) error - UpdateTksRole(role *model.Role) error + UpdateTksRole(role *domain.Role) error } type RoleUsecase struct { @@ -25,11 +25,11 @@ func NewRoleUsecase(repo repository.Repository) *RoleUsecase { } } -func (r RoleUsecase) CreateTksRole(role *model.Role) (string, error) { +func (r RoleUsecase) CreateTksRole(role *domain.Role) (string, error) { return r.repo.Create(role) } -func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { +func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) { roles, err := r.repo.ListTksRoles(organizationId, pg) if err != nil { return nil, err @@ -38,11 +38,11 @@ func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Paginati return roles, nil } -func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*model.Role, error) { +func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) { return r.repo.List(nil) } -func (r RoleUsecase) GetTksRole(id string) (*model.Role, error) { +func (r RoleUsecase) GetTksRole(id string) (*domain.Role, error) { role, err := r.repo.GetTksRole(id) if err != nil { return nil, err @@ -55,7 +55,7 @@ func (r RoleUsecase) DeleteTksRole(id string) error { return r.repo.Delete(id) } -func (r RoleUsecase) UpdateTksRole(role *model.Role) error { +func (r RoleUsecase) UpdateTksRole(role *domain.Role) error { err := r.repo.Update(role) if err != nil { return err diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 4c672e7a..2a258d16 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -7,21 +7,20 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" ) type IStackTemplateUsecase interface { - Get(ctx context.Context, stackTemplateId uuid.UUID) (model.StackTemplate, error) - Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.StackTemplate, error) - FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.StackTemplate, error) - Create(ctx context.Context, dto model.StackTemplate) (stackTemplate uuid.UUID, err error) - Update(ctx context.Context, dto model.StackTemplate) error - Delete(ctx context.Context, dto model.StackTemplate) error - UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error + Get(ctx context.Context, stackTemplateId uuid.UUID) (domain.StackTemplate, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]domain.StackTemplate, error) + Create(ctx context.Context, dto domain.StackTemplate) (stackTemplate uuid.UUID, err error) + Update(ctx context.Context, dto domain.StackTemplate) error + Delete(ctx context.Context, dto domain.StackTemplate) error + UpdateOrganizations(ctx context.Context, dto domain.StackTemplate) error } type StackTemplateUsecase struct { @@ -36,14 +35,13 @@ func NewStackTemplateUsecase(r repository.Repository) IStackTemplateUsecase { } } -func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { +func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - userId := user.GetUserId() - dto.CreatorId = &userId - dto.UpdatorId = &userId + dto.CreatorId = user.GetUserId() + dto.UpdatorId = user.GetUserId() pg := pagination.NewPaginationWithFilter("name", "", "$eq", []string{dto.Name}) stackTemplates, _ := u.Fetch(ctx, pg) @@ -78,7 +76,7 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTempla return stackTemplateId, nil } -func (u *StackTemplateUsecase) Update(ctx context.Context, dto model.StackTemplate) error { +func (u *StackTemplateUsecase) Update(ctx context.Context, dto domain.StackTemplate) error { _, err := u.repo.Get(dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") @@ -91,15 +89,15 @@ func (u *StackTemplateUsecase) Update(ctx context.Context, dto model.StackTempla return nil } -func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res model.StackTemplate, err error) { +func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res domain.StackTemplate, err error) { res, err = u.repo.Get(stackTemplateId) if err != nil { - return model.StackTemplate{}, err + return domain.StackTemplate{}, err } return } -func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (res []model.StackTemplate, err error) { +func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (res []domain.StackTemplate, err error) { res, err = u.repo.Fetch(pg) if err != nil { return nil, err @@ -107,25 +105,17 @@ func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Paginat return res, nil } -func (u *StackTemplateUsecase) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (res []model.StackTemplate, err error) { - res, err = u.repo.FetchWithOrganization(organizationId, pg) - if err != nil { - return nil, err - } - return res, nil -} - -func (u *StackTemplateUsecase) Delete(ctx context.Context, dto model.StackTemplate) (err error) { +func (u *StackTemplateUsecase) Delete(ctx context.Context, dto domain.StackTemplate) (err error) { return nil } -func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error { +func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto domain.StackTemplate) error { _, err := u.repo.Get(dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") } - organizations := make([]model.Organization, 0) + organizations := make([]domain.Organization, 0) for _, organizationId := range dto.OrganizationIds { organization, err := u.organizationRepo.Get(organizationId) if err == nil { diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 9daeea2a..3bb6f907 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -11,7 +11,6 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" @@ -25,13 +24,13 @@ import ( ) type IStackUsecase interface { - Get(ctx context.Context, stackId domain.StackId) (model.Stack, error) - GetByName(ctx context.Context, organizationId string, name string) (model.Stack, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Stack, error) - Create(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) + Get(ctx context.Context, stackId domain.StackId) (domain.Stack, error) + GetByName(ctx context.Context, organizationId string, name string) (domain.Stack, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Stack, error) + Create(ctx context.Context, dto domain.Stack) (stackId domain.StackId, err error) Install(ctx context.Context, stackId domain.StackId) (err error) - Update(ctx context.Context, dto model.Stack) error - Delete(ctx context.Context, dto model.Stack) error + Update(ctx context.Context, dto domain.Stack) error + Delete(ctx context.Context, dto domain.Stack) error GetKubeConfig(ctx context.Context, stackId domain.StackId) (kubeConfig string, err error) GetStepStatus(ctx context.Context, stackId domain.StackId) (out []domain.StackStepStatus, stackStatus string, err error) SetFavorite(ctx context.Context, stackId domain.StackId) error @@ -62,7 +61,7 @@ func NewStackUsecase(r repository.Repository, argoClient argowf.ArgoClient, dash } } -func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) { +func (u *StackUsecase) Create(ctx context.Context, dto domain.Stack) (stackId domain.StackId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -104,7 +103,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom // Make stack nodes var stackConf domain.StackConfResponse - if err = serializer.Map(dto, &stackConf); err != nil { + if err = domain.Map(dto.Conf, &stackConf); err != nil { log.InfoWithContext(ctx, err) } if stackTemplate.CloudService == "AWS" && stackTemplate.KubeType == "AWS" { @@ -197,7 +196,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err // Make stack nodes var stackConf domain.StackConfResponse - if err = serializer.Map(cluster, &stackConf); err != nil { + if err = domain.Map(cluster.Conf, &stackConf); err != nil { log.InfoWithContext(ctx, err) } @@ -222,7 +221,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err return nil } -func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out model.Stack, err error) { +func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out domain.Stack, err error) { cluster, err := u.clusterRepo.Get(domain.ClusterId(stackId)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -276,7 +275,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod return } -func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Stack, err error) { +func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, name string) (out domain.Stack, err error) { cluster, err := u.clusterRepo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -294,7 +293,7 @@ func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, nam return } -func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.Stack, err error) { +func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []domain.Stack, err error) { user, ok := request.UserFrom(ctx) if !ok { return out, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -353,7 +352,7 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return } -func (u *StackUsecase) Update(ctx context.Context, dto model.Stack) (err error) { +func (u *StackUsecase) Update(ctx context.Context, dto domain.Stack) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -365,7 +364,7 @@ func (u *StackUsecase) Update(ctx context.Context, dto model.Stack) (err error) } updatorId := user.GetUserId() - dtoCluster := model.Cluster{ + dtoCluster := domain.Cluster{ ID: domain.ClusterId(dto.ID), Description: dto.Description, UpdatorId: &updatorId, @@ -379,7 +378,7 @@ func (u *StackUsecase) Update(ctx context.Context, dto model.Stack) (err error) return nil } -func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) { +func (u *StackUsecase) Delete(ctx context.Context, dto domain.Stack) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -618,7 +617,7 @@ func (u *StackUsecase) DeleteFavorite(ctx context.Context, stackId domain.StackI return nil } -func reflectClusterToStack(cluster model.Cluster, appGroups []model.AppGroup) (out model.Stack) { +func reflectClusterToStack(cluster domain.Cluster, appGroups []domain.AppGroup) (out domain.Stack) { if err := serializer.Map(cluster, &out); err != nil { log.Error(err) } @@ -630,7 +629,7 @@ func reflectClusterToStack(cluster model.Cluster, appGroups []model.AppGroup) (o out.StatusDesc = statusDesc /* - return model.Stack{ + return domain.Stack{ ID: domain.StackId(cluster.ID), OrganizationId: cluster.OrganizationId, Name: cluster.Name, @@ -664,7 +663,7 @@ func reflectClusterToStack(cluster model.Cluster, appGroups []model.AppGroup) (o } // [TODO] more pretty -func getStackStatus(cluster model.Cluster, appGroups []model.AppGroup) (domain.StackStatus, string) { +func getStackStatus(cluster domain.Cluster, appGroups []domain.AppGroup) (domain.StackStatus, string) { for _, appGroup := range appGroups { if appGroup.Status == domain.AppGroupStatus_PENDING && cluster.Status == domain.ClusterStatus_RUNNING { return domain.StackStatus_APPGROUP_INSTALLING, appGroup.StatusDesc diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 0d3bd907..b851d2f5 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -10,32 +10,32 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/mail" - "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" ) type IUserUsecase interface { - CreateAdmin(organizationId string, email string) (*model.User, error) + CreateAdmin(organizationId string, email string) (*domain.User, error) DeleteAdmin(organizationId string) error DeleteAll(ctx context.Context, organizationId string) error - Create(ctx context.Context, user *model.User) (*model.User, error) - List(ctx context.Context, organizationId string) (*[]model.User, error) - ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.User, error) - Get(userId uuid.UUID) (*model.User, error) - Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) + Create(ctx context.Context, user *domain.User) (*domain.User, error) + List(ctx context.Context, organizationId string) (*[]domain.User, error) + ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]domain.User, error) + Get(userId uuid.UUID) (*domain.User, error) + Update(ctx context.Context, userId uuid.UUID, user *domain.User) (*domain.User, error) ResetPassword(userId uuid.UUID) error ResetPasswordByAccountId(accountId string, organizationId string) error GenerateRandomPassword() string Delete(userId uuid.UUID, organizationId string) error - GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) - GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) + GetByAccountId(ctx context.Context, accountId string, organizationId string) (*domain.User, error) + GetByEmail(ctx context.Context, email string, organizationId string) (*domain.User, error) SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error - UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) + UpdateByAccountId(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) UpdatePasswordByAccountId(ctx context.Context, accountId string, originPassword string, newPassword string, organizationId string) error RenewalPasswordExpiredTime(ctx context.Context, userId uuid.UUID) error RenewalPasswordExpiredTimeByAccountId(ctx context.Context, accountId string, organizationId string) error @@ -43,7 +43,7 @@ type IUserUsecase interface { ValidateAccount(userId uuid.UUID, password string, organizationId string) error ValidateAccountByAccountId(accountId string, password string, organizationId string) error - UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *model.User) (*model.User, error) + UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) } type UserUsecase struct { @@ -196,17 +196,17 @@ func (u *UserUsecase) DeleteAdmin(organizationId string) error { return nil } -func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*model.User, error) { +func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*domain.User, error) { // Generate Admin user object randomPassword := helper.GenerateRandomString(passwordLength) - user := model.User{ + user := domain.User{ AccountId: "admin", Password: randomPassword, Email: email, - Role: model.Role{ + Role: domain.Role{ Name: "admin", }, - Organization: model.Organization{ + Organization: domain.Organization{ ID: orgainzationId, }, Name: "admin", @@ -295,7 +295,7 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s return nil } -func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[]model.User, err error) { +func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[]domain.User, err error) { users, err = u.userRepository.List(u.userRepository.OrganizationFilter(organizationId)) if err != nil { return nil, err @@ -304,7 +304,7 @@ func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[ return } -func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (users *[]model.User, err error) { +func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (users *[]domain.User, err error) { users, err = u.userRepository.ListWithPagination(pg, organizationId) if err != nil { return nil, err @@ -313,7 +313,7 @@ func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId str return } -func (u *UserUsecase) Get(userId uuid.UUID) (*model.User, error) { +func (u *UserUsecase) Get(userId uuid.UUID) (*domain.User, error) { user, err := u.userRepository.GetByUuid(userId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -325,7 +325,7 @@ func (u *UserUsecase) Get(userId uuid.UUID) (*model.User, error) { return &user, nil } -func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) { +func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, organizationId string) (*domain.User, error) { users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), u.userRepository.AccountIdFilter(accountId)) if err != nil { @@ -335,7 +335,7 @@ func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, orga return &(*users)[0], nil } -func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) { +func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organizationId string) (*domain.User, error) { users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), u.userRepository.EmailFilter(email)) if err != nil { @@ -345,7 +345,7 @@ func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organization return &(*users)[0], nil } -func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) { +func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *domain.User) (*domain.User, error) { storedUser, err := u.Get(userId) if err != nil { return nil, err @@ -355,8 +355,8 @@ func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *model. return u.UpdateByAccountId(ctx, storedUser.AccountId, user) } -func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) { - var out model.User +func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) { + var out domain.User originUser, err := u.kc.GetUser(user.Organization.ID, accountId) if err != nil { @@ -438,7 +438,7 @@ func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, o return nil } -func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User, error) { +func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.User, error) { // Create user in keycloak groups := []string{fmt.Sprintf("%s@%s", user.Role.Name, user.Organization.ID)} userUuidStr, err := u.kc.CreateUser(user.Organization.ID, &gocloak.User{ @@ -492,7 +492,7 @@ func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User return &resUser, nil } -func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *model.User) (*model.User, error) { +func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *domain.User) (*domain.User, error) { deepCopyUser := *newUser user, err := u.UpdateByAccountId(ctx, accountId, &deepCopyUser) if err != nil { diff --git a/pkg/domain/admin/user.go b/pkg/domain/admin/user.go index 0a9e6820..7d53a51e 100644 --- a/pkg/domain/admin/user.go +++ b/pkg/domain/admin/user.go @@ -1,9 +1,8 @@ package admin import ( - "time" - "github.com/openinfradev/tks-api/pkg/domain" + "time" ) type CreateUserRequest struct { @@ -27,17 +26,17 @@ type ListUserResponse struct { type GetUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role domain.RoleResponse `json:"role"` - Organization domain.OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role domain.Role `json:"role"` + Organization domain.Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } @@ -52,16 +51,16 @@ type UpdateUserRequest struct { type UpdateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role domain.RoleResponse `json:"role"` - Organization domain.OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role domain.Role `json:"role"` + Organization domain.Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } diff --git a/pkg/domain/alert.go b/pkg/domain/alert.go index a60073bf..7201ef24 100644 --- a/pkg/domain/alert.go +++ b/pkg/domain/alert.go @@ -33,6 +33,50 @@ func (m AlertActionStatus) FromString(s string) AlertActionStatus { return AlertActionStatus_ERROR } +// 내부 +type Alert struct { + ID uuid.UUID + OrganizationId string + Organization Organization + Name string + Description string + Code string + Grade string + Message string + ClusterId ClusterId + Cluster Cluster + Node string + CheckPoint string + Summary string + GrafanaUrl string + FiredAt *time.Time + TakedAt *time.Time + ClosedAt *time.Time + TakedSec int + ProcessingSec int + Status AlertActionStatus + AlertActions []AlertAction + LastTaker User + RawData []byte + CreatorId *uuid.UUID + Creator User + UpdatorId *uuid.UUID + Updator User + CreatedAt time.Time + UpdatedAt time.Time +} + +type AlertAction struct { + ID uuid.UUID + AlertId uuid.UUID + Content string + Status AlertActionStatus + TakerId *uuid.UUID + Taker User + CreatedAt time.Time + UpdatedAt time.Time +} + type CreateAlertRequestAlert struct { Status string `json:"status"` GeneratorURL string `json:"generatorURL"` diff --git a/pkg/domain/app-group.go b/pkg/domain/app-group.go index 36dff144..d4e3211d 100644 --- a/pkg/domain/app-group.go +++ b/pkg/domain/app-group.go @@ -114,6 +114,33 @@ func (m AppGroupType) FromString(s string) AppGroupType { return AppGroupType_UNSPECIFIED } +type AppGroup = struct { + ID AppGroupId + Name string + ClusterId ClusterId + AppGroupType AppGroupType + Description string + WorkflowId string + Status AppGroupStatus + StatusDesc string + CreatorId *uuid.UUID + Creator User + UpdatorId *uuid.UUID + Updator User + CreatedAt time.Time + UpdatedAt time.Time +} + +type Application = struct { + ID uuid.UUID + AppGroupId AppGroupId + Endpoint string + Metadata string + ApplicationType ApplicationType + CreatedAt time.Time + UpdatedAt time.Time +} + type AppGroupResponse = struct { ID AppGroupId `json:"id"` Name string `json:"name"` diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index b1db60af..45239154 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -1,56 +1,71 @@ package domain -import "time" - -type AppServeAppResponse struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` // application name - Namespace string `json:"namespace,omitempty"` // application namespace - OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to - ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to - Type string `json:"type,omitempty"` // type (build/deploy/all) - AppType string `json:"appType,omitempty"` // appType (spring/springboot) - EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app - PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment - TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed - TargetClusterName string `json:"targetClusterName,omitempty"` // target cluster name - Status string `json:"status,omitempty"` // status is status of deployed app - GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app - CreatedAt time.Time `json:"createdAt" ` - UpdatedAt *time.Time `json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` - AppServeAppTasks []AppServeAppTaskResponse `json:"appServeAppTasks"` -} - -type AppServeAppTaskResponse struct { - ID string `json:"id,omitempty"` - AppServeAppId string `json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to - Version string `json:"version,omitempty"` // application version - Status string `json:"status,omitempty"` // status is app status - Output string `json:"output,omitempty"` // output for task result - ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) - ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app - ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image - Profile string `json:"profile,omitempty"` // java app profile - AppConfig string `json:"appConfig,omitempty"` // java app config - AppSecret string `json:"appSecret,omitempty"` // java app secret - ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app - Port string `json:"port,omitempty"` // java app port - ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod - HelmRevision int32 `json:"helmRevision,omitempty"` // revision of deployed helm release - Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) - RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +type AppServeApp struct { + ID string `gorm:"primarykey" json:"id,omitempty"` + Name string `gorm:"index" json:"name,omitempty"` // application name + Namespace string `json:"namespace,omitempty"` // application namespace + OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to + Type string `json:"type,omitempty"` // type (build/deploy/all) + AppType string `json:"appType,omitempty"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed + TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name + Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` + AppServeAppTasks []AppServeAppTask `gorm:"foreignKey:AppServeAppId" json:"appServeAppTasks"` +} + +type AppServeAppTask struct { + ID string `gorm:"primarykey" json:"id,omitempty"` + AppServeAppId string `gorm:"not null" json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to + Version string `json:"version,omitempty"` // application version + Status string `json:"status,omitempty"` // status is app status + Output string `json:"output,omitempty"` // output for task result + ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) + ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app + ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image + Profile string `json:"profile,omitempty"` // java app profile + AppConfig string `json:"appConfig,omitempty"` // java app config + AppSecret string `json:"appSecret,omitempty"` // java app secret + ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app + Port string `json:"port,omitempty"` // java app port + ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod + HelmRevision int32 `gorm:"default:0" json:"helmRevision,omitempty"` // revision of deployed helm release + Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) + RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version PvEnabled bool `json:"pvEnabled"` PvStorageClass string `json:"pvStorageClass"` PvAccessMode string `json:"pvAccessMode"` PvSize string `json:"pvSize"` PvMountPath string `json:"pvMountPath"` - AvailableRollback bool `json:"availableRollback"` - CreatedAt time.Time `json:"createdAt"` // createdAt is a creation timestamp for the application - UpdatedAt *time.Time `json:"updatedAt"` + AvailableRollback bool `gorm:"-:all" json:"availableRollback"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` // createdAt is a creation timestamp for the application + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` } +func (a *AppServeApp) BeforeCreate(tx *gorm.DB) (err error) { + a.ID = uuid.New().String() + return nil +} + +func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} + type CreateAppServeAppRequest struct { // App Name string `json:"name" validate:"required,rfc1123,name"` @@ -143,25 +158,25 @@ type RollbackAppServeAppRequest struct { } type GetAppServeAppsResponse struct { - AppServeApps []AppServeAppResponse `json:"appServeApps"` - Pagination PaginationResponse `json:"pagination"` + AppServeApps []AppServeApp `json:"appServeApps"` + Pagination PaginationResponse `json:"pagination"` } // TODO: This will be deprecated later type GetAppServeAppResponse struct { - AppServeApp AppServeAppResponse `json:"appServeApp"` - Stages []StageResponse `json:"stages"` + AppServeApp AppServeApp `json:"appServeApp"` + Stages []StageResponse `json:"stages"` } type GetAppServeAppTasksResponse struct { - AppServeAppTasks []AppServeAppTaskResponse `json:"appServeAppTasks"` - Pagination PaginationResponse `json:"pagination"` + AppServeAppTasks []AppServeAppTask `json:"appServeAppTasks"` + Pagination PaginationResponse `json:"pagination"` } type GetAppServeAppTaskResponse struct { - AppServeApp AppServeAppResponse `json:"appServeApp"` - AppServeAppTask AppServeAppTaskResponse `json:"appServeAppTask"` - Stages []StageResponse `json:"stages"` + AppServeApp AppServeApp `json:"appServeApp"` + AppServeAppTask AppServeAppTask `json:"appServeAppTask"` + Stages []StageResponse `json:"stages"` } type StageResponse struct { diff --git a/pkg/domain/audit.go b/pkg/domain/audit.go index 6622aa40..9599ccae 100644 --- a/pkg/domain/audit.go +++ b/pkg/domain/audit.go @@ -2,8 +2,25 @@ package domain import ( "time" + + "github.com/google/uuid" ) +// 내부 +type Audit struct { + ID uuid.UUID + OrganizationId string + Organization Organization + Group string + Message string + Description string + ClientIP string + UserId *uuid.UUID + User User + CreatedAt time.Time + UpdatedAt time.Time +} + type AuditResponse struct { ID string `json:"id"` OrganizationId string `json:"organizationId"` @@ -12,6 +29,7 @@ type AuditResponse struct { Group string `json:"group"` Message string `json:"message"` ClientIP string `json:"clientIP"` + UserId string `json:"userId"` User SimpleUserResponse `json:"user"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` diff --git a/pkg/domain/auth.go b/pkg/domain/auth.go index 4dbaeeef..abab6f97 100644 --- a/pkg/domain/auth.go +++ b/pkg/domain/auth.go @@ -13,13 +13,13 @@ type PingTokenRequest struct { type LoginResponse struct { User struct { - AccountId string `json:"accountId"` - Name string `json:"name"` - Token string `json:"token"` - Role RoleResponse `json:"role"` - Department string `json:"department"` - Organization OrganizationResponse `json:"organization"` - PasswordExpired bool `json:"passwordExpired"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Token string `json:"token"` + Role Role `json:"role"` + Department string `json:"department"` + Organization Organization `json:"organization"` + PasswordExpired bool `json:"passwordExpired"` } `json:"user"` } diff --git a/pkg/domain/cloud-account.go b/pkg/domain/cloud-account.go index 591356ac..5e4720c8 100644 --- a/pkg/domain/cloud-account.go +++ b/pkg/domain/cloud-account.go @@ -2,6 +2,8 @@ package domain import ( "time" + + "github.com/google/uuid" ) const CLOUD_ACCOUNT_INCLUSTER = "INCLUSTER" @@ -47,6 +49,30 @@ func (m CloudAccountStatus) FromString(s string) CloudAccountStatus { return CloudAccountStatus_PENDING } +// 내부 +type CloudAccount struct { + ID uuid.UUID + OrganizationId string + Name string + Description string + CloudService string + Resource string + Clusters int + AwsAccountId string + AccessKeyId string + SecretAccessKey string + SessionToken string + Status CloudAccountStatus + StatusDesc string + CreatedIAM bool + CreatorId uuid.UUID + Creator User + UpdatorId uuid.UUID + Updator User + CreatedAt time.Time + UpdatedAt time.Time +} + type ResourceQuotaAttr struct { Type string `json:"type"` Usage int `json:"usage"` @@ -131,7 +157,3 @@ type GetCloudAccountResourceQuotaResponse struct { Available bool `json:"available"` ResourceQuota ResourceQuota `json:"resourceQuota"` } - -type DeleteCloudAccountResponse struct { - ID string `json:"id"` -} diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index 0d7c854b..6c2ea884 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -3,6 +3,7 @@ package domain import ( "time" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" ) @@ -82,6 +83,34 @@ func (m ClusterType) FromString(s string) ClusterType { return ClusterType_USER } +// model +type Cluster struct { + ID ClusterId + CloudService string + OrganizationId string + Name string + Description string + CloudAccountId uuid.UUID + CloudAccount CloudAccount + StackTemplateId uuid.UUID + StackTemplate StackTemplate + Status ClusterStatus + StatusDesc string + Conf ClusterConf + Favorited bool + CreatorId *uuid.UUID + Creator User + ClusterType ClusterType + UpdatorId *uuid.UUID + Updator User + CreatedAt time.Time + UpdatedAt time.Time + ByoClusterEndpointHost string + ByoClusterEndpointPort int + IsStack bool + Kubeconfig []byte +} + type ClusterConf struct { TksCpNode int TksCpNodeMax int @@ -210,7 +239,6 @@ type ClusterResponse struct { ByoClusterEndpointHost string `json:"byoClusterEndpointHost,omitempty"` ByoClusterEndpointInt int `json:"byoClusterEndpointPort,omitempty"` IsStack bool `json:"isStack,omitempty"` - Favorited bool `json:"favorited,omitempty"` } type SimpleClusterResponse struct { diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 6f3e18e2..c7699fb7 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -37,6 +37,14 @@ func (m ChartType) FromString(s string) ChartType { return ChartType_ERROR } +// [TODO] +func (m ChartType) All() (out []string) { + for _, v := range chartType { + out = append(out, v) + } + return +} + // 내부 type DashboardChart struct { ChartType ChartType @@ -64,14 +72,6 @@ type DashboardStack struct { UpdatedAt time.Time } -// [TODO] -func (m ChartType) All() (out []string) { - for _, v := range chartType { - out = append(out, v) - } - return -} - type Unit struct { Name string `json:"name"` Data []string `json:"data"` diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index e2a2127d..c34a45ae 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -1,10 +1,11 @@ package domain -import "time" +import ( + "time" +) -type EndpointResponse struct { - Name string `json:"name"` - Group string `json:"group"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` +type Endpoint struct { + Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` + Group string `gorm:"type:text;" json:"group"` + CreatedAt time.Time } diff --git a/pkg/domain/mapper.go b/pkg/domain/mapper.go new file mode 100644 index 00000000..e3fa80ac --- /dev/null +++ b/pkg/domain/mapper.go @@ -0,0 +1,140 @@ +package domain + +import ( + "fmt" + "reflect" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/log" +) + +type ConverterMap map[compositeKey]func(interface{}) (interface{}, error) + +type compositeKey struct { + srcType reflect.Type + dstType reflect.Type +} + +func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) error { + srcVal := reflect.ValueOf(src) + srcType := srcVal.Type() + + dstVal := reflect.ValueOf(dst) + if dstVal.Kind() != reflect.Ptr || dstVal.IsNil() { + return fmt.Errorf("dst must be a non-nil pointer") + } + dstElem := dstVal.Elem() + + for i := 0; i < srcVal.NumField(); i++ { + fieldName := srcType.Field(i).Name + srcField := srcVal.Field(i) + dstField := dstElem.FieldByName(fieldName) + + if dstField.IsValid() && dstField.CanSet() { + if dstField.Type() == srcField.Type() { + dstField.Set(srcField) + continue + } else if srcField.Type().Kind() == reflect.Struct && dstField.Type().Kind() == reflect.Struct { + if err := recursiveMap(srcField.Interface(), dstField.Addr().Interface(), converterMap); err != nil { + return err + } + } else { + converterKey := compositeKey{srcType: srcField.Type(), dstType: dstField.Type()} + if converter, ok := converterMap[converterKey]; ok { + if converted, err := converter(srcField.Interface()); err != nil { + return err + } else { + dstField.Set(reflect.ValueOf(converted)) + } + } else { + log.Debugf("no converter found for %s -> %s", srcField.Type(), dstField.Type()) + continue + } + } + + /* + else if srcField.Type().Kind() == reflect.Ptr && dstField.Type().Kind() == reflect.Ptr { + log.Info("AAA ", dstField.Type()) + ptr := reflect.New(dstField.Elem().Type()) + if err := recursiveMap(srcField.Elem().Interface(), ptr.Elem().Interface(), converterMap); err != nil { + return err + } + } + */ + + } + } + + return nil +} +func Map(src interface{}, dst interface{}) error { + return recursiveMap(src, dst, ConverterMap{ + {srcType: reflect.TypeOf((*uuid.UUID)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(uuid.UUID).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*uuid.UUID)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + val, _ := uuid.Parse(i.(string)) + return val, nil + }, + {srcType: reflect.TypeOf((*OrganizationStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(OrganizationStatus).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*OrganizationStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return organizationStatusMap[i.(string)], nil + }, + {srcType: reflect.TypeOf((*Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(Role).Name, nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return Role{Name: i.(string)}, nil + }, + {srcType: reflect.TypeOf((*ClusterStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(ClusterStatus).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ClusterStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(ClusterStatus).FromString(i.(string)), nil + }, + {srcType: reflect.TypeOf((*AppGroupStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(AppGroupStatus).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AppGroupStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(AppGroupStatus).FromString(i.(string)), nil + }, + {srcType: reflect.TypeOf((*AppGroupType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(AppGroupType).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AppGroupType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(AppGroupType).FromString(i.(string)), nil + }, + {srcType: reflect.TypeOf((*StackStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(StackStatus).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*StackStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(StackStatus).FromString(i.(string)), nil + }, + {srcType: reflect.TypeOf((*ChartType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(ChartType).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ChartType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(ChartType).FromString(i.(string)), nil + }, + {srcType: reflect.TypeOf((*AlertActionStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(AlertActionStatus).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AlertActionStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(AlertActionStatus).FromString(i.(string)), nil + }, + {srcType: reflect.TypeOf((*ApplicationType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(ApplicationType).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ApplicationType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(ApplicationType).FromString(i.(string)), nil + }, + {srcType: reflect.TypeOf((*CloudAccountStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(CloudAccountStatus).String(), nil + }, + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*CloudAccountStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return new(CloudAccountStatus).FromString(i.(string)), nil + }, + }) +} diff --git a/pkg/domain/mapper_test.go b/pkg/domain/mapper_test.go new file mode 100644 index 00000000..c235e360 --- /dev/null +++ b/pkg/domain/mapper_test.go @@ -0,0 +1,117 @@ +package domain + +import ( + "fmt" + "github.com/google/uuid" + "testing" + "time" +) + +// test case +func TestConvert(t *testing.T) { + type args struct { + src interface{} + dst interface{} + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test case: CreateOrganizationRequest->Organization", + args: args{ + src: CreateOrganizationRequest{ + Name: "test", + Description: "test", + Phone: "test", + }, + dst: &Organization{}, + }, + wantErr: false, + }, + { + name: "test case Organization->CreateOrganizationResponse", + args: args{ + src: Organization{ + ID: "", + Name: "test", + Description: "test", + Phone: "test", + StatusDesc: "good", + Creator: "", + CreatedAt: time.Time{}, + UpdatedAt: time.Time{}, + }, + dst: &CreateOrganizationResponse{}, + }, + wantErr: false, + }, + { + name: "test case Organization->GetOrganizationResponse", + args: args{ + src: Organization{ + ID: "", + Name: "test", + Description: "test", + Phone: "test", + Status: OrganizationStatus_CREATE, + StatusDesc: "good", + Creator: "", + CreatedAt: time.Time{}, + UpdatedAt: time.Time{}, + }, + dst: &(&GetOrganizationResponse{}).Organization, + }, + wantErr: false, + }, + { + name: "test case CreateUserRequest->User", + args: args{ + src: CreateUserRequest{ + AccountId: "testAccount", + Password: "testPassword", + Name: "testName", + Email: "testEmail", + Department: "testDepartment", + Role: "testRole", + Description: "testDescription", + }, + dst: &User{}, + }, + wantErr: false, + }, + { + name: "test case User->GetUserResponse", + args: args{ + src: User{ + ID: uuid.New(), + AccountId: "testAccount", + Password: "testPassword", + Name: "testName", + Token: "testToken", + Role: Role{}, + Organization: Organization{}, + Creator: "", + CreatedAt: time.Time{}, + UpdatedAt: time.Time{}, + Email: "", + Department: "", + Description: "", + }, + dst: &GetUserResponse{}, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := Map(tt.args.src, tt.args.dst); (err != nil) != tt.wantErr { + t.Errorf("Map() error = %v, wantErr %v", err, tt.wantErr) + } else { + fmt.Printf("Input: %+v\n", tt.args.src) + fmt.Printf("Output: %+v\n\n", tt.args.dst) + } + }) + } +} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index efe7e5e3..fed0cfe9 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -2,6 +2,8 @@ package domain import ( "time" + + "gorm.io/gorm" ) // enum @@ -48,14 +50,18 @@ func (m OrganizationStatus) FromString(s string) OrganizationStatus { return OrganizationStatus_ERROR } -type OrganizationResponse struct { - ID string `json:"id"` +type Organization struct { + gorm.Model + + ID string `gorm:"primarykey;type:varchar(36);not null" json:"id"` Name string `json:"name"` Description string `json:"description"` Phone string `json:"phone"` PrimaryClusterId string `json:"primaryClusterId"` + WorkflowId string `json:"-"` Status OrganizationStatus `json:"status"` StatusDesc string `json:"statusDesc"` + Creator string `json:"creator"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } @@ -123,7 +129,3 @@ type UpdateOrganizationResponse struct { type UpdatePrimaryClusterRequest struct { PrimaryClusterId string `json:"primaryClusterId"` } - -type DeleteOrganizationResponse struct { - ID string `json:"id"` -} diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index f7b69f40..ad95656e 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -2,37 +2,626 @@ package domain import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/helper" + "gorm.io/gorm" ) -type PermissionResponse struct { - ID uuid.UUID `json:"ID"` - Name string `json:"name"` - IsAllowed *bool `json:"is_allowed,omitempty"` - RoleID *string `json:"role_id,omitempty"` - Role *RoleResponse `json:"role,omitempty"` - Endpoints []*EndpointResponse `json:"endpoints,omitempty"` - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Parent *PermissionResponse `json:"parent,omitempty"` - Children []*PermissionResponse `json:"children,omitempty"` +type PermissionKind string + +const ( + DashBoardPermission PermissionKind = "대시보드" + StackPermission PermissionKind = "스택 관리" + SecurityPolicyPermission PermissionKind = "보안/정책 관리" + ProjectManagementPermission PermissionKind = "프로젝트 관리" + NotificationPermission PermissionKind = "알림" + ConfigurationPermission PermissionKind = "설정" +) + +type Permission struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` + Name string `json:"name"` + + IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` + RoleID *string `json:"role_id,omitempty"` + Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` + Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` + // omit empty + + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` + Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` } -type PermissionSetResponse struct { - Dashboard *PermissionResponse `json:"dashboard,omitempty"` - Stack *PermissionResponse `json:"stack,omitempty"` - SecurityPolicy *PermissionResponse `json:"security_policy,omitempty"` - ProjectManagement *PermissionResponse `json:"project_management,omitempty"` - Notification *PermissionResponse `json:"notification,omitempty"` - Configuration *PermissionResponse `json:"configuration,omitempty"` +func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { + if p.ID == uuid.Nil { + p.ID = uuid.New() + } + return nil +} + +type PermissionSet struct { + Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` + Stack *Permission `gorm:"-:all" json:"stack,omitempty"` + SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` + ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` + Notification *Permission `gorm:"-:all" json:"notification,omitempty"` + Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` +} + +func NewDefaultPermissionSet() *PermissionSet { + return &PermissionSet{ + Dashboard: newDashboard(), + Stack: newStack(), + SecurityPolicy: newSecurityPolicy(), + ProjectManagement: newProjectManagement(), + Notification: newNotification(), + Configuration: newConfiguration(), + } } type GetPermissionTemplatesResponse struct { - Permissions []*PermissionResponse `json:"permissions"` + Permissions []*Permission `json:"permissions"` } type GetPermissionsByRoleIdResponse struct { - Permissions []*PermissionResponse `json:"permissions"` + Permissions []*Permission `json:"permissions"` } type UpdatePermissionsByRoleIdRequest struct { - Permissions []*PermissionResponse `json:"permissions"` + Permissions []*Permission `json:"permissions"` +} + +func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { + if root.Children == nil { + return append(edgePermissions, root) + } + + for _, child := range root.Children { + if f != nil && !(*f)(*child) { + continue + } + edgePermissions = GetEdgePermission(child, edgePermissions, f) + } + + return edgePermissions +} + +func SetRoleIDToPermission(roleID string, permission *Permission) { + permission.RoleID = helper.StringP(roleID) +} + +func endpointObjects(eps ...api.Endpoint) []*Endpoint { + var result []*Endpoint + for _, ep := range eps { + result = append(result, &Endpoint{ + Name: api.ApiMap[ep].Name, + Group: api.ApiMap[ep].Group, + }) + } + return result +} + +func newDashboard() *Permission { + dashboard := &Permission{ + Name: string(DashBoardPermission), + Children: []*Permission{ + { + Name: "대시보드", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetChartsDashboard, + api.GetChartDashboard, + api.GetStacksDashboard, + api.GetResourcesDashboard, + ), + }, + }, + }, + { + Name: "대시보드 설정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return dashboard +} + +func newStack() *Permission { + stack := &Permission{ + Name: string(StackPermission), + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetStacks, + api.GetStack, + api.CheckStackName, + api.GetStackStatus, + api.GetStackKubeConfig, + + api.SetFavoriteStack, + api.DeleteFavoriteStack, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateStack, + api.InstallStack, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateStack, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteStack, + ), + }, + }, + } + + return stack +} + +func newSecurityPolicy() *Permission { + security_policy := &Permission{ + Name: string(SecurityPolicyPermission), + Children: []*Permission{ + { + Name: "보안/정책", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return security_policy +} + +func newProjectManagement() *Permission { + projectManagement := &Permission{ + Name: string(ProjectManagementPermission), + Children: []*Permission{ + { + Name: "프로젝트", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProject, + ), + }, + }, + }, + { + Name: "앱 서빙", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetAppServeApps, + api.GetAppServeApp, + api.GetNumOfAppsOnStack, + api.GetAppServeAppLatestTask, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + ), + }, + { + Name: "빌드", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + Name: "배포", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteAppServeApp, + ), + }, + }, + }, + { + Name: "설정-일반", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + + api.GetProjectRoles, + api.GetProjectRole, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProject, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProject, + ), + }, + }, + }, + { + Name: "설정-멤버", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectMembers, + api.GetProjectMember, + api.GetProjectRoles, + api.GetProjectRole, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.AddProjectMember, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProjectMemberRole, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.RemoveProjectMember, + ), + }, + }, + }, + { + Name: "설정-네임스페이스", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectNamespaces, + api.GetProjectNamespace, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProjectNamespace, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects(), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProjectNamespace, + ), + }, + }, + }, + }, + } + + return projectManagement +} + +func newNotification() *Permission { + notification := &Permission{ + Name: string(NotificationPermission), + Children: []*Permission{ + { + Name: "시스템 경고", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "보안/정책 감사로그", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return notification +} + +func newConfiguration() *Permission { + configuration := &Permission{ + Name: string(ConfigurationPermission), + Children: []*Permission{ + { + Name: "일반", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "클라우드 계정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "스택 템플릿", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "프로젝트 관리", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자 권한 관리", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "알림 설정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return configuration +} + +func (p *PermissionSet) SetAllowedPermissionSet() { + edgePermissions := make([]*Permission, 0) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) + + for _, permission := range edgePermissions { + permission.IsAllowed = helper.BoolP(true) + } + + return +} + +func (p *PermissionSet) SetUserPermissionSet() { + f := func(permission Permission) bool { + return permission.Name == "조회" + } + edgePermissions := make([]*Permission, 0) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) + //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) + + for _, permission := range edgePermissions { + permission.IsAllowed = helper.BoolP(true) + } + + return +} + +func (p *PermissionSet) SetRoleId(roleId string) { + setRoleIdToPermission(p.Dashboard, roleId) + setRoleIdToPermission(p.Stack, roleId) + setRoleIdToPermission(p.SecurityPolicy, roleId) + setRoleIdToPermission(p.ProjectManagement, roleId) + setRoleIdToPermission(p.Notification, roleId) + setRoleIdToPermission(p.Configuration, roleId) +} + +func setRoleIdToPermission(root *Permission, roleId string) { + root.RoleID = helper.StringP(roleId) + + if root.Children == nil { + return + } + + for _, child := range root.Children { + setRoleIdToPermission(child, roleId) + } } diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index e2dd0810..baf8990f 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -73,7 +73,6 @@ type PolicyTemplateResponse struct { PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` } -/* type PolicyTemplate struct { ID PolicyTemplateId Type string @@ -98,7 +97,6 @@ type PolicyTemplate struct { PermittedOrganizationIds []string // 생성 시에만 사용 PermittedOrganizations []PermittedOrganization } -*/ type CreateCommonPolicyTemplateRequest struct { TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` diff --git a/pkg/domain/project.go b/pkg/domain/project.go index b63d6036..1007dd27 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -3,18 +3,17 @@ package domain import "time" type ProjectResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - IsMyProject string `json:"isMyProject"` - ProjectRoleId string `json:"projectRoleId"` - ProjectRoleName string `json:"projectRoleName"` - NamespaceCount int `json:"namespaceCount"` - AppCount int `json:"appCount"` - MemberCount int `json:"memberCount"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt *time.Time `json:"updatedAt"` + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + IsMyProject string `json:"isMyProject"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` + NamespaceCount int `json:"namespaceCount"` + AppCount int `json:"appCount"` + MemberCount int `json:"memberCount"` + CreatedAt time.Time `json:"createdAt"` } type GetProjectsResponse struct { diff --git a/pkg/domain/role.go b/pkg/domain/role.go index ab961b26..e177a76a 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -4,6 +4,7 @@ import ( "time" "github.com/google/uuid" + "gorm.io/gorm" ) type RoleType string @@ -14,23 +15,23 @@ const ( RoleTypeProject RoleType = "project" ) -type RoleResponse struct { - ID string `json:"id"` - Name string `json:"name"` - OrganizationID string `json:"organizationId"` - Organization OrganizationResponse `json:"organization"` - Type string `json:"type"` - Description string `json:"description"` - Creator uuid.UUID `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` +func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { + r.ID = uuid.New().String() + return nil } -type SimpleRoleResponse = struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - OrganizationID string `json:"organizationId"` +type Role struct { + gorm.Model + + ID string `gorm:"primarykey;" json:"id"` + Name string `json:"name"` + OrganizationID string `json:"organizationId"` + Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;" json:"organization"` + Type string `json:"type"` + Description string `json:"description"` + Creator uuid.UUID `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type CreateTksRoleRequest struct { diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index 122410d1..13b6e9da 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -2,11 +2,38 @@ package domain import ( "time" + + "github.com/google/uuid" ) const STACK_TEMPLATE_TYPE_STANDARD = "STANDARD" const STACK_TEMPLATE_TYPE_MSA = "MSA" +// 내부 +type StackTemplate struct { + ID uuid.UUID + OrganizationId string + Name string + Description string + Template string + TemplateType string + CloudService string + Version string + Platform string + KubeVersion string + KubeType string + OrganizationIds []string + Organizations []Organization + ServiceIds []string + Services []byte + CreatorId uuid.UUID + Creator User + UpdatorId uuid.UUID + Updator User + CreatedAt time.Time + UpdatedAt time.Time +} + type StackTemplateServiceApplicationResponse struct { Name string `json:"name"` Description string `json:"description"` diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index c56abc48..b4935bcb 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -3,6 +3,7 @@ package domain import ( "time" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" ) @@ -73,6 +74,45 @@ const MAX_STEP_LMA_REMOVE = 12 const MAX_STEP_SM_CREATE = 22 const MAX_STEP_SM_REMOVE = 4 +// model +type Stack = struct { + ID StackId + Name string + Description string + ClusterId string + OrganizationId string + CloudService string + CloudAccountId uuid.UUID + CloudAccount CloudAccount + StackTemplateId uuid.UUID + StackTemplate StackTemplate + Status StackStatus + StatusDesc string + Conf StackConf + PrimaryCluster bool + GrafanaUrl string + CreatorId *uuid.UUID + Creator User + UpdatorId *uuid.UUID + Updator User + CreatedAt time.Time + UpdatedAt time.Time + Favorited bool + ClusterEndpoint string + Resource DashboardStackResponse +} + +type StackConf struct { + TksCpNode int + TksCpNodeMax int + TksCpNodeType string + TksInfraNode int + TksInfraNodeMax int + TksInfraNodeType string + TksUserNode int + TksUserNodeMax int + TksUserNodeType string +} type StackStepStatus struct { Status string `json:"status"` Stage string `json:"stage"` @@ -136,19 +176,6 @@ type StackResponse struct { UpdatedAt time.Time `json:"updatedAt"` } -type SimpleStackResponse struct { - ID StackId `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - OrganizationId string `json:"organizationId"` - StackTemplate SimpleStackTemplateResponse `json:"stackTemplate,omitempty"` - CloudAccount SimpleCloudAccountResponse `json:"cloudAccount,omitempty"` - Status string `json:"status"` - PrimaryCluster bool `json:"primaryCluster"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - type GetStacksResponse struct { Stacks []StackResponse `json:"stacks"` Pagination PaginationResponse `json:"pagination"` diff --git a/pkg/domain/user.go b/pkg/domain/user.go index a4833494..d63b4605 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -1,49 +1,55 @@ package domain import ( - "time" - "github.com/google/uuid" + "gorm.io/gorm" + "time" ) -// // Deprecated: Policy is deprecated, use Permission instead. -// -// type Policy = struct { -// ID string `json:"id"` -// Name string `json:"name"` -// Create bool `json:"create"` -// CreatePriviledge string `json:"createPriviledge"` -// Update bool `json:"update"` -// UpdatePriviledge string `json:"updatePriviledge"` -// Read bool `json:"read"` -// ReadPriviledge string `json:"readPriviledge"` -// Delete bool `json:"delete"` -// DeletePriviledge string `json:"deletePriviledge"` -// Creator string `json:"creator"` -// CreatedAt time.Time `json:"createdAt"` -// UpdatedAt time.Time `json:"updatedAt"` -// } -type UserResponse struct { +type User struct { ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` Password string `gorm:"-:all" json:"password"` Name string `json:"name"` Token string `json:"token"` RoleId string - Role RoleResponse `gorm:"foreignKey:RoleId;references:ID" json:"role"` + Role Role `gorm:"foreignKey:RoleId;references:ID" json:"role"` OrganizationId string - Organization OrganizationResponse `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` - PasswordExpired bool `json:"passwordExpired"` + Organization Organization `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` + PasswordExpired bool `json:"passwordExpired"` Email string `json:"email"` Department string `json:"department"` Description string `json:"description"` } +func (g *User) BeforeCreate(tx *gorm.DB) (err error) { + g.PasswordUpdatedAt = time.Now() + return nil +} + +// +//// Deprecated: Policy is deprecated, use Permission instead. +//type Policy = struct { +// ID string `json:"id"` +// Name string `json:"name"` +// Create bool `json:"create"` +// CreatePriviledge string `json:"createPriviledge"` +// Update bool `json:"update"` +// UpdatePriviledge string `json:"updatePriviledge"` +// Read bool `json:"read"` +// ReadPriviledge string `json:"readPriviledge"` +// Delete bool `json:"delete"` +// DeletePriviledge string `json:"deletePriviledge"` +// Creator string `json:"creator"` +// CreatedAt time.Time `json:"createdAt"` +// UpdatedAt time.Time `json:"updatedAt"` +//} + type CreateUserRequest struct { AccountId string `json:"accountId" validate:"required"` Password string `json:"password" validate:"required"` @@ -54,38 +60,45 @@ type CreateUserRequest struct { Description string `json:"description" validate:"min=0,max=100"` } +type SimpleRoleResponse = struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` +} + type SimpleUserResponse struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role SimpleRoleResponse `json:"role"` } type CreateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role RoleResponse `json:"role"` - Organization OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role Role `json:"role"` + Organization Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` } `json:"user"` } type GetUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role RoleResponse `json:"role"` - Organization OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role Role `json:"role"` + Organization Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } @@ -94,17 +107,17 @@ type ListUserResponse struct { Pagination PaginationResponse `json:"pagination"` } type ListUserBody struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role RoleResponse `json:"role"` - Organization OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role Role `json:"role"` + Organization Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type UpdateUserRequest struct { @@ -117,28 +130,28 @@ type UpdateUserRequest struct { type UpdateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role RoleResponse `json:"role"` - Organization OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role Role `json:"role"` + Organization Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } type GetMyProfileResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role RoleResponse `json:"role"` - Organization OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role Role `json:"role"` + Organization Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` } `json:"user"` } type UpdateMyProfileRequest struct { @@ -150,13 +163,13 @@ type UpdateMyProfileRequest struct { type UpdateMyProfileResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role RoleResponse `json:"role"` - Organization OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role Role `json:"role"` + Organization Organization `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` } `json:"user"` } From 19566601ecb7e503acb578295096a98f82e088a3 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 14 Mar 2024 13:31:35 +0900 Subject: [PATCH 116/502] Revert "Merge pull request #277 from seungkyua/20240314_revert" This reverts commit 3c1aa54a7124eb2a06e12647bdd8d6289682157b, reversing changes made to 92dc48e12cba948799c857fd600b1ecf8f61d90e. --- api/swagger/docs.go | 1362 ++++++++--------- api/swagger/swagger.json | 1362 ++++++++--------- api/swagger/swagger.yaml | 837 +++++----- internal/database/database.go | 63 +- internal/delivery/api/endpoint.go | 4 +- .../delivery/api/generated_endpoints.go.go | 16 + internal/delivery/http/alert.go | 3 +- internal/delivery/http/app-group.go | 5 +- internal/delivery/http/app-serve-app.go | 51 +- internal/delivery/http/audit.go | 17 +- internal/delivery/http/auth.go | 5 +- internal/delivery/http/cloud-account.go | 13 +- internal/delivery/http/cluster.go | 34 +- internal/delivery/http/handler.go | 2 + internal/delivery/http/organization.go | 14 +- internal/delivery/http/permission.go | 57 +- internal/delivery/http/policy-template.go | 3 +- internal/delivery/http/role.go | 10 +- internal/delivery/http/stack-template.go | 127 +- internal/delivery/http/stack.go | 15 +- internal/delivery/http/user.go | 21 +- internal/filter/settings.go | 2 + internal/keycloak/keycloak.go | 34 +- internal/middleware/audit/audit-map.go | 88 +- internal/middleware/audit/audit.go | 4 +- internal/model/alert.go | 60 + internal/model/app-group.go | 47 + internal/model/app-serve-app.go | 67 + internal/model/audit.go | 26 + internal/model/cloud-account.go | 38 + internal/model/cluster.go | 84 + internal/model/dashboard.go | 4 + internal/model/end-point.go | 11 + internal/model/organization.go | 21 + internal/model/permission.go | 615 ++++++++ internal/model/policy-template.go | 48 + internal/model/role.go | 27 + internal/model/stack-template.go | 40 + internal/model/stack.go | 45 + internal/model/user.go | 34 + internal/pagination/pagination.go | 14 +- internal/repository/alert.go | 143 +- internal/repository/app-group.go | 127 +- internal/repository/app-serve-app.go | 63 +- internal/repository/audit.go | 63 +- internal/repository/cloud-account.go | 103 +- internal/repository/cluster.go | 183 +-- internal/repository/endpoint.go | 27 +- internal/repository/organization.go | 73 +- internal/repository/permission.go | 26 +- internal/repository/policy-template.go | 135 +- internal/repository/role.go | 51 +- internal/repository/stack-template.go | 117 +- internal/repository/user.go | 104 +- internal/route/route.go | 10 +- internal/serializer/serializer.go | 18 +- internal/usecase/alert.go | 42 +- internal/usecase/app-group.go | 23 +- internal/usecase/app-serve-app.go | 33 +- internal/usecase/audit.go | 22 +- internal/usecase/auth.go | 17 +- internal/usecase/cloud-account.go | 51 +- internal/usecase/cluster.go | 58 +- internal/usecase/dashboard.go | 5 +- internal/usecase/organization.go | 23 +- internal/usecase/permission.go | 54 +- internal/usecase/policy-template.go | 45 +- internal/usecase/role.go | 22 +- internal/usecase/stack-template.go | 44 +- internal/usecase/stack.go | 37 +- internal/usecase/user.go | 50 +- pkg/domain/admin/user.go | 45 +- pkg/domain/alert.go | 44 - pkg/domain/app-group.go | 27 - pkg/domain/app-serve-app.go | 119 +- pkg/domain/audit.go | 18 - pkg/domain/auth.go | 14 +- pkg/domain/cloud-account.go | 30 +- pkg/domain/cluster.go | 30 +- pkg/domain/dashboard.go | 16 +- pkg/domain/endpoint.go | 13 +- pkg/domain/mapper.go | 140 -- pkg/domain/mapper_test.go | 117 -- pkg/domain/organization.go | 14 +- pkg/domain/permission.go | 629 +------- pkg/domain/policy-template.go | 2 + pkg/domain/project.go | 23 +- pkg/domain/role.go | 31 +- pkg/domain/stack-template.go | 27 - pkg/domain/stack.go | 53 +- pkg/domain/user.go | 181 +-- 91 files changed, 4143 insertions(+), 4529 deletions(-) create mode 100644 internal/model/alert.go create mode 100644 internal/model/app-group.go create mode 100644 internal/model/app-serve-app.go create mode 100644 internal/model/audit.go create mode 100644 internal/model/cloud-account.go create mode 100644 internal/model/cluster.go create mode 100644 internal/model/dashboard.go create mode 100644 internal/model/end-point.go create mode 100644 internal/model/organization.go create mode 100644 internal/model/permission.go create mode 100644 internal/model/policy-template.go create mode 100644 internal/model/role.go create mode 100644 internal/model/stack-template.go create mode 100644 internal/model/stack.go create mode 100644 internal/model/user.go delete mode 100644 pkg/domain/mapper.go delete mode 100644 pkg/domain/mapper_test.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 4464bf58..4a544877 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -22,6 +22,186 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/admin/audits": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audits", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audits", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filter", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "or", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Create Audit", + "parameters": [ + { + "description": "create audit request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" + } + } + } + } + }, + "/admin/audits/{auditId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audit", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Delete Audit 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -816,7 +996,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "summary": "Create StackTemplate", "parameters": [ { "description": "create stack template request", @@ -918,7 +1098,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "summary": "Update StackTemplate", "parameters": [ { "description": "Update stack template request", @@ -952,7 +1132,7 @@ const docTemplate = `{ "tags": [ "StackTemplates" ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "summary": "Delete StackTemplate", "parameters": [ { "type": "string", @@ -1688,7 +1868,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse" } } } @@ -1721,10 +1901,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" - } + "description": "OK" } } } @@ -2105,7 +2282,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse" } } } @@ -2340,14 +2517,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/audits": { + "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Audits", + "description": "Get CloudAccounts", "consumes": [ "application/json" ], @@ -2355,10 +2532,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Audits" + "CloudAccounts" ], - "summary": "Get Audits", + "summary": "Get CloudAccounts", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -2390,17 +2574,7 @@ const docTemplate = `{ }, "collectionFormat": "csv", "description": "filters", - "name": "filter", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "or", + "name": "filters", "in": "query" } ], @@ -2408,7 +2582,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" } } } @@ -2419,7 +2593,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Create Audit", + "description": "Create CloudAccount", "consumes": [ "application/json" ], @@ -2427,17 +2601,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Audits" + "CloudAccounts" ], - "summary": "Create Audit", + "summary": "Create CloudAccount", "parameters": [ { - "description": "create audit request", + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" } } ], @@ -2445,20 +2626,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" } } } } }, - "/organizations/{organizationId}/audits/{auditId}": { + "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Audit", + "description": "Check awsAccountId for cloudAccount", "consumes": [ "application/json" ], @@ -2466,14 +2647,21 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Audits" + "CloudAccounts" ], - "summary": "Get Audit", + "summary": "Check awsAccountId for cloudAccount", "parameters": [ { "type": "string", - "description": "auditId", - "name": "auditId", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "awsAccountId", + "name": "awsAccountId", "in": "path", "required": true } @@ -2482,205 +2670,14 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" } } } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Delete Audit 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get CloudAccounts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Get CloudAccounts", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Create CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check awsAccountId for cloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Check awsAccountId for cloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "awsAccountId", - "name": "awsAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { - "get": { + } + }, + "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "get": { "security": [ { "JWT": [] @@ -3771,7 +3768,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" } } } @@ -4438,7 +4435,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" } } } @@ -5627,7 +5624,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" } } } @@ -5674,14 +5671,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/stack-templates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", + "description": "Get Organization StackTemplates", "consumes": [ "application/json" ], @@ -5689,17 +5686,10 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "StackTemplates" ], - "summary": "Get Stacks", + "summary": "Get Organization StackTemplates", "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, { "type": "string", "description": "pageSize", @@ -5725,9 +5715,13 @@ const docTemplate = `{ "in": "query" }, { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", "in": "query" } ], @@ -5735,18 +5729,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create Stack", + "description": "Get Organization StackTemplate", "consumes": [ "application/json" ], @@ -5754,45 +5750,27 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" - ], - "summary": "Create Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" - } - } + "StackTemplates" ], + "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" } } } } }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { + "/organizations/{organizationId}/stacks": { "get": { "security": [ { "JWT": [] } ], - "description": "Check name for stack", + "description": "Get Stacks", "consumes": [ "application/json" ], @@ -5802,7 +5780,7 @@ const docTemplate = `{ "tags": [ "Stacks" ], - "summary": "Check name for stack", + "summary": "Get Stacks", "parameters": [ { "type": "string", @@ -5813,11 +5791,122 @@ const docTemplate = `{ }, { "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "string", + "description": "combinedFilter", + "name": "combinedFilter", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Create Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Check name for stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, { "type": "string", "description": "name", @@ -6461,10 +6550,7 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - } + "description": "OK" } } } @@ -6532,7 +6618,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" } } } @@ -6620,6 +6706,177 @@ const docTemplate = `{ } }, "definitions": { + "github_com_openinfradev_tks-api_internal_model.AppServeApp": { + "type": "object", + "properties": { + "appServeAppTasks": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask" + } + }, + "appType": { + "description": "appType (spring/springboot)", + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "endpointUrl": { + "description": "endpoint URL of deployed app", + "type": "string" + }, + "grafanaUrl": { + "description": "grafana dashboard URL for deployed app", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "description": "application name", + "type": "string" + }, + "namespace": { + "description": "application namespace", + "type": "string" + }, + "organizationId": { + "description": "contractId is a contract ID which this app belongs to", + "type": "string" + }, + "previewEndpointUrl": { + "description": "preview svc endpoint URL in B/G deployment", + "type": "string" + }, + "projectId": { + "description": "project ID which this app belongs to", + "type": "string" + }, + "status": { + "description": "status is status of deployed app", + "type": "string" + }, + "targetClusterId": { + "description": "target cluster to which the app is deployed", + "type": "string" + }, + "targetClusterName": { + "description": "target cluster name", + "type": "string" + }, + "type": { + "description": "type (build/deploy/all)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_internal_model.AppServeAppTask": { + "type": "object", + "properties": { + "appConfig": { + "description": "java app config", + "type": "string" + }, + "appSecret": { + "description": "java app secret", + "type": "string" + }, + "appServeAppId": { + "description": "ID for appServeApp that this task belongs to", + "type": "string" + }, + "artifactUrl": { + "description": "URL of java app artifact (Eg, Jar)", + "type": "string" + }, + "availableRollback": { + "type": "boolean" + }, + "createdAt": { + "description": "createdAt is a creation timestamp for the application", + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "executablePath": { + "description": "Executable path of app image", + "type": "string" + }, + "extraEnv": { + "description": "env variable list for java app", + "type": "string" + }, + "helmRevision": { + "description": "revision of deployed helm release", + "type": "integer" + }, + "id": { + "type": "string" + }, + "imageUrl": { + "description": "URL of built image for app", + "type": "string" + }, + "output": { + "description": "output for task result", + "type": "string" + }, + "port": { + "description": "java app port", + "type": "string" + }, + "profile": { + "description": "java app profile", + "type": "string" + }, + "pvAccessMode": { + "type": "string" + }, + "pvEnabled": { + "type": "boolean" + }, + "pvMountPath": { + "type": "string" + }, + "pvSize": { + "type": "string" + }, + "pvStorageClass": { + "type": "string" + }, + "resourceSpec": { + "description": "resource spec of app pod", + "type": "string" + }, + "rollbackVersion": { + "description": "rollback target version", + "type": "string" + }, + "status": { + "description": "status is app status", + "type": "string" + }, + "strategy": { + "description": "deployment strategy (eg, rolling-update)", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "version": { + "description": "application version", + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { @@ -6828,13 +7085,13 @@ const docTemplate = `{ "AppGroupType_SERVICE_MESH" ] }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeApp": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse": { "type": "object", "properties": { "appServeAppTasks": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" } }, "appType": { @@ -6899,7 +7156,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse": { "type": "object", "properties": { "appConfig": { @@ -7086,9 +7343,6 @@ const docTemplate = `{ }, "user": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "userId": { - "type": "string" } } }, @@ -7158,71 +7412,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccount": { - "type": "object", - "properties": { - "accessKeyId": { - "type": "string" - }, - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusters": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "createdIAM": { - "type": "boolean" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "secretAccessKey": { - "type": "string" - }, - "sessionToken": { - "type": "string" - }, - "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { @@ -7241,165 +7430,32 @@ const docTemplate = `{ "createdIAM": { "type": "boolean" }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 - ], - "x-enum-varnames": [ - "CloudAccountStatus_PENDING", - "CloudAccountStatus_CREATING", - "CloudAccountStatus_CREATED", - "CloudAccountStatus_DELETING", - "CloudAccountStatus_DELETED", - "CloudAccountStatus_CREATE_ERROR", - "CloudAccountStatus_DELETE_ERROR" - ] - }, - "github_com_openinfradev_tks-api_pkg_domain.Cluster": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccount": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount" - }, - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "integer" - }, - "conf": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" }, - "favorited": { - "type": "boolean" - }, "id": { "type": "string" }, - "isStack": { - "type": "boolean" - }, - "kubeconfig": { - "type": "array", - "items": { - "type": "integer" - } - }, "name": { "type": "string" }, "organizationId": { "type": "string" }, - "stackTemplate": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate" - }, - "stackTemplateId": { + "resource": { "type": "string" }, "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus" - }, - "statusDesc": { "type": "string" }, "updatedAt": { "type": "string" }, "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterConf": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" } } }, @@ -7508,6 +7564,9 @@ const docTemplate = `{ "description": { "type": "string" }, + "favorited": { + "type": "boolean" + }, "id": { "type": "string" }, @@ -7584,33 +7643,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9 - ], - "x-enum-varnames": [ - "ClusterStatus_PENDING", - "ClusterStatus_INSTALLING", - "ClusterStatus_RUNNING", - "ClusterStatus_DELETING", - "ClusterStatus_DELETED", - "ClusterStatus_INSTALL_ERROR", - "ClusterStatus_DELETE_ERROR", - "ClusterStatus_BOOTSTRAPPING", - "ClusterStatus_BOOTSTRAPPED", - "ClusterStatus_BOOTSTRAP_ERROR" - ] - }, "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { @@ -8306,10 +8338,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -8425,7 +8457,15 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { + "github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { "createdAt": { @@ -8436,6 +8476,9 @@ const docTemplate = `{ }, "name": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -8568,7 +8611,7 @@ const docTemplate = `{ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" }, "stages": { "type": "array", @@ -8582,10 +8625,10 @@ const docTemplate = `{ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" }, "appServeAppTask": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" }, "stages": { "type": "array", @@ -8680,6 +8723,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { + "type": "object", + "properties": { + "cluster": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse": { "type": "object", "properties": { @@ -8754,10 +8805,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -9087,10 +9138,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -9253,10 +9304,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -9298,13 +9349,13 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "passwordExpired": { "type": "boolean" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "token": { "type": "string" @@ -9327,18 +9378,12 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Organization": { + "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { "createdAt": { "type": "string" }, - "creator": { - "type": "string" - }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "description": { "type": "string" }, @@ -9440,7 +9485,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Permission": { + "github_com_openinfradev_tks-api_pkg_domain.PermissionResponse": { "type": "object", "properties": { "ID": { @@ -9449,24 +9494,15 @@ const docTemplate = `{ "children": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "endpoints": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse" } }, - "id": { - "type": "integer" - }, "is_allowed": { "type": "boolean" }, @@ -9474,42 +9510,39 @@ const docTemplate = `{ "type": "string" }, "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "parent_id": { "type": "string" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "role_id": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { + "github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse": { "type": "object", "properties": { "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "security_policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } } }, @@ -9861,6 +9894,9 @@ const docTemplate = `{ }, "projectRoleName": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -9982,7 +10018,7 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Role": { + "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { "type": "object", "properties": { "createdAt": { @@ -9991,9 +10027,6 @@ const docTemplate = `{ "creator": { "type": "string" }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "description": { "type": "string" }, @@ -10004,7 +10037,7 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "organizationId": { "type": "string" @@ -10082,20 +10115,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -10139,9 +10158,6 @@ const docTemplate = `{ }, "name": { "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" } } }, @@ -10261,86 +10277,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.StackTemplate": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "organizationIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "organizations": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - } - }, - "platform": { - "type": "string" - }, - "serviceIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "services": { - "type": "array", - "items": { - "type": "integer" - } - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse": { "type": "object", "properties": { @@ -10606,10 +10542,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -10677,7 +10613,7 @@ const docTemplate = `{ "permissions": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } } } @@ -10901,10 +10837,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -10913,62 +10849,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.User": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - }, - "organizationId": { - "type": "string" - }, - "password": { - "type": "string" - }, - "passwordExpired": { - "type": "boolean" - }, - "passwordUpdatedAt": { - "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" - }, - "roleId": { - "type": "string" - }, - "token": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ @@ -11058,10 +10938,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -11129,10 +11009,10 @@ const docTemplate = `{ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -11157,18 +11037,6 @@ const docTemplate = `{ "type": "string" } } - }, - "gorm.DeletedAt": { - "type": "object", - "properties": { - "time": { - "type": "string" - }, - "valid": { - "description": "Valid is true if Time is not NULL", - "type": "boolean" - } - } } }, "securityDefinitions": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 86d8b058..8872bcf7 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -16,6 +16,186 @@ "host": "tks-api-dev.taco-cat.xyz", "basePath": "/api/1.0/", "paths": { + "/admin/audits": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audits", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audits", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filter", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "or", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Create Audit", + "parameters": [ + { + "description": "create audit request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" + } + } + } + } + }, + "/admin/audits/{auditId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Get Audit", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete Audit", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Audits" + ], + "summary": "Delete Audit 'NOT IMPLEMENTED'", + "parameters": [ + { + "type": "string", + "description": "auditId", + "name": "auditId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -810,7 +990,7 @@ "tags": [ "StackTemplates" ], - "summary": "Create StackTemplate 'NOT IMPLEMENTED'", + "summary": "Create StackTemplate", "parameters": [ { "description": "create stack template request", @@ -912,7 +1092,7 @@ "tags": [ "StackTemplates" ], - "summary": "Update StackTemplate 'NOT IMPLEMENTED'", + "summary": "Update StackTemplate", "parameters": [ { "description": "Update stack template request", @@ -946,7 +1126,7 @@ "tags": [ "StackTemplates" ], - "summary": "Delete StackTemplate 'NOT IMPLEMENTED'", + "summary": "Delete StackTemplate", "parameters": [ { "type": "string", @@ -1682,7 +1862,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse" } } } @@ -1715,10 +1895,7 @@ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster" - } + "description": "OK" } } } @@ -2099,7 +2276,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse" } } } @@ -2334,14 +2511,14 @@ } } }, - "/organizations/{organizationId}/audits": { + "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Audits", + "description": "Get CloudAccounts", "consumes": [ "application/json" ], @@ -2349,10 +2526,17 @@ "application/json" ], "tags": [ - "Audits" + "CloudAccounts" ], - "summary": "Get Audits", + "summary": "Get CloudAccounts", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -2384,17 +2568,7 @@ }, "collectionFormat": "csv", "description": "filters", - "name": "filter", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "or", + "name": "filters", "in": "query" } ], @@ -2402,7 +2576,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" } } } @@ -2413,7 +2587,7 @@ "JWT": [] } ], - "description": "Create Audit", + "description": "Create CloudAccount", "consumes": [ "application/json" ], @@ -2421,17 +2595,24 @@ "application/json" ], "tags": [ - "Audits" + "CloudAccounts" ], - "summary": "Create Audit", + "summary": "Create CloudAccount", "parameters": [ { - "description": "create audit request", + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" } } ], @@ -2439,20 +2620,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" } } } } }, - "/organizations/{organizationId}/audits/{auditId}": { + "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Audit", + "description": "Check awsAccountId for cloudAccount", "consumes": [ "application/json" ], @@ -2460,14 +2641,21 @@ "application/json" ], "tags": [ - "Audits" + "CloudAccounts" ], - "summary": "Get Audit", + "summary": "Check awsAccountId for cloudAccount", "parameters": [ { "type": "string", - "description": "auditId", - "name": "auditId", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "awsAccountId", + "name": "awsAccountId", "in": "path", "required": true } @@ -2476,205 +2664,14 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" } } } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Audit", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Audits" - ], - "summary": "Delete Audit 'NOT IMPLEMENTED'", - "parameters": [ - { - "type": "string", - "description": "auditId", - "name": "auditId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get CloudAccounts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Get CloudAccounts", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetCloudAccountsResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create CloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Create CloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateCloudAccountResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/aws-account-id/{awsAccountId}/existence": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Check awsAccountId for cloudAccount", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "CloudAccounts" - ], - "summary": "Check awsAccountId for cloudAccount", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "awsAccountId", - "name": "awsAccountId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckCloudAccountAwsAccountIdResponse" - } - } - } - } - }, - "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { - "get": { + } + }, + "/organizations/{organizationId}/cloud-accounts/name/{name}/existence": { + "get": { "security": [ { "JWT": [] @@ -3765,7 +3762,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" } } } @@ -4432,7 +4429,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" } } } @@ -5621,7 +5618,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" } } } @@ -5668,14 +5665,14 @@ } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/stack-templates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", + "description": "Get Organization StackTemplates", "consumes": [ "application/json" ], @@ -5683,17 +5680,10 @@ "application/json" ], "tags": [ - "Stacks" + "StackTemplates" ], - "summary": "Get Stacks", + "summary": "Get Organization StackTemplates", "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, { "type": "string", "description": "pageSize", @@ -5719,9 +5709,13 @@ "in": "query" }, { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", "in": "query" } ], @@ -5729,18 +5723,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create Stack", + "description": "Get Organization StackTemplate", "consumes": [ "application/json" ], @@ -5748,45 +5744,27 @@ "application/json" ], "tags": [ - "Stacks" - ], - "summary": "Create Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" - } - } + "StackTemplates" ], + "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" } } } } }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { + "/organizations/{organizationId}/stacks": { "get": { "security": [ { "JWT": [] } ], - "description": "Check name for stack", + "description": "Get Stacks", "consumes": [ "application/json" ], @@ -5796,7 +5774,7 @@ "tags": [ "Stacks" ], - "summary": "Check name for stack", + "summary": "Get Stacks", "parameters": [ { "type": "string", @@ -5807,11 +5785,122 @@ }, { "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "string", + "description": "combinedFilter", + "name": "combinedFilter", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Create Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Check name for stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, { "type": "string", "description": "name", @@ -6455,10 +6544,7 @@ ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - } + "description": "OK" } } } @@ -6526,7 +6612,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" } } } @@ -6614,6 +6700,177 @@ } }, "definitions": { + "github_com_openinfradev_tks-api_internal_model.AppServeApp": { + "type": "object", + "properties": { + "appServeAppTasks": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask" + } + }, + "appType": { + "description": "appType (spring/springboot)", + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "endpointUrl": { + "description": "endpoint URL of deployed app", + "type": "string" + }, + "grafanaUrl": { + "description": "grafana dashboard URL for deployed app", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "description": "application name", + "type": "string" + }, + "namespace": { + "description": "application namespace", + "type": "string" + }, + "organizationId": { + "description": "contractId is a contract ID which this app belongs to", + "type": "string" + }, + "previewEndpointUrl": { + "description": "preview svc endpoint URL in B/G deployment", + "type": "string" + }, + "projectId": { + "description": "project ID which this app belongs to", + "type": "string" + }, + "status": { + "description": "status is status of deployed app", + "type": "string" + }, + "targetClusterId": { + "description": "target cluster to which the app is deployed", + "type": "string" + }, + "targetClusterName": { + "description": "target cluster name", + "type": "string" + }, + "type": { + "description": "type (build/deploy/all)", + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_internal_model.AppServeAppTask": { + "type": "object", + "properties": { + "appConfig": { + "description": "java app config", + "type": "string" + }, + "appSecret": { + "description": "java app secret", + "type": "string" + }, + "appServeAppId": { + "description": "ID for appServeApp that this task belongs to", + "type": "string" + }, + "artifactUrl": { + "description": "URL of java app artifact (Eg, Jar)", + "type": "string" + }, + "availableRollback": { + "type": "boolean" + }, + "createdAt": { + "description": "createdAt is a creation timestamp for the application", + "type": "string" + }, + "deletedAt": { + "type": "string" + }, + "executablePath": { + "description": "Executable path of app image", + "type": "string" + }, + "extraEnv": { + "description": "env variable list for java app", + "type": "string" + }, + "helmRevision": { + "description": "revision of deployed helm release", + "type": "integer" + }, + "id": { + "type": "string" + }, + "imageUrl": { + "description": "URL of built image for app", + "type": "string" + }, + "output": { + "description": "output for task result", + "type": "string" + }, + "port": { + "description": "java app port", + "type": "string" + }, + "profile": { + "description": "java app profile", + "type": "string" + }, + "pvAccessMode": { + "type": "string" + }, + "pvEnabled": { + "type": "boolean" + }, + "pvMountPath": { + "type": "string" + }, + "pvSize": { + "type": "string" + }, + "pvStorageClass": { + "type": "string" + }, + "resourceSpec": { + "description": "resource spec of app pod", + "type": "string" + }, + "rollbackVersion": { + "description": "rollback target version", + "type": "string" + }, + "status": { + "description": "status is app status", + "type": "string" + }, + "strategy": { + "description": "deployment strategy (eg, rolling-update)", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "version": { + "description": "application version", + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { @@ -6822,13 +7079,13 @@ "AppGroupType_SERVICE_MESH" ] }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeApp": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse": { "type": "object", "properties": { "appServeAppTasks": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" } }, "appType": { @@ -6893,7 +7150,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask": { + "github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse": { "type": "object", "properties": { "appConfig": { @@ -7080,9 +7337,6 @@ }, "user": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "userId": { - "type": "string" } } }, @@ -7152,71 +7406,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccount": { - "type": "object", - "properties": { - "accessKeyId": { - "type": "string" - }, - "awsAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusters": { - "type": "integer" - }, - "createdAt": { - "type": "string" - }, - "createdIAM": { - "type": "boolean" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "secretAccessKey": { - "type": "string" - }, - "sessionToken": { - "type": "string" - }, - "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { @@ -7235,165 +7424,32 @@ "createdIAM": { "type": "boolean" }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "resource": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 - ], - "x-enum-varnames": [ - "CloudAccountStatus_PENDING", - "CloudAccountStatus_CREATING", - "CloudAccountStatus_CREATED", - "CloudAccountStatus_DELETING", - "CloudAccountStatus_DELETED", - "CloudAccountStatus_CREATE_ERROR", - "CloudAccountStatus_DELETE_ERROR" - ] - }, - "github_com_openinfradev_tks-api_pkg_domain.Cluster": { - "type": "object", - "properties": { - "byoClusterEndpointHost": { - "type": "string" - }, - "byoClusterEndpointPort": { - "type": "integer" - }, - "cloudAccount": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount" - }, - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string" - }, - "clusterType": { - "type": "integer" - }, - "conf": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, "description": { "type": "string" }, - "favorited": { - "type": "boolean" - }, "id": { "type": "string" }, - "isStack": { - "type": "boolean" - }, - "kubeconfig": { - "type": "array", - "items": { - "type": "integer" - } - }, "name": { "type": "string" }, "organizationId": { "type": "string" }, - "stackTemplate": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate" - }, - "stackTemplateId": { + "resource": { "type": "string" }, "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus" - }, - "statusDesc": { "type": "string" }, "updatedAt": { "type": "string" }, "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterConf": { - "type": "object", - "properties": { - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" } } }, @@ -7502,6 +7558,9 @@ "description": { "type": "string" }, + "favorited": { + "type": "boolean" + }, "id": { "type": "string" }, @@ -7578,33 +7637,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9 - ], - "x-enum-varnames": [ - "ClusterStatus_PENDING", - "ClusterStatus_INSTALLING", - "ClusterStatus_RUNNING", - "ClusterStatus_DELETING", - "ClusterStatus_DELETED", - "ClusterStatus_INSTALL_ERROR", - "ClusterStatus_DELETE_ERROR", - "ClusterStatus_BOOTSTRAPPING", - "ClusterStatus_BOOTSTRAPPED", - "ClusterStatus_BOOTSTRAP_ERROR" - ] - }, "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { @@ -8300,10 +8332,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -8419,7 +8451,15 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Endpoint": { + "github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { "createdAt": { @@ -8430,6 +8470,9 @@ }, "name": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -8562,7 +8605,7 @@ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" }, "stages": { "type": "array", @@ -8576,10 +8619,10 @@ "type": "object", "properties": { "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" }, "appServeAppTask": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" }, "stages": { "type": "array", @@ -8674,6 +8717,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { + "type": "object", + "properties": { + "cluster": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse": { "type": "object", "properties": { @@ -8748,10 +8799,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -9081,10 +9132,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -9247,10 +9298,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -9292,13 +9343,13 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "passwordExpired": { "type": "boolean" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "token": { "type": "string" @@ -9321,18 +9372,12 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Organization": { + "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { "createdAt": { "type": "string" }, - "creator": { - "type": "string" - }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "description": { "type": "string" }, @@ -9434,7 +9479,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Permission": { + "github_com_openinfradev_tks-api_pkg_domain.PermissionResponse": { "type": "object", "properties": { "ID": { @@ -9443,24 +9488,15 @@ "children": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } }, - "createdAt": { - "type": "string" - }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "endpoints": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse" } }, - "id": { - "type": "integer" - }, "is_allowed": { "type": "boolean" }, @@ -9468,42 +9504,39 @@ "type": "string" }, "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "parent_id": { "type": "string" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "role_id": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSet": { + "github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse": { "type": "object", "properties": { "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "security_policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } } }, @@ -9855,6 +9888,9 @@ }, "projectRoleName": { "type": "string" + }, + "updatedAt": { + "type": "string" } } }, @@ -9976,7 +10012,7 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Role": { + "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { "type": "object", "properties": { "createdAt": { @@ -9985,9 +10021,6 @@ "creator": { "type": "string" }, - "deletedAt": { - "$ref": "#/definitions/gorm.DeletedAt" - }, "description": { "type": "string" }, @@ -9998,7 +10031,7 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "organizationId": { "type": "string" @@ -10076,20 +10109,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -10133,9 +10152,6 @@ }, "name": { "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" } } }, @@ -10255,86 +10271,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.StackTemplate": { - "type": "object", - "properties": { - "cloudService": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "creatorId": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kubeType": { - "type": "string" - }, - "kubeVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "organizationIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "organizations": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - } - }, - "platform": { - "type": "string" - }, - "serviceIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "services": { - "type": "array", - "items": { - "type": "integer" - } - }, - "template": { - "type": "string" - }, - "templateType": { - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "updator": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.User" - }, - "updatorId": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse": { "type": "object", "properties": { @@ -10600,10 +10536,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" } } } @@ -10671,7 +10607,7 @@ "permissions": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" } } } @@ -10895,10 +10831,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -10907,62 +10843,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.User": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" - }, - "organizationId": { - "type": "string" - }, - "password": { - "type": "string" - }, - "passwordExpired": { - "type": "boolean" - }, - "passwordUpdatedAt": { - "type": "string" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" - }, - "roleId": { - "type": "string" - }, - "token": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ @@ -11052,10 +10932,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -11123,10 +11003,10 @@ "type": "string" }, "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" }, "updatedAt": { "type": "string" @@ -11151,18 +11031,6 @@ "type": "string" } } - }, - "gorm.DeletedAt": { - "type": "object", - "properties": { - "time": { - "type": "string" - }, - "valid": { - "description": "Valid is true if Time is not NULL", - "type": "boolean" - } - } } }, "securityDefinitions": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 188af9fd..a94fa389 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1,5 +1,128 @@ basePath: /api/1.0/ definitions: + github_com_openinfradev_tks-api_internal_model.AppServeApp: + properties: + appServeAppTasks: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask' + type: array + appType: + description: appType (spring/springboot) + type: string + createdAt: + type: string + deletedAt: + type: string + endpointUrl: + description: endpoint URL of deployed app + type: string + grafanaUrl: + description: grafana dashboard URL for deployed app + type: string + id: + type: string + name: + description: application name + type: string + namespace: + description: application namespace + type: string + organizationId: + description: contractId is a contract ID which this app belongs to + type: string + previewEndpointUrl: + description: preview svc endpoint URL in B/G deployment + type: string + projectId: + description: project ID which this app belongs to + type: string + status: + description: status is status of deployed app + type: string + targetClusterId: + description: target cluster to which the app is deployed + type: string + targetClusterName: + description: target cluster name + type: string + type: + description: type (build/deploy/all) + type: string + updatedAt: + type: string + type: object + github_com_openinfradev_tks-api_internal_model.AppServeAppTask: + properties: + appConfig: + description: java app config + type: string + appSecret: + description: java app secret + type: string + appServeAppId: + description: ID for appServeApp that this task belongs to + type: string + artifactUrl: + description: URL of java app artifact (Eg, Jar) + type: string + availableRollback: + type: boolean + createdAt: + description: createdAt is a creation timestamp for the application + type: string + deletedAt: + type: string + executablePath: + description: Executable path of app image + type: string + extraEnv: + description: env variable list for java app + type: string + helmRevision: + description: revision of deployed helm release + type: integer + id: + type: string + imageUrl: + description: URL of built image for app + type: string + output: + description: output for task result + type: string + port: + description: java app port + type: string + profile: + description: java app profile + type: string + pvAccessMode: + type: string + pvEnabled: + type: boolean + pvMountPath: + type: string + pvSize: + type: string + pvStorageClass: + type: string + resourceSpec: + description: resource spec of app pod + type: string + rollbackVersion: + description: rollback target version + type: string + status: + description: status is app status + type: string + strategy: + description: deployment strategy (eg, rolling-update) + type: string + updatedAt: + type: string + version: + description: application version + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ActionResponse: properties: body: @@ -143,11 +266,11 @@ definitions: - AppGroupType_UNSPECIFIED - AppGroupType_LMA - AppGroupType_SERVICE_MESH - github_com_openinfradev_tks-api_pkg_domain.AppServeApp: + github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse: properties: appServeAppTasks: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse' type: array appType: description: appType (spring/springboot) @@ -194,7 +317,7 @@ definitions: updatedAt: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask: + github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse: properties: appConfig: description: java app config @@ -331,8 +454,6 @@ definitions: type: string user: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' - userId: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.Axis: properties: @@ -376,49 +497,6 @@ definitions: existed: type: boolean type: object - github_com_openinfradev_tks-api_pkg_domain.CloudAccount: - properties: - accessKeyId: - type: string - awsAccountId: - type: string - cloudService: - type: string - clusters: - type: integer - createdAt: - type: string - createdIAM: - type: boolean - creator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - creatorId: - type: string - description: - type: string - id: - type: string - name: - type: string - organizationId: - type: string - resource: - type: string - secretAccessKey: - type: string - sessionToken: - type: string - status: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus' - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - updatorId: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse: properties: awsAccountId: @@ -450,98 +528,6 @@ definitions: updator: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' type: object - github_com_openinfradev_tks-api_pkg_domain.CloudAccountStatus: - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - type: integer - x-enum-varnames: - - CloudAccountStatus_PENDING - - CloudAccountStatus_CREATING - - CloudAccountStatus_CREATED - - CloudAccountStatus_DELETING - - CloudAccountStatus_DELETED - - CloudAccountStatus_CREATE_ERROR - - CloudAccountStatus_DELETE_ERROR - github_com_openinfradev_tks-api_pkg_domain.Cluster: - properties: - byoClusterEndpointHost: - type: string - byoClusterEndpointPort: - type: integer - cloudAccount: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CloudAccount' - cloudAccountId: - type: string - cloudService: - type: string - clusterType: - type: integer - conf: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterConf' - createdAt: - type: string - creator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - creatorId: - type: string - description: - type: string - favorited: - type: boolean - id: - type: string - isStack: - type: boolean - kubeconfig: - items: - type: integer - type: array - name: - type: string - organizationId: - type: string - stackTemplate: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplate' - stackTemplateId: - type: string - status: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterStatus' - statusDesc: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - updatorId: - type: string - type: object - github_com_openinfradev_tks-api_pkg_domain.ClusterConf: - properties: - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.ClusterConfResponse: properties: tksCpNode: @@ -611,6 +597,8 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string + favorited: + type: boolean id: type: string isStack: @@ -661,30 +649,6 @@ definitions: tksUserNodeType: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.ClusterStatus: - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9 - type: integer - x-enum-varnames: - - ClusterStatus_PENDING - - ClusterStatus_INSTALLING - - ClusterStatus_RUNNING - - ClusterStatus_DELETING - - ClusterStatus_DELETED - - ClusterStatus_INSTALL_ERROR - - ClusterStatus_DELETE_ERROR - - ClusterStatus_BOOTSTRAPPING - - ClusterStatus_BOOTSTRAPPED - - ClusterStatus_BOOTSTRAP_ERROR github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse: properties: result: @@ -1164,9 +1128,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' type: object type: object github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse: @@ -1243,7 +1207,12 @@ definitions: - accessKeyId - secretAccessKey type: object - github_com_openinfradev_tks-api_pkg_domain.Endpoint: + github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse: + properties: + id: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.EndpointResponse: properties: createdAt: type: string @@ -1251,6 +1220,8 @@ definitions: type: string name: type: string + updatedAt: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse: type: object @@ -1338,7 +1309,7 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse: properties: appServeApp: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse' stages: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' @@ -1347,9 +1318,9 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse: properties: appServeApp: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse' appServeAppTask: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTask' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse' stages: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' @@ -1409,6 +1380,11 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse: + properties: + cluster: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.GetClustersResponse: properties: clusters: @@ -1457,9 +1433,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' type: object type: object github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse: @@ -1670,9 +1646,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object @@ -1779,9 +1755,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object @@ -1809,11 +1785,11 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' passwordExpired: type: boolean role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' token: type: string type: object @@ -1827,14 +1803,10 @@ definitions: type: array type: object type: object - github_com_openinfradev_tks-api_pkg_domain.Organization: + github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse: properties: createdAt: type: string - creator: - type: string - deletedAt: - $ref: '#/definitions/gorm.DeletedAt' description: type: string id: @@ -1906,53 +1878,45 @@ definitions: type: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.Permission: + github_com_openinfradev_tks-api_pkg_domain.PermissionResponse: properties: ID: type: string children: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' type: array - createdAt: - type: string - deletedAt: - $ref: '#/definitions/gorm.DeletedAt' endpoints: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Endpoint' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse' type: array - id: - type: integer is_allowed: type: boolean name: type: string parent: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' parent_id: type: string role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' role_id: type: string - updatedAt: - type: string type: object - github_com_openinfradev_tks-api_pkg_domain.PermissionSet: + github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse: properties: configuration: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' dashboard: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' notification: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' project_management: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' security_policy: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' stack: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' type: object github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization: properties: @@ -2191,6 +2155,8 @@ definitions: type: string projectRoleName: type: string + updatedAt: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.ProjectRoleResponse: properties: @@ -2270,14 +2236,12 @@ definitions: usage: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.Role: + github_com_openinfradev_tks-api_pkg_domain.RoleResponse: properties: createdAt: type: string creator: type: string - deletedAt: - $ref: '#/definitions/gorm.DeletedAt' description: type: string id: @@ -2285,7 +2249,7 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' organizationId: type: string type: @@ -2335,15 +2299,6 @@ definitions: name: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse: - properties: - description: - type: string - id: - type: string - name: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse: properties: cloudService: @@ -2373,8 +2328,6 @@ definitions: type: string name: type: string - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' type: object github_com_openinfradev_tks-api_pkg_domain.StackConfResponse: properties: @@ -2454,59 +2407,6 @@ definitions: step: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.StackTemplate: - properties: - cloudService: - type: string - createdAt: - type: string - creator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - creatorId: - type: string - description: - type: string - id: - type: string - kubeType: - type: string - kubeVersion: - type: string - name: - type: string - organizationId: - type: string - organizationIds: - items: - type: string - type: array - organizations: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' - type: array - platform: - type: string - serviceIds: - items: - type: string - type: array - services: - items: - type: integer - type: array - template: - type: string - templateType: - type: string - updatedAt: - type: string - updator: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' - updatorId: - type: string - version: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.StackTemplateResponse: properties: cloudService: @@ -2683,9 +2583,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' type: object type: object github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest: @@ -2730,7 +2630,7 @@ definitions: properties: permissions: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Permission' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' type: array type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest: @@ -2880,50 +2780,13 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object type: object - github_com_openinfradev_tks-api_pkg_domain.User: - properties: - accountId: - type: string - createdAt: - type: string - creator: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' - organizationId: - type: string - password: - type: string - passwordExpired: - type: boolean - passwordUpdatedAt: - type: string - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' - roleId: - type: string - token: - type: string - updatedAt: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest: properties: email: @@ -2984,9 +2847,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object @@ -3032,9 +2895,9 @@ definitions: name: type: string organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Role' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' updatedAt: type: string type: object @@ -3049,27 +2912,133 @@ definitions: type: integer text: type: string - type: object - gorm.DeletedAt: - properties: - time: + type: object +host: tks-api-dev.taco-cat.xyz +info: + contact: + email: taekyu.kang@sk.com + name: taekyu.kang@sk.com + description: This is backend api service for tks platform + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + title: tks-api service + version: "1.0" +paths: + /admin/audits: + get: + consumes: + - application/json + description: Get Audits + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filter + type: array + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: or + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse' + security: + - JWT: [] + summary: Get Audits + tags: + - Audits + post: + consumes: + - application/json + description: Create Audit + parameters: + - description: create audit request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse' + security: + - JWT: [] + summary: Create Audit + tags: + - Audits + /admin/audits/{auditId}: + delete: + consumes: + - application/json + description: Delete Audit + parameters: + - description: auditId + in: path + name: auditId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete Audit 'NOT IMPLEMENTED' + tags: + - Audits + get: + consumes: + - application/json + description: Get Audit + parameters: + - description: auditId + in: path + name: auditId + required: true type: string - valid: - description: Valid is true if Time is not NULL - type: boolean - type: object -host: tks-api-dev.taco-cat.xyz -info: - contact: - email: taekyu.kang@sk.com - name: taekyu.kang@sk.com - description: This is backend api service for tks platform - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - title: tks-api service - version: "1.0" -paths: + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse' + security: + - JWT: [] + summary: Get Audit + tags: + - Audits /admin/organizations/{organizationId}/projects: get: consumes: @@ -3586,7 +3555,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackTemplateResponse' security: - JWT: [] - summary: Create StackTemplate 'NOT IMPLEMENTED' + summary: Create StackTemplate tags: - StackTemplates /admin/stack-templates/{stackTemplateId}: @@ -3607,7 +3576,7 @@ paths: description: OK security: - JWT: [] - summary: Delete StackTemplate 'NOT IMPLEMENTED' + summary: Delete StackTemplate tags: - StackTemplates get: @@ -3650,7 +3619,7 @@ paths: description: OK security: - JWT: [] - summary: Update StackTemplate 'NOT IMPLEMENTED' + summary: Update StackTemplate tags: - StackTemplates /admin/stack-templates/{stackTemplateId}/organizations: @@ -4106,8 +4075,6 @@ paths: responses: "200": description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster' security: - JWT: [] summary: Delete cluster @@ -4129,7 +4096,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Cluster' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse' security: - JWT: [] summary: Get cluster @@ -4342,7 +4309,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Organization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteOrganizationResponse' security: - JWT: [] summary: Delete organization @@ -4544,120 +4511,6 @@ paths: summary: Create alert action tags: - Alerts - /organizations/{organizationId}/audits: - get: - consumes: - - application/json - description: Get Audits - parameters: - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filter - type: array - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: or - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditsResponse' - security: - - JWT: [] - summary: Get Audits - tags: - - Audits - post: - consumes: - - application/json - description: Create Audit - parameters: - - description: create audit request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAuditResponse' - security: - - JWT: [] - summary: Create Audit - tags: - - Audits - /organizations/{organizationId}/audits/{auditId}: - delete: - consumes: - - application/json - description: Delete Audit - parameters: - - description: auditId - in: path - name: auditId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete Audit 'NOT IMPLEMENTED' - tags: - - Audits - get: - consumes: - - application/json - description: Get Audit - parameters: - - description: auditId - in: path - name: auditId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAuditResponse' - security: - - JWT: [] - summary: Get Audit - tags: - - Audits /organizations/{organizationId}/cloud-accounts: get: consumes: @@ -5366,7 +5219,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp' type: array security: - JWT: [] @@ -5733,7 +5586,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeApp' + $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp' type: array security: - JWT: [] @@ -6657,7 +6510,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse' security: - JWT: [] summary: Get Permissions By Role ID @@ -6689,6 +6542,64 @@ paths: summary: Update Permissions By Role ID tags: - Permission + /organizations/{organizationId}/stack-templates: + get: + consumes: + - application/json + description: Get Organization StackTemplates + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' + security: + - JWT: [] + summary: Get Organization StackTemplates + tags: + - StackTemplates + /organizations/{organizationId}/stack-templates/{stackTemplateId}: + get: + consumes: + - application/json + description: Get Organization StackTemplate + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse' + security: + - JWT: [] + summary: Get Organization StackTemplate + tags: + - StackTemplates /organizations/{organizationId}/stacks: get: consumes: @@ -7079,8 +6990,6 @@ paths: responses: "200": description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.User' security: - JWT: [] summary: Delete user @@ -7236,7 +7145,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSet' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse' security: - JWT: [] summary: Get Permission Templates diff --git a/internal/database/database.go b/internal/database/database.go index 1fd29171..4c34a427 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -14,7 +14,6 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" ) func InitDB() (*gorm.DB, error) { @@ -60,68 +59,68 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&repository.CacheEmailCode{}); err != nil { return err } - if err := db.AutoMigrate(&domain.User{}); err != nil { + if err := db.AutoMigrate(&model.User{}); err != nil { return err } - if err := db.AutoMigrate(&domain.Role{}); err != nil { + if err := db.AutoMigrate(&model.Role{}); err != nil { return err } // Organization - if err := db.AutoMigrate(&domain.Organization{}); err != nil { + if err := db.AutoMigrate(&model.Organization{}); err != nil { return err } // CloudAccount - if err := db.AutoMigrate(&repository.CloudAccount{}); err != nil { + if err := db.AutoMigrate(&model.CloudAccount{}); err != nil { return err } // StackTemplate - if err := db.AutoMigrate(&repository.StackTemplate{}); err != nil { + if err := db.AutoMigrate(&model.StackTemplate{}); err != nil { return err } // Cluster - if err := db.AutoMigrate(&repository.Cluster{}); err != nil { + if err := db.AutoMigrate(&model.Cluster{}); err != nil { return err } - if err := db.AutoMigrate(&repository.ClusterFavorite{}); err != nil { + if err := db.AutoMigrate(&model.ClusterFavorite{}); err != nil { return err } // Services - if err := db.AutoMigrate(&repository.AppGroup{}); err != nil { + if err := db.AutoMigrate(&model.AppGroup{}); err != nil { return err } - if err := db.AutoMigrate(&repository.Application{}); err != nil { + if err := db.AutoMigrate(&model.Application{}); err != nil { return err } // AppServe - if err := db.AutoMigrate(&domain.AppServeApp{}); err != nil { + if err := db.AutoMigrate(&model.AppServeApp{}); err != nil { return err } - if err := db.AutoMigrate(&domain.AppServeAppTask{}); err != nil { + if err := db.AutoMigrate(&model.AppServeAppTask{}); err != nil { return err } // Alert - if err := db.AutoMigrate(&repository.Alert{}); err != nil { + if err := db.AutoMigrate(&model.Alert{}); err != nil { return err } - if err := db.AutoMigrate(&repository.AlertAction{}); err != nil { + if err := db.AutoMigrate(&model.AlertAction{}); err != nil { return err } // Role - if err := db.AutoMigrate(&domain.Role{}); err != nil { + if err := db.AutoMigrate(&model.Role{}); err != nil { return err } - if err := db.AutoMigrate(&domain.Permission{}); err != nil { + if err := db.AutoMigrate(&model.Permission{}); err != nil { return err } - if err := db.AutoMigrate(&domain.Endpoint{}); err != nil { + if err := db.AutoMigrate(&model.Endpoint{}); err != nil { return err } @@ -139,6 +138,20 @@ func migrateSchema(db *gorm.DB) error { return err } + // Audit + if err := db.AutoMigrate(&model.Audit{}); err != nil { + return err + } + + // PolicyTemplate + if err := db.AutoMigrate(&model.PolicyTemplateSupportedVersion{}); err != nil { + return err + } + + if err := db.AutoMigrate(&model.PolicyTemplate{}); err != nil { + return err + } + return nil } @@ -172,7 +185,7 @@ func EnsureDefaultRows(db *gorm.DB) error { } for _, ep := range api.ApiMap { if _, ok := storedEps[ep.Name]; !ok { - if err := repoFactory.Endpoint.Create(&domain.Endpoint{ + if err := repoFactory.Endpoint.Create(&model.Endpoint{ Name: ep.Name, Group: ep.Group, }); err != nil { @@ -181,19 +194,5 @@ func EnsureDefaultRows(db *gorm.DB) error { } } - // Audit - if err := db.AutoMigrate(&repository.Audit{}); err != nil { - return err - } - - // PolicyTemplate - if err := db.AutoMigrate(&repository.PolicyTemplateSupportedVersion{}); err != nil { - return err - } - - if err := db.AutoMigrate(&repository.PolicyTemplate{}); err != nil { - return err - } - return nil } diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 9d7c0966..4c6a3bdd 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -102,6 +102,8 @@ const ( Admin_UpdateStackTemplate Admin_DeleteStackTemplate Admin_UpdateStackTemplateOrganizations + GetOrganizationStackTemplates + GetOrganizationStackTemplate // Dashboard GetChartsDashboard // 대시보드/대시보드/조회 @@ -119,7 +121,7 @@ const ( // Stack GetStacks // 스택관리/조회 - CreateStack // // 스택관리/생성 + CreateStack // 스택관리/생성 CheckStackName // 스택관리/조회 GetStack // 스택관리/조회 UpdateStack // 스택관리/수정 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index aeea2305..32a81fb6 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -303,6 +303,14 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, + GetOrganizationStackTemplates: { + Name: "GetOrganizationStackTemplates", + Group: "StackTemplate", + }, + GetOrganizationStackTemplate: { + Name: "GetOrganizationStackTemplate", + Group: "StackTemplate", + }, GetChartsDashboard: { Name: "GetChartsDashboard", Group: "Dashboard", @@ -880,6 +888,10 @@ func (e Endpoint) String() string { return "Admin_DeleteStackTemplate" case Admin_UpdateStackTemplateOrganizations: return "Admin_UpdateStackTemplateOrganizations" + case GetOrganizationStackTemplates: + return "GetOrganizationStackTemplates" + case GetOrganizationStackTemplate: + return "GetOrganizationStackTemplate" case GetChartsDashboard: return "GetChartsDashboard" case GetChartDashboard: @@ -1248,6 +1260,10 @@ func GetEndpoint(name string) Endpoint { return Admin_DeleteStackTemplate case "Admin_UpdateStackTemplateOrganizations": return Admin_UpdateStackTemplateOrganizations + case "GetOrganizationStackTemplates": + return GetOrganizationStackTemplates + case "GetOrganizationStackTemplate": + return GetOrganizationStackTemplate case "GetChartsDashboard": return GetChartsDashboard case "GetChartDashboard": diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index 5b03746f..bf878aef 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -272,7 +273,7 @@ func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) log.InfoWithContext(r.Context(), "alert : ", helper.ModelToJson(input)) - var dto domain.AlertAction + var dto model.AlertAction if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 26dbb840..27543035 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -6,6 +6,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -43,7 +44,7 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) return } - var dto domain.AppGroup + var dto model.AppGroup if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -264,7 +265,7 @@ func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Reque return } - var dto domain.Application + var dto model.Application if err := serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index d738685f..aa6f92b1 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -12,6 +12,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -115,7 +116,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re (appReq).SetDefaultValue() - var app domain.AppServeApp + var app model.AppServeApp if err = serializer.Map(appReq, &app); err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -131,7 +132,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re app.Status = "PREPARING" app.CreatedAt = now - var task domain.AppServeAppTask + var task model.AppServeAppTask if err = serializer.Map(appReq, &task); err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -230,7 +231,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} []domain.AppServeApp +// @Success 200 {object} []model.AppServeApp // @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { @@ -264,7 +265,13 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ } var out domain.GetAppServeAppsResponse - out.AppServeApps = apps + out.AppServeApps = make([]domain.AppServeAppResponse, len(apps)) + for i, app := range apps { + if err := serializer.Map(app, &out.AppServeApps[i]); err != nil { + log.InfoWithContext(r.Context(), err) + continue + } + } if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) @@ -317,7 +324,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque return } - newTasks := make([]domain.AppServeAppTask, 0) + newTasks := make([]model.AppServeAppTask, 0) for idx, t := range app.AppServeAppTasks { // Rollbacking to latest task should be blocked. @@ -330,7 +337,10 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque app.AppServeAppTasks = newTasks var out domain.GetAppServeAppResponse - out.AppServeApp = *app + if err := serializer.Map(app, &out.AppServeApp); err != nil { + log.InfoWithContext(r.Context(), err) + } + // NOTE: makeStages function's been changed to use task instead of app //out.Stages = makeStages(app) @@ -377,7 +387,9 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - out.AppServeAppTask = *task + if err := serializer.Map(task, &out.AppServeAppTask); err != nil { + log.InfoWithContext(r.Context(), err) + } ResponseJSON(w, r, http.StatusOK, out) } @@ -435,7 +447,7 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. // @Param sortColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} []domain.AppServeApp +// @Success 200 {object} []model.AppServeApp // @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks [get] // @Security JWT func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r *http.Request) { @@ -463,7 +475,13 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r } var out domain.GetAppServeAppTasksResponse - out.AppServeAppTasks = tasks + out.AppServeAppTasks = make([]domain.AppServeAppTaskResponse, len(tasks)) + for i, task := range tasks { + if err := serializer.Map(task, &out.AppServeAppTasks[i]); err != nil { + log.InfoWithContext(r.Context(), err) + continue + } + } if out.Pagination, err = pg.Response(); err != nil { log.InfoWithContext(r.Context(), err) @@ -533,14 +551,19 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - out.AppServeApp = *app - out.AppServeAppTask = *task + if err := serializer.Map(app, &out.AppServeApp); err != nil { + log.InfoWithContext(r.Context(), err) + } + if err := serializer.Map(task, &out.AppServeAppTask); err != nil { + log.InfoWithContext(r.Context(), err) + } + out.Stages = makeStages(task, app) ResponseJSON(w, r, http.StatusOK, out) } -func makeStages(task *domain.AppServeAppTask, app *domain.AppServeApp) []domain.StageResponse { +func makeStages(task *model.AppServeAppTask, app *model.AppServeApp) []domain.StageResponse { stages := make([]domain.StageResponse, 0) var stage domain.StageResponse @@ -582,7 +605,7 @@ func makeStages(task *domain.AppServeAppTask, app *domain.AppServeApp) []domain. return stages } -func makeStage(task *domain.AppServeAppTask, app *domain.AppServeApp, pl string) domain.StageResponse { +func makeStage(task *model.AppServeAppTask, app *model.AppServeApp, pl string) domain.StageResponse { taskStatus := task.Status strategy := task.Strategy @@ -774,7 +797,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re // from existing app config. //appReq.SetDefaultValue() - var task domain.AppServeAppTask + var task model.AppServeAppTask //tasks := app.AppServeAppTasks //sort.Slice(tasks, func(i, j int) bool { // return tasks[i].CreatedAt.String() > tasks[j].CreatedAt.String() diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 395d9112..2a7b2b99 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -34,7 +34,7 @@ func NewAuditHandler(h usecase.Usecase) *AuditHandler { // @Produce json // @Param body body domain.CreateAuditRequest true "create audit request" // @Success 200 {object} domain.CreateAuditResponse -// @Router /organizations/{organizationId}/audits [post] +// @Router /admin/audits [post] // @Security JWT func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) @@ -54,19 +54,12 @@ func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { // @Param filter query []string false "filters" // @Param or query []string false "filters" // @Success 200 {object} domain.GetAuditsResponse -// @Router /organizations/{organizationId}/audits [get] +// @Router /admin/audits [get] // @Security JWT func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) - return - } - urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - audits, err := h.usecase.Fetch(r.Context(), organizationId, pg) + audits, err := h.usecase.Fetch(r.Context(), pg) if err != nil { ErrorJSON(w, r, err) return @@ -96,7 +89,7 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} domain.GetAuditResponse -// @Router /organizations/{organizationId}/audits/{auditId} [get] +// @Router /admin/audits/{auditId} [get] // @Security JWT func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -137,7 +130,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param auditId path string true "auditId" // @Success 200 {object} nil -// @Router /organizations/{organizationId}/audits/{auditId} [delete] +// @Router /admin/audits/{auditId} [delete] // @Security JWT func (h *AuditHandler) DeleteAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("need implementation")) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 72a56812..d2fea4d3 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -7,6 +7,7 @@ import ( "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/audit" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" @@ -61,7 +62,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { user, err := h.usecase.Login(input.AccountId, input.Password, input.OrganizationId) if err != nil { errorResponse, _ := httpErrors.ErrorResponse(err) - _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ + _, _ = h.auditUsecase.Create(r.Context(), model.Audit{ OrganizationId: input.OrganizationId, Group: "Auth", Message: fmt.Sprintf("[%s]님이 로그인에 실패하였습니다.", input.AccountId), @@ -73,7 +74,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } else { - _, _ = h.auditUsecase.Create(r.Context(), domain.Audit{ + _, _ = h.auditUsecase.Create(r.Context(), model.Audit{ OrganizationId: input.OrganizationId, Group: "Auth", Message: fmt.Sprintf("[%s]님이 로그인 하였습니다.", input.AccountId), diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 15b4f6a1..5c29a04d 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -7,6 +7,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -53,7 +54,7 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. return } - var dto domain.CloudAccount + var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -198,7 +199,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. return } - var dto domain.CloudAccount + var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -248,7 +249,7 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. return } - var dto domain.CloudAccount + var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -295,7 +296,11 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * return } - ResponseJSON(w, r, http.StatusOK, nil) + out := domain.DeleteCloudAccountResponse{ + ID: cloudAccountId, + } + + ResponseJSON(w, r, http.StatusOK, out) } // CheckCloudAccountName godoc diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 1f8fb6a9..d0811b04 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -4,8 +4,8 @@ import ( "fmt" "net/http" - "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -58,6 +58,13 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { log.InfoWithContext(r.Context(), err) continue } + + if cluster.Favorites != nil && len(*cluster.Favorites) > 0 { + out.Clusters[i].Favorited = true + } else { + out.Clusters[i].Favorited = false + } + } if out.Pagination, err = pg.Response(); err != nil { @@ -75,7 +82,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.Cluster +// @Success 200 {object} domain.GetClusterResponse // @Router /clusters/{clusterId} [get] // @Security JWT func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { @@ -150,19 +157,13 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Cluster + var dto model.Cluster if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } - if err = serializer.Map(input, &dto.Conf); err != nil { - log.InfoWithContext(r.Context(), err) - } - - // [TODO] set default value dto.ClusterType = domain.ClusterType_USER - dto.Conf.SetDefault() - log.InfoWithContext(r.Context(), dto.Conf) + dto.SetDefaultConf() //txHandle := r.Context().Value("txHandle").(*gorm.DB) clusterId := domain.ClusterId("") @@ -210,18 +211,13 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Cluster + var dto model.Cluster if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } + dto.SetDefaultConf() - if err = serializer.Map(input, &dto.Conf); err != nil { - log.InfoWithContext(r.Context(), err) - } - dto.Conf.SetDefault() - log.InfoWithContext(r.Context(), dto.Conf) - - dto.CloudAccountId = uuid.Nil + dto.CloudAccountId = nil clusterId, err := h.usecase.Import(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) @@ -270,7 +266,7 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) // @Accept json // @Produce json // @Param clusterId path string true "clusterId" -// @Success 200 {object} domain.Cluster +// @Success 200 {object} nil // @Router /clusters/{clusterId} [delete] // @Security JWT func (h *ClusterHandler) DeleteCluster(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index 680c338d..d2b6e180 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -1,6 +1,7 @@ package http import ( + "bytes" "encoding/json" "errors" "io" @@ -49,6 +50,7 @@ func UnmarshalRequestInput(r *http.Request, in any) error { if err != nil { return err } + r.Body = io.NopCloser(bytes.NewBuffer(body)) err = json.Unmarshal(body, &in) if err != nil { diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 26bbb8d7..264a3611 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -6,6 +6,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -52,7 +53,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } ctx := r.Context() - var organization domain.Organization + var organization model.Organization if err = serializer.Map(input, &organization); err != nil { log.ErrorWithContext(r.Context(), err) } @@ -66,7 +67,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. organization.ID = organizationId // Role 생성 - adminRole := domain.Role{ + adminRole := model.Role{ OrganizationID: organizationId, Name: "admin", Description: "admin", @@ -78,7 +79,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. ErrorJSON(w, r, err) return } - userRole := domain.Role{ + userRole := model.Role{ OrganizationID: organizationId, Name: "user", Description: "user", @@ -216,7 +217,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Success 200 {object} domain.Organization +// @Success 200 {object} domain.DeleteOrganizationResponse // @Router /organizations/{organizationId} [delete] // @Security JWT func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { @@ -253,7 +254,10 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. return } - ResponseJSON(w, r, http.StatusOK, nil) + out := domain.DeleteOrganizationResponse{ + ID: organizationId, + } + ResponseJSON(w, r, http.StatusOK, out) } // UpdateOrganization godoc diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 22bdfb64..d7ca79d9 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -1,12 +1,15 @@ package http import ( + "net/http" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" - "net/http" ) type IPermissionHandler interface { @@ -32,19 +35,24 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { // @Description Get Permission Templates // @Accept json // @Produce json -// @Success 200 {object} domain.PermissionSet +// @Success 200 {object} domain.PermissionSetResponse // @Router /permissions/templates [get] // @Security JWT func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { - permissionSet := domain.NewDefaultPermissionSet() + permissionSet := model.NewDefaultPermissionSet() + + var premissionSetResponse domain.PermissionSetResponse + if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { + log.InfoWithContext(r.Context(), err) + } var out domain.GetPermissionTemplatesResponse - out.Permissions = append(out.Permissions, permissionSet.Dashboard) - out.Permissions = append(out.Permissions, permissionSet.Stack) - out.Permissions = append(out.Permissions, permissionSet.SecurityPolicy) - out.Permissions = append(out.Permissions, permissionSet.ProjectManagement) - out.Permissions = append(out.Permissions, permissionSet.Notification) - out.Permissions = append(out.Permissions, permissionSet.Configuration) + out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) + out.Permissions = append(out.Permissions, premissionSetResponse.Stack) + out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) + out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) + out.Permissions = append(out.Permissions, premissionSetResponse.Notification) + out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) ResponseJSON(w, r, http.StatusOK, out) } @@ -56,7 +64,7 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http // @Description Get Permissions By Role ID // @Accept json // @Produce json -// @Success 200 {object} domain.PermissionSet +// @Success 200 {object} domain.PermissionSetResponse // @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] // @Security JWT func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { @@ -77,13 +85,18 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http return } + var premissionSetResponse domain.PermissionSetResponse + if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { + log.InfoWithContext(r.Context(), err) + } + var out domain.GetPermissionsByRoleIdResponse - out.Permissions = append(out.Permissions, permissionSet.Dashboard) - out.Permissions = append(out.Permissions, permissionSet.Stack) - out.Permissions = append(out.Permissions, permissionSet.SecurityPolicy) - out.Permissions = append(out.Permissions, permissionSet.ProjectManagement) - out.Permissions = append(out.Permissions, permissionSet.Notification) - out.Permissions = append(out.Permissions, permissionSet.Configuration) + out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) + out.Permissions = append(out.Permissions, premissionSetResponse.Stack) + out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) + out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) + out.Permissions = append(out.Permissions, premissionSetResponse.Notification) + out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) ResponseJSON(w, r, http.StatusOK, out) } @@ -122,9 +135,15 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h } log.Debugf("input: %+v", input) - for _, permission := range input.Permissions { - log.Debugf("permission: %+v", permission) - if err := h.permissionUsecase.UpdatePermission(permission); err != nil { + for _, permissionResponse := range input.Permissions { + log.Debugf("permissionResponse: %+v", permissionResponse) + + var permission model.Permission + if err := serializer.Map(permissionResponse, &permission); err != nil { + log.InfoWithContext(r.Context(), err) + } + + if err := h.permissionUsecase.UpdatePermission(&permission); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 8126e00f..e747a98f 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -67,7 +68,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h return } - var dto domain.PolicyTemplate + var dto model.PolicyTemplate if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 1ad67b29..7fdb1157 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -1,14 +1,16 @@ package http import ( + "net/http" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" - "net/http" ) type IRoleHandler interface { @@ -67,7 +69,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - dto := domain.Role{ + dto := model.Role{ OrganizationID: organizationId, Name: input.Name, Description: input.Description, @@ -82,7 +84,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { } // create permission - defaultPermissionSet := domain.NewDefaultPermissionSet() + defaultPermissionSet := model.NewDefaultPermissionSet() h.permissionUsecase.SetRoleIdToPermissionSet(roleId, defaultPermissionSet) err = h.permissionUsecase.CreatePermissionSet(defaultPermissionSet) if err != nil { @@ -256,7 +258,7 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { } // input to dto - dto := domain.Role{ + dto := model.Role{ ID: roleId, Description: input.Description, } diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 107e621b..60cad92a 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -30,7 +31,7 @@ func NewStackTemplateHandler(h usecase.Usecase) *StackTemplateHandler { // CreateStackTemplate godoc // // @Tags StackTemplates -// @Summary Create StackTemplate 'NOT IMPLEMENTED' +// @Summary Create StackTemplate // @Description Create StackTemplate // @Accept json // @Produce json @@ -46,7 +47,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt return } - var dto domain.StackTemplate + var dto model.StackTemplate if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -170,7 +171,7 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R // UpdateStackTemplate godoc // // @Tags StackTemplates -// @Summary Update StackTemplate 'NOT IMPLEMENTED' +// @Summary Update StackTemplate // @Description Update StackTemplate // @Accept json // @Produce json @@ -192,7 +193,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt return } - var dto domain.StackTemplate + var dto model.StackTemplate if err := serializer.Map(r, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -209,7 +210,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt // DeleteStackTemplate godoc // // @Tags StackTemplates -// @Summary Delete StackTemplate 'NOT IMPLEMENTED' +// @Summary Delete StackTemplate // @Description Delete StackTemplate // @Accept json // @Produce json @@ -287,7 +288,7 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW return } - var dto domain.StackTemplate + var dto model.StackTemplate if err := serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -300,3 +301,117 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW } ResponseJSON(w, r, http.StatusOK, nil) } + +// GetOrganizationStackTemplates godoc +// +// @Tags StackTemplates +// @Summary Get Organization StackTemplates +// @Description Get Organization StackTemplates +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetStackTemplatesResponse +// @Router /organizations/{organizationId}/stack-templates [get] +// @Security JWT +func (h *StackTemplateHandler) GetOrganizationStackTemplates(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + stackTemplates, err := h.usecase.FetchWithOrganization(r.Context(), organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetStackTemplatesResponse + out.StackTemplates = make([]domain.StackTemplateResponse, len(stackTemplates)) + for i, stackTemplate := range stackTemplates { + if err := serializer.Map(stackTemplate, &out.StackTemplates[i]); err != nil { + log.InfoWithContext(r.Context(), err) + } + + out.StackTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) + for j, organization := range stackTemplate.Organizations { + if err := serializer.Map(organization, &out.StackTemplates[i].Organizations[j]); err != nil { + log.InfoWithContext(r.Context(), err) + } + } + + err := json.Unmarshal(stackTemplate.Services, &out.StackTemplates[i].Services) + if err != nil { + log.ErrorWithContext(r.Context(), err) + } + } + + if out.Pagination, err = pg.Response(); err != nil { + log.InfoWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetOrganizationStackTemplate godoc +// +// @Tags StackTemplates +// @Summary Get Organization StackTemplate +// @Description Get Organization StackTemplate +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetStackTemplateResponse +// @Router /organizations/{organizationId}/stack-templates/{stackTemplateId} [get] +// @Security JWT +func (h *StackTemplateHandler) GetOrganizationStackTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + _, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + strId, ok := vars["stackTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + stackTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + stackTemplate, err := h.usecase.Get(r.Context(), stackTemplateId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetStackTemplateResponse + if err := serializer.Map(stackTemplate, &out.StackTemplate); err != nil { + log.InfoWithContext(r.Context(), err) + } + + out.StackTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) + for i, organization := range stackTemplate.Organizations { + if err := serializer.Map(organization, &out.StackTemplate.Organizations[i]); err != nil { + log.InfoWithContext(r.Context(), err) + } + } + + err = json.Unmarshal(stackTemplate.Services, &out.StackTemplate.Services) + if err != nil { + log.ErrorWithContext(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index fd84da4e..9a40cf22 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -51,13 +52,10 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Stack + var dto model.Stack if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } - if err = serializer.Map(input, &dto.Conf); err != nil { - log.InfoWithContext(r.Context(), err) - } dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -126,7 +124,10 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { for i, stack := range stacks { if err := serializer.Map(stack, &out.Stacks[i]); err != nil { log.InfoWithContext(r.Context(), err) - continue + } + + if err := serializer.Map(stack.CreatedAt, &out.Stacks[i].CreatedAt); err != nil { + log.InfoWithContext(r.Context(), err) } err = json.Unmarshal(stack.StackTemplate.Services, &out.Stacks[i].StackTemplate.Services) @@ -259,7 +260,7 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Stack + var dto model.Stack if err = serializer.Map(input, &dto); err != nil { log.InfoWithContext(r.Context(), err) } @@ -302,7 +303,7 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { return } - var dto domain.Stack + var dto model.Stack dto.ID = domain.StackId(strId) dto.OrganizationId = organizationId diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 7df3a3bc..9fa3b8b7 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -9,6 +9,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" @@ -86,11 +87,11 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user domain.User + var user model.User if err = serializer.Map(input, &user); err != nil { log.ErrorWithContext(r.Context(), err) } - user.Organization = domain.Organization{ + user.Organization = model.Organization{ ID: organizationId, } @@ -231,7 +232,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Success 200 {object} domain.User +// @Success 200 {object} nil // @Router /organizations/{organizationId}/users/{accountId} [delete] // @Security JWT func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { @@ -298,12 +299,12 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user domain.User + var user model.User if err = serializer.Map(input, &user); err != nil { ErrorJSON(w, r, err) return } - user.Organization = domain.Organization{ + user.Organization = model.Organization{ ID: organizationId, } user.AccountId = accountId @@ -451,7 +452,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user domain.User + var user model.User if err = serializer.Map(input, &user); err != nil { log.ErrorWithContext(r.Context(), err) ErrorJSON(w, r, err) @@ -710,7 +711,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } } - user := domain.User{ + user := model.User{ Name: input.Name, AccountId: input.AccountId, Email: input.Email, @@ -732,7 +733,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } } - user.Organization = domain.Organization{ + user.Organization = model.Organization{ ID: organizationId, } @@ -973,14 +974,14 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - user := domain.User{ + user := model.User{ AccountId: accountId, Name: input.Name, Email: input.Email, Department: input.Department, Description: input.Description, } - user.Organization = domain.Organization{ + user.Organization = model.Organization{ ID: organizationId, } diff --git a/internal/filter/settings.go b/internal/filter/settings.go index ac2a31a8..4e06fc48 100644 --- a/internal/filter/settings.go +++ b/internal/filter/settings.go @@ -316,6 +316,7 @@ func getField(field string, sch *schema.Schema, blacklist *Blacklist) (*schema.F if !ok || (relation.Type != schema.HasOne && relation.Type != schema.BelongsTo) { return nil, nil, "" } + s = relation.FieldSchema if blacklist != nil { blacklist = blacklist.Relations[v] @@ -330,6 +331,7 @@ func getField(field string, sch *schema.Schema, blacklist *Blacklist) (*schema.F if !ok { return nil, nil, "" } + return col, s, joinName } diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 8d2252f5..610d59ad 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -10,7 +10,7 @@ import ( "time" "github.com/Nerzal/gocloak/v13" - "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" ) @@ -18,15 +18,15 @@ import ( type IKeycloak interface { InitializeKeycloak() error - LoginAdmin(accountId string, password string) (*domain.User, error) - Login(accountId string, password string, organizationId string) (*domain.User, error) + LoginAdmin(accountId string, password string) (*model.User, error) + Login(accountId string, password string, organizationId string) (*model.User, error) Logout(sessionId string, organizationId string) error CreateRealm(organizationId string) (string, error) - GetRealm(organizationId string) (*domain.Organization, error) - GetRealms() ([]*domain.Organization, error) + GetRealm(organizationId string) (*model.Organization, error) + GetRealms() ([]*model.Organization, error) DeleteRealm(organizationId string) error - UpdateRealm(organizationId string, organizationConfig domain.Organization) error + UpdateRealm(organizationId string, organizationConfig model.Organization) error CreateUser(organizationId string, user *gocloak.User) (string, error) GetUser(organizationId string, userAccountId string) (*gocloak.User, error) @@ -51,7 +51,7 @@ type Keycloak struct { adminCliToken *gocloak.JWT } -func (k *Keycloak) LoginAdmin(accountId string, password string) (*domain.User, error) { +func (k *Keycloak) LoginAdmin(accountId string, password string) (*model.User, error) { ctx := context.Background() JWTToken, err := k.client.LoginAdmin(ctx, accountId, password, DefaultMasterRealm) if err != nil { @@ -59,17 +59,17 @@ func (k *Keycloak) LoginAdmin(accountId string, password string) (*domain.User, return nil, err } - return &domain.User{Token: JWTToken.AccessToken}, nil + return &model.User{Token: JWTToken.AccessToken}, nil } -func (k *Keycloak) Login(accountId string, password string, organizationId string) (*domain.User, error) { +func (k *Keycloak) Login(accountId string, password string, organizationId string) (*model.User, error) { ctx := context.Background() JWTToken, err := k.client.Login(ctx, DefaultClientID, k.config.ClientSecret, organizationId, accountId, password) if err != nil { log.Error(err) return nil, err } - return &domain.User{Token: JWTToken.AccessToken}, nil + return &model.User{Token: JWTToken.AccessToken}, nil } func New(config *Config) IKeycloak { @@ -249,7 +249,7 @@ func (k *Keycloak) CreateRealm(organizationId string) (string, error) { return realmUUID, nil } -func (k *Keycloak) GetRealm(organizationId string) (*domain.Organization, error) { +func (k *Keycloak) GetRealm(organizationId string) (*model.Organization, error) { ctx := context.Background() token := k.adminCliToken realm, err := k.client.GetRealm(ctx, token.AccessToken, organizationId) @@ -260,14 +260,14 @@ func (k *Keycloak) GetRealm(organizationId string) (*domain.Organization, error) return k.reflectOrganization(*realm), nil } -func (k *Keycloak) GetRealms() ([]*domain.Organization, error) { +func (k *Keycloak) GetRealms() ([]*model.Organization, error) { ctx := context.Background() token := k.adminCliToken realms, err := k.client.GetRealms(ctx, token.AccessToken) if err != nil { return nil, err } - organization := make([]*domain.Organization, 0) + organization := make([]*model.Organization, 0) for _, realm := range realms { organization = append(organization, k.reflectOrganization(*realm)) } @@ -275,7 +275,7 @@ func (k *Keycloak) GetRealms() ([]*domain.Organization, error) { return organization, nil } -func (k *Keycloak) UpdateRealm(organizationId string, organizationConfig domain.Organization) error { +func (k *Keycloak) UpdateRealm(organizationId string, organizationConfig model.Organization) error { ctx := context.Background() token := k.adminCliToken realm := k.reflectRealmRepresentation(organizationConfig) @@ -844,14 +844,14 @@ func (k *Keycloak) createDefaultClient(ctx context.Context, accessToken string, return id, nil } -func (k *Keycloak) reflectOrganization(org gocloak.RealmRepresentation) *domain.Organization { - return &domain.Organization{ +func (k *Keycloak) reflectOrganization(org gocloak.RealmRepresentation) *model.Organization { + return &model.Organization{ ID: *org.ID, Name: *org.Realm, } } -func (k *Keycloak) reflectRealmRepresentation(org domain.Organization) *gocloak.RealmRepresentation { +func (k *Keycloak) reflectRealmRepresentation(org model.Organization) *gocloak.RealmRepresentation { return &gocloak.RealmRepresentation{ Realm: gocloak.StringP(org.Name), } diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index 85a80d9d..863b71fd 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -19,7 +19,6 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } - if isSuccess(statusCode) { return fmt.Sprintf("스택 [%s]을 생성하였습니다.", input.Name), "" } else { @@ -30,22 +29,101 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } - if isSuccess(statusCode) { return fmt.Sprintf("프로젝트 [%s]를 생성하였습니다.", input.Name), "" } else { - return "프로젝트 [%s]를 생성하는데 실패하였습니다. ", errorText(out) + return fmt.Sprintf("프로젝트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) } }, internalApi.CreateCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateCloudAccountRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(err) } - if isSuccess(statusCode) { return fmt.Sprintf("클라우드 어카운트 [%s]를 생성하였습니다.", input.Name), "" } else { - return "프로젝트 [%s]를 생성하는데 실패하였습니다. ", errorText(out) + return fmt.Sprintf("클라우드 어카운트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.DeleteCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + if isSuccess(statusCode) { + output := domain.DeleteCloudAccountResponse{} + if err := json.Unmarshal(in, &output); err != nil { + log.Error(err) + } + return fmt.Sprintf("클라우드어카운트 [ID:%s]를 삭제하였습니다.", output.ID), "" + } else { + return "클라우드어카운트 [%s]를 삭제하는데 실패하였습니다. ", errorText(out) + } + }, internalApi.CreateUser: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateUserRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("사용자 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("사용자 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.CreateOrganization: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateOrganizationRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("조직 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("조직 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.DeleteOrganization: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + if isSuccess(statusCode) { + output := domain.DeleteOrganizationResponse{} + if err := json.Unmarshal(in, &output); err != nil { + log.Error(err) + } + return fmt.Sprintf("조직 [ID:%s]를 삭제하였습니다.", output.ID), "" + } else { + return "조직 [%s]를 삭제하는데 실패하였습니다. ", errorText(out) + } + }, internalApi.CreateAppServeApp: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateAppServeAppRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("앱서빙 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("앱서빙 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.Admin_CreateStackTemplate: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateStackTemplateRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + log.Info(input) + if isSuccess(statusCode) { + return fmt.Sprintf("스택 템플릿 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("스택 템플릿 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.Admin_CreateUser: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreateUserRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("어드민 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + } + }, internalApi.CreatePolicyTemplate: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + input := domain.CreatePolicyTemplateRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("폴리시템플릿 [%s]를 생성하였습니다.", input.TemplateName), "" + } else { + return fmt.Sprintf("폴리시템플릿 [%s]을 생성하는데 실패하였습니다.", input.TemplateName), errorText(out) } }, } diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 428f8d35..12360269 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -10,8 +10,8 @@ import ( internalApi "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/middleware/logging" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) @@ -59,7 +59,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han message, description = fn(lrw.GetBody(), body, statusCode) r.Body = io.NopCloser(bytes.NewBuffer(body)) - dto := domain.Audit{ + dto := model.Audit{ OrganizationId: organizationId, Group: internalApi.ApiMap[endpoint].Group, Message: message, diff --git a/internal/model/alert.go b/internal/model/alert.go new file mode 100644 index 00000000..5d360781 --- /dev/null +++ b/internal/model/alert.go @@ -0,0 +1,60 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +// Models +type Alert struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Name string + Code string + Description string + Grade string + Message string + ClusterId domain.ClusterId + Cluster Cluster `gorm:"foreignKey:ClusterId"` + Node string + CheckPoint string + GrafanaUrl string + FiredAt *time.Time `gorm:"-:all"` + TakedAt *time.Time `gorm:"-:all"` + ClosedAt *time.Time `gorm:"-:all"` + TakedSec int `gorm:"-:all"` + ProcessingSec int `gorm:"-:all"` + LastTaker User `gorm:"-:all"` + AlertActions []AlertAction + Summary string + RawData datatypes.JSON + Status domain.AlertActionStatus `gorm:"index"` +} + +func (c *Alert) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + +type AlertAction struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + AlertId uuid.UUID + Content string + Status domain.AlertActionStatus + TakerId *uuid.UUID `gorm:"type:uuid"` + Taker User `gorm:"foreignKey:TakerId"` +} + +func (c *AlertAction) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/app-group.go b/internal/model/app-group.go new file mode 100644 index 00000000..fea48726 --- /dev/null +++ b/internal/model/app-group.go @@ -0,0 +1,47 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +// Models +type AppGroup struct { + gorm.Model + + ID domain.AppGroupId `gorm:"primarykey"` + AppGroupType domain.AppGroupType + ClusterId domain.ClusterId + Name string + Description string + WorkflowId string + Status domain.AppGroupStatus + StatusDesc string + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = domain.AppGroupId(helper.GenerateApplicaionGroupId()) + return nil +} + +type Application struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid"` + AppGroupId domain.AppGroupId + Endpoint string + Metadata datatypes.JSON + Type domain.ApplicationType +} + +func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go new file mode 100644 index 00000000..4b6e779e --- /dev/null +++ b/internal/model/app-serve-app.go @@ -0,0 +1,67 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +type AppServeApp struct { + ID string `gorm:"primarykey" json:"id,omitempty"` + Name string `gorm:"index" json:"name,omitempty"` // application name + Namespace string `json:"namespace,omitempty"` // application namespace + OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to + Type string `json:"type,omitempty"` // type (build/deploy/all) + AppType string `json:"appType,omitempty"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed + TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name + Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` + AppServeAppTasks []AppServeAppTask `gorm:"foreignKey:AppServeAppId" json:"appServeAppTasks"` +} + +type AppServeAppTask struct { + ID string `gorm:"primarykey" json:"id,omitempty"` + AppServeAppId string `gorm:"not null" json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to + Version string `json:"version,omitempty"` // application version + Status string `json:"status,omitempty"` // status is app status + Output string `json:"output,omitempty"` // output for task result + ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) + ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app + ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image + Profile string `json:"profile,omitempty"` // java app profile + AppConfig string `json:"appConfig,omitempty"` // java app config + AppSecret string `json:"appSecret,omitempty"` // java app secret + ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app + Port string `json:"port,omitempty"` // java app port + ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod + HelmRevision int32 `gorm:"default:0" json:"helmRevision,omitempty"` // revision of deployed helm release + Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) + RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version + PvEnabled bool `json:"pvEnabled"` + PvStorageClass string `json:"pvStorageClass"` + PvAccessMode string `json:"pvAccessMode"` + PvSize string `json:"pvSize"` + PvMountPath string `json:"pvMountPath"` + AvailableRollback bool `gorm:"-:all" json:"availableRollback"` + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` // createdAt is a creation timestamp for the application + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` +} + +func (a *AppServeApp) BeforeCreate(tx *gorm.DB) (err error) { + a.ID = uuid.New().String() + return nil +} + +func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} diff --git a/internal/model/audit.go b/internal/model/audit.go new file mode 100644 index 00000000..bfa853c1 --- /dev/null +++ b/internal/model/audit.go @@ -0,0 +1,26 @@ +package model + +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) + +// Models +type Audit struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Group string + Message string + Description string + ClientIP string + UserId *uuid.UUID `gorm:"type:uuid"` + User User `gorm:"foreignKey:UserId"` +} + +func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/cloud-account.go b/internal/model/cloud-account.go new file mode 100644 index 00000000..33d3a14b --- /dev/null +++ b/internal/model/cloud-account.go @@ -0,0 +1,38 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +// Models +type CloudAccount struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Name string `gorm:"index"` + Description string `gorm:"index"` + Resource string + CloudService string + WorkflowId string + Status domain.CloudAccountStatus + StatusDesc string + AwsAccountId string + AccessKeyId string `gorm:"-:all"` + SecretAccessKey string `gorm:"-:all"` + SessionToken string `gorm:"-:all"` + Clusters int `gorm:"-:all"` + CreatedIAM bool + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/cluster.go b/internal/model/cluster.go new file mode 100644 index 00000000..8ca4b764 --- /dev/null +++ b/internal/model/cluster.go @@ -0,0 +1,84 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +// Models +type Cluster struct { + gorm.Model + + ID domain.ClusterId `gorm:"primarykey"` + Name string `gorm:"index"` + CloudService string `gorm:"default:AWS"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Description string `gorm:"index"` + WorkflowId string + Status domain.ClusterStatus + StatusDesc string + CloudAccountId *uuid.UUID + CloudAccount CloudAccount `gorm:"foreignKey:CloudAccountId"` + StackTemplateId uuid.UUID + StackTemplate StackTemplate `gorm:"foreignKey:StackTemplateId"` + Favorites *[]ClusterFavorite + ClusterType domain.ClusterType `gorm:"default:0"` + ByoClusterEndpointHost string + ByoClusterEndpointPort int + IsStack bool `gorm:"default:false"` + TksCpNode int + TksCpNodeMax int + TksCpNodeType string + TksInfraNode int + TksInfraNodeMax int + TksInfraNodeType string + TksUserNode int + TksUserNodeMax int + TksUserNodeType string + Kubeconfig []byte `gorm:"-:all"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (m *Cluster) SetDefaultConf() { + m.TksCpNodeMax = m.TksCpNode + + if m.TksInfraNode == 0 { + m.TksInfraNode = 3 + } + m.TksInfraNodeMax = m.TksInfraNode + + if m.TksUserNode == 0 { + m.TksUserNode = 1 + } + m.TksUserNodeMax = m.TksUserNode + + if m.TksCpNodeType == "" { + m.TksCpNodeType = "t3.xlarge" + } + if m.TksInfraNodeType == "" { + m.TksInfraNodeType = "t3.2xlarge" + } + if m.TksUserNodeType == "" { + m.TksUserNodeType = "t3.large" + } +} + +type ClusterFavorite struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid"` + ClusterId domain.ClusterId + Cluster Cluster `gorm:"foreignKey:ClusterId"` + UserId uuid.UUID `gorm:"type:uuid"` + User User `gorm:"foreignKey:UserId"` +} + +func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/dashboard.go b/internal/model/dashboard.go new file mode 100644 index 00000000..3cb73ce4 --- /dev/null +++ b/internal/model/dashboard.go @@ -0,0 +1,4 @@ +package model + +// Dashboard 는 DB repository 접근이 없이 외부 데이터만을 참조하므로, 일단 pkg/domain 의 model 을 사용하도록 해둡니다. +// 즉, usecase 에서 직접 pkg/domain 을 참조하도록 해 두었습니다. diff --git a/internal/model/end-point.go b/internal/model/end-point.go new file mode 100644 index 00000000..912fa0ce --- /dev/null +++ b/internal/model/end-point.go @@ -0,0 +1,11 @@ +package model + +import ( + "time" +) + +type Endpoint struct { + Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` + Group string `gorm:"type:text;" json:"group"` + CreatedAt time.Time +} diff --git a/internal/model/organization.go b/internal/model/organization.go new file mode 100644 index 00000000..74264c16 --- /dev/null +++ b/internal/model/organization.go @@ -0,0 +1,21 @@ +package model + +import ( + "gorm.io/gorm" + + "github.com/openinfradev/tks-api/pkg/domain" +) + +type Organization struct { + gorm.Model + + ID string `gorm:"primarykey;type:varchar(36);not null"` + Name string + Description string + Phone string + PrimaryClusterId string + WorkflowId string + Status domain.OrganizationStatus + StatusDesc string + Creator string +} diff --git a/internal/model/permission.go b/internal/model/permission.go new file mode 100644 index 00000000..b83824af --- /dev/null +++ b/internal/model/permission.go @@ -0,0 +1,615 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/helper" + "gorm.io/gorm" +) + +type PermissionKind string + +const ( + DashBoardPermission PermissionKind = "대시보드" + StackPermission PermissionKind = "스택 관리" + SecurityPolicyPermission PermissionKind = "보안/정책 관리" + ProjectManagementPermission PermissionKind = "프로젝트 관리" + NotificationPermission PermissionKind = "알림" + ConfigurationPermission PermissionKind = "설정" +) + +type Permission struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` + Name string `json:"name"` + + IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` + RoleID *string `json:"role_id,omitempty"` + Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` + Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` + // omit empty + + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` + Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` +} + +func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { + if p.ID == uuid.Nil { + p.ID = uuid.New() + } + return nil +} + +type PermissionSet struct { + Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` + Stack *Permission `gorm:"-:all" json:"stack,omitempty"` + SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` + ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` + Notification *Permission `gorm:"-:all" json:"notification,omitempty"` + Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` +} + +func NewDefaultPermissionSet() *PermissionSet { + return &PermissionSet{ + Dashboard: newDashboard(), + Stack: newStack(), + SecurityPolicy: newSecurityPolicy(), + ProjectManagement: newProjectManagement(), + Notification: newNotification(), + Configuration: newConfiguration(), + } +} + +func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { + if root.Children == nil { + return append(edgePermissions, root) + } + + for _, child := range root.Children { + if f != nil && !(*f)(*child) { + continue + } + edgePermissions = GetEdgePermission(child, edgePermissions, f) + } + + return edgePermissions +} + +func SetRoleIDToPermission(roleID string, permission *Permission) { + permission.RoleID = helper.StringP(roleID) +} + +func endpointObjects(eps ...api.Endpoint) []*Endpoint { + var result []*Endpoint + for _, ep := range eps { + result = append(result, &Endpoint{ + Name: api.ApiMap[ep].Name, + Group: api.ApiMap[ep].Group, + }) + } + return result +} + +func newDashboard() *Permission { + dashboard := &Permission{ + Name: string(DashBoardPermission), + Children: []*Permission{ + { + Name: "대시보드", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetChartsDashboard, + api.GetChartDashboard, + api.GetStacksDashboard, + api.GetResourcesDashboard, + ), + }, + }, + }, + { + Name: "대시보드 설정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return dashboard +} + +func newStack() *Permission { + stack := &Permission{ + Name: string(StackPermission), + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetStacks, + api.GetStack, + api.CheckStackName, + api.GetStackStatus, + api.GetStackKubeConfig, + + api.SetFavoriteStack, + api.DeleteFavoriteStack, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateStack, + api.InstallStack, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateStack, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteStack, + ), + }, + }, + } + + return stack +} + +func newSecurityPolicy() *Permission { + security_policy := &Permission{ + Name: string(SecurityPolicyPermission), + Children: []*Permission{ + { + Name: "보안/정책", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return security_policy +} + +func newProjectManagement() *Permission { + projectManagement := &Permission{ + Name: string(ProjectManagementPermission), + Children: []*Permission{ + { + Name: "프로젝트", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProject, + ), + }, + }, + }, + { + Name: "앱 서빙", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetAppServeApps, + api.GetAppServeApp, + api.GetNumOfAppsOnStack, + api.GetAppServeAppLatestTask, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + ), + }, + { + Name: "빌드", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + Name: "배포", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteAppServeApp, + ), + }, + }, + }, + { + Name: "설정-일반", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + + api.GetProjectRoles, + api.GetProjectRole, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProject, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProject, + ), + }, + }, + }, + { + Name: "설정-멤버", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectMembers, + api.GetProjectMember, + api.GetProjectRoles, + api.GetProjectRole, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.AddProjectMember, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProjectMemberRole, + ), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.RemoveProjectMember, + ), + }, + }, + }, + { + Name: "설정-네임스페이스", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectNamespaces, + api.GetProjectNamespace, + ), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProjectNamespace, + ), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects(), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProjectNamespace, + ), + }, + }, + }, + }, + } + + return projectManagement +} + +func newNotification() *Permission { + notification := &Permission{ + Name: string(NotificationPermission), + Children: []*Permission{ + { + Name: "시스템 경고", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "보안/정책 감사로그", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return notification +} + +func newConfiguration() *Permission { + configuration := &Permission{ + Name: string(ConfigurationPermission), + Children: []*Permission{ + { + Name: "일반", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "클라우드 계정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "스택 템플릿", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "프로젝트 관리", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "사용자 권한 관리", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + { + Name: "알림 설정", + Children: []*Permission{ + { + Name: "조회", + IsAllowed: helper.BoolP(false), + }, + { + Name: "생성", + IsAllowed: helper.BoolP(false), + }, + { + Name: "수정", + IsAllowed: helper.BoolP(false), + }, + { + Name: "삭제", + IsAllowed: helper.BoolP(false), + }, + }, + }, + }, + } + + return configuration +} + +func (p *PermissionSet) SetAllowedPermissionSet() { + edgePermissions := make([]*Permission, 0) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) + + for _, permission := range edgePermissions { + permission.IsAllowed = helper.BoolP(true) + } + + return +} + +func (p *PermissionSet) SetUserPermissionSet() { + f := func(permission Permission) bool { + return permission.Name == "조회" + } + edgePermissions := make([]*Permission, 0) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) + //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) + + for _, permission := range edgePermissions { + permission.IsAllowed = helper.BoolP(true) + } + + return +} + +func (p *PermissionSet) SetRoleId(roleId string) { + setRoleIdToPermission(p.Dashboard, roleId) + setRoleIdToPermission(p.Stack, roleId) + setRoleIdToPermission(p.SecurityPolicy, roleId) + setRoleIdToPermission(p.ProjectManagement, roleId) + setRoleIdToPermission(p.Notification, roleId) + setRoleIdToPermission(p.Configuration, roleId) +} + +func setRoleIdToPermission(root *Permission, roleId string) { + root.RoleID = helper.StringP(roleId) + + if root.Children == nil { + return + } + + for _, child := range root.Children { + setRoleIdToPermission(child, roleId) + } +} diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go new file mode 100644 index 00000000..430c4b7d --- /dev/null +++ b/internal/model/policy-template.go @@ -0,0 +1,48 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +type PolicyTemplateSupportedVersion struct { + gorm.Model + + PolicyTemplateId uuid.UUID `gorm:"index:template_version,unique"` + Version string `gorm:"index:template_version,unique"` + + ParameterSchema string `gorm:"type:text"` + Rego string `gorm:"type:text"` + Libs string `gorm:"type:text"` +} + +type PolicyTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` + Type string // Org or Tks + Name string + Version string + SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` + Description string + Kind string + Deprecated bool + Mandatory bool // Tks 인 경우에는 무시 + Severity string + PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organiations;"` + TemplateName string `gorm:"-:all" json:"templateName"` + ParametersSchema []domain.ParameterDef `gorm:"-:all" json:"parametersSchema,omitempty"` + Rego string `gorm:"-:all"` + Libs []string `gorm:"-:all"` + PermittedOrganizationIds []string `gorm:"-:all"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/model/role.go b/internal/model/role.go new file mode 100644 index 00000000..01f6497a --- /dev/null +++ b/internal/model/role.go @@ -0,0 +1,27 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { + r.ID = uuid.New().String() + return nil +} + +type Role struct { + gorm.Model + + ID string `gorm:"primarykey;" json:"id"` + Name string `json:"name"` + OrganizationID string `json:"organizationId"` + Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;" json:"organization"` + Type string `json:"type"` + Description string `json:"description"` + Creator uuid.UUID `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} diff --git a/internal/model/stack-template.go b/internal/model/stack-template.go new file mode 100644 index 00000000..c74cad06 --- /dev/null +++ b/internal/model/stack-template.go @@ -0,0 +1,40 @@ +package model + +import ( + "github.com/google/uuid" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +type StackTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index"` + Description string `gorm:"index"` + Template string + TemplateType string + Version string + CloudService string + Platform string + KubeVersion string + KubeType string + Organizations []Organization `gorm:"many2many:stack_template_organizations"` + Services datatypes.JSON + ServiceIds []string `gorm:"-:all"` + OrganizationIds []string `gorm:"-:all"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + +type StackTemplateOrganization struct { + StackTemplateId uuid.UUID `gorm:"primarykey"` + OrganizationId string `gorm:"primarykey"` +} diff --git a/internal/model/stack.go b/internal/model/stack.go new file mode 100644 index 00000000..72300ee5 --- /dev/null +++ b/internal/model/stack.go @@ -0,0 +1,45 @@ +package model + +import ( + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +type Stack = struct { + gorm.Model + + ID domain.StackId + Name string + Description string + ClusterId string + OrganizationId string + CloudService string + CloudAccountId uuid.UUID + CloudAccount CloudAccount + StackTemplateId uuid.UUID + StackTemplate StackTemplate + Status domain.StackStatus + StatusDesc string + PrimaryCluster bool + GrafanaUrl string + CreatorId *uuid.UUID + Creator User + UpdatorId *uuid.UUID + Updator User + Favorited bool + ClusterEndpoint string + Resource domain.DashboardStack +} + +type StackConf struct { + TksCpNode int + TksCpNodeMax int + TksCpNodeType string + TksInfraNode int + TksInfraNodeMax int + TksInfraNodeType string + TksUserNode int + TksUserNodeMax int + TksUserNodeType string +} diff --git a/internal/model/user.go b/internal/model/user.go new file mode 100644 index 00000000..96303110 --- /dev/null +++ b/internal/model/user.go @@ -0,0 +1,34 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +type User struct { + ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` + AccountId string `json:"accountId"` + Password string `gorm:"-:all" json:"password"` + Name string `json:"name"` + Token string `json:"token"` + RoleId string + Role Role `gorm:"foreignKey:RoleId;references:ID" json:"role"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` + PasswordExpired bool `json:"passwordExpired"` + + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` +} + +func (g *User) BeforeCreate(tx *gorm.DB) (err error) { + g.PasswordUpdatedAt = time.Now() + return nil +} diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 0de16f10..591a498c 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -9,6 +9,8 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" + "golang.org/x/text/cases" + "golang.org/x/text/language" "gorm.io/gorm" "goyave.dev/goyave/v4" @@ -84,6 +86,10 @@ func (p *Pagination) GetFilters() []Filter { return p.Filters } +func (p *Pagination) AddFilter(f Filter) { + p.Filters = append(p.Filters, f) +} + func (p *Pagination) MakePaginationRequest() { if p.PaginationRequest == nil { p.PaginationRequest = &goyave.Request{} @@ -114,9 +120,11 @@ func (p *Pagination) MakePaginationRequest() { } pgSorts = append(pgSorts, &pgSort) + pgJoins := filter.Join{} + p.PaginationRequest.Data = map[string]interface{}{ - "filter": pgFilters, - //"join": pgJoins, + "filter": pgFilters, + "join": pgJoins, "page": p.Page, "per_page": p.Limit, "sort": pgSorts, @@ -212,7 +220,7 @@ func NewPagination(urlParams *url.Values) *Pagination { releation := "" arrColumns := strings.Split(column, ".") if len(arrColumns) > 1 { - releation = arrColumns[0] + releation = cases.Title(language.English, cases.Compact).String(arrColumns[0]) column = arrColumns[1] } diff --git a/internal/repository/alert.go b/internal/repository/alert.go index 4e8c8575..2d35f536 100644 --- a/internal/repository/alert.go +++ b/internal/repository/alert.go @@ -4,27 +4,25 @@ import ( "time" "github.com/google/uuid" - "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAlertRepository interface { - Get(alertId uuid.UUID) (domain.Alert, error) - GetByName(organizationId string, name string) (domain.Alert, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]domain.Alert, error) - FetchPodRestart(organizationId string, start time.Time, end time.Time) ([]domain.Alert, error) - Create(dto domain.Alert) (alertId uuid.UUID, err error) - Update(dto domain.Alert) (err error) - Delete(dto domain.Alert) (err error) - - CreateAlertAction(dto domain.AlertAction) (alertActionId uuid.UUID, err error) + Get(alertId uuid.UUID) (model.Alert, error) + GetByName(organizationId string, name string) (model.Alert, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]model.Alert, error) + FetchPodRestart(organizationId string, start time.Time, end time.Time) ([]model.Alert, error) + Create(dto model.Alert) (alertId uuid.UUID, err error) + Update(dto model.Alert) (err error) + Delete(dto model.Alert) (err error) + + CreateAlertAction(dto model.AlertAction) (alertActionId uuid.UUID, err error) } type AlertRepository struct { @@ -37,114 +35,55 @@ func NewAlertRepository(db *gorm.DB) IAlertRepository { } } -// Models -type Alert struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Name string - Code string - Description string - Grade string - Message string - ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - Node string - CheckPoint string - GrafanaUrl string - Summary string - AlertActions []AlertAction - RawData datatypes.JSON - Status domain.AlertActionStatus `gorm:"index"` -} - -func (c *Alert) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - -type AlertAction struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - AlertId uuid.UUID - Content string - Status domain.AlertActionStatus - TakerId *uuid.UUID `gorm:"type:uuid"` - Taker domain.User `gorm:"foreignKey:TakerId"` -} - -func (c *AlertAction) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *AlertRepository) Get(alertId uuid.UUID) (out domain.Alert, err error) { - var alert Alert - res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&alert, "id = ?", alertId) +func (r *AlertRepository) Get(alertId uuid.UUID) (out model.Alert, err error) { + res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "id = ?", alertId) if res.Error != nil { - return domain.Alert{}, res.Error + return model.Alert{}, res.Error } - out = reflectAlert(alert) return } -func (r *AlertRepository) GetByName(organizationId string, name string) (out domain.Alert, err error) { - var alert Alert - res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&alert, "organization_id = ? AND name = ?", organizationId, name) - +func (r *AlertRepository) GetByName(organizationId string, name string) (out model.Alert, err error) { + res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { - return domain.Alert{}, res.Error + return model.Alert{}, res.Error } - out = reflectAlert(alert) return } -func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.Alert, err error) { - var alerts []Alert +func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.Alert, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&Alert{}). + _, res := pg.Fetch(r.db.Model(&model.Alert{}). Preload("AlertActions", func(db *gorm.DB) *gorm.DB { return db.Order("created_at ASC") }).Preload("AlertActions.Taker"). Preload("Cluster", "status = 2"). Preload("Organization"). Joins("join clusters on clusters.id = alerts.cluster_id AND clusters.status = 2"). - Where("alerts.organization_id = ?", organizationId), &alerts) + Where("alerts.organization_id = ?", organizationId), &out) if res.Error != nil { return nil, res.Error } - - for _, alert := range alerts { - out = append(out, reflectAlert(alert)) - } return } -func (r *AlertRepository) FetchPodRestart(organizationId string, start time.Time, end time.Time) (out []domain.Alert, err error) { - var alerts []Alert +func (r *AlertRepository) FetchPodRestart(organizationId string, start time.Time, end time.Time) (out []model.Alert, err error) { res := r.db.Preload(clause.Associations).Order("created_at DESC"). Where("organization_id = ? AND name = 'pod-restart-frequently' AND created_at BETWEEN ? AND ?", organizationId, start, end). - Find(&alerts) + Find(&out) if res.Error != nil { return nil, res.Error } - - for _, alert := range alerts { - out = append(out, reflectAlert(alert)) - } return } -func (r *AlertRepository) Create(dto domain.Alert) (alertId uuid.UUID, err error) { - alert := Alert{ +func (r *AlertRepository) Create(dto model.Alert) (alertId uuid.UUID, err error) { + alert := model.Alert{ OrganizationId: dto.OrganizationId, Name: dto.Name, Code: dto.Code, @@ -166,8 +105,8 @@ func (r *AlertRepository) Create(dto domain.Alert) (alertId uuid.UUID, err error return alert.ID, nil } -func (r *AlertRepository) Update(dto domain.Alert) (err error) { - res := r.db.Model(&Alert{}). +func (r *AlertRepository) Update(dto model.Alert) (err error) { + res := r.db.Model(&model.Alert{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description}) if res.Error != nil { @@ -176,16 +115,16 @@ func (r *AlertRepository) Update(dto domain.Alert) (err error) { return nil } -func (r *AlertRepository) Delete(dto domain.Alert) (err error) { - res := r.db.Delete(&Alert{}, "id = ?", dto.ID) +func (r *AlertRepository) Delete(dto model.Alert) (err error) { + res := r.db.Delete(&model.Alert{}, "id = ?", dto.ID) if res.Error != nil { return res.Error } return nil } -func (r *AlertRepository) CreateAlertAction(dto domain.AlertAction) (alertActionId uuid.UUID, err error) { - alert := AlertAction{ +func (r *AlertRepository) CreateAlertAction(dto model.AlertAction) (alertActionId uuid.UUID, err error) { + alert := model.AlertAction{ AlertId: dto.AlertId, Content: dto.Content, Status: dto.Status, @@ -195,7 +134,7 @@ func (r *AlertRepository) CreateAlertAction(dto domain.AlertAction) (alertAction if res.Error != nil { return uuid.Nil, res.Error } - res = r.db.Model(&Alert{}). + res = r.db.Model(&model.Alert{}). Where("id = ?", dto.AlertId). Update("status", dto.Status) if res.Error != nil { @@ -204,25 +143,3 @@ func (r *AlertRepository) CreateAlertAction(dto domain.AlertAction) (alertAction return alert.ID, nil } - -func reflectAlert(alert Alert) (out domain.Alert) { - if err := serializer.Map(alert.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(alert, &out); err != nil { - log.Error(err) - } - - out.AlertActions = make([]domain.AlertAction, len(alert.AlertActions)) - for i, alertAction := range alert.AlertActions { - if err := serializer.Map(alertAction.Model, &out.AlertActions[i]); err != nil { - log.Error(err) - continue - } - if err := serializer.Map(alertAction, &out.AlertActions[i]); err != nil { - log.Error(err) - continue - } - } - return -} diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index d78aa1bc..bd824996 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -3,26 +3,24 @@ package repository import ( "fmt" - "github.com/google/uuid" "gorm.io/datatypes" "gorm.io/gorm" - "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAppGroupRepository interface { - Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (res []domain.AppGroup, err error) - Get(id domain.AppGroupId) (domain.AppGroup, error) - Create(dto domain.AppGroup) (id domain.AppGroupId, err error) - Update(dto domain.AppGroup) (err error) + Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (res []model.AppGroup, err error) + Get(id domain.AppGroupId) (model.AppGroup, error) + Create(dto model.AppGroup) (id domain.AppGroupId, err error) + Update(dto model.AppGroup) (err error) Delete(id domain.AppGroupId) error - GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (applications []domain.Application, err error) - UpsertApplication(dto domain.Application) error + GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (applications []model.Application, err error) + UpsertApplication(dto model.Application) error InitWorkflow(appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error InitWorkflowDescription(clusterId domain.ClusterId) error } @@ -37,76 +35,31 @@ func NewAppGroupRepository(db *gorm.DB) IAppGroupRepository { } } -// Models -type AppGroup struct { - gorm.Model - - ID domain.AppGroupId `gorm:"primarykey"` - AppGroupType domain.AppGroupType - ClusterId domain.ClusterId - Name string - Description string - WorkflowId string - Status domain.AppGroupStatus - StatusDesc string - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = domain.AppGroupId(helper.GenerateApplicaionGroupId()) - return nil -} - -type Application struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid"` - AppGroupId domain.AppGroupId - Endpoint string - Metadata datatypes.JSON - Type domain.ApplicationType -} - -func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (out []domain.AppGroup, err error) { - var appGroups []AppGroup +func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&AppGroup{}). - Where("cluster_id = ?", clusterId), &appGroups) + _, res := pg.Fetch(r.db.Model(&model.AppGroup{}). + Where("cluster_id = ?", clusterId), &out) if res.Error != nil { return nil, res.Error } - for _, appGroup := range appGroups { - outAppGroup := reflectAppGroup(appGroup) - out = append(out, outAppGroup) - } return out, nil } -func (r *AppGroupRepository) Get(id domain.AppGroupId) (domain.AppGroup, error) { - var appGroup AppGroup - res := r.db.First(&appGroup, "id = ?", id) +func (r *AppGroupRepository) Get(id domain.AppGroupId) (out model.AppGroup, err error) { + res := r.db.First(&out, "id = ?", id) if res.RowsAffected == 0 || res.Error != nil { - return domain.AppGroup{}, fmt.Errorf("Not found appGroup for %s", id) + return model.AppGroup{}, fmt.Errorf("Not found appGroup for %s", id) } - resAppGroup := reflectAppGroup(appGroup) - return resAppGroup, nil + return out, nil } -func (r *AppGroupRepository) Create(dto domain.AppGroup) (appGroupId domain.AppGroupId, err error) { - appGroup := AppGroup{ +func (r *AppGroupRepository) Create(dto model.AppGroup) (appGroupId domain.AppGroupId, err error) { + appGroup := model.AppGroup{ ClusterId: dto.ClusterId, AppGroupType: dto.AppGroupType, Name: dto.Name, @@ -124,8 +77,8 @@ func (r *AppGroupRepository) Create(dto domain.AppGroup) (appGroupId domain.AppG return appGroup.ID, nil } -func (r *AppGroupRepository) Update(dto domain.AppGroup) (err error) { - res := r.db.Model(&AppGroup{}). +func (r *AppGroupRepository) Update(dto model.AppGroup) (err error) { + res := r.db.Model(&model.AppGroup{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ "ClusterId": dto.ClusterId, @@ -141,35 +94,30 @@ func (r *AppGroupRepository) Update(dto domain.AppGroup) (err error) { } func (r *AppGroupRepository) Delete(id domain.AppGroupId) error { - res := r.db.Unscoped().Delete(&AppGroup{}, "id = ?", id) + res := r.db.Unscoped().Delete(&model.AppGroup{}, "id = ?", id) if res.Error != nil { return fmt.Errorf("could not delete appGroup %s", id) } return nil } -func (r *AppGroupRepository) GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) { - var applications []Application - res := r.db.Where("app_group_id = ? AND type = ?", id, applicationType).Find(&applications) +func (r *AppGroupRepository) GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { + res := r.db.Where("app_group_id = ? AND type = ?", id, applicationType).Find(&out) if res.Error != nil { return nil, res.Error } - for _, application := range applications { - outApplication := reflectApplication(application) - out = append(out, outApplication) - } return out, nil } -func (r *AppGroupRepository) UpsertApplication(dto domain.Application) error { - res := r.db.Where(Application{ +func (r *AppGroupRepository) UpsertApplication(dto model.Application) error { + res := r.db.Where(model.Application{ AppGroupId: dto.AppGroupId, - Type: dto.ApplicationType, + Type: dto.Type, }). - Assign(Application{ + Assign(model.Application{ Endpoint: dto.Endpoint, Metadata: datatypes.JSON([]byte(dto.Metadata))}). - FirstOrCreate(&Application{}) + FirstOrCreate(&model.Application{}) if res.Error != nil { return res.Error } @@ -178,7 +126,7 @@ func (r *AppGroupRepository) UpsertApplication(dto domain.Application) error { } func (r *AppGroupRepository) InitWorkflow(appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error { - res := r.db.Model(&AppGroup{}). + res := r.db.Model(&model.AppGroup{}). Where("ID = ?", appGroupId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId, "StatusDesc": ""}) @@ -190,7 +138,7 @@ func (r *AppGroupRepository) InitWorkflow(appGroupId domain.AppGroupId, workflow } func (r *AppGroupRepository) InitWorkflowDescription(clusterId domain.ClusterId) error { - res := r.db.Model(&AppGroup{}). + res := r.db.Model(&model.AppGroup{}). Where("cluster_id = ?", clusterId). Updates(map[string]interface{}{"WorkflowId": "", "StatusDesc": ""}) @@ -200,22 +148,3 @@ func (r *AppGroupRepository) InitWorkflowDescription(clusterId domain.ClusterId) return nil } - -func reflectAppGroup(appGroup AppGroup) (out domain.AppGroup) { - if err := serializer.Map(appGroup.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(appGroup, &out); err != nil { - log.Error(err) - } - return -} - -func reflectApplication(application Application) (out domain.Application) { - if err := serializer.Map(application, &out); err != nil { - log.Error(err) - } - out.Metadata = application.Metadata.String() - return - -} diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 479f4e77..a1d3e291 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" @@ -11,19 +12,19 @@ import ( ) type IAppServeAppRepository interface { - CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) - GetAppServeAppById(appId string) (*domain.AppServeApp, error) + CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) + GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) + GetAppServeAppById(appId string) (*model.AppServeApp, error) - GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) - GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) + GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) + GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) - GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) + GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) IsAppServeAppExist(appId string) (int64, error) IsAppServeAppNameExist(orgId string, appName string) (int64, error) - CreateTask(task *domain.AppServeAppTask) (taskId string, err error) + CreateTask(task *model.AppServeAppTask) (taskId string, err error) UpdateStatus(appId string, taskId string, status string, output string) error UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error GetTaskCountById(appId string) (int64, error) @@ -39,7 +40,7 @@ func NewAppServeAppRepository(db *gorm.DB) IAppServeAppRepository { } } -func (r *AppServeAppRepository) CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) { +func (r *AppServeAppRepository) CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) { res := r.db.Create(&app) if res.Error != nil { @@ -51,7 +52,7 @@ func (r *AppServeAppRepository) CreateAppServeApp(app *domain.AppServeApp) (appI // Update creates new appServeApp task for existing appServeApp. func (r *AppServeAppRepository) CreateTask( - task *domain.AppServeAppTask) (string, error) { + task *model.AppServeAppTask) (string, error) { res := r.db.Create(task) if res.Error != nil { return "", res.Error @@ -60,14 +61,14 @@ func (r *AppServeAppRepository) CreateTask( return task.ID, nil } -func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) (apps []domain.AppServeApp, err error) { - var clusters []Cluster +func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) (apps []model.AppServeApp, err error) { + var clusters []model.Cluster if pg == nil { pg = pagination.NewPagination(nil) } // TODO: should return different records based on showAll param - _, res := pg.Fetch(r.db.Model(&domain.AppServeApp{}). + _, res := pg.Fetch(r.db.Model(&model.AppServeApp{}). Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId), &apps) if res.Error != nil { return nil, fmt.Errorf("error while finding appServeApps with organizationId: %s", organizationId) @@ -97,9 +98,9 @@ func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll b return } -func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppServeApp, error) { - var app domain.AppServeApp - var cluster Cluster +func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*model.AppServeApp, error) { + var app model.AppServeApp + var cluster model.Cluster res := r.db.Where("id = ?", appId).First(&app) if res.Error != nil { @@ -123,12 +124,12 @@ func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*domain.AppSer return &app, nil } -func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []domain.AppServeAppTask, err error) { +func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []model.AppServeAppTask, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&domain.AppServeAppTask{}). + _, res := pg.Fetch(r.db.Model(&model.AppServeAppTask{}). Where("app_serve_app_tasks.app_serve_app_id = ?", appId), &tasks) if res.Error != nil { return nil, fmt.Errorf("Error while finding tasks with appId: %s", appId) @@ -143,9 +144,9 @@ func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pag } // Return single task info along with its parent app info -func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) { - var task domain.AppServeAppTask - var app domain.AppServeApp +func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { + var task model.AppServeAppTask + var app model.AppServeApp // Retrieve task info res := r.db.Where("id = ?", taskId).First(&task) @@ -170,8 +171,8 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*domain.A return &task, &app, nil } -func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) { - var task domain.AppServeAppTask +func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) { + var task model.AppServeAppTask // TODO: Does this work?? where's app ID here? res := r.db.Order("created_at desc").First(&task) @@ -187,7 +188,7 @@ func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*domain. } func (r *AppServeAppRepository) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) { - var apps []domain.AppServeApp + var apps []model.AppServeApp queryStr := fmt.Sprintf("organization_id = '%s' AND target_cluster_id = '%s' AND status <> 'DELETE_SUCCESS'", organizationId, clusterId) res := r.db.Find(&apps, queryStr) @@ -227,7 +228,7 @@ func (r *AppServeAppRepository) IsAppServeAppNameExist(orgId string, appName str func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status string, output string) error { now := time.Now() - app := domain.AppServeApp{ + app := model.AppServeApp{ ID: appId, Status: status, UpdatedAt: &now, @@ -237,7 +238,7 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status return fmt.Errorf("UpdateStatus: nothing updated in AppServeApp with ID %s", appId) } - task := domain.AppServeAppTask{ + task := model.AppServeAppTask{ ID: taskId, Status: status, Output: output, @@ -249,16 +250,16 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status } //// Update task status - //res := r.db.Model(&domain.AppServeAppTask{}). + //res := r.db.Model(&model.AppServeAppTask{}). // Where("ID = ?", taskId). - // Updates(domain.AppServeAppTask{Status: status, Output: output}) + // Updates(model.AppServeAppTask{Status: status, Output: output}) // //if res.Error != nil || res.RowsAffected == 0 { // return fmt.Errorf("UpdateStatus: nothing updated in AppServeAppTask with ID %s", taskId) //} // //// Update status of the app. - //res = r.db.Model(&domain.AppServeApp{}). + //res = r.db.Model(&model.AppServeApp{}). // Where("ID = ?", appId). // Update("Status", status) //if res.Error != nil || res.RowsAffected == 0 { @@ -270,14 +271,14 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error { now := time.Now() - app := domain.AppServeApp{ + app := model.AppServeApp{ ID: appId, EndpointUrl: endpoint, PreviewEndpointUrl: previewEndpoint, UpdatedAt: &now, } - task := domain.AppServeAppTask{ + task := model.AppServeAppTask{ ID: taskId, HelmRevision: helmRevision, UpdatedAt: &now, @@ -316,7 +317,7 @@ func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endp func (r *AppServeAppRepository) GetTaskCountById(appId string) (int64, error) { var count int64 - if err := r.db.Model(&domain.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { + if err := r.db.Model(&model.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { return 0, fmt.Errorf("could not select count AppServeAppTask with ID: %s", appId) } return count, nil diff --git a/internal/repository/audit.go b/internal/repository/audit.go index bbee184c..f7e0c5dd 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -7,17 +7,15 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" - "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IAuditRepository interface { - Get(auditId uuid.UUID) (domain.Audit, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]domain.Audit, error) - Create(dto domain.Audit) (auditId uuid.UUID, err error) + Get(auditId uuid.UUID) (model.Audit, error) + Fetch(pg *pagination.Pagination) ([]model.Audit, error) + Create(dto model.Audit) (auditId uuid.UUID, err error) Delete(auditId uuid.UUID) (err error) } @@ -31,59 +29,30 @@ func NewAuditRepository(db *gorm.DB) IAuditRepository { } } -// Models -type Audit struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Group string - Message string - Description string - ClientIP string - UserId *uuid.UUID `gorm:"type:uuid"` - User domain.User `gorm:"foreignKey:UserId"` -} - -func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *AuditRepository) Get(auditId uuid.UUID) (out domain.Audit, err error) { - var audit Audit - res := r.db.Preload(clause.Associations).First(&audit, "id = ?", auditId) +func (r *AuditRepository) Get(auditId uuid.UUID) (out model.Audit, err error) { + res := r.db.Preload(clause.Associations).First(&out, "id = ?", auditId) if res.Error != nil { return } - out = reflectAudit(audit) return } -func (r *AuditRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.Audit, err error) { - var audits []Audit - +func (r *AuditRepository) Fetch(pg *pagination.Pagination) (out []model.Audit, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - db := r.db.Model(&Audit{}).Preload(clause.Associations).Where("organization_id = ?", organizationId) - _, res := pg.Fetch(db, &audits) + db := r.db.Model(&model.Audit{}).Preload(clause.Associations) + _, res := pg.Fetch(db, &out) if res.Error != nil { return nil, res.Error } - - for _, audit := range audits { - out = append(out, reflectAudit(audit)) - } - return } -func (r *AuditRepository) Create(dto domain.Audit) (auditId uuid.UUID, err error) { - audit := Audit{ +func (r *AuditRepository) Create(dto model.Audit) (auditId uuid.UUID, err error) { + audit := model.Audit{ OrganizationId: dto.OrganizationId, Group: dto.Group, Message: dto.Message, @@ -100,13 +69,3 @@ func (r *AuditRepository) Create(dto domain.Audit) (auditId uuid.UUID, err error func (r *AuditRepository) Delete(auditId uuid.UUID) (err error) { return fmt.Errorf("to be implemented") } - -func reflectAudit(audit Audit) (out domain.Audit) { - if err := serializer.Map(audit.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(audit, &out); err != nil { - log.Error(err) - } - return -} diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index 5d9a7de9..08f635c8 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -7,20 +7,19 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type ICloudAccountRepository interface { - Get(cloudAccountId uuid.UUID) (domain.CloudAccount, error) - GetByName(organizationId string, name string) (domain.CloudAccount, error) - GetByAwsAccountId(awsAccountId string) (domain.CloudAccount, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]domain.CloudAccount, error) - Create(dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) - Update(dto domain.CloudAccount) (err error) + Get(cloudAccountId uuid.UUID) (model.CloudAccount, error) + GetByName(organizationId string, name string) (model.CloudAccount, error) + GetByAwsAccountId(awsAccountId string) (model.CloudAccount, error) + Fetch(organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) + Create(dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) + Update(dto model.CloudAccount) (err error) Delete(cloudAccountId uuid.UUID) (err error) InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) (err error) } @@ -35,86 +34,46 @@ func NewCloudAccountRepository(db *gorm.DB) ICloudAccountRepository { } } -// Models -type CloudAccount struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Name string `gorm:"index"` - Description string `gorm:"index"` - Resource string - CloudService string - WorkflowId string - Status domain.CloudAccountStatus - StatusDesc string - AwsAccountId string - CreatedIAM bool - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *CloudAccountRepository) Get(cloudAccountId uuid.UUID) (out domain.CloudAccount, err error) { - var cloudAccount CloudAccount - res := r.db.Preload(clause.Associations).First(&cloudAccount, "id = ?", cloudAccountId) +func (r *CloudAccountRepository) Get(cloudAccountId uuid.UUID) (out model.CloudAccount, err error) { + res := r.db.Preload(clause.Associations).First(&out, "id = ?", cloudAccountId) if res.Error != nil { - return domain.CloudAccount{}, res.Error + return model.CloudAccount{}, res.Error } - out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) GetByName(organizationId string, name string) (out domain.CloudAccount, err error) { - var cloudAccount CloudAccount - res := r.db.Preload(clause.Associations).First(&cloudAccount, "organization_id = ? AND name = ?", organizationId, name) - +func (r *CloudAccountRepository) GetByName(organizationId string, name string) (out model.CloudAccount, err error) { + res := r.db.Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { - return domain.CloudAccount{}, res.Error + return model.CloudAccount{}, res.Error } - out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) GetByAwsAccountId(awsAccountId string) (out domain.CloudAccount, err error) { - var cloudAccount CloudAccount - res := r.db.Preload(clause.Associations).First(&cloudAccount, "aws_account_id = ? AND status != ?", awsAccountId, domain.CloudAccountStatus_DELETED) - +func (r *CloudAccountRepository) GetByAwsAccountId(awsAccountId string) (out model.CloudAccount, err error) { + res := r.db.Preload(clause.Associations).First(&out, "aws_account_id = ? AND status != ?", awsAccountId, domain.CloudAccountStatus_DELETED) if res.Error != nil { - return domain.CloudAccount{}, res.Error + return model.CloudAccount{}, res.Error } - out = reflectCloudAccount(cloudAccount) return } -func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []domain.CloudAccount, err error) { - var cloudAccounts []CloudAccount +func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.CloudAccount, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&CloudAccount{}). + _, res := pg.Fetch(r.db.Model(&model.CloudAccount{}). Preload(clause.Associations). - Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED), &cloudAccounts) + Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED), &out) if res.Error != nil { return nil, res.Error } - - for _, cloudAccount := range cloudAccounts { - out = append(out, reflectCloudAccount(cloudAccount)) - } return } -func (r *CloudAccountRepository) Create(dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) { - cloudAccount := CloudAccount{ +func (r *CloudAccountRepository) Create(dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { + cloudAccount := model.CloudAccount{ OrganizationId: dto.OrganizationId, Name: dto.Name, Description: dto.Description, @@ -123,7 +82,7 @@ func (r *CloudAccountRepository) Create(dto domain.CloudAccount) (cloudAccountId AwsAccountId: dto.AwsAccountId, CreatedIAM: false, Status: domain.CloudAccountStatus_PENDING, - CreatorId: &dto.CreatorId} + CreatorId: dto.CreatorId} res := r.db.Create(&cloudAccount) if res.Error != nil { return uuid.Nil, res.Error @@ -131,8 +90,8 @@ func (r *CloudAccountRepository) Create(dto domain.CloudAccount) (cloudAccountId return cloudAccount.ID, nil } -func (r *CloudAccountRepository) Update(dto domain.CloudAccount) (err error) { - res := r.db.Model(&CloudAccount{}). +func (r *CloudAccountRepository) Update(dto model.CloudAccount) (err error) { + res := r.db.Model(&model.CloudAccount{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description, "Resource": dto.Resource, "UpdatorId": dto.UpdatorId}) if res.Error != nil { @@ -142,7 +101,7 @@ func (r *CloudAccountRepository) Update(dto domain.CloudAccount) (err error) { } func (r *CloudAccountRepository) Delete(cloudAccountId uuid.UUID) (err error) { - res := r.db.Delete(&CloudAccount{}, "id = ?", cloudAccountId) + res := r.db.Delete(&model.CloudAccount{}, "id = ?", cloudAccountId) if res.Error != nil { return res.Error } @@ -150,7 +109,7 @@ func (r *CloudAccountRepository) Delete(cloudAccountId uuid.UUID) (err error) { } func (r *CloudAccountRepository) InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) error { - res := r.db.Model(&CloudAccount{}). + res := r.db.Model(&model.CloudAccount{}). Where("ID = ?", cloudAccountId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) @@ -160,13 +119,3 @@ func (r *CloudAccountRepository) InitWorkflow(cloudAccountId uuid.UUID, workflow return nil } - -func reflectCloudAccount(cloudAccount CloudAccount) (out domain.CloudAccount) { - if err := serializer.Map(cloudAccount.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(cloudAccount, &out); err != nil { - log.Error(err) - } - return -} diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index e637c040..05d2cb00 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -8,8 +8,8 @@ import ( "gorm.io/gorm/clause" "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" ) @@ -17,13 +17,13 @@ import ( // Interfaces type IClusterRepository interface { WithTrx(*gorm.DB) IClusterRepository - Fetch(pg *pagination.Pagination) (res []domain.Cluster, err error) - FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (res []domain.Cluster, err error) - FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (res []domain.Cluster, err error) - Get(id domain.ClusterId) (domain.Cluster, error) - GetByName(organizationId string, name string) (domain.Cluster, error) - Create(dto domain.Cluster) (clusterId domain.ClusterId, err error) - Update(dto domain.Cluster) (err error) + Fetch(pg *pagination.Pagination) (res []model.Cluster, err error) + FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) + FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) + Get(id domain.ClusterId) (model.Cluster, error) + GetByName(organizationId string, name string) (model.Cluster, error) + Create(dto model.Cluster) (clusterId domain.ClusterId, err error) + Update(dto model.Cluster) (err error) Delete(id domain.ClusterId) error InitWorkflow(clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error @@ -45,58 +45,6 @@ func NewClusterRepository(db *gorm.DB) IClusterRepository { } } -// Models -type Cluster struct { - gorm.Model - - ID domain.ClusterId `gorm:"primarykey"` - Name string `gorm:"index"` - CloudService string `gorm:"default:AWS"` - OrganizationId string - Organization domain.Organization `gorm:"foreignKey:OrganizationId"` - Description string `gorm:"index"` - WorkflowId string - Status domain.ClusterStatus - StatusDesc string - CloudAccountId *uuid.UUID - CloudAccount CloudAccount `gorm:"foreignKey:CloudAccountId"` - StackTemplateId uuid.UUID - StackTemplate StackTemplate `gorm:"foreignKey:StackTemplateId"` - Favorites *[]ClusterFavorite - ClusterType domain.ClusterType `gorm:"default:0"` - ByoClusterEndpointHost string - ByoClusterEndpointPort int - IsStack bool `gorm:"default:false"` - TksCpNode int - TksCpNodeMax int - TksCpNodeType string - TksInfraNode int - TksInfraNodeMax int - TksInfraNodeType string - TksUserNode int - TksUserNodeMax int - TksUserNodeType string - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -type ClusterFavorite struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid"` - ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - UserId uuid.UUID `gorm:"type:uuid"` - User domain.User `gorm:"foreignKey:UserId"` -} - -func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { if trxHandle == nil { @@ -107,91 +55,70 @@ func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { return r } -func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []domain.Cluster, err error) { - var clusters []Cluster +func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db, &clusters) + _, res := pg.Fetch(r.db.Model(&model.Cluster{}).Preload(clause.Associations), &out) if res.Error != nil { return nil, res.Error } - for _, cluster := range clusters { - outCluster := reflectCluster(cluster) - out = append(out, outCluster) - } return } -func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { - var clusters []Cluster +func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&Cluster{}). + _, res := pg.Fetch(r.db.Model(&model.Cluster{}). Preload(clause.Associations). Joins("left outer join cluster_favorites on clusters.id = cluster_favorites.cluster_id AND cluster_favorites.user_id = ?", userId). Where("organization_id = ? AND status != ?", organizationId, domain.ClusterStatus_DELETED). - Order("cluster_favorites.cluster_id"), &clusters) - + Order("cluster_favorites.cluster_id"), &out) if res.Error != nil { return nil, res.Error } - for _, cluster := range clusters { - outCluster := reflectCluster(cluster) - out = append(out, outCluster) - } - return } -func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { - var clusters []Cluster +func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&Cluster{}).Preload("CloudAccount"). - Where("cloud_account_id = ?", cloudAccountId), &clusters) + _, res := pg.Fetch(r.db.Model(&model.Cluster{}).Preload("CloudAccount"). + Where("cloud_account_id = ?", cloudAccountId), &out) if res.Error != nil { return nil, res.Error } - for _, cluster := range clusters { - outCluster := reflectCluster(cluster) - out = append(out, outCluster) - } return } -func (r *ClusterRepository) Get(id domain.ClusterId) (out domain.Cluster, err error) { - var cluster Cluster - res := r.db.Preload(clause.Associations).First(&cluster, "id = ?", id) +func (r *ClusterRepository) Get(id domain.ClusterId) (out model.Cluster, err error) { + res := r.db.Preload(clause.Associations).First(&out, "id = ?", id) if res.Error != nil { - return domain.Cluster{}, res.Error + return model.Cluster{}, res.Error } - out = reflectCluster(cluster) return } -func (r *ClusterRepository) GetByName(organizationId string, name string) (out domain.Cluster, err error) { - var cluster Cluster - res := r.db.Preload(clause.Associations).First(&cluster, "organization_id = ? AND name = ?", organizationId, name) +func (r *ClusterRepository) GetByName(organizationId string, name string) (out model.Cluster, err error) { + res := r.db.Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { - return domain.Cluster{}, res.Error + return model.Cluster{}, res.Error } - out = reflectCluster(cluster) return } -func (r *ClusterRepository) Create(dto domain.Cluster) (clusterId domain.ClusterId, err error) { +func (r *ClusterRepository) Create(dto model.Cluster) (clusterId domain.ClusterId, err error) { var cloudAccountId *uuid.UUID - cloudAccountId = &dto.CloudAccountId - if dto.CloudService == domain.CloudService_BYOH || dto.CloudAccountId == uuid.Nil { + cloudAccountId = dto.CloudAccountId + if dto.CloudService == domain.CloudService_BYOH || *dto.CloudAccountId == uuid.Nil { cloudAccountId = nil } - cluster := Cluster{ + cluster := model.Cluster{ ID: domain.ClusterId(helper.GenerateClusterId()), OrganizationId: dto.OrganizationId, Name: dto.Name, @@ -206,15 +133,15 @@ func (r *ClusterRepository) Create(dto domain.Cluster) (clusterId domain.Cluster ByoClusterEndpointHost: dto.ByoClusterEndpointHost, ByoClusterEndpointPort: dto.ByoClusterEndpointPort, IsStack: dto.IsStack, - TksCpNode: dto.Conf.TksCpNode, - TksCpNodeMax: dto.Conf.TksCpNodeMax, - TksCpNodeType: dto.Conf.TksCpNodeType, - TksInfraNode: dto.Conf.TksInfraNode, - TksInfraNodeMax: dto.Conf.TksInfraNodeMax, - TksInfraNodeType: dto.Conf.TksInfraNodeType, - TksUserNode: dto.Conf.TksUserNode, - TksUserNodeMax: dto.Conf.TksUserNodeMax, - TksUserNodeType: dto.Conf.TksUserNodeType, + TksCpNode: dto.TksCpNode, + TksCpNodeMax: dto.TksCpNodeMax, + TksCpNodeType: dto.TksCpNodeType, + TksInfraNode: dto.TksInfraNode, + TksInfraNodeMax: dto.TksInfraNodeMax, + TksInfraNodeType: dto.TksInfraNodeType, + TksUserNode: dto.TksUserNode, + TksUserNodeMax: dto.TksUserNodeMax, + TksUserNodeType: dto.TksUserNodeType, } if dto.ID != "" { cluster.ID = dto.ID @@ -230,15 +157,15 @@ func (r *ClusterRepository) Create(dto domain.Cluster) (clusterId domain.Cluster } func (r *ClusterRepository) Delete(clusterId domain.ClusterId) error { - res := r.db.Unscoped().Delete(&Cluster{}, "id = ?", clusterId) + res := r.db.Unscoped().Delete(&model.Cluster{}, "id = ?", clusterId) if res.Error != nil { return fmt.Errorf("could not delete cluster for clusterId %s", clusterId) } return nil } -func (r *ClusterRepository) Update(dto domain.Cluster) error { - res := r.db.Model(&Cluster{}). +func (r *ClusterRepository) Update(dto model.Cluster) error { + res := r.db.Model(&model.Cluster{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description, "UpdatorId": dto.UpdatorId}) if res.Error != nil { @@ -248,7 +175,7 @@ func (r *ClusterRepository) Update(dto domain.Cluster) error { } func (r *ClusterRepository) InitWorkflow(clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error { - res := r.db.Model(&Cluster{}). + res := r.db.Model(&model.Cluster{}). Where("ID = ?", clusterId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId, "StatusDesc": ""}) @@ -260,7 +187,7 @@ func (r *ClusterRepository) InitWorkflow(clusterId domain.ClusterId, workflowId } func (r *ClusterRepository) InitWorkflowDescription(clusterId domain.ClusterId) error { - res := r.db.Model(&AppGroup{}). + res := r.db.Model(&model.AppGroup{}). Where("id = ?", clusterId). Updates(map[string]interface{}{"WorkflowId": "", "StatusDesc": ""}) @@ -272,7 +199,7 @@ func (r *ClusterRepository) InitWorkflowDescription(clusterId domain.ClusterId) } func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid.UUID) error { - var clusterFavorites []ClusterFavorite + var clusterFavorites []model.ClusterFavorite res := r.db.Where("cluster_id = ? AND user_id = ?", clusterId, userId).Find(&clusterFavorites) if res.Error != nil { log.Info(res.Error) @@ -283,7 +210,7 @@ func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid. return nil } - clusterFavorite := ClusterFavorite{ + clusterFavorite := model.ClusterFavorite{ ClusterId: clusterId, UserId: userId, } @@ -297,34 +224,10 @@ func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid. } func (r *ClusterRepository) DeleteFavorite(clusterId domain.ClusterId, userId uuid.UUID) error { - res := r.db.Unscoped().Delete(&ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) + res := r.db.Unscoped().Delete(&model.ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) if res.Error != nil { log.Error(res.Error) return fmt.Errorf("could not delete cluster favorite for clusterId %s, userId %s", clusterId, userId) } return nil } - -func reflectCluster(cluster Cluster) (out domain.Cluster) { - if err := serializer.Map(cluster.Model, &out); err != nil { - log.Error(err) - } - - if err := serializer.Map(cluster, &out); err != nil { - log.Error(err) - } - - if err := serializer.Map(cluster, &out.Conf); err != nil { - log.Error(err) - } - out.StackTemplate.Services = cluster.StackTemplate.Services - - if cluster.Favorites != nil && len(*cluster.Favorites) > 0 { - out.Favorited = true - - } else { - out.Favorited = false - } - - return -} diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go index 707d8d58..2b290779 100644 --- a/internal/repository/endpoint.go +++ b/internal/repository/endpoint.go @@ -2,16 +2,17 @@ package repository import ( "fmt" + "math" + + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" - "math" ) type IEndpointRepository interface { - Create(endpoint *domain.Endpoint) error - List(pg *pagination.Pagination) ([]*domain.Endpoint, error) - Get(id uint) (*domain.Endpoint, error) + Create(endpoint *model.Endpoint) error + List(pg *pagination.Pagination) ([]*model.Endpoint, error) + Get(id uint) (*model.Endpoint, error) } type EndpointRepository struct { @@ -24,8 +25,8 @@ func NewEndpointRepository(db *gorm.DB) *EndpointRepository { } } -func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { - obj := &domain.Endpoint{ +func (e *EndpointRepository) Create(endpoint *model.Endpoint) error { + obj := &model.Endpoint{ Name: endpoint.Name, Group: endpoint.Group, } @@ -37,14 +38,14 @@ func (e *EndpointRepository) Create(endpoint *domain.Endpoint) error { return nil } -func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint, error) { - var endpoints []*domain.Endpoint +func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*model.Endpoint, error) { + var endpoints []*model.Endpoint if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("endpoints", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(e.db.Model(&domain.Endpoint{})) + db := filterFunc(e.db.Model(&model.Endpoint{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -58,14 +59,14 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*domain.Endpoint return endpoints, nil } -func (e *EndpointRepository) Get(id uint) (*domain.Endpoint, error) { - var obj domain.Endpoint +func (e *EndpointRepository) Get(id uint) (*model.Endpoint, error) { + var obj model.Endpoint if err := e.db.Preload("Permission").First(&obj, "id = ?", id).Error; err != nil { return nil, err } - return &domain.Endpoint{ + return &model.Endpoint{ Name: obj.Name, Group: obj.Group, }, nil diff --git a/internal/repository/organization.go b/internal/repository/organization.go index a7839166..69ed3cce 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -2,8 +2,8 @@ package repository import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" @@ -11,10 +11,10 @@ import ( // Interfaces type IOrganizationRepository interface { - Create(organizationId string, name string, creator uuid.UUID, phone string, description string) (domain.Organization, error) - Fetch(pg *pagination.Pagination) (res *[]domain.Organization, err error) - Get(organizationId string) (res domain.Organization, err error) - Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) + Create(organizationId string, name string, creator uuid.UUID, phone string, description string) (model.Organization, error) + Fetch(pg *pagination.Pagination) (res *[]model.Organization, err error) + Get(organizationId string) (res model.Organization, err error) + Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error Delete(organizationId string) (err error) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error @@ -40,7 +40,7 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { // Description string // Phone string // WorkflowId string -// Status domain.OrganizationStatus +// Status model.OrganizationStatus // StatusDesc string // Creator uuid.UUID // PrimaryClusterId string // allow null @@ -52,8 +52,8 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { //} func (r *OrganizationRepository) Create(organizationId string, name string, creator uuid.UUID, phone string, - description string) (domain.Organization, error) { - organization := domain.Organization{ + description string) (model.Organization, error) { + organization := model.Organization{ ID: organizationId, Name: name, Creator: creator.String(), @@ -64,45 +64,36 @@ func (r *OrganizationRepository) Create(organizationId string, name string, crea res := r.db.Create(&organization) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Organization{}, res.Error + return model.Organization{}, res.Error } - return r.reflect(organization), nil + return organization, nil } -func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (*[]domain.Organization, error) { - var organizations []domain.Organization - var out []domain.Organization +func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (out *[]model.Organization, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db, &organizations) + _, res := pg.Fetch(r.db, &out) if res.Error != nil { return nil, res.Error } - - for _, organization := range organizations { - outOrganization := r.reflect(organization) - out = append(out, outOrganization) - } - return &out, nil + return } -func (r *OrganizationRepository) Get(id string) (domain.Organization, error) { - var organization domain.Organization - res := r.db.First(&organization, "id = ?", id) +func (r *OrganizationRepository) Get(id string) (out model.Organization, err error) { + res := r.db.First(&out, "id = ?", id) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Organization{}, res.Error + return model.Organization{}, res.Error } - return r.reflect(organization), nil + return } -func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) { - var organization domain.Organization - res := r.db.Model(&domain.Organization{}). +func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateOrganizationRequest) (out model.Organization, err error) { + res := r.db.Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "name": in.Name, @@ -112,19 +103,19 @@ func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateO if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Organization{}, res.Error + return model.Organization{}, res.Error } - res = r.db.Model(&domain.Organization{}).Where("id = ?", organizationId).Find(&organization) + res = r.db.Model(&model.Organization{}).Where("id = ?", organizationId).Find(&out) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Organization{}, res.Error + return model.Organization{}, res.Error } - return r.reflect(organization), nil + return } func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error { - res := r.db.Model(&domain.Organization{}). + res := r.db.Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "primary_cluster_id": primaryClusterId, @@ -138,7 +129,7 @@ func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, p } func (r *OrganizationRepository) Delete(organizationId string) error { - res := r.db.Delete(&domain.Organization{}, "id = ?", organizationId) + res := r.db.Delete(&model.Organization{}, "id = ?", organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -148,7 +139,7 @@ func (r *OrganizationRepository) Delete(organizationId string) error { } func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error { - res := r.db.Model(&domain.Organization{}). + res := r.db.Model(&model.Organization{}). Where("ID = ?", organizationId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) if res.Error != nil { @@ -157,15 +148,3 @@ func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId } return nil } - -func (r *OrganizationRepository) reflect(organization domain.Organization) (out domain.Organization) { - if err := serializer.Map(organization.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(organization, &out); err != nil { - log.Error(err) - } - out.Creator = organization.Creator - return - -} diff --git a/internal/repository/permission.go b/internal/repository/permission.go index db097922..ebed52e6 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -2,16 +2,16 @@ package repository import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/internal/model" "gorm.io/gorm" ) type IPermissionRepository interface { - Create(permission *domain.Permission) error - List(roleId string) ([]*domain.Permission, error) - Get(id uuid.UUID) (*domain.Permission, error) + Create(permission *model.Permission) error + List(roleId string) ([]*model.Permission, error) + Get(id uuid.UUID) (*model.Permission, error) Delete(id uuid.UUID) error - Update(permission *domain.Permission) error + Update(permission *model.Permission) error } type PermissionRepository struct { @@ -24,7 +24,7 @@ func NewPermissionRepository(db *gorm.DB) *PermissionRepository { } } -func (r PermissionRepository) Create(p *domain.Permission) error { +func (r PermissionRepository) Create(p *model.Permission) error { //var parent *Permission //var children []*Permission // @@ -49,8 +49,8 @@ func (r PermissionRepository) Create(p *domain.Permission) error { return r.db.Create(p).Error } -func (r PermissionRepository) List(roleId string) ([]*domain.Permission, error) { - var permissions []*domain.Permission +func (r PermissionRepository) List(roleId string) ([]*model.Permission, error) { + var permissions []*model.Permission err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL AND role_id = ?", roleId).Find(&permissions).Error if err != nil { @@ -60,8 +60,8 @@ func (r PermissionRepository) List(roleId string) ([]*domain.Permission, error) return permissions, nil } -func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { - permission := &domain.Permission{} +func (r PermissionRepository) Get(id uuid.UUID) (*model.Permission, error) { + permission := &model.Permission{} result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) if result.Error != nil { return nil, result.Error @@ -71,10 +71,10 @@ func (r PermissionRepository) Get(id uuid.UUID) (*domain.Permission, error) { } func (r PermissionRepository) Delete(id uuid.UUID) error { - return r.db.Delete(&domain.Permission{}, "id = ?", id).Error + return r.db.Delete(&model.Permission{}, "id = ?", id).Error } -func (r PermissionRepository) Update(p *domain.Permission) error { +func (r PermissionRepository) Update(p *model.Permission) error { // update on is_allowed - return r.db.Model(&domain.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error + return r.db.Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error } diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index bc12f8fe..7500369b 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -16,18 +17,18 @@ import ( ) type IPolicyTemplateRepository interface { - Create(dto domain.PolicyTemplate) (policyTemplateId uuid.UUID, err error) + Create(dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) Update(dto domain.UpdatePolicyTemplateUpdate) (err error) - Fetch(pg *pagination.Pagination) (out []domain.PolicyTemplate, err error) - GetByName(policyTemplateName string) (out *domain.PolicyTemplate, err error) - GetByKind(policyTemplateKind string) (out *domain.PolicyTemplate, err error) - GetByID(policyTemplateId uuid.UUID) (out *domain.PolicyTemplate, err error) + Fetch(pg *pagination.Pagination) (out []model.PolicyTemplate, err error) + GetByName(policyTemplateName string) (out *model.PolicyTemplate, err error) + GetByKind(policyTemplateKind string) (out *model.PolicyTemplate, err error) + GetByID(policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) Delete(policyTemplateId uuid.UUID) (err error) ExistByName(policyTemplateName string) (exist bool, err error) ExistByKind(policyTemplateKind string) (exist bool, err error) ExistByID(policyTemplateId uuid.UUID) (exist bool, err error) ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) - GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) + GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) } @@ -42,54 +43,18 @@ func NewPolicyTemplateRepository(db *gorm.DB) IPolicyTemplateRepository { } } -type PolicyTemplateSupportedVersion struct { - gorm.Model - - PolicyTemplateId uuid.UUID `gorm:"index:template_version,unique"` - Version string `gorm:"index:template_version,unique"` - - ParameterSchema string `gorm:"type:text"` - Rego string `gorm:"type:text"` - Libs string `gorm:"type:text"` -} - -type PolicyTemplate struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` - Type string // Org or Tks - Name string - Version string - SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` - Description string - Kind string - Deprecated bool - Mandatory bool // Tks 인 경우에는 무시 - Severity string - PermittedOrganizations []domain.Organization `gorm:"many2many:policy_template_permitted_organiations;"` - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - -func (r *PolicyTemplateRepository) Create(dto domain.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { +func (r *PolicyTemplateRepository) Create(dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { jsonByte, err := json.Marshal(dto.ParametersSchema) if err != nil { return uuid.Nil, err } - policyTemplate := PolicyTemplate{ + policyTemplate := model.PolicyTemplate{ Type: "tks", Name: dto.TemplateName, Version: "v1.0.0", - SupportedVersions: []PolicyTemplateSupportedVersion{ + SupportedVersions: []model.PolicyTemplateSupportedVersion{ { Version: "v1.0.0", ParameterSchema: string(jsonByte), @@ -111,9 +76,9 @@ func (r *PolicyTemplateRepository) Create(dto domain.PolicyTemplate) (policyTemp } if dto.PermittedOrganizationIds != nil { - permittedOrganizations := make([]domain.Organization, len(dto.PermittedOrganizationIds)) + permittedOrganizations := make([]model.Organization, len(dto.PermittedOrganizationIds)) for i, permittedOrganizationId := range dto.PermittedOrganizationIds { - permittedOrganizations[i] = domain.Organization{ID: permittedOrganizationId} + permittedOrganizations[i] = model.Organization{ID: permittedOrganizationId} } err = tx.Model(&policyTemplate).Association("PermittedOrganizations").Replace(permittedOrganizations) @@ -156,14 +121,14 @@ func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) fmt.Printf("--updateMap=%+v\n--", updateMap) - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate policyTemplate.ID = dto.ID return r.db.Transaction(func(tx *gorm.DB) error { if dto.PermittedOrganizationIds != nil { - permittedOrganizations := make([]domain.Organization, len(*dto.PermittedOrganizationIds)) + permittedOrganizations := make([]model.Organization, len(*dto.PermittedOrganizationIds)) for i, permittedOrganizationId := range *dto.PermittedOrganizationIds { - permittedOrganizations[i] = domain.Organization{ID: permittedOrganizationId} + permittedOrganizations[i] = model.Organization{ID: permittedOrganizationId} } err = r.db.Model(&policyTemplate).Limit(1). @@ -189,20 +154,20 @@ func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) }) } -func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain.PolicyTemplate, err error) { - var policyTemplates []PolicyTemplate +func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.PolicyTemplate, err error) { + var policyTemplates []model.PolicyTemplate if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations).Model(&PolicyTemplate{}). + _, res := pg.Fetch(r.db.Preload(clause.Associations).Model(&model.PolicyTemplate{}). Where("type = 'tks'"), &policyTemplates) if res.Error != nil { return nil, res.Error } for _, policyTemplate := range policyTemplates { - var policyTemplateVersion PolicyTemplateSupportedVersion + var policyTemplateVersion model.PolicyTemplateSupportedVersion res = r.db. Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). First(&policyTemplateVersion) @@ -221,7 +186,7 @@ func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []domai return out, nil } -func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTemplate, policyTemplateVersion PolicyTemplateSupportedVersion) (out domain.PolicyTemplate) { +func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.PolicyTemplate, policyTemplateVersion model.PolicyTemplateSupportedVersion) (out model.PolicyTemplate) { if err := serializer.Map(policyTemplate.Model, &out); err != nil { log.Error(err) } @@ -229,7 +194,7 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTe log.Error(err) } out.TemplateName = policyTemplate.Name - out.ID = domain.PolicyTemplateId(policyTemplate.ID.String()) + out.ID = policyTemplate.ID var schemas []domain.ParameterDef @@ -241,14 +206,20 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTe } } - out.PermittedOrganizations = make([]domain.PermittedOrganization, len(policyTemplate.PermittedOrganizations)) - for i, org := range policyTemplate.PermittedOrganizations { - out.PermittedOrganizations[i] = domain.PermittedOrganization{ - OrganizationId: org.ID, - OrganizationName: org.Name, - Permitted: true, + // ktkfree : 이 부분은 재 구현 부탁 드립니다. + // PermittedOrganizations 필드가 model 과 response 를 위한 객체의 형이 다르네요. + // 아울러 reflect 는 repository 가 아닌 usecase 에 표현되는게 더 좋겠습니다. + + /* + out.PermittedOrganizations = make([]domain.PermittedOrganization, len(policyTemplate.PermittedOrganizations)) + for i, org := range policyTemplate.PermittedOrganizations { + out.PermittedOrganizations[i] = domain.PermittedOrganization{ + OrganizationId: org.ID, + OrganizationName: org.Name, + Permitted: true, + } } - } + */ out.Rego = policyTemplateVersion.Rego out.Libs = strings.Split(policyTemplateVersion.Libs, "---\n") @@ -259,7 +230,7 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate PolicyTe func (r *PolicyTemplateRepository) ExistsBy(key string, value interface{}) (exists bool, err error) { query := fmt.Sprintf("%s = ?", key) - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate res := r.db.Where(query, value). First(&policyTemplate) @@ -288,10 +259,10 @@ func (r *PolicyTemplateRepository) ExistByID(policyTemplateId uuid.UUID) (exist return r.ExistsBy("id", policyTemplateId) } -func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *domain.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *model.PolicyTemplate, err error) { query := fmt.Sprintf("%s = ?", key) - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate res := r.db.Preload(clause.Associations).Where(query, value). First(&policyTemplate) @@ -305,7 +276,7 @@ func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *do } } - var policyTemplateVersion PolicyTemplateSupportedVersion + var policyTemplateVersion model.PolicyTemplateSupportedVersion res = r.db.Limit(1). Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). First(&policyTemplateVersion) @@ -327,7 +298,7 @@ func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *do return &result, nil } -func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *domain.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) { return r.GetBy("id", policyTemplateId) // var policyTemplate PolicyTemplate @@ -349,7 +320,7 @@ func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *dom // return &result, nil } -func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *domain.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *model.PolicyTemplate, err error) { return r.GetBy("name", policyTemplateName) // var policyTemplate PolicyTemplate @@ -371,21 +342,21 @@ func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *do // return &result, nil } -func (r *PolicyTemplateRepository) GetByKind(policyTemplateKind string) (out *domain.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetByKind(policyTemplateKind string) (out *model.PolicyTemplate, err error) { return r.GetBy("kind", policyTemplateKind) } func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error) { return r.db.Transaction(func(tx *gorm.DB) error { - if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&PolicyTemplateSupportedVersion{}).Error; err != nil { + if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&model.PolicyTemplateSupportedVersion{}).Error; err != nil { return err } - if err := tx.Model(&PolicyTemplate{ID: policyTemplateId}).Association("PermittedOrganizations").Clear(); err != nil { + if err := tx.Model(&model.PolicyTemplate{ID: policyTemplateId}).Association("PermittedOrganizations").Clear(); err != nil { return err } - if err := tx.Where("id = ?", policyTemplateId).Delete(&PolicyTemplate{}).Error; err != nil { + if err := tx.Where("id = ?", policyTemplateId).Delete(&model.PolicyTemplate{}).Error; err != nil { return err } @@ -394,7 +365,7 @@ func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error } func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { - var supportedVersions []PolicyTemplateSupportedVersion + var supportedVersions []model.PolicyTemplateSupportedVersion res := r.db.Where("policy_template_id = ?", policyTemplateId).Find(&supportedVersions) if res.Error != nil { @@ -420,8 +391,8 @@ func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId u return result, nil } -func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) { - var policyTemplateVersion PolicyTemplateSupportedVersion +func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { + var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db. Where("policy_template_id = ? and version = ?", policyTemplateId, version). First(&policyTemplateVersion) @@ -435,7 +406,7 @@ func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uui } } - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate res = r.db. Where("id = ?", policyTemplateId). First(&policyTemplate) @@ -455,7 +426,7 @@ func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uui } func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) { - var policyTemplate PolicyTemplate + var policyTemplate model.PolicyTemplate res := r.db.Select("version").First(&policyTemplate) if res.Error != nil { @@ -475,7 +446,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId // TODO: Operator에 현재 버전 사용중인 정책이 있는지 체크 필요 - var policyTemplateVersion PolicyTemplateSupportedVersion + var policyTemplateVersion model.PolicyTemplateSupportedVersion res = r.db.Where("policy_template_id = ? and version = ?", policyTemplateId, version). Delete(&policyTemplateVersion) if res.Error != nil { @@ -492,7 +463,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId } func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { - var policyTemplateVersion PolicyTemplateSupportedVersion + var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db.Limit(1). Where("policy_template_id = ? and version = ?", policyTemplateId, version). First(&policyTemplateVersion) @@ -525,7 +496,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId return "", parseErr } - newPolicyTemplateVersion := &PolicyTemplateSupportedVersion{ + newPolicyTemplateVersion := &model.PolicyTemplateSupportedVersion{ PolicyTemplateId: policyTemplateId, Version: newVersion, Rego: rego, @@ -538,7 +509,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId return err } - if err := tx.Model(&PolicyTemplate{}).Where("id = ?", policyTemplateId).Update("version", newVersion).Error; err != nil { + if err := tx.Model(&model.PolicyTemplate{}).Where("id = ?", policyTemplateId).Update("version", newVersion).Error; err != nil { return err } diff --git a/internal/repository/role.go b/internal/repository/role.go index d7bdb198..ab5c7f50 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -2,29 +2,30 @@ package repository import ( "fmt" + "math" + + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" - "math" ) type IRoleRepository interface { - Create(roleObj *domain.Role) (string, error) - List(pg *pagination.Pagination) ([]*domain.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) - Get(id string) (*domain.Role, error) - GetTksRole(id string) (*domain.Role, error) - GetTksRoleByRoleName(roleName string) (*domain.Role, error) + Create(roleObj *model.Role) (string, error) + List(pg *pagination.Pagination) ([]*model.Role, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) + Get(id string) (*model.Role, error) + GetTksRole(id string) (*model.Role, error) + GetTksRoleByRoleName(roleName string) (*model.Role, error) Delete(id string) error - Update(roleObj *domain.Role) error + Update(roleObj *model.Role) error } type RoleRepository struct { db *gorm.DB } -func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.Role, error) { - var role domain.Role +func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*model.Role, error) { + var role model.Role if err := r.db.Preload("Role").First(&role, "Role.name = ?", roleName).Error; err != nil { return nil, err } @@ -32,7 +33,7 @@ func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*domain.Role, err return &role, nil } -func (r RoleRepository) Create(roleObj *domain.Role) (string, error) { +func (r RoleRepository) Create(roleObj *model.Role) (string, error) { if roleObj == nil { return "", fmt.Errorf("roleObj is nil") } @@ -43,14 +44,14 @@ func (r RoleRepository) Create(roleObj *domain.Role) (string, error) { return roleObj.ID, nil } -func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) { - var roles []*domain.Role +func (r RoleRepository) List(pg *pagination.Pagination) ([]*model.Role, error) { + var roles []*model.Role if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.Role{})) + db := filterFunc(r.db.Model(&model.Role{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -65,14 +66,14 @@ func (r RoleRepository) List(pg *pagination.Pagination) ([]*domain.Role, error) return roles, nil } -func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) { - var roles []*domain.Role +func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { + var roles []*model.Role if pg == nil { pg = pagination.NewPagination(nil) } filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&domain.Role{})) + db := filterFunc(r.db.Model(&model.Role{})) db.Count(&pg.TotalRows) pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) @@ -91,8 +92,8 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin return roles, nil } -func (r RoleRepository) Get(id string) (*domain.Role, error) { - var role domain.Role +func (r RoleRepository) Get(id string) (*model.Role, error) { + var role model.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } @@ -100,8 +101,8 @@ func (r RoleRepository) Get(id string) (*domain.Role, error) { return &role, nil } -func (r RoleRepository) GetTksRole(id string) (*domain.Role, error) { - var role domain.Role +func (r RoleRepository) GetTksRole(id string) (*model.Role, error) { + var role model.Role if err := r.db.First(&role, "id = ?", id).Error; err != nil { return nil, err } @@ -109,12 +110,12 @@ func (r RoleRepository) GetTksRole(id string) (*domain.Role, error) { return &role, nil } -func (r RoleRepository) Update(roleObj *domain.Role) error { +func (r RoleRepository) Update(roleObj *model.Role) error { if roleObj == nil { return fmt.Errorf("roleObj is nil") } - err := r.db.Model(&domain.Role{}).Where("id = ?", roleObj.ID).Updates(domain.Role{ + err := r.db.Model(&model.Role{}).Where("id = ?", roleObj.ID).Updates(model.Role{ Name: roleObj.Name, Description: roleObj.Description, }).Error @@ -127,7 +128,7 @@ func (r RoleRepository) Update(roleObj *domain.Role) error { } func (r RoleRepository) Delete(id string) error { - if err := r.db.Delete(&domain.Role{}, "id = ?", id).Error; err != nil { + if err := r.db.Delete(&model.Role{}, "id = ?", id).Error; err != nil { return err } diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 9c55df46..103aec44 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -2,24 +2,22 @@ package repository import ( "github.com/google/uuid" - "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" - "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces type IStackTemplateRepository interface { - Get(stackTemplateId uuid.UUID) (domain.StackTemplate, error) - Fetch(pg *pagination.Pagination) ([]domain.StackTemplate, error) - Create(dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) - Update(dto domain.StackTemplate) (err error) - Delete(dto domain.StackTemplate) (err error) - UpdateOrganizations(stackTemplateId uuid.UUID, organizationIds []domain.Organization) (err error) + Get(stackTemplateId uuid.UUID) (model.StackTemplate, error) + Fetch(pg *pagination.Pagination) ([]model.StackTemplate, error) + FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) + Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) + Update(dto model.StackTemplate) (err error) + Delete(dto model.StackTemplate) (err error) + UpdateOrganizations(stackTemplateId uuid.UUID, organizationIds []model.Organization) (err error) } type StackTemplateRepository struct { @@ -32,87 +30,52 @@ func NewStackTemplateRepository(db *gorm.DB) IStackTemplateRepository { } } -// Models -type StackTemplate struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - Name string `gorm:"index"` - Description string `gorm:"index"` - Template string - TemplateType string - Version string - CloudService string - Platform string - KubeVersion string - KubeType string - Organizations []domain.Organization `gorm:"many2many:stack_template_organizations"` - Services datatypes.JSON - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator domain.User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator domain.User `gorm:"foreignKey:UpdatorId"` -} - -func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - // Logics -func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out domain.StackTemplate, err error) { - var stackTemplate StackTemplate - res := r.db.Preload(clause.Associations).First(&stackTemplate, "id = ?", stackTemplateId) +func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out model.StackTemplate, err error) { + res := r.db.Preload(clause.Associations).First(&out, "id = ?", stackTemplateId) if res.Error != nil { - return domain.StackTemplate{}, res.Error + return model.StackTemplate{}, res.Error } - out = reflectStackTemplate(stackTemplate) return } -// [TODO] organizationId 별로 생성하지 않고, 하나의 stackTemplate 을 모든 organization 에서 재사용한다. ( 5월 한정, 추후 rearchitecture 필요) -func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []domain.StackTemplate, err error) { - var stackTemplates []StackTemplate - +func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.StackTemplate, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations), &stackTemplates) + _, res := pg.Fetch(r.db.Preload(clause.Associations), &out) if res.Error != nil { return nil, res.Error } + return +} - for _, stackTemplate := range stackTemplates { - out = append(out, reflectStackTemplate(stackTemplate)) +func (r *StackTemplateRepository) FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) } + _, res := pg.Fetch( + r.db.Preload(clause.Associations). + Joins("JOIN stack_template_organizations ON stack_template_organizations.stack_template_id = stack_templates.id AND stack_template_organizations.organization_id = ?", organizationId), + &out) + if res.Error != nil { + return nil, res.Error + } return } -func (r *StackTemplateRepository) Create(dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) { - stackTemplate := StackTemplate{ - Name: dto.Name, - Description: dto.Description, - Template: dto.Template, - TemplateType: dto.TemplateType, - Version: dto.Version, - CloudService: dto.CloudService, - Platform: dto.Platform, - KubeVersion: dto.KubeVersion, - KubeType: dto.KubeType, - Services: dto.Services, - CreatorId: &dto.CreatorId, - UpdatorId: &dto.CreatorId} - res := r.db.Create(&stackTemplate) +func (r *StackTemplateRepository) Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { + res := r.db.Create(&dto) if res.Error != nil { return uuid.Nil, res.Error } - return stackTemplate.ID, nil + return dto.ID, nil } -func (r *StackTemplateRepository) Update(dto domain.StackTemplate) (err error) { - res := r.db.Model(&StackTemplate{}). +func (r *StackTemplateRepository) Update(dto model.StackTemplate) (err error) { + res := r.db.Model(&model.StackTemplate{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ "Template": dto.Template, @@ -131,16 +94,16 @@ func (r *StackTemplateRepository) Update(dto domain.StackTemplate) (err error) { return nil } -func (r *StackTemplateRepository) Delete(dto domain.StackTemplate) (err error) { - res := r.db.Delete(&StackTemplate{}, "id = ?", dto.ID) +func (r *StackTemplateRepository) Delete(dto model.StackTemplate) (err error) { + res := r.db.Delete(&model.StackTemplate{}, "id = ?", dto.ID) if res.Error != nil { return res.Error } return nil } -func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, organizations []domain.Organization) (err error) { - var stackTemplate = StackTemplate{} +func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, organizations []model.Organization) (err error) { + var stackTemplate = model.StackTemplate{} res := r.db.Preload("Organizations").First(&stackTemplate, "id = ?", stackTemplateId) if res.Error != nil { return res.Error @@ -152,15 +115,3 @@ func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, return nil } - -func reflectStackTemplate(stackTemplate StackTemplate) (out domain.StackTemplate) { - if err := serializer.Map(stackTemplate.Model, &out); err != nil { - log.Error(err) - } - if err := serializer.Map(stackTemplate, &out); err != nil { - log.Error(err) - } - - out.Services = stackTemplate.Services - return -} diff --git a/internal/repository/user.go b/internal/repository/user.go index 12ed1a50..fcfd4981 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -4,8 +4,8 @@ import ( "time" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" @@ -14,13 +14,13 @@ import ( // Interface type IUserRepository interface { CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, - department string, description string, organizationId string, roleId string) (domain.User, error) - List(filters ...FilterFunc) (out *[]domain.User, err error) - ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]domain.User, err error) - Get(accountId string, organizationId string) (domain.User, error) - GetByUuid(userId uuid.UUID) (domain.User, error) + department string, description string, organizationId string, roleId string) (model.User, error) + List(filters ...FilterFunc) (out *[]model.User, err error) + ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]model.User, err error) + Get(accountId string, organizationId string) (model.User, error) + GetByUuid(userId uuid.UUID) (model.User, error) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, email string, - department string, description string) (domain.User, error) + department string, description string) (model.User, error) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error DeleteWithUuid(uuid uuid.UUID) error Flush(organizationId string) error @@ -36,7 +36,7 @@ type UserRepository struct { } func (r *UserRepository) Flush(organizationId string) error { - res := r.db.Where("organization_id = ?", organizationId).Delete(&domain.User{}) + res := r.db.Where("organization_id = ?", organizationId).Delete(&model.User{}) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -77,9 +77,9 @@ func NewUserRepository(db *gorm.DB) IUserRepository { //} func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, - department string, description string, organizationId string, roleId string) (domain.User, error) { + department string, description string, organizationId string, roleId string) (model.User, error) { - newUser := domain.User{ + newUser := model.User{ ID: uuid, AccountId: accountId, Name: name, @@ -92,11 +92,11 @@ func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name s res := r.db.Create(&newUser) if res.Error != nil { log.Error(res.Error.Error()) - return domain.User{}, res.Error + return model.User{}, res.Error } user, err := r.getUserByAccountId(accountId, organizationId) if err != nil { - return domain.User{}, err + return model.User{}, err } return user, nil @@ -122,12 +122,12 @@ func (r *UserRepository) NameFilter(name string) FilterFunc { } } -func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { - var users []domain.User +func (r *UserRepository) List(filters ...FilterFunc) (*[]model.User, error) { + var users []model.User var res *gorm.DB if filters == nil { - res = r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Find(&users) + res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Find(&users) } else { combinedFilter := func(filters ...FilterFunc) FilterFunc { return func(user *gorm.DB) *gorm.DB { @@ -138,7 +138,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { } } cFunc := combinedFilter(filters...) - res = cFunc(r.db.Model(&domain.User{}).Preload("Organization").Preload("Role")).Find(&users) + res = cFunc(r.db.Model(&model.User{}).Preload("Organization").Preload("Role")).Find(&users) } if res.Error != nil { @@ -149,7 +149,7 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } - var out []domain.User + var out []model.User for _, user := range users { out = append(out, user) } @@ -157,20 +157,20 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]domain.User, error) { return &out, nil } -func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizationId string) (*[]domain.User, error) { - var users []domain.User +func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizationId string) (*[]model.User, error) { + var users []model.User if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&domain.User{}).Where("organization_id = ?", organizationId), &users) + _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&model.User{}).Where("organization_id = ?", organizationId), &users) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error } - var out []domain.User + var out []model.User for _, user := range users { out = append(out, user) } @@ -178,32 +178,32 @@ func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizat return &out, nil } -func (r *UserRepository) Get(accountId string, organizationId string) (domain.User, error) { +func (r *UserRepository) Get(accountId string, organizationId string) (model.User, error) { user, err := r.getUserByAccountId(accountId, organizationId) if err != nil { - return domain.User{}, err + return model.User{}, err } return user, nil } -func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser domain.User, err error) { - user := domain.User{} - res := r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) +func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser model.User, err error) { + user := model.User{} + res := r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.User{}, res.Error + return model.User{}, res.Error } if res.RowsAffected == 0 { - return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } return user, nil } func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, - email string, department string, description string) (domain.User, error) { - var user domain.User - res := r.db.Model(&domain.User{}).Where("id = ?", uuid).Updates(domain.User{ + email string, department string, description string) (model.User, error) { + var user model.User + res := r.db.Model(&model.User{}).Where("id = ?", uuid).Updates(model.User{ AccountId: accountId, Name: name, Email: email, @@ -212,26 +212,26 @@ func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name s RoleId: roleId, }) if res.RowsAffected == 0 || res.Error != nil { - return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.User{}, res.Error + return model.User{}, res.Error } - res = r.db.Model(&domain.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) + res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) if res.Error != nil { - return domain.User{}, res.Error + return model.User{}, res.Error } return user, nil } func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error { - var updateUser = domain.User{} + var updateUser = model.User{} if isTemporary { updateUser.PasswordUpdatedAt = time.Time{} } else { updateUser.PasswordUpdatedAt = time.Now() } - res := r.db.Model(&domain.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). + res := r.db.Model(&model.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). Select("password_updated_at").Updates(updateUser) if res.RowsAffected == 0 || res.Error != nil { @@ -245,7 +245,7 @@ func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId strin return nil } func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { - res := r.db.Unscoped().Delete(&domain.User{}, "id = ?", uuid) + res := r.db.Unscoped().Delete(&model.User{}, "id = ?", uuid) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -273,17 +273,17 @@ func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { // Creator uuid.UUID //} -func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { +func (r *UserRepository) GetRoleByName(roleName string) (model.Role, error) { role, err := r.getRoleByName(roleName) if err != nil { - return domain.Role{}, err + return model.Role{}, err } return role, nil } -//func (r *UserRepository) FetchRoles() (*[]domain.Role, error) { -// var roles []domain.Role +//func (r *UserRepository) FetchRoles() (*[]model.Role, error) { +// var roles []model.Role // res := r.db.Find(&roles) // // if res.Error != nil { @@ -295,7 +295,7 @@ func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { // return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") // } // -// var out []domain.Role +// var out []model.Role // for _, role := range roles { // outRole := r.reflectRole(role) // out = append(out, outRole) @@ -305,30 +305,30 @@ func (r *UserRepository) GetRoleByName(roleName string) (domain.Role, error) { //} // private members -func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (domain.User, error) { - user := domain.User{} - res := r.db.Model(&domain.User{}).Preload("Organization").Preload("Role"). +func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (model.User, error) { + user := model.User{} + res := r.db.Model(&model.User{}).Preload("Organization").Preload("Role"). Find(&user, "account_id = ? AND organization_id = ?", accountId, organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.User{}, res.Error + return model.User{}, res.Error } if res.RowsAffected == 0 { - return domain.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } return user, nil } -func (r *UserRepository) getRoleByName(roleName string) (domain.Role, error) { - role := domain.Role{} +func (r *UserRepository) getRoleByName(roleName string) (model.Role, error) { + role := model.Role{} res := r.db.First(&role, "name = ?", roleName) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) - return domain.Role{}, res.Error + return model.Role{}, res.Error } if res.RowsAffected == 0 { - return domain.Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") + return model.Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } //if res.RowsAffected == 0 { diff --git a/internal/route/route.go b/internal/route/route.go index c28e1da8..0346e233 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -181,12 +181,14 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa stackTemplateHandler := delivery.NewStackTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}/organizations", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplateOrganizations, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplateOrganizations))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.GetOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetOrganizationStackTemplate, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplate))).Methods(http.MethodGet) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) @@ -244,9 +246,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) auditHandler := delivery.NewAuditHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/admin/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/admin/audits/{auditId}", customMiddleware.Handle(internalApi.GetAudit, http.HandlerFunc(auditHandler.GetAudit))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/admin/audits/{auditId}", customMiddleware.Handle(internalApi.DeleteAudit, http.HandlerFunc(auditHandler.DeleteAudit))).Methods(http.MethodDelete) roleHandler := delivery.NewRoleHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.CreateTksRole, http.HandlerFunc(roleHandler.CreateTksRole))).Methods(http.MethodPost) diff --git a/internal/serializer/serializer.go b/internal/serializer/serializer.go index 70e96552..043a9ba4 100644 --- a/internal/serializer/serializer.go +++ b/internal/serializer/serializer.go @@ -5,7 +5,7 @@ import ( "reflect" "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/pkg/log" ) @@ -85,8 +85,14 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e } } */ - + } else { + if fieldName == "Model" { + if err := recursiveMap(srcField.Interface(), dst, converterMap); err != nil { + return err + } + } } + } return nil @@ -100,11 +106,11 @@ func Map(src interface{}, dst interface{}) error { val, _ := uuid.Parse(i.(string)) return val, nil }, - {srcType: reflect.TypeOf((*domain.Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(domain.Role).Name, nil + {srcType: reflect.TypeOf((*model.Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { + return i.(model.Role).Name, nil }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*domain.Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return domain.Role{Name: i.(string)}, nil + {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*model.Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { + return model.Role{Name: i.(string)}, nil }, }) } diff --git a/internal/usecase/alert.go b/internal/usecase/alert.go index 99fafa9c..de77595a 100644 --- a/internal/usecase/alert.go +++ b/internal/usecase/alert.go @@ -7,9 +7,9 @@ import ( "strings" "time" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" @@ -20,14 +20,14 @@ import ( ) type IAlertUsecase interface { - Get(ctx context.Context, alertId uuid.UUID) (domain.Alert, error) - GetByName(ctx context.Context, organizationId string, name string) (domain.Alert, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Alert, error) + Get(ctx context.Context, alertId uuid.UUID) (model.Alert, error) + GetByName(ctx context.Context, organizationId string, name string) (model.Alert, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Alert, error) Create(ctx context.Context, dto domain.CreateAlertRequest) (err error) - Update(ctx context.Context, dto domain.Alert) error - Delete(ctx context.Context, dto domain.Alert) error + Update(ctx context.Context, dto model.Alert) error + Delete(ctx context.Context, dto model.Alert) error - CreateAlertAction(ctx context.Context, dto domain.AlertAction) (alertActionId uuid.UUID, err error) + CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) } type AlertUsecase struct { @@ -101,7 +101,7 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque node = alert.Labels.Instance } - dto := domain.Alert{ + dto := model.Alert{ OrganizationId: organizationId, Name: alert.Labels.AlertName, Code: alert.Labels.AlertName, @@ -125,11 +125,11 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque return nil } -func (u *AlertUsecase) Update(ctx context.Context, dto domain.Alert) error { +func (u *AlertUsecase) Update(ctx context.Context, dto model.Alert) error { return nil } -func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert domain.Alert, err error) { +func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert model.Alert, err error) { alert, err = u.repo.Get(alertId) if err != nil { return alert, err @@ -139,7 +139,7 @@ func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert domain return } -func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, name string) (out domain.Alert, err error) { +func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Alert, err error) { out, err = u.repo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -150,7 +150,7 @@ func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, nam return } -func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (alerts []domain.Alert, err error) { +func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (alerts []model.Alert, err error) { alerts, err = u.repo.Fetch(organizationId, pg) if err != nil { return nil, err @@ -163,8 +163,8 @@ func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return alerts, nil } -func (u *AlertUsecase) Delete(ctx context.Context, dto domain.Alert) (err error) { - user, ok := request.UserFrom(ctx) +func (u *AlertUsecase) Delete(ctx context.Context, dto model.Alert) (err error) { + _, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") } @@ -174,8 +174,6 @@ func (u *AlertUsecase) Delete(ctx context.Context, dto domain.Alert) (err error) return httpErrors.NewNotFoundError(err, "AL_NOT_FOUND_ALERT", "") } - *dto.UpdatorId = user.GetUserId() - err = u.repo.Delete(dto) if err != nil { return err @@ -184,7 +182,7 @@ func (u *AlertUsecase) Delete(ctx context.Context, dto domain.Alert) (err error) return nil } -func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto domain.AlertAction) (alertActionId uuid.UUID, err error) { +func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -208,7 +206,7 @@ func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto domain.AlertAc return } -func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]domain.Cluster, strId string) (organizationId string, err error) { +func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]model.Cluster, strId string) (organizationId string, err error) { clusterId := domain.ClusterId(strId) if !clusterId.Validate() { return "", fmt.Errorf("Invalid clusterId %s", strId) @@ -223,9 +221,9 @@ func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]domain.Cluster, st return "", fmt.Errorf("No martched organization %s", strId) } -func (u *AlertUsecase) makeAdditionalInfo(alert *domain.Alert) { +func (u *AlertUsecase) makeAdditionalInfo(alert *model.Alert) { alert.FiredAt = &alert.CreatedAt - //alert.Status = domain.AlertActionStatus_CREATED + //alert.Status = model.AlertActionStatus_CREATED if len(alert.AlertActions) > 0 { alert.TakedAt = &alert.AlertActions[0].CreatedAt @@ -242,7 +240,7 @@ func (u *AlertUsecase) makeAdditionalInfo(alert *domain.Alert) { } } -func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster domain.Cluster, alert domain.CreateAlertRequestAlert, clusterId domain.ClusterId) (url string) { +func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, alert domain.CreateAlertRequestAlert, clusterId domain.ClusterId) (url string) { primaryGrafanaEndpoint := "" appGroups, err := u.appGroupRepo.Fetch(primaryCluster.ID, nil) if err == nil { diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index f6a2d7b4..a73c0e6b 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -17,12 +18,12 @@ import ( ) type IAppGroupUsecase interface { - Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) ([]domain.AppGroup, error) - Create(ctx context.Context, dto domain.AppGroup) (id domain.AppGroupId, err error) - Get(ctx context.Context, id domain.AppGroupId) (out domain.AppGroup, err error) + Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) ([]model.AppGroup, error) + Create(ctx context.Context, dto model.AppGroup) (id domain.AppGroupId, err error) + Get(ctx context.Context, id domain.AppGroupId) (out model.AppGroup, err error) Delete(ctx context.Context, id domain.AppGroupId) (err error) - GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) - UpdateApplication(ctx context.Context, dto domain.Application) (err error) + GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) + UpdateApplication(ctx context.Context, dto model.Application) (err error) } type AppGroupUsecase struct { @@ -41,7 +42,7 @@ func NewAppGroupUsecase(r repository.Repository, argoClient argowf.ArgoClient) I } } -func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (out []domain.AppGroup, err error) { +func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { out, err = u.repo.Fetch(clusterId, pg) if err != nil { return nil, err @@ -49,7 +50,7 @@ func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, return } -func (u *AppGroupUsecase) Create(ctx context.Context, dto domain.AppGroup) (id domain.AppGroupId, err error) { +func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id domain.AppGroupId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -158,10 +159,10 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto domain.AppGroup) (id d return dto.ID, nil } -func (u *AppGroupUsecase) Get(ctx context.Context, id domain.AppGroupId) (out domain.AppGroup, err error) { +func (u *AppGroupUsecase) Get(ctx context.Context, id domain.AppGroupId) (out model.AppGroup, err error) { appGroup, err := u.repo.Get(id) if err != nil { - return domain.AppGroup{}, err + return model.AppGroup{}, err } return appGroup, nil } @@ -255,7 +256,7 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err return nil } -func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []domain.Application, err error) { +func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { out, err = u.repo.GetApplications(id, applicationType) if err != nil { return nil, err @@ -263,7 +264,7 @@ func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGrou return } -func (u *AppGroupUsecase) UpdateApplication(ctx context.Context, dto domain.Application) (err error) { +func (u *AppGroupUsecase) UpdateApplication(ctx context.Context, dto model.Application) (err error) { err = u.repo.UpsertApplication(dto) if err != nil { return err diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index b16163f1..198b31a3 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -14,6 +14,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -23,19 +24,19 @@ import ( ) type IAppServeAppUsecase interface { - CreateAppServeApp(app *domain.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) - GetAppServeAppById(appId string) (*domain.AppServeApp, error) - GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) - GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) - GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) + CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) + GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) + GetAppServeAppById(appId string) (*model.AppServeApp, error) + GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) + GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) + GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) IsAppServeAppExist(appId string) (bool, error) IsAppServeAppNameExist(orgId string, appName string) (bool, error) IsAppServeAppNamespaceExist(clusterId string, namespace string) (bool, error) UpdateAppServeAppStatus(appId string, taskId string, status string, output string) (ret string, err error) DeleteAppServeApp(appId string) (res string, err error) - UpdateAppServeApp(app *domain.AppServeApp, appTask *domain.AppServeAppTask) (ret string, err error) + UpdateAppServeApp(app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) UpdateAppServeAppEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) (string, error) PromoteAppServeApp(appId string) (ret string, err error) AbortAppServeApp(appId string) (ret string, err error) @@ -58,7 +59,7 @@ func NewAppServeAppUsecase(r repository.Repository, argoClient argowf.ArgoClient } } -func (u *AppServeAppUsecase) CreateAppServeApp(app *domain.AppServeApp) (string, string, error) { +func (u *AppServeAppUsecase) CreateAppServeApp(app *model.AppServeApp) (string, string, error) { if app == nil { return "", "", fmt.Errorf("invalid app obj") } @@ -179,7 +180,7 @@ func (u *AppServeAppUsecase) CreateAppServeApp(app *domain.AppServeApp) (string, return appId, app.Name, nil } -func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]domain.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) { apps, err := u.repo.GetAppServeApps(organizationId, showAll, pg) if err != nil { fmt.Println(apps) @@ -188,7 +189,7 @@ func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool return apps, nil } -func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*domain.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*model.AppServeApp, error) { asa, err := u.repo.GetAppServeAppById(appId) if err != nil { return nil, err @@ -222,7 +223,7 @@ func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*domain.AppServeA return asa, nil } -func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]domain.AppServeAppTask, error) { +func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) { tasks, err := u.repo.GetAppServeAppTasksByAppId(appId, pg) if err != nil { log.Debugf("Tasks: %v", tasks) @@ -231,7 +232,7 @@ func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pa return tasks, nil } -func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*domain.AppServeAppTask, *domain.AppServeApp, error) { +func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { task, app, err := u.repo.GetAppServeAppTaskById(taskId) if err != nil { return nil, nil, err @@ -240,7 +241,7 @@ func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*domain.AppS return task, app, nil } -func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*domain.AppServeAppTask, error) { +func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) { task, err := u.repo.GetAppServeAppLatestTask(appId) if err != nil { return nil, err @@ -361,7 +362,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er * Start delete task * ********************/ - appTask := &domain.AppServeAppTask{ + appTask := &model.AppServeAppTask{ AppServeAppId: app.ID, Version: strconv.Itoa(len(app.AppServeAppTasks) + 1), ArtifactUrl: "", @@ -412,7 +413,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er "Confirm result by checking the app status after a while.", app.Name), nil } -func (u *AppServeAppUsecase) UpdateAppServeApp(app *domain.AppServeApp, appTask *domain.AppServeAppTask) (ret string, err error) { +func (u *AppServeAppUsecase) UpdateAppServeApp(app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) { if appTask == nil { return "", errors.New("invalid parameters. appTask is nil") } @@ -659,7 +660,7 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(appId string, taskId string) (r } // Find target(dest) task - var task domain.AppServeAppTask + var task model.AppServeAppTask for _, t := range app.AppServeAppTasks { if t.ID == taskId { task = t diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index 7461cf05..0e3e5165 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -5,17 +5,17 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" ) type IAuditUsecase interface { - Get(ctx context.Context, auditId uuid.UUID) (domain.Audit, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Audit, error) - Create(ctx context.Context, dto domain.Audit) (auditId uuid.UUID, err error) - Delete(ctx context.Context, dto domain.Audit) error + Get(ctx context.Context, auditId uuid.UUID) (model.Audit, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.Audit, error) + Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) + Delete(ctx context.Context, dto model.Audit) error } type AuditUsecase struct { @@ -28,7 +28,7 @@ func NewAuditUsecase(r repository.Repository) IAuditUsecase { } } -func (u *AuditUsecase) Create(ctx context.Context, dto domain.Audit) (auditId uuid.UUID, err error) { +func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { if dto.UserId == nil { user, ok := request.UserFrom(ctx) if ok { @@ -43,23 +43,23 @@ func (u *AuditUsecase) Create(ctx context.Context, dto domain.Audit) (auditId uu return auditId, nil } -func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res domain.Audit, err error) { +func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res model.Audit, err error) { res, err = u.repo.Get(auditId) if err != nil { - return domain.Audit{}, err + return model.Audit{}, err } return } -func (u *AuditUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (audits []domain.Audit, err error) { - audits, err = u.repo.Fetch(organizationId, pg) +func (u *AuditUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (audits []model.Audit, err error) { + audits, err = u.repo.Fetch(pg) if err != nil { return nil, err } return } -func (u *AuditUsecase) Delete(ctx context.Context, dto domain.Audit) (err error) { +func (u *AuditUsecase) Delete(ctx context.Context, dto model.Audit) (err error) { err = u.repo.Delete(dto.ID) if err != nil { return httpErrors.NewNotFoundError(err, "", "") diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 4fe4fd15..7213d1f2 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -24,13 +24,14 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/mail" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" ) type IAuthUsecase interface { - Login(accountId string, password string, organizationId string) (domain.User, error) + Login(accountId string, password string, organizationId string) (model.User, error) Logout(accessToken string, organizationId string) error PingToken(accessToken string, organizationId string) error FindId(code string, email string, userName string, organizationId string) (string, error) @@ -67,28 +68,28 @@ func NewAuthUsecase(r repository.Repository, kc keycloak.IKeycloak) IAuthUsecase } } -func (u *AuthUsecase) Login(accountId string, password string, organizationId string) (domain.User, error) { +func (u *AuthUsecase) Login(accountId string, password string, organizationId string) (model.User, error) { // Authentication with DB user, err := u.userRepository.Get(accountId, organizationId) if err != nil { - return domain.User{}, httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") + return model.User{}, httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") } - var accountToken *domain.User + var accountToken *model.User accountToken, err = u.kc.Login(accountId, password, organizationId) if err != nil { apiErr, ok := err.(*gocloak.APIError) if ok { if apiErr.Code == 401 { - return domain.User{}, httpErrors.NewBadRequestError(fmt.Errorf("Mismatch password"), "A_INVALID_PASSWORD", "") + return model.User{}, httpErrors.NewBadRequestError(fmt.Errorf("Mismatch password"), "A_INVALID_PASSWORD", "") } } - return domain.User{}, httpErrors.NewInternalServerError(err, "", "") + return model.User{}, httpErrors.NewInternalServerError(err, "", "") } log.Errorf("err: %v", err) if err != nil { //TODO: implement not found handling - return domain.User{}, err + return model.User{}, err } // Insert token @@ -254,7 +255,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, } func (u *AuthUsecase) VerifyIdentity(accountId string, email string, userName string, organizationId string) error { - var users *[]domain.User + var users *[]model.User var err error if accountId == "" { diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index a938066f..b6719bbb 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -15,10 +15,10 @@ import ( "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2" "github.com/aws/aws-sdk-go-v2/service/servicequotas" "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - - "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -32,14 +32,14 @@ import ( const MAX_WORKFLOW_TIME = 30 type ICloudAccountUsecase interface { - Get(ctx context.Context, cloudAccountId uuid.UUID) (domain.CloudAccount, error) - GetByName(ctx context.Context, organizationId string, name string) (domain.CloudAccount, error) - GetByAwsAccountId(ctx context.Context, awsAccountId string) (domain.CloudAccount, error) + Get(ctx context.Context, cloudAccountId uuid.UUID) (model.CloudAccount, error) + GetByName(ctx context.Context, organizationId string, name string) (model.CloudAccount, error) + GetByAwsAccountId(ctx context.Context, awsAccountId string) (model.CloudAccount, error) GetResourceQuota(ctx context.Context, cloudAccountId uuid.UUID) (available bool, out domain.ResourceQuota, err error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.CloudAccount, error) - Create(ctx context.Context, dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) - Update(ctx context.Context, dto domain.CloudAccount) error - Delete(ctx context.Context, dto domain.CloudAccount) error + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) + Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) + Update(ctx context.Context, dto model.CloudAccount) error + Delete(ctx context.Context, dto model.CloudAccount) error DeleteForce(ctx context.Context, cloudAccountId uuid.UUID) error } @@ -57,14 +57,15 @@ func NewCloudAccountUsecase(r repository.Repository, argoClient argowf.ArgoClien } } -func (u *CloudAccountUsecase) Create(ctx context.Context, dto domain.CloudAccount) (cloudAccountId uuid.UUID, err error) { +func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } + userId := user.GetUserId() dto.Resource = "TODO server result or additional information" - dto.CreatorId = user.GetUserId() + dto.CreatorId = &userId _, err = u.GetByName(ctx, dto.OrganizationId, dto.Name) if err == nil { @@ -114,14 +115,15 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto domain.CloudAccoun return cloudAccountId, nil } -func (u *CloudAccountUsecase) Update(ctx context.Context, dto domain.CloudAccount) error { +func (u *CloudAccountUsecase) Update(ctx context.Context, dto model.CloudAccount) error { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } + userId := user.GetUserId() dto.Resource = "TODO server result or additional information" - dto.UpdatorId = user.GetUserId() + dto.UpdatorId = &userId err := u.repo.Update(dto) if err != nil { return httpErrors.NewInternalServerError(err, "", "") @@ -129,10 +131,10 @@ func (u *CloudAccountUsecase) Update(ctx context.Context, dto domain.CloudAccoun return nil } -func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) (res domain.CloudAccount, err error) { +func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) (res model.CloudAccount, err error) { res, err = u.repo.Get(cloudAccountId) if err != nil { - return domain.CloudAccount{}, err + return model.CloudAccount{}, err } res.Clusters = u.getClusterCnt(cloudAccountId) @@ -140,31 +142,31 @@ func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) return } -func (u *CloudAccountUsecase) GetByName(ctx context.Context, organizationId string, name string) (res domain.CloudAccount, err error) { +func (u *CloudAccountUsecase) GetByName(ctx context.Context, organizationId string, name string) (res model.CloudAccount, err error) { res, err = u.repo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return domain.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") + return model.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") } - return domain.CloudAccount{}, err + return model.CloudAccount{}, err } res.Clusters = u.getClusterCnt(res.ID) return } -func (u *CloudAccountUsecase) GetByAwsAccountId(ctx context.Context, awsAccountId string) (res domain.CloudAccount, err error) { +func (u *CloudAccountUsecase) GetByAwsAccountId(ctx context.Context, awsAccountId string) (res model.CloudAccount, err error) { res, err = u.repo.GetByAwsAccountId(awsAccountId) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return domain.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") + return model.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") } - return domain.CloudAccount{}, err + return model.CloudAccount{}, err } res.Clusters = u.getClusterCnt(res.ID) return } -func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (cloudAccounts []domain.CloudAccount, err error) { +func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (cloudAccounts []model.CloudAccount, err error) { cloudAccounts, err = u.repo.Fetch(organizationId, pg) if err != nil { return nil, err @@ -176,17 +178,18 @@ func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, return } -func (u *CloudAccountUsecase) Delete(ctx context.Context, dto domain.CloudAccount) (err error) { +func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } + userId := user.GetUserId() cloudAccount, err := u.Get(ctx, dto.ID) if err != nil { return httpErrors.NewNotFoundError(err, "", "") } - dto.UpdatorId = user.GetUserId() + dto.UpdatorId = &userId if u.getClusterCnt(dto.ID) > 0 { return fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index f298fff7..e22233f3 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -8,13 +8,11 @@ import ( "strings" "time" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" - byoh "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" @@ -25,19 +23,21 @@ import ( gcache "github.com/patrickmn/go-cache" "github.com/pkg/errors" "github.com/spf13/viper" + byoh "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1" "gopkg.in/yaml.v3" "gorm.io/gorm" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type IClusterUsecase interface { WithTrx(*gorm.DB) IClusterUsecase - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Cluster, error) - FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) - Create(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) - Import(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) - Bootstrap(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Cluster, error) + FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) + Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) + Import(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) + Bootstrap(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) Install(ctx context.Context, clusterId domain.ClusterId) (err error) - Get(ctx context.Context, clusterId domain.ClusterId) (out domain.Cluster, err error) + Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) GetClusterSiteValues(ctx context.Context, clusterId domain.ClusterId) (out domain.ClusterSiteValuesResponse, err error) Delete(ctx context.Context, clusterId domain.ClusterId) (err error) CreateBootstrapKubeconfig(ctx context.Context, clusterId domain.ClusterId) (out domain.BootstrapKubeconfig, err error) @@ -101,7 +101,7 @@ func (u *ClusterUsecase) WithTrx(trxHandle *gorm.DB) IClusterUsecase { return u } -func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []domain.Cluster, err error) { +func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.Cluster, err error) { user, ok := request.UserFrom(ctx) if !ok { return out, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -120,7 +120,7 @@ func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *p return out, nil } -func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []domain.Cluster, err error) { +func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { if cloudAccountId == uuid.Nil { return nil, fmt.Errorf("Invalid cloudAccountId") } @@ -133,7 +133,7 @@ func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccount return out, nil } -func (u *ClusterUsecase) Create(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -153,7 +153,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto domain.Cluster) (cluste tksCloudAccountId := dto.CloudAccountId.String() isExist := false for _, ca := range cloudAccounts { - if ca.ID == dto.CloudAccountId { + if ca.ID == *dto.CloudAccountId { // FOR TEST. ADD MAGIC KEYWORD if strings.Contains(ca.Name, domain.CLOUD_ACCOUNT_INCLUSTER) { @@ -213,7 +213,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto domain.Cluster) (cluste return clusterId, nil } -func (u *ClusterUsecase) Import(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -275,7 +275,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto domain.Cluster) (cluste return clusterId, nil } -func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto domain.Cluster) (clusterId domain.ClusterId, err error) { +func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -374,10 +374,10 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId return nil } -func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (out domain.Cluster, err error) { +func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) { cluster, err := u.repo.Get(clusterId) if err != nil { - return domain.Cluster{}, err + return model.Cluster{}, err } return cluster, nil @@ -453,13 +453,13 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom out.SshKeyName = "tks-seoul" out.ClusterRegion = "ap-northeast-2" - if err := serializer.Map(cluster.Conf, &out); err != nil { + if err := serializer.Map(cluster, &out); err != nil { log.ErrorWithContext(ctx, err) } if cluster.StackTemplate.CloudService == "AWS" && cluster.StackTemplate.KubeType == "AWS" { - out.TksUserNode = cluster.Conf.TksUserNode / domain.MAX_AZ_NUM - out.TksUserNodeMax = cluster.Conf.TksUserNodeMax / domain.MAX_AZ_NUM + out.TksUserNode = cluster.TksUserNode / domain.MAX_AZ_NUM + out.TksUserNodeMax = cluster.TksUserNodeMax / domain.MAX_AZ_NUM } if err := serializer.Map(cluster, &out); err != nil { @@ -712,30 +712,30 @@ func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterI out = []domain.ClusterNode{ { Type: "TKS_CP_NODE", - Targeted: cluster.Conf.TksCpNode, + Targeted: cluster.TksCpNode, Registered: tksCpNodeRegistered, Registering: tksCpNodeRegistering, - Status: clusterNodeStatus(cluster.Conf.TksCpNode, tksCpNodeRegistered), + Status: clusterNodeStatus(cluster.TksCpNode, tksCpNodeRegistered), Command: command + "control-plane", Validity: bootstrapKubeconfig.Expiration, Hosts: tksCpHosts, }, { Type: "TKS_INFRA_NODE", - Targeted: cluster.Conf.TksInfraNode, + Targeted: cluster.TksInfraNode, Registered: tksInfraNodeRegistered, Registering: tksInfraNodeRegistering, - Status: clusterNodeStatus(cluster.Conf.TksInfraNode, tksInfraNodeRegistered), + Status: clusterNodeStatus(cluster.TksInfraNode, tksInfraNodeRegistered), Command: command + "tks", Validity: bootstrapKubeconfig.Expiration, Hosts: tksInfraHosts, }, { Type: "TKS_USER_NODE", - Targeted: cluster.Conf.TksUserNode, + Targeted: cluster.TksUserNode, Registered: tksUserNodeRegistered, Registering: tksUserNodeRegistering, - Status: clusterNodeStatus(cluster.Conf.TksUserNode, tksUserNodeRegistered), + Status: clusterNodeStatus(cluster.TksUserNode, tksUserNodeRegistered), Command: command + "worker", Validity: bootstrapKubeconfig.Expiration, Hosts: tksUserHosts, @@ -779,7 +779,7 @@ func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterI } /* -func (u *ClusterUsecase) constructClusterConf(rawConf *domain.ClusterConf) (clusterConf *domain.ClusterConf, err error) { +func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clusterConf *model.ClusterConf, err error) { region := "ap-northeast-2" if rawConf != nil && rawConf.Region != "" { region = rawConf.Region @@ -857,7 +857,7 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *domain.ClusterConf) (clus } // Construct cluster conf - tempConf := domain.ClusterConf{ + tempConf := model.ClusterConf{ SshKeyName: sshKeyName, Region: region, NumOfAz: int(numOfAz), diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 18ceda50..a4f271a8 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -153,11 +154,11 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri return out, err } - filteredClusters := funk.Filter(clusters, func(x domain.Cluster) bool { + filteredClusters := funk.Filter(clusters, func(x model.Cluster) bool { return x.Status != domain.ClusterStatus_DELETED }) if filteredClusters != nil { - out.Stack = fmt.Sprintf("%d 개", len(filteredClusters.([]domain.Cluster))) + out.Stack = fmt.Sprintf("%d 개", len(filteredClusters.([]model.Cluster))) } else { out.Stack = "0 개" } diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 832430a1..dcc7bb60 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" @@ -19,10 +20,10 @@ import ( ) type IOrganizationUsecase interface { - Create(context.Context, *domain.Organization) (organizationId string, err error) - Fetch(pg *pagination.Pagination) (*[]domain.Organization, error) - Get(organizationId string) (domain.Organization, error) - Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) + Create(context.Context, *model.Organization) (organizationId string, err error) + Fetch(pg *pagination.Pagination) (*[]model.Organization, error) + Get(organizationId string) (model.Organization, error) + Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) UpdatePrimaryClusterId(organizationId string, clusterId string) (err error) Delete(organizationId string, accessToken string) error } @@ -43,7 +44,7 @@ func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClien } } -func (u *OrganizationUsecase) Create(ctx context.Context, in *domain.Organization) (organizationId string, err error) { +func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization) (organizationId string, err error) { creator := uuid.Nil if in.Creator != "" { creator, err = uuid.Parse(in.Creator) @@ -84,17 +85,17 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *domain.Organizatio return organizationId, nil } -func (u *OrganizationUsecase) Fetch(pg *pagination.Pagination) (out *[]domain.Organization, err error) { +func (u *OrganizationUsecase) Fetch(pg *pagination.Pagination) (out *[]model.Organization, err error) { organizations, err := u.repo.Fetch(pg) if err != nil { return nil, err } return organizations, nil } -func (u *OrganizationUsecase) Get(organizationId string) (res domain.Organization, err error) { +func (u *OrganizationUsecase) Get(organizationId string) (res model.Organization, err error) { res, err = u.repo.Get(organizationId) if err != nil { - return domain.Organization{}, httpErrors.NewNotFoundError(err, "", "") + return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") } return res, nil } @@ -130,15 +131,15 @@ func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) return nil } -func (u *OrganizationUsecase) Update(organizationId string, in domain.UpdateOrganizationRequest) (domain.Organization, error) { +func (u *OrganizationUsecase) Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) { _, err := u.Get(organizationId) if err != nil { - return domain.Organization{}, httpErrors.NewNotFoundError(err, "", "") + return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") } res, err := u.repo.Update(organizationId, in) if err != nil { - return domain.Organization{}, err + return model.Organization{}, err } return res, nil diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index 4d38cca3..bcce7e95 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -2,21 +2,21 @@ package usecase import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" ) type IPermissionUsecase interface { - CreatePermissionSet(permissionSet *domain.PermissionSet) error - GetPermissionSetByRoleId(roleId string) (*domain.PermissionSet, error) - ListPermissions(roleId string) ([]*domain.Permission, error) - //GetPermission(id uuid.UUID) (*domain.Permission, error) + CreatePermissionSet(permissionSet *model.PermissionSet) error + GetPermissionSetByRoleId(roleId string) (*model.PermissionSet, error) + ListPermissions(roleId string) ([]*model.Permission, error) + //GetPermission(id uuid.UUID) (*model.Permission, error) //DeletePermission(id uuid.UUID) error - //UpdatePermission(permission *domain.Permission) error - SetRoleIdToPermissionSet(roleId string, permissionSet *domain.PermissionSet) - GetAllowedPermissionSet() *domain.PermissionSet - GetUserPermissionSet() *domain.PermissionSet - UpdatePermission(permission *domain.Permission) error + //UpdatePermission(permission *model.Permission) error + SetRoleIdToPermissionSet(roleId string, permissionSet *model.PermissionSet) + GetAllowedPermissionSet() *model.PermissionSet + GetUserPermissionSet() *model.PermissionSet + UpdatePermission(permission *model.Permission) error } type PermissionUsecase struct { @@ -29,7 +29,7 @@ func NewPermissionUsecase(repo repository.Repository) *PermissionUsecase { } } -func (p PermissionUsecase) CreatePermissionSet(permissionSet *domain.PermissionSet) error { +func (p PermissionUsecase) CreatePermissionSet(permissionSet *model.PermissionSet) error { var err error if err = p.repo.Create(permissionSet.Dashboard); err != nil { return err @@ -52,8 +52,8 @@ func (p PermissionUsecase) CreatePermissionSet(permissionSet *domain.PermissionS return nil } -func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*domain.PermissionSet, error) { - permissionSet := &domain.PermissionSet{ +func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*model.PermissionSet, error) { + permissionSet := &model.PermissionSet{ Dashboard: nil, Stack: nil, SecurityPolicy: nil, @@ -68,17 +68,17 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*domain.Perm } for _, permission := range permissionList { switch permission.Name { - case string(domain.DashBoardPermission): + case string(model.DashBoardPermission): permissionSet.Dashboard = permission - case string(domain.StackPermission): + case string(model.StackPermission): permissionSet.Stack = permission - case string(domain.SecurityPolicyPermission): + case string(model.SecurityPolicyPermission): permissionSet.SecurityPolicy = permission - case string(domain.ProjectManagementPermission): + case string(model.ProjectManagementPermission): permissionSet.ProjectManagement = permission - case string(domain.NotificationPermission): + case string(model.NotificationPermission): permissionSet.Notification = permission - case string(domain.ConfigurationPermission): + case string(model.ConfigurationPermission): permissionSet.Configuration = permission } } @@ -86,11 +86,11 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*domain.Perm return permissionSet, nil } -func (p PermissionUsecase) ListPermissions(roleId string) ([]*domain.Permission, error) { +func (p PermissionUsecase) ListPermissions(roleId string) ([]*model.Permission, error) { return p.repo.List(roleId) } -func (p PermissionUsecase) GetPermission(id uuid.UUID) (*domain.Permission, error) { +func (p PermissionUsecase) GetPermission(id uuid.UUID) (*model.Permission, error) { return p.repo.Get(id) } @@ -98,22 +98,22 @@ func (p PermissionUsecase) DeletePermission(id uuid.UUID) error { return p.repo.Delete(id) } -func (p PermissionUsecase) UpdatePermission(permission *domain.Permission) error { +func (p PermissionUsecase) UpdatePermission(permission *model.Permission) error { return p.repo.Update(permission) } -func (p PermissionUsecase) SetRoleIdToPermissionSet(roleId string, permissionSet *domain.PermissionSet) { +func (p PermissionUsecase) SetRoleIdToPermissionSet(roleId string, permissionSet *model.PermissionSet) { permissionSet.SetRoleId(roleId) } -func (p PermissionUsecase) GetAllowedPermissionSet() *domain.PermissionSet { - permissionSet := domain.NewDefaultPermissionSet() +func (p PermissionUsecase) GetAllowedPermissionSet() *model.PermissionSet { + permissionSet := model.NewDefaultPermissionSet() permissionSet.SetAllowedPermissionSet() return permissionSet } -func (p PermissionUsecase) GetUserPermissionSet() *domain.PermissionSet { - permissionSet := domain.NewDefaultPermissionSet() +func (p PermissionUsecase) GetUserPermissionSet() *model.PermissionSet { + permissionSet := model.NewDefaultPermissionSet() permissionSet.SetUserPermissionSet() return permissionSet } diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 9f1b8263..7c76a846 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -9,21 +9,23 @@ import ( "github.com/google/uuid" "github.com/open-policy-agent/opa/ast" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" ) type IPolicyTemplateUsecase interface { - Create(ctx context.Context, policyTemplate domain.PolicyTemplate) (policyTemplateId string, err error) - Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []domain.PolicyTemplate, err error) + Create(ctx context.Context, policyTemplate model.PolicyTemplate) (policyTemplateId string, err error) + Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) Update(ctx context.Context, policyTemplateId uuid.UUID, update domain.UpdatePolicyTemplateRequest) (err error) - Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *domain.PolicyTemplate, err error) + Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) IsPolicyTemplateKindExist(ctx context.Context, policyTemplateKind string) (bool, error) - GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) + GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) @@ -45,7 +47,7 @@ func NewPolicyTemplateUsecase(r repository.Repository) IPolicyTemplateUsecase { } } -func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto domain.PolicyTemplate) (policyTemplateId string, err error) { +func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId string, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") @@ -79,7 +81,7 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto domain.PolicyTem return id.String(), nil } -func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []domain.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) { policyTemplates, err = u.repo.Fetch(pg) if err != nil { @@ -99,7 +101,7 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagina } -func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *domain.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetByID(policyTemplateID) if err != nil { @@ -173,7 +175,7 @@ func (u *PolicyTemplateUsecase) IsPolicyTemplateKindExist(ctx context.Context, p return u.repo.ExistByKind(policyTemplateKind) } -func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *domain.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetPolicyTemplateVersion(policyTemplateId, version) if err != nil { @@ -190,10 +192,12 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, po return policyTemplate, nil } -func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]domain.Organization, permittedOrgIdSet map[string]string, policyTemplate *domain.PolicyTemplate) { +func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]model.Organization, permittedOrgIdSet map[string]string, policyTemplate *model.PolicyTemplate) { // 허용리스트가 비어있으면 모든 Org에 대해서 허용 permitted := len(permittedOrgIdSet) == 0 + log.Info("CHECK HERE ", permitted) + for _, organization := range *organizations { _, ok := permittedOrgIdSet[organization.ID] @@ -201,21 +205,30 @@ func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]doma if !ok { policyTemplate.PermittedOrganizations = append( policyTemplate.PermittedOrganizations, - domain.PermittedOrganization{ - OrganizationId: organization.ID, - OrganizationName: organization.Name, - Permitted: permitted, - }) + + // ktkfree : 역시 이부분 확인 부탁 드립니다. + /* + domain.PermittedOrganization{ + OrganizationId: organization.ID, + OrganizationName: organization.Name, + Permitted: permitted, + } + */ + ) } } } -func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *domain.PolicyTemplate) map[string]string { +func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *model.PolicyTemplate) map[string]string { permittedOrgIdSet := make(map[string]string) for _, permittedOrg := range policyTemplate.PermittedOrganizations { // Set 처리를 위해서 키만 사용, 값은 아무거나 - permittedOrgIdSet[permittedOrg.OrganizationId] = "1" + + // ktkfree : 이부분 확인 부탁 드립니다. + // + //permittedOrgIdSet[permittedOrg.OrganizationId] = "1" + log.Info("CHECK HERE ", permittedOrg) } return permittedOrgIdSet } diff --git a/internal/usecase/role.go b/internal/usecase/role.go index 70d51081..bc5d3734 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -1,18 +1,18 @@ package usecase import ( + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" ) type IRoleUsecase interface { - CreateTksRole(role *domain.Role) (string, error) - ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) - GetTksRole(id string) (*domain.Role, error) + CreateTksRole(role *model.Role) (string, error) + ListRoles(pg *pagination.Pagination) ([]*model.Role, error) + ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) + GetTksRole(id string) (*model.Role, error) DeleteTksRole(id string) error - UpdateTksRole(role *domain.Role) error + UpdateTksRole(role *model.Role) error } type RoleUsecase struct { @@ -25,11 +25,11 @@ func NewRoleUsecase(repo repository.Repository) *RoleUsecase { } } -func (r RoleUsecase) CreateTksRole(role *domain.Role) (string, error) { +func (r RoleUsecase) CreateTksRole(role *model.Role) (string, error) { return r.repo.Create(role) } -func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*domain.Role, error) { +func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { roles, err := r.repo.ListTksRoles(organizationId, pg) if err != nil { return nil, err @@ -38,11 +38,11 @@ func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Paginati return roles, nil } -func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*domain.Role, error) { +func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*model.Role, error) { return r.repo.List(nil) } -func (r RoleUsecase) GetTksRole(id string) (*domain.Role, error) { +func (r RoleUsecase) GetTksRole(id string) (*model.Role, error) { role, err := r.repo.GetTksRole(id) if err != nil { return nil, err @@ -55,7 +55,7 @@ func (r RoleUsecase) DeleteTksRole(id string) error { return r.repo.Delete(id) } -func (r RoleUsecase) UpdateTksRole(role *domain.Role) error { +func (r RoleUsecase) UpdateTksRole(role *model.Role) error { err := r.repo.Update(role) if err != nil { return err diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 2a258d16..4c672e7a 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -7,20 +7,21 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" ) type IStackTemplateUsecase interface { - Get(ctx context.Context, stackTemplateId uuid.UUID) (domain.StackTemplate, error) - Fetch(ctx context.Context, pg *pagination.Pagination) ([]domain.StackTemplate, error) - Create(ctx context.Context, dto domain.StackTemplate) (stackTemplate uuid.UUID, err error) - Update(ctx context.Context, dto domain.StackTemplate) error - Delete(ctx context.Context, dto domain.StackTemplate) error - UpdateOrganizations(ctx context.Context, dto domain.StackTemplate) error + Get(ctx context.Context, stackTemplateId uuid.UUID) (model.StackTemplate, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.StackTemplate, error) + FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.StackTemplate, error) + Create(ctx context.Context, dto model.StackTemplate) (stackTemplate uuid.UUID, err error) + Update(ctx context.Context, dto model.StackTemplate) error + Delete(ctx context.Context, dto model.StackTemplate) error + UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error } type StackTemplateUsecase struct { @@ -35,13 +36,14 @@ func NewStackTemplateUsecase(r repository.Repository) IStackTemplateUsecase { } } -func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTemplate) (stackTemplateId uuid.UUID, err error) { +func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - dto.CreatorId = user.GetUserId() - dto.UpdatorId = user.GetUserId() + userId := user.GetUserId() + dto.CreatorId = &userId + dto.UpdatorId = &userId pg := pagination.NewPaginationWithFilter("name", "", "$eq", []string{dto.Name}) stackTemplates, _ := u.Fetch(ctx, pg) @@ -76,7 +78,7 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto domain.StackTempl return stackTemplateId, nil } -func (u *StackTemplateUsecase) Update(ctx context.Context, dto domain.StackTemplate) error { +func (u *StackTemplateUsecase) Update(ctx context.Context, dto model.StackTemplate) error { _, err := u.repo.Get(dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") @@ -89,15 +91,15 @@ func (u *StackTemplateUsecase) Update(ctx context.Context, dto domain.StackTempl return nil } -func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res domain.StackTemplate, err error) { +func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res model.StackTemplate, err error) { res, err = u.repo.Get(stackTemplateId) if err != nil { - return domain.StackTemplate{}, err + return model.StackTemplate{}, err } return } -func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (res []domain.StackTemplate, err error) { +func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (res []model.StackTemplate, err error) { res, err = u.repo.Fetch(pg) if err != nil { return nil, err @@ -105,17 +107,25 @@ func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Paginat return res, nil } -func (u *StackTemplateUsecase) Delete(ctx context.Context, dto domain.StackTemplate) (err error) { +func (u *StackTemplateUsecase) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (res []model.StackTemplate, err error) { + res, err = u.repo.FetchWithOrganization(organizationId, pg) + if err != nil { + return nil, err + } + return res, nil +} + +func (u *StackTemplateUsecase) Delete(ctx context.Context, dto model.StackTemplate) (err error) { return nil } -func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto domain.StackTemplate) error { +func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error { _, err := u.repo.Get(dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") } - organizations := make([]domain.Organization, 0) + organizations := make([]model.Organization, 0) for _, organizationId := range dto.OrganizationIds { organization, err := u.organizationRepo.Get(organizationId) if err == nil { diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 3bb6f907..9daeea2a 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -11,6 +11,7 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" @@ -24,13 +25,13 @@ import ( ) type IStackUsecase interface { - Get(ctx context.Context, stackId domain.StackId) (domain.Stack, error) - GetByName(ctx context.Context, organizationId string, name string) (domain.Stack, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]domain.Stack, error) - Create(ctx context.Context, dto domain.Stack) (stackId domain.StackId, err error) + Get(ctx context.Context, stackId domain.StackId) (model.Stack, error) + GetByName(ctx context.Context, organizationId string, name string) (model.Stack, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Stack, error) + Create(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) Install(ctx context.Context, stackId domain.StackId) (err error) - Update(ctx context.Context, dto domain.Stack) error - Delete(ctx context.Context, dto domain.Stack) error + Update(ctx context.Context, dto model.Stack) error + Delete(ctx context.Context, dto model.Stack) error GetKubeConfig(ctx context.Context, stackId domain.StackId) (kubeConfig string, err error) GetStepStatus(ctx context.Context, stackId domain.StackId) (out []domain.StackStepStatus, stackStatus string, err error) SetFavorite(ctx context.Context, stackId domain.StackId) error @@ -61,7 +62,7 @@ func NewStackUsecase(r repository.Repository, argoClient argowf.ArgoClient, dash } } -func (u *StackUsecase) Create(ctx context.Context, dto domain.Stack) (stackId domain.StackId, err error) { +func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) { user, ok := request.UserFrom(ctx) if !ok { return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -103,7 +104,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto domain.Stack) (stackId do // Make stack nodes var stackConf domain.StackConfResponse - if err = domain.Map(dto.Conf, &stackConf); err != nil { + if err = serializer.Map(dto, &stackConf); err != nil { log.InfoWithContext(ctx, err) } if stackTemplate.CloudService == "AWS" && stackTemplate.KubeType == "AWS" { @@ -196,7 +197,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err // Make stack nodes var stackConf domain.StackConfResponse - if err = domain.Map(cluster.Conf, &stackConf); err != nil { + if err = serializer.Map(cluster, &stackConf); err != nil { log.InfoWithContext(ctx, err) } @@ -221,7 +222,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err return nil } -func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out domain.Stack, err error) { +func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out model.Stack, err error) { cluster, err := u.clusterRepo.Get(domain.ClusterId(stackId)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -275,7 +276,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out dom return } -func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, name string) (out domain.Stack, err error) { +func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Stack, err error) { cluster, err := u.clusterRepo.GetByName(organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -293,7 +294,7 @@ func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, nam return } -func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []domain.Stack, err error) { +func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.Stack, err error) { user, ok := request.UserFrom(ctx) if !ok { return out, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") @@ -352,7 +353,7 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return } -func (u *StackUsecase) Update(ctx context.Context, dto domain.Stack) (err error) { +func (u *StackUsecase) Update(ctx context.Context, dto model.Stack) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -364,7 +365,7 @@ func (u *StackUsecase) Update(ctx context.Context, dto domain.Stack) (err error) } updatorId := user.GetUserId() - dtoCluster := domain.Cluster{ + dtoCluster := model.Cluster{ ID: domain.ClusterId(dto.ID), Description: dto.Description, UpdatorId: &updatorId, @@ -378,7 +379,7 @@ func (u *StackUsecase) Update(ctx context.Context, dto domain.Stack) (err error) return nil } -func (u *StackUsecase) Delete(ctx context.Context, dto domain.Stack) (err error) { +func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") @@ -617,7 +618,7 @@ func (u *StackUsecase) DeleteFavorite(ctx context.Context, stackId domain.StackI return nil } -func reflectClusterToStack(cluster domain.Cluster, appGroups []domain.AppGroup) (out domain.Stack) { +func reflectClusterToStack(cluster model.Cluster, appGroups []model.AppGroup) (out model.Stack) { if err := serializer.Map(cluster, &out); err != nil { log.Error(err) } @@ -629,7 +630,7 @@ func reflectClusterToStack(cluster domain.Cluster, appGroups []domain.AppGroup) out.StatusDesc = statusDesc /* - return domain.Stack{ + return model.Stack{ ID: domain.StackId(cluster.ID), OrganizationId: cluster.OrganizationId, Name: cluster.Name, @@ -663,7 +664,7 @@ func reflectClusterToStack(cluster domain.Cluster, appGroups []domain.AppGroup) } // [TODO] more pretty -func getStackStatus(cluster domain.Cluster, appGroups []domain.AppGroup) (domain.StackStatus, string) { +func getStackStatus(cluster model.Cluster, appGroups []model.AppGroup) (domain.StackStatus, string) { for _, appGroup := range appGroups { if appGroup.Status == domain.AppGroupStatus_PENDING && cluster.Status == domain.ClusterStatus_RUNNING { return domain.StackStatus_APPGROUP_INSTALLING, appGroup.StatusDesc diff --git a/internal/usecase/user.go b/internal/usecase/user.go index b851d2f5..0d3bd907 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -10,32 +10,32 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/mail" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" ) type IUserUsecase interface { - CreateAdmin(organizationId string, email string) (*domain.User, error) + CreateAdmin(organizationId string, email string) (*model.User, error) DeleteAdmin(organizationId string) error DeleteAll(ctx context.Context, organizationId string) error - Create(ctx context.Context, user *domain.User) (*domain.User, error) - List(ctx context.Context, organizationId string) (*[]domain.User, error) - ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]domain.User, error) - Get(userId uuid.UUID) (*domain.User, error) - Update(ctx context.Context, userId uuid.UUID, user *domain.User) (*domain.User, error) + Create(ctx context.Context, user *model.User) (*model.User, error) + List(ctx context.Context, organizationId string) (*[]model.User, error) + ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.User, error) + Get(userId uuid.UUID) (*model.User, error) + Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) ResetPassword(userId uuid.UUID) error ResetPasswordByAccountId(accountId string, organizationId string) error GenerateRandomPassword() string Delete(userId uuid.UUID, organizationId string) error - GetByAccountId(ctx context.Context, accountId string, organizationId string) (*domain.User, error) - GetByEmail(ctx context.Context, email string, organizationId string) (*domain.User, error) + GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) + GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error - UpdateByAccountId(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) + UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) UpdatePasswordByAccountId(ctx context.Context, accountId string, originPassword string, newPassword string, organizationId string) error RenewalPasswordExpiredTime(ctx context.Context, userId uuid.UUID) error RenewalPasswordExpiredTimeByAccountId(ctx context.Context, accountId string, organizationId string) error @@ -43,7 +43,7 @@ type IUserUsecase interface { ValidateAccount(userId uuid.UUID, password string, organizationId string) error ValidateAccountByAccountId(accountId string, password string, organizationId string) error - UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) + UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *model.User) (*model.User, error) } type UserUsecase struct { @@ -196,17 +196,17 @@ func (u *UserUsecase) DeleteAdmin(organizationId string) error { return nil } -func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*domain.User, error) { +func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*model.User, error) { // Generate Admin user object randomPassword := helper.GenerateRandomString(passwordLength) - user := domain.User{ + user := model.User{ AccountId: "admin", Password: randomPassword, Email: email, - Role: domain.Role{ + Role: model.Role{ Name: "admin", }, - Organization: domain.Organization{ + Organization: model.Organization{ ID: orgainzationId, }, Name: "admin", @@ -295,7 +295,7 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s return nil } -func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[]domain.User, err error) { +func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[]model.User, err error) { users, err = u.userRepository.List(u.userRepository.OrganizationFilter(organizationId)) if err != nil { return nil, err @@ -304,7 +304,7 @@ func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[ return } -func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (users *[]domain.User, err error) { +func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (users *[]model.User, err error) { users, err = u.userRepository.ListWithPagination(pg, organizationId) if err != nil { return nil, err @@ -313,7 +313,7 @@ func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId str return } -func (u *UserUsecase) Get(userId uuid.UUID) (*domain.User, error) { +func (u *UserUsecase) Get(userId uuid.UUID) (*model.User, error) { user, err := u.userRepository.GetByUuid(userId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -325,7 +325,7 @@ func (u *UserUsecase) Get(userId uuid.UUID) (*domain.User, error) { return &user, nil } -func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, organizationId string) (*domain.User, error) { +func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) { users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), u.userRepository.AccountIdFilter(accountId)) if err != nil { @@ -335,7 +335,7 @@ func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, orga return &(*users)[0], nil } -func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organizationId string) (*domain.User, error) { +func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) { users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), u.userRepository.EmailFilter(email)) if err != nil { @@ -345,7 +345,7 @@ func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organization return &(*users)[0], nil } -func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *domain.User) (*domain.User, error) { +func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) { storedUser, err := u.Get(userId) if err != nil { return nil, err @@ -355,8 +355,8 @@ func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *domain return u.UpdateByAccountId(ctx, storedUser.AccountId, user) } -func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *domain.User) (*domain.User, error) { - var out domain.User +func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) { + var out model.User originUser, err := u.kc.GetUser(user.Organization.ID, accountId) if err != nil { @@ -438,7 +438,7 @@ func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, o return nil } -func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.User, error) { +func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User, error) { // Create user in keycloak groups := []string{fmt.Sprintf("%s@%s", user.Role.Name, user.Organization.ID)} userUuidStr, err := u.kc.CreateUser(user.Organization.ID, &gocloak.User{ @@ -492,7 +492,7 @@ func (u *UserUsecase) Create(ctx context.Context, user *domain.User) (*domain.Us return &resUser, nil } -func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *domain.User) (*domain.User, error) { +func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *model.User) (*model.User, error) { deepCopyUser := *newUser user, err := u.UpdateByAccountId(ctx, accountId, &deepCopyUser) if err != nil { diff --git a/pkg/domain/admin/user.go b/pkg/domain/admin/user.go index 7d53a51e..0a9e6820 100644 --- a/pkg/domain/admin/user.go +++ b/pkg/domain/admin/user.go @@ -1,8 +1,9 @@ package admin import ( - "github.com/openinfradev/tks-api/pkg/domain" "time" + + "github.com/openinfradev/tks-api/pkg/domain" ) type CreateUserRequest struct { @@ -26,17 +27,17 @@ type ListUserResponse struct { type GetUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role domain.Role `json:"role"` - Organization domain.Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role domain.RoleResponse `json:"role"` + Organization domain.OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } @@ -51,16 +52,16 @@ type UpdateUserRequest struct { type UpdateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role domain.Role `json:"role"` - Organization domain.Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role domain.RoleResponse `json:"role"` + Organization domain.OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } diff --git a/pkg/domain/alert.go b/pkg/domain/alert.go index 7201ef24..a60073bf 100644 --- a/pkg/domain/alert.go +++ b/pkg/domain/alert.go @@ -33,50 +33,6 @@ func (m AlertActionStatus) FromString(s string) AlertActionStatus { return AlertActionStatus_ERROR } -// 내부 -type Alert struct { - ID uuid.UUID - OrganizationId string - Organization Organization - Name string - Description string - Code string - Grade string - Message string - ClusterId ClusterId - Cluster Cluster - Node string - CheckPoint string - Summary string - GrafanaUrl string - FiredAt *time.Time - TakedAt *time.Time - ClosedAt *time.Time - TakedSec int - ProcessingSec int - Status AlertActionStatus - AlertActions []AlertAction - LastTaker User - RawData []byte - CreatorId *uuid.UUID - Creator User - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time -} - -type AlertAction struct { - ID uuid.UUID - AlertId uuid.UUID - Content string - Status AlertActionStatus - TakerId *uuid.UUID - Taker User - CreatedAt time.Time - UpdatedAt time.Time -} - type CreateAlertRequestAlert struct { Status string `json:"status"` GeneratorURL string `json:"generatorURL"` diff --git a/pkg/domain/app-group.go b/pkg/domain/app-group.go index d4e3211d..36dff144 100644 --- a/pkg/domain/app-group.go +++ b/pkg/domain/app-group.go @@ -114,33 +114,6 @@ func (m AppGroupType) FromString(s string) AppGroupType { return AppGroupType_UNSPECIFIED } -type AppGroup = struct { - ID AppGroupId - Name string - ClusterId ClusterId - AppGroupType AppGroupType - Description string - WorkflowId string - Status AppGroupStatus - StatusDesc string - CreatorId *uuid.UUID - Creator User - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time -} - -type Application = struct { - ID uuid.UUID - AppGroupId AppGroupId - Endpoint string - Metadata string - ApplicationType ApplicationType - CreatedAt time.Time - UpdatedAt time.Time -} - type AppGroupResponse = struct { ID AppGroupId `json:"id"` Name string `json:"name"` diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index 45239154..b1db60af 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -1,71 +1,56 @@ package domain -import ( - "time" - - "github.com/google/uuid" - "gorm.io/gorm" -) - -type AppServeApp struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - Name string `gorm:"index" json:"name,omitempty"` // application name - Namespace string `json:"namespace,omitempty"` // application namespace - OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to - ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to - Type string `json:"type,omitempty"` // type (build/deploy/all) - AppType string `json:"appType,omitempty"` // appType (spring/springboot) - EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app - PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment - TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed - TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name - Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app - GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` - AppServeAppTasks []AppServeAppTask `gorm:"foreignKey:AppServeAppId" json:"appServeAppTasks"` -} - -type AppServeAppTask struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - AppServeAppId string `gorm:"not null" json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to - Version string `json:"version,omitempty"` // application version - Status string `json:"status,omitempty"` // status is app status - Output string `json:"output,omitempty"` // output for task result - ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) - ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app - ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image - Profile string `json:"profile,omitempty"` // java app profile - AppConfig string `json:"appConfig,omitempty"` // java app config - AppSecret string `json:"appSecret,omitempty"` // java app secret - ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app - Port string `json:"port,omitempty"` // java app port - ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod - HelmRevision int32 `gorm:"default:0" json:"helmRevision,omitempty"` // revision of deployed helm release - Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) - RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version +import "time" + +type AppServeAppResponse struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` // application name + Namespace string `json:"namespace,omitempty"` // application namespace + OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to + Type string `json:"type,omitempty"` // type (build/deploy/all) + AppType string `json:"appType,omitempty"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed + TargetClusterName string `json:"targetClusterName,omitempty"` // target cluster name + Status string `json:"status,omitempty"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + CreatedAt time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` + AppServeAppTasks []AppServeAppTaskResponse `json:"appServeAppTasks"` +} + +type AppServeAppTaskResponse struct { + ID string `json:"id,omitempty"` + AppServeAppId string `json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to + Version string `json:"version,omitempty"` // application version + Status string `json:"status,omitempty"` // status is app status + Output string `json:"output,omitempty"` // output for task result + ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) + ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app + ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image + Profile string `json:"profile,omitempty"` // java app profile + AppConfig string `json:"appConfig,omitempty"` // java app config + AppSecret string `json:"appSecret,omitempty"` // java app secret + ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app + Port string `json:"port,omitempty"` // java app port + ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod + HelmRevision int32 `json:"helmRevision,omitempty"` // revision of deployed helm release + Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) + RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version PvEnabled bool `json:"pvEnabled"` PvStorageClass string `json:"pvStorageClass"` PvAccessMode string `json:"pvAccessMode"` PvSize string `json:"pvSize"` PvMountPath string `json:"pvMountPath"` - AvailableRollback bool `gorm:"-:all" json:"availableRollback"` - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` // createdAt is a creation timestamp for the application - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + AvailableRollback bool `json:"availableRollback"` + CreatedAt time.Time `json:"createdAt"` // createdAt is a creation timestamp for the application + UpdatedAt *time.Time `json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` } -func (a *AppServeApp) BeforeCreate(tx *gorm.DB) (err error) { - a.ID = uuid.New().String() - return nil -} - -func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} - type CreateAppServeAppRequest struct { // App Name string `json:"name" validate:"required,rfc1123,name"` @@ -158,25 +143,25 @@ type RollbackAppServeAppRequest struct { } type GetAppServeAppsResponse struct { - AppServeApps []AppServeApp `json:"appServeApps"` - Pagination PaginationResponse `json:"pagination"` + AppServeApps []AppServeAppResponse `json:"appServeApps"` + Pagination PaginationResponse `json:"pagination"` } // TODO: This will be deprecated later type GetAppServeAppResponse struct { - AppServeApp AppServeApp `json:"appServeApp"` - Stages []StageResponse `json:"stages"` + AppServeApp AppServeAppResponse `json:"appServeApp"` + Stages []StageResponse `json:"stages"` } type GetAppServeAppTasksResponse struct { - AppServeAppTasks []AppServeAppTask `json:"appServeAppTasks"` - Pagination PaginationResponse `json:"pagination"` + AppServeAppTasks []AppServeAppTaskResponse `json:"appServeAppTasks"` + Pagination PaginationResponse `json:"pagination"` } type GetAppServeAppTaskResponse struct { - AppServeApp AppServeApp `json:"appServeApp"` - AppServeAppTask AppServeAppTask `json:"appServeAppTask"` - Stages []StageResponse `json:"stages"` + AppServeApp AppServeAppResponse `json:"appServeApp"` + AppServeAppTask AppServeAppTaskResponse `json:"appServeAppTask"` + Stages []StageResponse `json:"stages"` } type StageResponse struct { diff --git a/pkg/domain/audit.go b/pkg/domain/audit.go index 9599ccae..6622aa40 100644 --- a/pkg/domain/audit.go +++ b/pkg/domain/audit.go @@ -2,25 +2,8 @@ package domain import ( "time" - - "github.com/google/uuid" ) -// 내부 -type Audit struct { - ID uuid.UUID - OrganizationId string - Organization Organization - Group string - Message string - Description string - ClientIP string - UserId *uuid.UUID - User User - CreatedAt time.Time - UpdatedAt time.Time -} - type AuditResponse struct { ID string `json:"id"` OrganizationId string `json:"organizationId"` @@ -29,7 +12,6 @@ type AuditResponse struct { Group string `json:"group"` Message string `json:"message"` ClientIP string `json:"clientIP"` - UserId string `json:"userId"` User SimpleUserResponse `json:"user"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` diff --git a/pkg/domain/auth.go b/pkg/domain/auth.go index abab6f97..4dbaeeef 100644 --- a/pkg/domain/auth.go +++ b/pkg/domain/auth.go @@ -13,13 +13,13 @@ type PingTokenRequest struct { type LoginResponse struct { User struct { - AccountId string `json:"accountId"` - Name string `json:"name"` - Token string `json:"token"` - Role Role `json:"role"` - Department string `json:"department"` - Organization Organization `json:"organization"` - PasswordExpired bool `json:"passwordExpired"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Token string `json:"token"` + Role RoleResponse `json:"role"` + Department string `json:"department"` + Organization OrganizationResponse `json:"organization"` + PasswordExpired bool `json:"passwordExpired"` } `json:"user"` } diff --git a/pkg/domain/cloud-account.go b/pkg/domain/cloud-account.go index 5e4720c8..591356ac 100644 --- a/pkg/domain/cloud-account.go +++ b/pkg/domain/cloud-account.go @@ -2,8 +2,6 @@ package domain import ( "time" - - "github.com/google/uuid" ) const CLOUD_ACCOUNT_INCLUSTER = "INCLUSTER" @@ -49,30 +47,6 @@ func (m CloudAccountStatus) FromString(s string) CloudAccountStatus { return CloudAccountStatus_PENDING } -// 내부 -type CloudAccount struct { - ID uuid.UUID - OrganizationId string - Name string - Description string - CloudService string - Resource string - Clusters int - AwsAccountId string - AccessKeyId string - SecretAccessKey string - SessionToken string - Status CloudAccountStatus - StatusDesc string - CreatedIAM bool - CreatorId uuid.UUID - Creator User - UpdatorId uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time -} - type ResourceQuotaAttr struct { Type string `json:"type"` Usage int `json:"usage"` @@ -157,3 +131,7 @@ type GetCloudAccountResourceQuotaResponse struct { Available bool `json:"available"` ResourceQuota ResourceQuota `json:"resourceQuota"` } + +type DeleteCloudAccountResponse struct { + ID string `json:"id"` +} diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index 6c2ea884..0d7c854b 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -3,7 +3,6 @@ package domain import ( "time" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" ) @@ -83,34 +82,6 @@ func (m ClusterType) FromString(s string) ClusterType { return ClusterType_USER } -// model -type Cluster struct { - ID ClusterId - CloudService string - OrganizationId string - Name string - Description string - CloudAccountId uuid.UUID - CloudAccount CloudAccount - StackTemplateId uuid.UUID - StackTemplate StackTemplate - Status ClusterStatus - StatusDesc string - Conf ClusterConf - Favorited bool - CreatorId *uuid.UUID - Creator User - ClusterType ClusterType - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time - ByoClusterEndpointHost string - ByoClusterEndpointPort int - IsStack bool - Kubeconfig []byte -} - type ClusterConf struct { TksCpNode int TksCpNodeMax int @@ -239,6 +210,7 @@ type ClusterResponse struct { ByoClusterEndpointHost string `json:"byoClusterEndpointHost,omitempty"` ByoClusterEndpointInt int `json:"byoClusterEndpointPort,omitempty"` IsStack bool `json:"isStack,omitempty"` + Favorited bool `json:"favorited,omitempty"` } type SimpleClusterResponse struct { diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index c7699fb7..6f3e18e2 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -37,14 +37,6 @@ func (m ChartType) FromString(s string) ChartType { return ChartType_ERROR } -// [TODO] -func (m ChartType) All() (out []string) { - for _, v := range chartType { - out = append(out, v) - } - return -} - // 내부 type DashboardChart struct { ChartType ChartType @@ -72,6 +64,14 @@ type DashboardStack struct { UpdatedAt time.Time } +// [TODO] +func (m ChartType) All() (out []string) { + for _, v := range chartType { + out = append(out, v) + } + return +} + type Unit struct { Name string `json:"name"` Data []string `json:"data"` diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index c34a45ae..e2a2127d 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -1,11 +1,10 @@ package domain -import ( - "time" -) +import "time" -type Endpoint struct { - Name string `gorm:"primary_key;type:text;not null;unique" json:"name"` - Group string `gorm:"type:text;" json:"group"` - CreatedAt time.Time +type EndpointResponse struct { + Name string `json:"name"` + Group string `json:"group"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } diff --git a/pkg/domain/mapper.go b/pkg/domain/mapper.go deleted file mode 100644 index e3fa80ac..00000000 --- a/pkg/domain/mapper.go +++ /dev/null @@ -1,140 +0,0 @@ -package domain - -import ( - "fmt" - "reflect" - - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/log" -) - -type ConverterMap map[compositeKey]func(interface{}) (interface{}, error) - -type compositeKey struct { - srcType reflect.Type - dstType reflect.Type -} - -func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) error { - srcVal := reflect.ValueOf(src) - srcType := srcVal.Type() - - dstVal := reflect.ValueOf(dst) - if dstVal.Kind() != reflect.Ptr || dstVal.IsNil() { - return fmt.Errorf("dst must be a non-nil pointer") - } - dstElem := dstVal.Elem() - - for i := 0; i < srcVal.NumField(); i++ { - fieldName := srcType.Field(i).Name - srcField := srcVal.Field(i) - dstField := dstElem.FieldByName(fieldName) - - if dstField.IsValid() && dstField.CanSet() { - if dstField.Type() == srcField.Type() { - dstField.Set(srcField) - continue - } else if srcField.Type().Kind() == reflect.Struct && dstField.Type().Kind() == reflect.Struct { - if err := recursiveMap(srcField.Interface(), dstField.Addr().Interface(), converterMap); err != nil { - return err - } - } else { - converterKey := compositeKey{srcType: srcField.Type(), dstType: dstField.Type()} - if converter, ok := converterMap[converterKey]; ok { - if converted, err := converter(srcField.Interface()); err != nil { - return err - } else { - dstField.Set(reflect.ValueOf(converted)) - } - } else { - log.Debugf("no converter found for %s -> %s", srcField.Type(), dstField.Type()) - continue - } - } - - /* - else if srcField.Type().Kind() == reflect.Ptr && dstField.Type().Kind() == reflect.Ptr { - log.Info("AAA ", dstField.Type()) - ptr := reflect.New(dstField.Elem().Type()) - if err := recursiveMap(srcField.Elem().Interface(), ptr.Elem().Interface(), converterMap); err != nil { - return err - } - } - */ - - } - } - - return nil -} -func Map(src interface{}, dst interface{}) error { - return recursiveMap(src, dst, ConverterMap{ - {srcType: reflect.TypeOf((*uuid.UUID)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(uuid.UUID).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*uuid.UUID)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - val, _ := uuid.Parse(i.(string)) - return val, nil - }, - {srcType: reflect.TypeOf((*OrganizationStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(OrganizationStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*OrganizationStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return organizationStatusMap[i.(string)], nil - }, - {srcType: reflect.TypeOf((*Role)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(Role).Name, nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*Role)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return Role{Name: i.(string)}, nil - }, - {srcType: reflect.TypeOf((*ClusterStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(ClusterStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ClusterStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(ClusterStatus).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*AppGroupStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(AppGroupStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AppGroupStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(AppGroupStatus).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*AppGroupType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(AppGroupType).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AppGroupType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(AppGroupType).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*StackStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(StackStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*StackStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(StackStatus).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*ChartType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(ChartType).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ChartType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(ChartType).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*AlertActionStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(AlertActionStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*AlertActionStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(AlertActionStatus).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*ApplicationType)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(ApplicationType).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*ApplicationType)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(ApplicationType).FromString(i.(string)), nil - }, - {srcType: reflect.TypeOf((*CloudAccountStatus)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { - return i.(CloudAccountStatus).String(), nil - }, - {srcType: reflect.TypeOf(""), dstType: reflect.TypeOf((*CloudAccountStatus)(nil)).Elem()}: func(i interface{}) (interface{}, error) { - return new(CloudAccountStatus).FromString(i.(string)), nil - }, - }) -} diff --git a/pkg/domain/mapper_test.go b/pkg/domain/mapper_test.go deleted file mode 100644 index c235e360..00000000 --- a/pkg/domain/mapper_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package domain - -import ( - "fmt" - "github.com/google/uuid" - "testing" - "time" -) - -// test case -func TestConvert(t *testing.T) { - type args struct { - src interface{} - dst interface{} - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "test case: CreateOrganizationRequest->Organization", - args: args{ - src: CreateOrganizationRequest{ - Name: "test", - Description: "test", - Phone: "test", - }, - dst: &Organization{}, - }, - wantErr: false, - }, - { - name: "test case Organization->CreateOrganizationResponse", - args: args{ - src: Organization{ - ID: "", - Name: "test", - Description: "test", - Phone: "test", - StatusDesc: "good", - Creator: "", - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - }, - dst: &CreateOrganizationResponse{}, - }, - wantErr: false, - }, - { - name: "test case Organization->GetOrganizationResponse", - args: args{ - src: Organization{ - ID: "", - Name: "test", - Description: "test", - Phone: "test", - Status: OrganizationStatus_CREATE, - StatusDesc: "good", - Creator: "", - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - }, - dst: &(&GetOrganizationResponse{}).Organization, - }, - wantErr: false, - }, - { - name: "test case CreateUserRequest->User", - args: args{ - src: CreateUserRequest{ - AccountId: "testAccount", - Password: "testPassword", - Name: "testName", - Email: "testEmail", - Department: "testDepartment", - Role: "testRole", - Description: "testDescription", - }, - dst: &User{}, - }, - wantErr: false, - }, - { - name: "test case User->GetUserResponse", - args: args{ - src: User{ - ID: uuid.New(), - AccountId: "testAccount", - Password: "testPassword", - Name: "testName", - Token: "testToken", - Role: Role{}, - Organization: Organization{}, - Creator: "", - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - Email: "", - Department: "", - Description: "", - }, - dst: &GetUserResponse{}, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := Map(tt.args.src, tt.args.dst); (err != nil) != tt.wantErr { - t.Errorf("Map() error = %v, wantErr %v", err, tt.wantErr) - } else { - fmt.Printf("Input: %+v\n", tt.args.src) - fmt.Printf("Output: %+v\n\n", tt.args.dst) - } - }) - } -} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index fed0cfe9..efe7e5e3 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -2,8 +2,6 @@ package domain import ( "time" - - "gorm.io/gorm" ) // enum @@ -50,18 +48,14 @@ func (m OrganizationStatus) FromString(s string) OrganizationStatus { return OrganizationStatus_ERROR } -type Organization struct { - gorm.Model - - ID string `gorm:"primarykey;type:varchar(36);not null" json:"id"` +type OrganizationResponse struct { + ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` Phone string `json:"phone"` PrimaryClusterId string `json:"primaryClusterId"` - WorkflowId string `json:"-"` Status OrganizationStatus `json:"status"` StatusDesc string `json:"statusDesc"` - Creator string `json:"creator"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } @@ -129,3 +123,7 @@ type UpdateOrganizationResponse struct { type UpdatePrimaryClusterRequest struct { PrimaryClusterId string `json:"primaryClusterId"` } + +type DeleteOrganizationResponse struct { + ID string `json:"id"` +} diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index ad95656e..f7b69f40 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -2,626 +2,37 @@ package domain import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/delivery/api" - "github.com/openinfradev/tks-api/internal/helper" - "gorm.io/gorm" ) -type PermissionKind string - -const ( - DashBoardPermission PermissionKind = "대시보드" - StackPermission PermissionKind = "스택 관리" - SecurityPolicyPermission PermissionKind = "보안/정책 관리" - ProjectManagementPermission PermissionKind = "프로젝트 관리" - NotificationPermission PermissionKind = "알림" - ConfigurationPermission PermissionKind = "설정" -) - -type Permission struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` - Name string `json:"name"` - - IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` - RoleID *string `json:"role_id,omitempty"` - Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` - Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` - // omit empty - - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` - Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` +type PermissionResponse struct { + ID uuid.UUID `json:"ID"` + Name string `json:"name"` + IsAllowed *bool `json:"is_allowed,omitempty"` + RoleID *string `json:"role_id,omitempty"` + Role *RoleResponse `json:"role,omitempty"` + Endpoints []*EndpointResponse `json:"endpoints,omitempty"` + ParentID *uuid.UUID `json:"parent_id,omitempty"` + Parent *PermissionResponse `json:"parent,omitempty"` + Children []*PermissionResponse `json:"children,omitempty"` } -func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { - if p.ID == uuid.Nil { - p.ID = uuid.New() - } - return nil -} - -type PermissionSet struct { - Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` - Stack *Permission `gorm:"-:all" json:"stack,omitempty"` - SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` - ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` - Notification *Permission `gorm:"-:all" json:"notification,omitempty"` - Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` -} - -func NewDefaultPermissionSet() *PermissionSet { - return &PermissionSet{ - Dashboard: newDashboard(), - Stack: newStack(), - SecurityPolicy: newSecurityPolicy(), - ProjectManagement: newProjectManagement(), - Notification: newNotification(), - Configuration: newConfiguration(), - } +type PermissionSetResponse struct { + Dashboard *PermissionResponse `json:"dashboard,omitempty"` + Stack *PermissionResponse `json:"stack,omitempty"` + SecurityPolicy *PermissionResponse `json:"security_policy,omitempty"` + ProjectManagement *PermissionResponse `json:"project_management,omitempty"` + Notification *PermissionResponse `json:"notification,omitempty"` + Configuration *PermissionResponse `json:"configuration,omitempty"` } type GetPermissionTemplatesResponse struct { - Permissions []*Permission `json:"permissions"` + Permissions []*PermissionResponse `json:"permissions"` } type GetPermissionsByRoleIdResponse struct { - Permissions []*Permission `json:"permissions"` + Permissions []*PermissionResponse `json:"permissions"` } type UpdatePermissionsByRoleIdRequest struct { - Permissions []*Permission `json:"permissions"` -} - -func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { - if root.Children == nil { - return append(edgePermissions, root) - } - - for _, child := range root.Children { - if f != nil && !(*f)(*child) { - continue - } - edgePermissions = GetEdgePermission(child, edgePermissions, f) - } - - return edgePermissions -} - -func SetRoleIDToPermission(roleID string, permission *Permission) { - permission.RoleID = helper.StringP(roleID) -} - -func endpointObjects(eps ...api.Endpoint) []*Endpoint { - var result []*Endpoint - for _, ep := range eps { - result = append(result, &Endpoint{ - Name: api.ApiMap[ep].Name, - Group: api.ApiMap[ep].Group, - }) - } - return result -} - -func newDashboard() *Permission { - dashboard := &Permission{ - Name: string(DashBoardPermission), - Children: []*Permission{ - { - Name: "대시보드", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetChartsDashboard, - api.GetChartDashboard, - api.GetStacksDashboard, - api.GetResourcesDashboard, - ), - }, - }, - }, - { - Name: "대시보드 설정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return dashboard -} - -func newStack() *Permission { - stack := &Permission{ - Name: string(StackPermission), - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetStacks, - api.GetStack, - api.CheckStackName, - api.GetStackStatus, - api.GetStackKubeConfig, - - api.SetFavoriteStack, - api.DeleteFavoriteStack, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateStack, - api.InstallStack, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateStack, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteStack, - ), - }, - }, - } - - return stack -} - -func newSecurityPolicy() *Permission { - security_policy := &Permission{ - Name: string(SecurityPolicyPermission), - Children: []*Permission{ - { - Name: "보안/정책", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return security_policy -} - -func newProjectManagement() *Permission { - projectManagement := &Permission{ - Name: string(ProjectManagementPermission), - Children: []*Permission{ - { - Name: "프로젝트", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateProject, - ), - }, - }, - }, - { - Name: "앱 서빙", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetAppServeApps, - api.GetAppServeApp, - api.GetNumOfAppsOnStack, - api.GetAppServeAppLatestTask, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - ), - }, - { - Name: "빌드", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), - }, - { - Name: "배포", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteAppServeApp, - ), - }, - }, - }, - { - Name: "설정-일반", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, - - api.GetProjectRoles, - api.GetProjectRole, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProject, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProject, - ), - }, - }, - }, - { - Name: "설정-멤버", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjectMembers, - api.GetProjectMember, - api.GetProjectRoles, - api.GetProjectRole, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.AddProjectMember, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProjectMemberRole, - ), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.RemoveProjectMember, - ), - }, - }, - }, - { - Name: "설정-네임스페이스", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjectNamespaces, - api.GetProjectNamespace, - ), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateProjectNamespace, - ), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects(), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProjectNamespace, - ), - }, - }, - }, - }, - } - - return projectManagement -} - -func newNotification() *Permission { - notification := &Permission{ - Name: string(NotificationPermission), - Children: []*Permission{ - { - Name: "시스템 경고", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "보안/정책 감사로그", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return notification -} - -func newConfiguration() *Permission { - configuration := &Permission{ - Name: string(ConfigurationPermission), - Children: []*Permission{ - { - Name: "일반", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "클라우드 계정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "스택 템플릿", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "프로젝트 관리", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "사용자", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "사용자 권한 관리", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "알림 설정", - Children: []*Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } - - return configuration -} - -func (p *PermissionSet) SetAllowedPermissionSet() { - edgePermissions := make([]*Permission, 0) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) - - for _, permission := range edgePermissions { - permission.IsAllowed = helper.BoolP(true) - } - - return -} - -func (p *PermissionSet) SetUserPermissionSet() { - f := func(permission Permission) bool { - return permission.Name == "조회" - } - edgePermissions := make([]*Permission, 0) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) - //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) - - for _, permission := range edgePermissions { - permission.IsAllowed = helper.BoolP(true) - } - - return -} - -func (p *PermissionSet) SetRoleId(roleId string) { - setRoleIdToPermission(p.Dashboard, roleId) - setRoleIdToPermission(p.Stack, roleId) - setRoleIdToPermission(p.SecurityPolicy, roleId) - setRoleIdToPermission(p.ProjectManagement, roleId) - setRoleIdToPermission(p.Notification, roleId) - setRoleIdToPermission(p.Configuration, roleId) -} - -func setRoleIdToPermission(root *Permission, roleId string) { - root.RoleID = helper.StringP(roleId) - - if root.Children == nil { - return - } - - for _, child := range root.Children { - setRoleIdToPermission(child, roleId) - } + Permissions []*PermissionResponse `json:"permissions"` } diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index baf8990f..e2dd0810 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -73,6 +73,7 @@ type PolicyTemplateResponse struct { PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` } +/* type PolicyTemplate struct { ID PolicyTemplateId Type string @@ -97,6 +98,7 @@ type PolicyTemplate struct { PermittedOrganizationIds []string // 생성 시에만 사용 PermittedOrganizations []PermittedOrganization } +*/ type CreateCommonPolicyTemplateRequest struct { TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 1007dd27..b63d6036 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -3,17 +3,18 @@ package domain import "time" type ProjectResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - IsMyProject string `json:"isMyProject"` - ProjectRoleId string `json:"projectRoleId"` - ProjectRoleName string `json:"projectRoleName"` - NamespaceCount int `json:"namespaceCount"` - AppCount int `json:"appCount"` - MemberCount int `json:"memberCount"` - CreatedAt time.Time `json:"createdAt"` + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + IsMyProject string `json:"isMyProject"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` + NamespaceCount int `json:"namespaceCount"` + AppCount int `json:"appCount"` + MemberCount int `json:"memberCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt *time.Time `json:"updatedAt"` } type GetProjectsResponse struct { diff --git a/pkg/domain/role.go b/pkg/domain/role.go index e177a76a..ab961b26 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -4,7 +4,6 @@ import ( "time" "github.com/google/uuid" - "gorm.io/gorm" ) type RoleType string @@ -15,23 +14,23 @@ const ( RoleTypeProject RoleType = "project" ) -func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { - r.ID = uuid.New().String() - return nil +type RoleResponse struct { + ID string `json:"id"` + Name string `json:"name"` + OrganizationID string `json:"organizationId"` + Organization OrganizationResponse `json:"organization"` + Type string `json:"type"` + Description string `json:"description"` + Creator uuid.UUID `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } -type Role struct { - gorm.Model - - ID string `gorm:"primarykey;" json:"id"` - Name string `json:"name"` - OrganizationID string `json:"organizationId"` - Organization Organization `gorm:"foreignKey:OrganizationID;references:ID;" json:"organization"` - Type string `json:"type"` - Description string `json:"description"` - Creator uuid.UUID `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` +type SimpleRoleResponse = struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + OrganizationID string `json:"organizationId"` } type CreateTksRoleRequest struct { diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index 13b6e9da..122410d1 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -2,38 +2,11 @@ package domain import ( "time" - - "github.com/google/uuid" ) const STACK_TEMPLATE_TYPE_STANDARD = "STANDARD" const STACK_TEMPLATE_TYPE_MSA = "MSA" -// 내부 -type StackTemplate struct { - ID uuid.UUID - OrganizationId string - Name string - Description string - Template string - TemplateType string - CloudService string - Version string - Platform string - KubeVersion string - KubeType string - OrganizationIds []string - Organizations []Organization - ServiceIds []string - Services []byte - CreatorId uuid.UUID - Creator User - UpdatorId uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time -} - type StackTemplateServiceApplicationResponse struct { Name string `json:"name"` Description string `json:"description"` diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index b4935bcb..c56abc48 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -3,7 +3,6 @@ package domain import ( "time" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" ) @@ -74,45 +73,6 @@ const MAX_STEP_LMA_REMOVE = 12 const MAX_STEP_SM_CREATE = 22 const MAX_STEP_SM_REMOVE = 4 -// model -type Stack = struct { - ID StackId - Name string - Description string - ClusterId string - OrganizationId string - CloudService string - CloudAccountId uuid.UUID - CloudAccount CloudAccount - StackTemplateId uuid.UUID - StackTemplate StackTemplate - Status StackStatus - StatusDesc string - Conf StackConf - PrimaryCluster bool - GrafanaUrl string - CreatorId *uuid.UUID - Creator User - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time - Favorited bool - ClusterEndpoint string - Resource DashboardStackResponse -} - -type StackConf struct { - TksCpNode int - TksCpNodeMax int - TksCpNodeType string - TksInfraNode int - TksInfraNodeMax int - TksInfraNodeType string - TksUserNode int - TksUserNodeMax int - TksUserNodeType string -} type StackStepStatus struct { Status string `json:"status"` Stage string `json:"stage"` @@ -176,6 +136,19 @@ type StackResponse struct { UpdatedAt time.Time `json:"updatedAt"` } +type SimpleStackResponse struct { + ID StackId `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + OrganizationId string `json:"organizationId"` + StackTemplate SimpleStackTemplateResponse `json:"stackTemplate,omitempty"` + CloudAccount SimpleCloudAccountResponse `json:"cloudAccount,omitempty"` + Status string `json:"status"` + PrimaryCluster bool `json:"primaryCluster"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + type GetStacksResponse struct { Stacks []StackResponse `json:"stacks"` Pagination PaginationResponse `json:"pagination"` diff --git a/pkg/domain/user.go b/pkg/domain/user.go index d63b4605..a4833494 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -1,55 +1,49 @@ package domain import ( - "github.com/google/uuid" - "gorm.io/gorm" "time" + + "github.com/google/uuid" ) -type User struct { +// // Deprecated: Policy is deprecated, use Permission instead. +// +// type Policy = struct { +// ID string `json:"id"` +// Name string `json:"name"` +// Create bool `json:"create"` +// CreatePriviledge string `json:"createPriviledge"` +// Update bool `json:"update"` +// UpdatePriviledge string `json:"updatePriviledge"` +// Read bool `json:"read"` +// ReadPriviledge string `json:"readPriviledge"` +// Delete bool `json:"delete"` +// DeletePriviledge string `json:"deletePriviledge"` +// Creator string `json:"creator"` +// CreatedAt time.Time `json:"createdAt"` +// UpdatedAt time.Time `json:"updatedAt"` +// } +type UserResponse struct { ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` Password string `gorm:"-:all" json:"password"` Name string `json:"name"` Token string `json:"token"` RoleId string - Role Role `gorm:"foreignKey:RoleId;references:ID" json:"role"` + Role RoleResponse `gorm:"foreignKey:RoleId;references:ID" json:"role"` OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` - PasswordExpired bool `json:"passwordExpired"` + Organization OrganizationResponse `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` + PasswordExpired bool `json:"passwordExpired"` Email string `json:"email"` Department string `json:"department"` Description string `json:"description"` } -func (g *User) BeforeCreate(tx *gorm.DB) (err error) { - g.PasswordUpdatedAt = time.Now() - return nil -} - -// -//// Deprecated: Policy is deprecated, use Permission instead. -//type Policy = struct { -// ID string `json:"id"` -// Name string `json:"name"` -// Create bool `json:"create"` -// CreatePriviledge string `json:"createPriviledge"` -// Update bool `json:"update"` -// UpdatePriviledge string `json:"updatePriviledge"` -// Read bool `json:"read"` -// ReadPriviledge string `json:"readPriviledge"` -// Delete bool `json:"delete"` -// DeletePriviledge string `json:"deletePriviledge"` -// Creator string `json:"creator"` -// CreatedAt time.Time `json:"createdAt"` -// UpdatedAt time.Time `json:"updatedAt"` -//} - type CreateUserRequest struct { AccountId string `json:"accountId" validate:"required"` Password string `json:"password" validate:"required"` @@ -60,45 +54,38 @@ type CreateUserRequest struct { Description string `json:"description" validate:"min=0,max=100"` } -type SimpleRoleResponse = struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` -} - type SimpleUserResponse struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role SimpleRoleResponse `json:"role"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` } type CreateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` } `json:"user"` } type GetUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } @@ -107,17 +94,17 @@ type ListUserResponse struct { Pagination PaginationResponse `json:"pagination"` } type ListUserBody struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + Creator string `json:"creator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type UpdateUserRequest struct { @@ -130,28 +117,28 @@ type UpdateUserRequest struct { type UpdateUserResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } `json:"user"` } type GetMyProfileResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` } `json:"user"` } type UpdateMyProfileRequest struct { @@ -163,13 +150,13 @@ type UpdateMyProfileRequest struct { type UpdateMyProfileResponse struct { User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Role Role `json:"role"` - Organization Organization `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Role RoleResponse `json:"role"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` } `json:"user"` } From 0b0aff77f8db75447ccc9877db5d7ef9fbc0480a Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 14 Mar 2024 17:14:32 +0900 Subject: [PATCH 117/502] feature. enhanced organization creation & add master admin to organization --- api/swagger/docs.go | 159 ++++++++++++------------- api/swagger/swagger.json | 159 ++++++++++++------------- api/swagger/swagger.yaml | 119 +++++++++--------- internal/delivery/http/organization.go | 32 ++++- internal/model/organization.go | 8 +- internal/repository/organization.go | 38 ++++-- internal/serializer/serializer.go | 13 +- internal/usecase/organization.go | 62 +++++++--- internal/usecase/user.go | 14 +-- pkg/domain/organization.go | 56 ++++----- pkg/domain/policy-template.go | 8 ++ pkg/domain/user.go | 8 +- scripts/patch_postgres.sql | 7 ++ 13 files changed, 364 insertions(+), 319 deletions(-) create mode 100644 scripts/patch_postgres.sql diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 4a544877..97b5e970 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -2128,7 +2128,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse" } } } @@ -7925,11 +7925,18 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { "type": "object", "required": [ - "Email", + "adminAccountId", + "adminEmail", "name" ], "properties": { - "Email": { + "adminAccountId": { + "type": "string" + }, + "adminEmail": { + "type": "string" + }, + "adminName": { "type": "string" }, "description": { @@ -7939,9 +7946,6 @@ const docTemplate = `{ }, "name": { "type": "string" - }, - "phone": { - "type": "string" } } }, @@ -8818,39 +8822,7 @@ const docTemplate = `{ "type": "object", "properties": { "organization": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" } } }, @@ -9192,32 +9164,17 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody": { + "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "string" + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + } }, - "updatedAt": { - "type": "string" + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, @@ -9381,6 +9338,9 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { + "admin": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, "createdAt": { "type": "string" }, @@ -9396,11 +9356,26 @@ const docTemplate = `{ "phone": { "type": "string" }, + "policyTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimplePolicyTemplateResponse" + } + }, "primaryClusterId": { "type": "string" }, + "stackCount": { + "type": "integer" + }, + "stackTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse" + } + }, "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus" + "type": "string" }, "statusDesc": { "type": "string" @@ -9410,29 +9385,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7 - ], - "x-enum-varnames": [ - "OrganizationStatus_PENDING", - "OrganizationStatus_CREATE", - "OrganizationStatus_CREATING", - "OrganizationStatus_CREATED", - "OrganizationStatus_DELETE", - "OrganizationStatus_DELETING", - "OrganizationStatus_DELETED", - "OrganizationStatus_ERROR" - ] - }, "github_com_openinfradev_tks-api_pkg_domain.PaginationResponse": { "type": "object", "properties": { @@ -10115,6 +10067,35 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimplePolicyTemplateResponse": { + "type": "object", + "properties": { + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "type": { + "type": "string", + "enum": [ + "tks", + "organization" + ], + "example": "tks" + }, + "version": { + "type": "string", + "example": "v1.0.1" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -10153,6 +10134,12 @@ const docTemplate = `{ "accountId": { "type": "string" }, + "department": { + "type": "string" + }, + "email": { + "type": "string" + }, "id": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 8872bcf7..e627d9e4 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -2122,7 +2122,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse" } } } @@ -7919,11 +7919,18 @@ "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { "type": "object", "required": [ - "Email", + "adminAccountId", + "adminEmail", "name" ], "properties": { - "Email": { + "adminAccountId": { + "type": "string" + }, + "adminEmail": { + "type": "string" + }, + "adminName": { "type": "string" }, "description": { @@ -7933,9 +7940,6 @@ }, "name": { "type": "string" - }, - "phone": { - "type": "string" } } }, @@ -8812,39 +8816,7 @@ "type": "object", "properties": { "organization": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "string" - }, - "statusDesc": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" } } }, @@ -9186,32 +9158,17 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody": { + "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "primaryClusterId": { - "type": "string" - }, - "status": { - "type": "string" + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + } }, - "updatedAt": { - "type": "string" + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" } } }, @@ -9375,6 +9332,9 @@ "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { + "admin": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, "createdAt": { "type": "string" }, @@ -9390,11 +9350,26 @@ "phone": { "type": "string" }, + "policyTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimplePolicyTemplateResponse" + } + }, "primaryClusterId": { "type": "string" }, + "stackCount": { + "type": "integer" + }, + "stackTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse" + } + }, "status": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus" + "type": "string" }, "statusDesc": { "type": "string" @@ -9404,29 +9379,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7 - ], - "x-enum-varnames": [ - "OrganizationStatus_PENDING", - "OrganizationStatus_CREATE", - "OrganizationStatus_CREATING", - "OrganizationStatus_CREATED", - "OrganizationStatus_DELETE", - "OrganizationStatus_DELETING", - "OrganizationStatus_DELETED", - "OrganizationStatus_ERROR" - ] - }, "github_com_openinfradev_tks-api_pkg_domain.PaginationResponse": { "type": "object", "properties": { @@ -10109,6 +10061,35 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimplePolicyTemplateResponse": { + "type": "object", + "properties": { + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "type": { + "type": "string", + "enum": [ + "tks", + "organization" + ], + "example": "tks" + }, + "version": { + "type": "string", + "example": "v1.0.1" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -10147,6 +10128,12 @@ "accountId": { "type": "string" }, + "department": { + "type": "string" + }, + "email": { + "type": "string" + }, "id": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index a94fa389..7404dc21 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -842,7 +842,11 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest: properties: - Email: + adminAccountId: + type: string + adminEmail: + type: string + adminName: type: string description: maxLength: 100 @@ -850,10 +854,9 @@ definitions: type: string name: type: string - phone: - type: string required: - - Email + - adminAccountId + - adminEmail - name type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse: @@ -1441,28 +1444,7 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse: properties: organization: - properties: - createdAt: - type: string - creator: - type: string - description: - type: string - id: - type: string - name: - type: string - phone: - type: string - primaryClusterId: - type: string - status: - type: string - statusDesc: - type: string - updatedAt: - type: string - type: object + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' type: object github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse: properties: @@ -1681,24 +1663,14 @@ definitions: id: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody: + github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse: properties: - createdAt: - type: string - description: - type: string - id: - type: string - name: - type: string - phone: - type: string - primaryClusterId: - type: string - status: - type: string - updatedAt: - type: string + organizations: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + type: array + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse: properties: @@ -1805,6 +1777,8 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse: properties: + admin: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' createdAt: type: string description: @@ -1815,35 +1789,25 @@ definitions: type: string phone: type: string + policyTemplates: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimplePolicyTemplateResponse' + type: array primaryClusterId: type: string + stackCount: + type: integer + stackTemplates: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse' + type: array status: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus' + type: string statusDesc: type: string updatedAt: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.OrganizationStatus: - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - type: integer - x-enum-varnames: - - OrganizationStatus_PENDING - - OrganizationStatus_CREATE - - OrganizationStatus_CREATING - - OrganizationStatus_CREATED - - OrganizationStatus_DELETE - - OrganizationStatus_DELETING - - OrganizationStatus_DELETED - - OrganizationStatus_ERROR github_com_openinfradev_tks-api_pkg_domain.PaginationResponse: properties: filters: @@ -2299,6 +2263,27 @@ definitions: name: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SimplePolicyTemplateResponse: + properties: + description: + example: 이 정책은 ... + type: string + id: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + templateName: + example: 필수 Label 검사 + type: string + type: + enum: + - tks + - organization + example: tks + type: string + version: + example: v1.0.1 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse: properties: cloudService: @@ -2324,6 +2309,10 @@ definitions: properties: accountId: type: string + department: + type: string + email: + type: string id: type: string name: @@ -4262,7 +4251,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationBody' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse' type: array security: - JWT: [] diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 264a3611..a588758d 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -1,6 +1,7 @@ package http import ( + "encoding/json" "fmt" "net/http" @@ -112,13 +113,21 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } // Admin user 생성 - _, err = h.userUsecase.CreateAdmin(organizationId, input.Email) + admin, err := h.userUsecase.CreateAdmin(organizationId, input.AdminAccountId, input.AdminName, input.AdminEmail) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } + err = h.usecase.ChangeAdminId(organizationId, admin.ID) + if err != nil { + log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + organization.AdminId = &admin.ID + var out domain.CreateOrganizationResponse if err = serializer.Map(organization, &out); err != nil { log.ErrorWithContext(r.Context(), err) @@ -139,7 +148,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} []domain.ListOrganizationBody +// @Success 200 {object} []domain.ListOrganizationResponse // @Router /organizations [get] // @Security JWT func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Request) { @@ -154,7 +163,7 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re } var out domain.ListOrganizationResponse - out.Organizations = make([]domain.ListOrganizationBody, len(*organizations)) + out.Organizations = make([]domain.OrganizationResponse, len(*organizations)) for i, organization := range *organizations { if err = serializer.Map(organization, &out.Organizations[i]); err != nil { @@ -206,6 +215,23 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req log.ErrorWithContext(r.Context(), err) } + out.Organization.StackTemplates = make([]domain.SimpleStackTemplateResponse, len(organization.StackTemplates)) + for i, stackTemplate := range organization.StackTemplates { + if err = serializer.Map(stackTemplate, &out.Organization.StackTemplates[i]); err != nil { + log.ErrorWithContext(r.Context(), err) + } + err := json.Unmarshal(stackTemplate.Services, &out.Organization.StackTemplates[i].Services) + if err != nil { + log.ErrorWithContext(r.Context(), err) + } + } + out.Organization.PolicyTemplates = make([]domain.SimplePolicyTemplateResponse, len(organization.PolicyTemplates)) + for i, policyTemplate := range organization.PolicyTemplates { + if err = serializer.Map(policyTemplate, &out.Organization.PolicyTemplates[i]); err != nil { + log.ErrorWithContext(r.Context(), err) + } + } + ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/model/organization.go b/internal/model/organization.go index 74264c16..f95a8a5b 100644 --- a/internal/model/organization.go +++ b/internal/model/organization.go @@ -3,6 +3,7 @@ package model import ( "gorm.io/gorm" + "github.com/google/uuid" "github.com/openinfradev/tks-api/pkg/domain" ) @@ -17,5 +18,10 @@ type Organization struct { WorkflowId string Status domain.OrganizationStatus StatusDesc string - Creator string + CreatorId *uuid.UUID `gorm:"type:uuid"` + StackTemplates []StackTemplate `gorm:"many2many:stack_template_organizations"` + PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organiations;"` + ClusterCount int `gorm:"-:all"` + AdminId *uuid.UUID + Admin *User `gorm:"foreignKey:AdminId"` } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 69ed3cce..7b21fb77 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -7,15 +7,17 @@ import ( "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" + "gorm.io/gorm/clause" ) // Interfaces type IOrganizationRepository interface { - Create(organizationId string, name string, creator uuid.UUID, phone string, description string) (model.Organization, error) + Create(dto *model.Organization) (model.Organization, error) Fetch(pg *pagination.Pagination) (res *[]model.Organization, err error) Get(organizationId string) (res model.Organization, err error) Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error + UpdateAdminId(organizationId string, adminId uuid.UUID) error Delete(organizationId string) (err error) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error } @@ -51,15 +53,14 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { // return nil //} -func (r *OrganizationRepository) Create(organizationId string, name string, creator uuid.UUID, phone string, - description string) (model.Organization, error) { +func (r *OrganizationRepository) Create(dto *model.Organization) (model.Organization, error) { organization := model.Organization{ - ID: organizationId, - Name: name, - Creator: creator.String(), - Phone: phone, - Description: description, + ID: dto.ID, + Name: dto.Name, + CreatorId: dto.CreatorId, + Description: dto.Description, Status: domain.OrganizationStatus_PENDING, + Phone: dto.Phone, } res := r.db.Create(&organization) if res.Error != nil { @@ -75,7 +76,7 @@ func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (out *[]model. pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db, &out) + _, res := pg.Fetch(r.db.Preload(clause.Associations), &out) if res.Error != nil { return nil, res.Error } @@ -83,12 +84,12 @@ func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (out *[]model. } func (r *OrganizationRepository) Get(id string) (out model.Organization, err error) { - res := r.db.First(&out, "id = ?", id) + res := r.db.Preload(clause.Associations). + First(&out, "id = ?", id) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return model.Organization{}, res.Error } - return } @@ -110,7 +111,6 @@ func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateO log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return model.Organization{}, res.Error } - return } @@ -128,6 +128,20 @@ func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, p return nil } +func (r *OrganizationRepository) UpdateAdminId(organizationId string, adminId uuid.UUID) (err error) { + res := r.db.Model(&model.Organization{}). + Where("id = ?", organizationId). + Updates(map[string]interface{}{ + "admin_id": adminId, + }) + + if res.Error != nil { + log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + return res.Error + } + return nil +} + func (r *OrganizationRepository) Delete(organizationId string) error { res := r.db.Delete(&model.Organization{}, "id = ?", organizationId) if res.Error != nil { diff --git a/internal/serializer/serializer.go b/internal/serializer/serializer.go index 043a9ba4..01fdec59 100644 --- a/internal/serializer/serializer.go +++ b/internal/serializer/serializer.go @@ -41,7 +41,15 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e continue } else if srcField.Type().Kind() == reflect.Struct && dstField.Type().Kind() == reflect.Struct { if err := recursiveMap(srcField.Interface(), dstField.Addr().Interface(), converterMap); err != nil { - return err + log.Error(err) + continue + } + } else if srcField.Kind() == reflect.Pointer && dstField.Type().Kind() == reflect.Struct { + if !reflect.Value.IsNil(srcField) { + if err := recursiveMap(srcField.Elem().Interface(), dstField.Addr().Interface(), converterMap); err != nil { + log.Error(err) + continue + } } } else { if functionExists(srcField.Interface(), "String") && @@ -66,7 +74,8 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e converterKey := compositeKey{srcType: srcField.Type(), dstType: dstField.Type()} if converter, ok := converterMap[converterKey]; ok { if converted, err := converter(srcField.Interface()); err != nil { - return err + log.Error(err) + continue } else { dstField.Set(reflect.ValueOf(converted)) } diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index dcc7bb60..7dafe447 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" @@ -25,41 +26,44 @@ type IOrganizationUsecase interface { Get(organizationId string) (model.Organization, error) Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) UpdatePrimaryClusterId(organizationId string, clusterId string) (err error) + ChangeAdminId(organizationId string, adminId uuid.UUID) error Delete(organizationId string, accessToken string) error } type OrganizationUsecase struct { - repo repository.IOrganizationRepository - roleRepo repository.IRoleRepository - argo argowf.ArgoClient - kc keycloak.IKeycloak + repo repository.IOrganizationRepository + roleRepo repository.IRoleRepository + clusterRepo repository.IClusterRepository + argo argowf.ArgoClient + kc keycloak.IKeycloak } func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClient, kc keycloak.IKeycloak) IOrganizationUsecase { return &OrganizationUsecase{ - repo: r.Organization, - roleRepo: r.Role, - argo: argoClient, - kc: kc, + repo: r.Organization, + roleRepo: r.Role, + clusterRepo: r.Cluster, + argo: argoClient, + kc: kc, } } func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization) (organizationId string, err error) { - creator := uuid.Nil - if in.Creator != "" { - creator, err = uuid.Parse(in.Creator) - if err != nil { - return "", err - } + user, ok := request.UserFrom(ctx) + if !ok { + return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } + userId := user.GetUserId() + in.CreatorId = &userId // Create realm in keycloak if organizationId, err = u.kc.CreateRealm(helper.GenerateOrganizationId()); err != nil { return "", err } + in.ID = organizationId // Create organization in DB - _, err = u.repo.Create(organizationId, in.Name, creator, in.Phone, in.Description) + _, err = u.repo.Create(in) if err != nil { return "", err } @@ -92,12 +96,20 @@ func (u *OrganizationUsecase) Fetch(pg *pagination.Pagination) (out *[]model.Org } return organizations, nil } -func (u *OrganizationUsecase) Get(organizationId string) (res model.Organization, err error) { - res, err = u.repo.Get(organizationId) +func (u *OrganizationUsecase) Get(organizationId string) (out model.Organization, err error) { + out, err = u.repo.Get(organizationId) if err != nil { return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") } - return res, nil + + clusters, err := u.clusterRepo.FetchByOrganizationId(organizationId, uuid.Nil, nil) + if err != nil { + log.Info(err) + out.ClusterCount = 0 + } + out.ClusterCount = len(clusters) + return out, nil + } func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) (err error) { @@ -161,3 +173,17 @@ func (u *OrganizationUsecase) UpdatePrimaryClusterId(organizationId string, clus } return nil } + +func (u *OrganizationUsecase) ChangeAdminId(organizationId string, adminId uuid.UUID) error { + _, err := u.Get(organizationId) + if err != nil { + return httpErrors.NewNotFoundError(err, "", "") + } + + err = u.repo.UpdateAdminId(organizationId, adminId) + if err != nil { + return err + } + + return nil +} diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 0d3bd907..b3ebef7d 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -19,7 +19,7 @@ import ( ) type IUserUsecase interface { - CreateAdmin(organizationId string, email string) (*model.User, error) + CreateAdmin(organizationId string, accountId string, accountName string, email string) (*model.User, error) DeleteAdmin(organizationId string) error DeleteAll(ctx context.Context, organizationId string) error Create(ctx context.Context, user *model.User) (*model.User, error) @@ -196,20 +196,20 @@ func (u *UserUsecase) DeleteAdmin(organizationId string) error { return nil } -func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*model.User, error) { +func (u *UserUsecase) CreateAdmin(organizationId string, accountId string, accountName string, email string) (*model.User, error) { // Generate Admin user object randomPassword := helper.GenerateRandomString(passwordLength) user := model.User{ - AccountId: "admin", + AccountId: accountId, Password: randomPassword, Email: email, Role: model.Role{ Name: "admin", }, Organization: model.Organization{ - ID: orgainzationId, + ID: organizationId, }, - Name: "admin", + Name: accountName, } // Create Admin user in keycloak & DB @@ -219,11 +219,11 @@ func (u *UserUsecase) CreateAdmin(orgainzationId string, email string) (*model.U } // Send mail of temporary password - organizationInfo, err := u.organizationRepository.Get(orgainzationId) + organizationInfo, err := u.organizationRepository.Get(organizationId) if err != nil { return nil, err } - message, err := mail.MakeGeneratingOrganizationMessage(orgainzationId, organizationInfo.Name, user.Email, user.AccountId, randomPassword) + message, err := mail.MakeGeneratingOrganizationMessage(organizationId, organizationInfo.Name, user.Email, user.AccountId, randomPassword) if err != nil { return nil, httpErrors.NewInternalServerError(err, "", "") } diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index efe7e5e3..7153744d 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -49,15 +49,19 @@ func (m OrganizationStatus) FromString(s string) OrganizationStatus { } type OrganizationResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Phone string `json:"phone"` - PrimaryClusterId string `json:"primaryClusterId"` - Status OrganizationStatus `json:"status"` - StatusDesc string `json:"statusDesc"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Phone string `json:"phone"` + PrimaryClusterId string `json:"primaryClusterId"` + Status string `json:"status"` + StatusDesc string `json:"statusDesc"` + StackTemplates []SimpleStackTemplateResponse `json:"stackTemplates"` + PolicyTemplates []SimplePolicyTemplateResponse `json:"policyTemplates"` + Admin SimpleUserResponse `json:"admin"` + ClusterCount int `json:"stackCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type SimpleOrganizationResponse = struct { @@ -67,10 +71,11 @@ type SimpleOrganizationResponse = struct { } type CreateOrganizationRequest struct { - Name string `json:"name" validate:"required,name"` - Description string `json:"description" validate:"omitempty,min=0,max=100"` - Phone string `json:"phone"` - Email string `json:"Email" validate:"required,email"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` + AdminAccountId string `json:"adminAccountId" validate:"required"` + AdminName string `json:"adminName" validate:"name"` + AdminEmail string `json:"adminEmail" validate:"required,email"` } type CreateOrganizationResponse struct { @@ -78,33 +83,12 @@ type CreateOrganizationResponse struct { } type GetOrganizationResponse struct { - Organization struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Phone string `json:"phone"` - PrimaryClusterId string `json:"primaryClusterId"` - Status string `json:"status"` - StatusDesc string `json:"statusDesc"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - } `json:"organization"` + Organization OrganizationResponse `json:"organization"` } type ListOrganizationResponse struct { - Organizations []ListOrganizationBody `json:"organizations"` + Organizations []OrganizationResponse `json:"organizations"` Pagination PaginationResponse `json:"pagination"` } -type ListOrganizationBody struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Phone string `json:"phone"` - PrimaryClusterId string `json:"primaryClusterId"` - Status string `json:"status"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} type UpdateOrganizationRequest struct { PrimaryClusterId string `json:"primaryClusterId"` diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index e2dd0810..20a0b80a 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -73,6 +73,14 @@ type PolicyTemplateResponse struct { PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` } +type SimplePolicyTemplateResponse struct { + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + Type string `json:"type" enums:"tks,organization" example:"tks"` + Name string `json:"templateName" example:"필수 Label 검사"` + Version string `json:"version,omitempty" example:"v1.0.1"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` +} + /* type PolicyTemplate struct { ID PolicyTemplateId diff --git a/pkg/domain/user.go b/pkg/domain/user.go index a4833494..c955425a 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -55,9 +55,11 @@ type CreateUserRequest struct { } type SimpleUserResponse struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Department string `json:"department"` + Email string `json:"email"` } type CreateUserResponse struct { diff --git a/scripts/patch_postgres.sql b/scripts/patch_postgres.sql new file mode 100644 index 00000000..00cdab42 --- /dev/null +++ b/scripts/patch_postgres.sql @@ -0,0 +1,7 @@ +# organization 에 신규로 추가된 admin_id 를 일괄 업데이트 하는 쿼리 +# v.4.0.0 deploy 후 아래 쿼리를 실행할 것 + +UPDATE organizations AS a +SET admin_id = b.id +FROM users b +WHERE b.account_id = 'admin' AND a.id = b.organization_id \ No newline at end of file From b4f060f1759ac27e18873251defb4986dff08d8c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 14 Mar 2024 18:05:09 +0900 Subject: [PATCH 118/502] feature. add api to stack-templates for checking name --- api/swagger/docs.go | 45 +++++++++++++++++++ api/swagger/swagger.json | 45 +++++++++++++++++++ api/swagger/swagger.yaml | 28 ++++++++++++ internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 ++++ internal/delivery/http/stack-template.go | 36 +++++++++++++++ internal/repository/stack-template.go | 9 ++++ internal/route/route.go | 1 + internal/usecase/stack-template.go | 17 ++++++- pkg/domain/stack-template.go | 4 ++ pkg/httpErrors/errorCode.go | 2 + 11 files changed, 195 insertions(+), 1 deletion(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 4a544877..9cae0a67 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1018,6 +1018,43 @@ const docTemplate = `{ } } }, + "/admin/stack-templates/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for stackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Check name for stackTemplate", + "parameters": [ + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse" + } + } + } + } + }, "/admin/stack-templates/services": { "get": { "security": [ @@ -7412,6 +7449,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 8872bcf7..f9433dab 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1012,6 +1012,43 @@ } } }, + "/admin/stack-templates/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for stackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Check name for stackTemplate", + "parameters": [ + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse" + } + } + } + } + }, "/admin/stack-templates/services": { "get": { "security": [ @@ -7406,6 +7443,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index a94fa389..49299b8e 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -497,6 +497,11 @@ definitions: existed: type: boolean type: object + github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse: + properties: + existed: + type: boolean + type: object github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse: properties: awsAccountId: @@ -3644,6 +3649,29 @@ paths: summary: Update StackTemplate organizations tags: - StackTemplates + /admin/stack-templates/name/{name}/existence: + get: + consumes: + - application/json + description: Check name for stackTemplate + parameters: + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse' + security: + - JWT: [] + summary: Check name for stackTemplate + tags: + - StackTemplates /admin/stack-templates/services: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 4c6a3bdd..f1482cd0 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -102,6 +102,7 @@ const ( Admin_UpdateStackTemplate Admin_DeleteStackTemplate Admin_UpdateStackTemplateOrganizations + Admin_CheckStackTemplateName GetOrganizationStackTemplates GetOrganizationStackTemplate diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 32a81fb6..26f11263 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -303,6 +303,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, + Admin_CheckStackTemplateName: { + Name: "Admin_CheckStackTemplateName", + Group: "StackTemplate", + }, GetOrganizationStackTemplates: { Name: "GetOrganizationStackTemplates", Group: "StackTemplate", @@ -888,6 +892,8 @@ func (e Endpoint) String() string { return "Admin_DeleteStackTemplate" case Admin_UpdateStackTemplateOrganizations: return "Admin_UpdateStackTemplateOrganizations" + case Admin_CheckStackTemplateName: + return "Admin_CheckStackTemplateName" case GetOrganizationStackTemplates: return "GetOrganizationStackTemplates" case GetOrganizationStackTemplate: @@ -1260,6 +1266,8 @@ func GetEndpoint(name string) Endpoint { return Admin_DeleteStackTemplate case "Admin_UpdateStackTemplateOrganizations": return Admin_UpdateStackTemplateOrganizations + case "Admin_CheckStackTemplateName": + return Admin_CheckStackTemplateName case "GetOrganizationStackTemplates": return GetOrganizationStackTemplates case "GetOrganizationStackTemplate": diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 60cad92a..724f9907 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -415,3 +415,39 @@ func (h *StackTemplateHandler) GetOrganizationStackTemplate(w http.ResponseWrite ResponseJSON(w, r, http.StatusOK, out) } + +// CheckStackTemplateName godoc +// +// @Tags StackTemplates +// @Summary Check name for stackTemplate +// @Description Check name for stackTemplate +// @Accept json +// @Produce json +// @Param name path string true "name" +// @Success 200 {object} domain.CheckStackTemplateNameResponse +// @Router /admin/stack-templates/name/{name}/existence [GET] +// @Security JWT +func (h *StackTemplateHandler) CheckStackTemplateName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name, ok := vars["name"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid name"), "ST_INVALID_STACK_TEMAPLTE_NAME", "")) + return + } + + exist := true + _, err := h.usecase.GetByName(r.Context(), name) + if err != nil { + if _, code := httpErrors.ErrorResponse(err); code == http.StatusNotFound { + exist = false + } else { + ErrorJSON(w, r, err) + return + } + } + + var out domain.CheckStackTemplateNameResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 103aec44..7fdf1b4e 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -12,6 +12,7 @@ import ( // Interfaces type IStackTemplateRepository interface { Get(stackTemplateId uuid.UUID) (model.StackTemplate, error) + GetByName(name string) (model.StackTemplate, error) Fetch(pg *pagination.Pagination) ([]model.StackTemplate, error) FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) @@ -39,6 +40,14 @@ func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out model.Stac return } +func (r *StackTemplateRepository) GetByName(name string) (out model.StackTemplate, err error) { + res := r.db.First(&out, "name = ?", name) + if res.Error != nil { + return out, res.Error + } + return +} + func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.StackTemplate, err error) { if pg == nil { pg = pagination.NewPagination(nil) diff --git a/internal/route/route.go b/internal/route/route.go index 0346e233..6c8f16a3 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -182,6 +182,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa stackTemplateHandler := delivery.NewStackTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/name/{name}/existence", customMiddleware.Handle(internalApi.Admin_CheckStackTemplateName, http.HandlerFunc(stackTemplateHandler.CheckStackTemplateName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}/organizations", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplateOrganizations, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplateOrganizations))).Methods(http.MethodPut) diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 4c672e7a..58edef83 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -12,6 +12,8 @@ import ( "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" + "gorm.io/gorm" ) type IStackTemplateUsecase interface { @@ -22,6 +24,7 @@ type IStackTemplateUsecase interface { Update(ctx context.Context, dto model.StackTemplate) error Delete(ctx context.Context, dto model.StackTemplate) error UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error + GetByName(ctx context.Context, name string) (model.StackTemplate, error) } type StackTemplateUsecase struct { @@ -94,11 +97,23 @@ func (u *StackTemplateUsecase) Update(ctx context.Context, dto model.StackTempla func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res model.StackTemplate, err error) { res, err = u.repo.Get(stackTemplateId) if err != nil { - return model.StackTemplate{}, err + return res, err } return } +func (u *StackTemplateUsecase) GetByName(ctx context.Context, name string) (out model.StackTemplate, err error) { + out, err = u.repo.GetByName(name) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return out, httpErrors.NewNotFoundError(err, "ST_FAILED_FETCH_STACK_TEMPLATE", "") + } + return out, err + } + + return +} + func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (res []model.StackTemplate, err error) { res, err = u.repo.Fetch(pg) if err != nil { diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index 122410d1..d25a570a 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -96,3 +96,7 @@ type GetStackTemplateServicesResponse struct { type UpdateStackTemplateOrganizationsRequest struct { OrganizationIds []string `json:"organizationIds" validate:"required"` } + +type CheckStackTemplateNameResponse struct { + Existed bool `json:"existed"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 342fecc5..8c51361d 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -83,6 +83,8 @@ var errorMap = map[ErrorCode]string{ "ST_CREATE_ALREADY_EXISTED_NAME": "스택 템플릿에 이미 존재하는 이름입니다.", "ST_FAILED_UPDATE_ORGANIZATION": "스택 템플릿에 조직을 설정하는데 실패했습니다.", "ST_NOT_EXISTED_STACK_TEMPLATE": "업데이트할 스택템플릿이 존재하지 않습니다.", + "ST_INVALID_STACK_TEMAPLTE_NAME": "유효하지 않은 스택템플릿 이름입니다. 스택템플릿 이름을 확인하세요.", + "ST_FAILED_FETCH_STACK_TEMPLATE": "스택템플릿을 가져오는데 실패했습니다.", // PolicyTemplate "PT_CREATE_ALREADY_EXISTED_NAME": "정첵 템플릿에 이미 존재하는 이름입니다.", From 5e32b2fafd31fa964837f1c022c3a4a93a84c73a Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 15 Mar 2024 12:58:25 +0900 Subject: [PATCH 119/502] enhance rego parameter extraction --- api/swagger/docs.go | 6 + api/swagger/swagger.json | 6 + api/swagger/swagger.yaml | 4 + internal/delivery/http/policy-template.go | 7 +- internal/usecase/policy-template-rego.go | 348 ++++++++++++++++++++++ internal/usecase/policy-template.go | 108 +------ pkg/domain/policy-template.go | 5 +- 7 files changed, 372 insertions(+), 112 deletions(-) create mode 100644 internal/usecase/policy-template-rego.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 57da07e4..37878fe7 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -9948,6 +9948,12 @@ const docTemplate = `{ "rego" ], "properties": { + "libs": { + "type": "array", + "items": { + "type": "string" + } + }, "rego": { "type": "string", "example": "Rego 코드" diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 01ede94c..95fb048a 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -9942,6 +9942,12 @@ "rego" ], "properties": { + "libs": { + "type": "array", + "items": { + "type": "string" + } + }, "rego": { "type": "string", "example": "Rego 코드" diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index afe88e01..e0de0963 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2160,6 +2160,10 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest: properties: + libs: + items: + type: string + type: array rego: example: Rego 코드 type: string diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index e747a98f..ac7d777e 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -635,11 +635,12 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, // @Router /policytemplates/rego-compile [post] // @Security JWT func (h *PolicyTemplateHandler) RegoCompile(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) parseParameter := false - parse, ok := vars["parseParameter"] - if ok { + urlParams := r.URL.Query() + + parse := urlParams.Get("parseParameter") + if len(parse) > 0 { parsedBool, err := strconv.ParseBool(parse) if err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid parseParameter: '%s'", parse), "PT_INVALID_REGO_PARSEPARAMETER", "")) diff --git a/internal/usecase/policy-template-rego.go b/internal/usecase/policy-template-rego.go new file mode 100644 index 00000000..53836580 --- /dev/null +++ b/internal/usecase/policy-template-rego.go @@ -0,0 +1,348 @@ +package usecase + +import ( + "regexp" + "sort" + "strings" + + "github.com/open-policy-agent/opa/ast" + "github.com/openinfradev/tks-api/pkg/domain" + "golang.org/x/exp/maps" +) + +const ( + input_param_prefix = "input.parameters" + input_extract_pattern = `input(\.parameters|\[\"parameters\"\])((\[\"[\w\-]+\"\])|(\[_\])|(\.\w+))*` //(\.\w+)*` // (\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))*` + // input_extract_pattern = `input\.parameters((\[\".+\"\])?(\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))+` + obj_get_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+)\, \"*([^,\"]+)\"*, [^\)]+\)` +) + +var ( + input_extract_regex = regexp.MustCompile(input_extract_pattern) + obj_get_regex = regexp.MustCompile(obj_get_pattern) +) + +func extractInputExprFromModule(module *ast.Module) []string { + rules := module.Rules + + passedInputMap := []string{} + + violationRule := []*ast.Rule{} + nonViolatonRule := []*ast.Rule{} + + for _, rule := range rules { + if rule.Head.Name == "violation" { + violationRule = append(violationRule, rule) + } else { + nonViolatonRule = append(nonViolatonRule, rule) + } + } + + paramRefs := map[string]string{} + + for _, rule := range violationRule { + processRule(rule, paramRefs, passedInputMap, nonViolatonRule) + } + + // 중복제거를 위해 사용한 맵을 소팅하기 위해 키 리스트로 변환 + paramRefsList := maps.Keys(paramRefs) + + /* 가장 depth가 깊은 변수부터 우선 처리해서 최초 trverse 시 child가 있는지 효율적으로 확인하기 위해 역순으로 정렬 + 이러한 소팅을 통해서 input.parameters.labels[_] 보다는 input.parameters.labels[_]의 자식들이 리스트의 앞순에 위치하도록 함 + input.parameters.labels[_]가 먼저 오면 input.parameters.labels[_]의 자식들이 존재 여부는 이 후 리스트 목록에 따라 달라지지만 + 역순으로 소팅한 상태에서는 항상 자식들이 리스트 앞에 위치 + + input.parameters.labels[_].key + input.parameters.labels[_].allowedRegex + input.parameters.labels[_] + */ + sort.Sort(sort.Reverse(sort.StringSlice(paramRefsList))) + + return paramRefsList +} + +func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []string, nonViolatonRule []*ast.Rule) { + exprs := rule.Body + localAssignMap := map[string]string{} + + for i, param := range passedParams { + if isSubstitutionRequired(param) { + argName := rule.Head.Args[i].String() + localAssignMap[argName] = param + } + } + + for _, expr := range exprs { + exprString := expr.String() + + exprString = substituteWithLocalAssignMap(localAssignMap, exprString) + exprString = replaceAllObjectGet(exprString) + exprString = substituteWithLocalAssignMap(localAssignMap, exprString) + + matches := input_extract_regex.FindAllString(exprString, -1) + + if len(matches) > 0 { + for _, match := range matches { + paramRefs[match] = "1" + } + } + + updateLocalAssignMap(expr, localAssignMap) + + if expr.IsCall() { + call := expr.Terms.([]*ast.Term) + if len(call) > 2 { + ruleName := call[0].String() + + args := call[1:] + + inputPassed, passingParams := processingInputArgs(args, localAssignMap) + + if inputPassed { + for _, nvrule := range nonViolatonRule { + if ruleName == nvrule.Head.Name.String() { + + processRule(nvrule, paramRefs, passingParams, nonViolatonRule) + } + } + } + } + } + + ast.WalkTerms(expr, func(t *ast.Term) bool { + switch t.Value.(type) { + case ast.Ref: // 인자가 없는 정책을 단순히 호출하는 경우, 호출하는 정책을 따라가 봄 + { + ruleRef := ([]*ast.Term)(t.Value.(ast.Ref)) + ruleName := ruleRef[0].Value.String() + + for _, nvrule := range nonViolatonRule { + if ruleName == nvrule.Head.Name.String() { + processRule(nvrule, paramRefs, []string{}, nonViolatonRule) + } + } + } + case ast.Call: // 인자가 있는 정책 호출, input 치환되는 인자가 있으면 passingParams으로 전달 + call := ([]*ast.Term)(t.Value.(ast.Call)) + + // 인자가 없으므로 처리 불필요 + if len(call) < 2 { + return false + } + + ruleName := call[0].String() + + args := call[1:] + + inputPassed, passingParams := processingInputArgs(args, localAssignMap) + + if inputPassed { + for _, nvrule := range nonViolatonRule { + if ruleName == nvrule.Head.Name.String() { + processRule(nvrule, paramRefs, passingParams, nonViolatonRule) + } + } + } + + return false + default: + for _, nvrule := range nonViolatonRule { + ruleName := nvrule.Head.Name.String() + if t.Value.String() == ruleName { + processRule(nvrule, paramRefs, []string{}, nonViolatonRule) + } + } + + return false + } + + return false + }) + } +} + +// object.get(object.get(input, "parameters", {}), "exemptImages", [])) -> input.parameters.exemptImages와 같은 패턴 변환 +func replaceAllObjectGet(expr string) string { + if !strings.Contains(expr, "object.get") { + return expr + } + + result := obj_get_regex.ReplaceAllString(expr, "$1.$2") + + if result == expr { + return expr + } + + return replaceAllObjectGet(result) +} + +func processingInputArgs(args []*ast.Term, localAssignMap map[string]string) (bool, []string) { + inputPassed := false + passingParams := []string{} + + for i := 0; i < len(args); i++ { + if args[i] != nil { + arg := args[i].String() + arg = substituteWithLocalAssignMap(localAssignMap, arg) + arg = replaceAllObjectGet(arg) + arg = substituteWithLocalAssignMap(localAssignMap, arg) + + if isSubstitutionRequired(arg) { + passingParams = append(passingParams, arg) + inputPassed = true + } + passingParams = append(passingParams, "") + } + } + return inputPassed, passingParams +} + +func updateLocalAssignMap(expr *ast.Expr, localAssignMap map[string]string) { + if expr.IsAssignment() { + vars := expr.Operand(0).Vars() + assigned := replaceAllObjectGet(expr.Operand(1).String()) + + if len(vars) == 1 && isSubstitutionRequired(assigned) { + localAssignMap[expr.Operand(0).String()] = assigned + } + } +} + +func substituteWithLocalAssignMap(localAssignMap map[string]string, exprString string) string { + for k, v := range localAssignMap { + //pattern := `([^\w\"])` + "parameters" + `([^\w\"])` + // pattern := `([ \[\]\(\)])` + k + `([ \[\]\(\)\.])` + + if strings.Contains(exprString, v) { + continue + } else if exprString == k { + exprString = v + } else { + pattern := `(\W)` + k + `(\W)` + + rx := regexp.MustCompile(pattern) + + exprString = rx.ReplaceAllString(exprString, `${1}`+v+`${2}`) + } + + } + return exprString +} + +func isSubstitutionRequired(expr string) bool { + trimmed := strings.TrimSpace(expr) + + // input.review 등 input.parameters가 아닌 input은 해석할 필요 없음 + // input이 assign 되었으면 input.review가 될지 parameter가 될지 모르므로 일단 input으로 대체 필요 + // input.parameters 자체를 변수로 assign하는 패턴도 처리 필요 + // input.parameters 하위의 속성도 처리 필요 + return trimmed == "input" || + trimmed == "input.parameters" || + strings.HasPrefix(trimmed, "input.parameters.") +} + +func extractParameter(modules map[string]*ast.Module) []*domain.ParameterDef { + defStore := NewParamDefStore() + + for _, module := range modules { + inputExprs := extractInputExprFromModule(module) + + for _, inputExpr := range inputExprs { + remainder := inputExpr[len(input_param_prefix):] + + // 문법 변환: aa["a"]["B"][_]->aa.a.B[_] + regex := regexp.MustCompile(`\[\"([\w-]+)\"\]`) + remainder = regex.ReplaceAllString(remainder, ".${1}") + + params := strings.Split(remainder, ".") + + if len(params) == 0 { + continue + } + + defStore.AddDefinition(params) + } + + } + + return defStore.store +} + +type ParamDefStore struct { + store []*domain.ParameterDef +} + +func NewParamDefStore() *ParamDefStore { + return &ParamDefStore{store: []*domain.ParameterDef{}} +} + +func (s *ParamDefStore) GetStore() []*domain.ParameterDef { + return s.store +} + +func (s *ParamDefStore) AddDefinition(params []string) { + init := &s.store + + for i, param := range params { + if param == "" { + continue + } + + isLast := i == len(params)-1 + + key := findKey(*init, param) + + if key == nil { + key = createKey(param, isLast) + + *init = append(*init, key) + } + + init = &key.Children + } +} + +func findKey(defs []*domain.ParameterDef, key string) *domain.ParameterDef { + for _, def := range defs { + if def.Key == key || def.Key+"[_]" == key { + return def + } + } + + return nil +} + +func createKey(key string, isLast bool) *domain.ParameterDef { + finalType := "any" + + pKey := key + isArray := false + + if strings.HasSuffix(pKey, "[_]") { + pKey, _ = strings.CutSuffix(pKey, "[_]") + isArray = true + } + + if isLast { + if isArray { + finalType = "any[]" + } else { + finalType = "any" + } + } else { + if isArray { + finalType = "object[]" + } else { + finalType = "object" + } + } + + newDef := &domain.ParameterDef{ + Key: pKey, + Type: finalType, + Children: []*domain.ParameterDef{}, + IsArray: isArray, + } + + return newDef +} diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 7c76a846..4222e2ae 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -3,8 +3,6 @@ package usecase import ( "context" "fmt" - "regexp" - "strings" "github.com/google/uuid" "github.com/open-policy-agent/opa/ast" @@ -274,112 +272,8 @@ func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, } if parseParameter { - response.ParametersSchema = extractParameter(request.Rego) + response.ParametersSchema = extractParameter(modules) } return response, nil } - -func extractParameter(rego string) []*domain.ParameterDef { - pattern := `input\.parameters\.[\w\.\[\]]+` - - prefix := "input.parameters." - - // Compile the regex pattern - regex := regexp.MustCompile(pattern) - - matches := regex.FindAllString(rego, -1) - - defStore := NewParamDefStore() - - for _, match := range matches { - remainder := match[len(prefix):] - - // 문법 변환: aa["a"]["B"][_]->aa.a.B[_] - regex := regexp.MustCompile(`\[\"(\w+)\"\]`) - remainder = regex.ReplaceAllString(remainder, ".$1") - - params := strings.Split(remainder, ".") - - if len(params) == 0 { - continue - } - - defStore.AddDefinition(params) - } - - return defStore.store -} - -type ParamDefStore struct { - store []*domain.ParameterDef -} - -func NewParamDefStore() *ParamDefStore { - return &ParamDefStore{store: []*domain.ParameterDef{}} -} - -func (s *ParamDefStore) GetStore() []*domain.ParameterDef { - return s.store -} - -func (s *ParamDefStore) AddDefinition(params []string) { - init := &s.store - - for i, param := range params { - isLast := i == len(params)-1 - - key := findKey(s.store, param) - - if key == nil { - key = createKey(param, isLast) - *init = append(*init, key) - } - - init = &key.Children - } -} - -func findKey(defs []*domain.ParameterDef, key string) *domain.ParameterDef { - for _, def := range defs { - if def.Key == key || def.Key+"[_]" == key { - return def - } - } - - return nil -} - -func createKey(key string, isLast bool) *domain.ParameterDef { - finalType := "any" - - pKey := key - isArray := false - - if strings.HasSuffix(pKey, "[_]") { - pKey, _ = strings.CutSuffix(pKey, "[_]") - isArray = true - } - - if isLast { - if isArray { - finalType = "any[]" - } else { - finalType = "any" - } - } else { - if isArray { - finalType = "object[]" - } else { - finalType = "object" - } - } - - newDef := &domain.ParameterDef{ - Key: pKey, - Type: finalType, - Children: []*domain.ParameterDef{}, - } - - return newDef -} diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 20a0b80a..5faa8640 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -291,11 +291,12 @@ type ParameterDef struct { Type string `json:"type"` DefaultValue string `json:"defaultValue"` Children []*ParameterDef `json:"children"` - IsArray bool + IsArray bool `json:"isArray"` } type RegoCompileRequest struct { - Rego string `json:"rego" example:"Rego 코드" validate:"required"` + Rego string `json:"rego" example:"Rego 코드" validate:"required"` + Libs []string `json:"libs,omitempty"` } type RegoCompieError struct { From bde599db77d00b1b5fca0d8367ce24044c396579 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 8 Mar 2024 11:16:35 +0900 Subject: [PATCH 120/502] remove unused files --- internal/usecase/role_test.go | 217 ---------------------------------- 1 file changed, 217 deletions(-) delete mode 100644 internal/usecase/role_test.go diff --git a/internal/usecase/role_test.go b/internal/usecase/role_test.go deleted file mode 100644 index a0b47c5b..00000000 --- a/internal/usecase/role_test.go +++ /dev/null @@ -1,217 +0,0 @@ -package usecase_test - -import ( - "fmt" - "gorm_test/config" - "testing" - - "github.com/google/uuid" - myRepository "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/internal/usecase" - "gorm.io/driver/postgres" - "gorm.io/gorm" -) - -func TestNewRoleUsecase(t *testing.T) { - conf := config.NewDefaultConfig() - dsn := fmt.Sprintf( - "host=%s dbname=%s user=%s password=%s port=%d sslmode=disable TimeZone=Asia/Seoul", - conf.Address, conf.Database, conf.AdminId, conf.AdminPassword, conf.Port, - ) - - t.Logf("dsn: %s", dsn) - - db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) - if err != nil { - panic(err) - } - - if err = db.AutoMigrate(&myRepository.Organization{}); err != nil { - panic(err) - } - if err = db.AutoMigrate(&myRepository.Role{}); err != nil { - panic(err) - } - if err = db.AutoMigrate(&myRepository.TksRole{}); err != nil { - panic(err) - } - if err = db.AutoMigrate(&myRepository.ProjectRole{}); err != nil { - panic(err) - } - - orgaizationRepository := myRepository.NewOrganizationRepository(db) - roleDbClient := myRepository.NewRoleRepository(db) - - roleUsecase := usecase.NewRoleUsecase(roleDbClient) - - // create organization - // organizationId = "test" - if _, err := orgaizationRepository.Get("test"); err != nil { - if _, err := orgaizationRepository.Create("test", "test", uuid.New(), "test", "test"); err != nil { - panic(err) - } - } - - // create project - // projectName = "testProject" - projectRepository := myRepository.NewProjectRepository(db) - projectFound := false - if projects, err := projectRepository.List(); err != nil { - panic(err) - } else { - for _, project := range projects { - if project.Name == "testProject" { - projectFound = true - break - } - } - } - - if !projectFound { - project := &domain.Project{ - Name: "testProject", - OrganizationID: "test", - Description: "testDesc", - } - if err := projectRepository.Create(project); err != nil { - panic(err) - } - } - - // get id of project - projects, err := projectRepository.List() - if err != nil { - panic(err) - } - var projectId uuid.UUID - for _, project := range projects { - if project.Name == "testProject" { - projectId = project.ID - break - } - } - - // create tks role - tksRoles, err := roleUsecase.ListTksRoles() - if err != nil { - panic(err) - } - tksRoleFound := false - for _, role := range tksRoles { - if role.Name == "testTksRole" { - tksRoleFound = true - break - } - } - if !tksRoleFound { - role := &domain.TksRole{ - Role: domain.Role{ - Name: "testTksRole", - OrganizationID: "test", - Description: "testDesc", - }, - } - if err := roleUsecase.CreateTksRole(role); err != nil { - panic(err) - } - } - - // create project role - projectRoles, err := roleUsecase.ListProjectRoles() - if err != nil { - panic(err) - } - - projectRoleFound := false - for _, role := range projectRoles { - if role.Role.Name == "testProjectRole" { - projectRoleFound = true - break - } - } - - if !projectRoleFound { - role := &domain.ProjectRole{ - Role: domain.Role{ - Name: "testProjectRole", - OrganizationID: "test", - Description: "testDesc", - }, - ProjectID: projectId, - } - if err := roleUsecase.CreateProjectRole(role); err != nil { - panic(err) - } - } - - // list tks role - tksRoles, err = roleUsecase.ListTksRoles() - if err != nil { - panic(err) - } - for i, role := range tksRoles { - t.Logf("index: %d, tksRole: %+v", i, role) - } - - // list project role - projectRoles, err = roleUsecase.ListProjectRoles() - if err != nil { - panic(err) - } - for i, role := range projectRoles { - t.Logf("index: %d, projectRole: %+v", i, role) - } - - // list all role - roles, err := roleUsecase.ListRoles() - if err != nil { - panic(err) - } - for i, role := range roles { - t.Logf("index: %d, role: %+v", i, role) - } - - t.Logf("now delete all roles") - - // delete tks role - for _, role := range tksRoles { - if err := roleDbClient.Delete(role.RoleID); err != nil { - panic(err) - } - } - - // delete project role - for _, role := range projectRoles { - if err := roleDbClient.Delete(role.RoleID); err != nil { - panic(err) - } - } - - // print tks role - tksRoles, err = roleUsecase.ListTksRoles() - if err != nil { - panic(err) - } - for i, role := range tksRoles { - t.Logf("index: %d, tksRole: %+v", i, role) - } - - // print project role - projectRoles, err = roleUsecase.ListProjectRoles() - if err != nil { - panic(err) - } - for i, role := range projectRoles { - t.Logf("index: %d, projectRole: %+v", i, role) - } - - // print all role - roles, err = roleUsecase.ListRoles() - if err != nil { - panic(err) - } - for i, role := range roles { - t.Logf("index: %d, role: %+v", i, role) - } - -} From 7a6474853c25c93118b9ee1d92ef9105e62543aa Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 8 Mar 2024 11:18:37 +0900 Subject: [PATCH 121/502] improvement: make for sql log to contain req IDt --- internal/database/database.go | 4 +- internal/gorm/gorm.go | 152 +++++++++++++++++++++++++++++ pkg/log/log.go | 179 ++++++++++++++++++---------------- 3 files changed, 249 insertions(+), 86 deletions(-) create mode 100644 internal/gorm/gorm.go diff --git a/internal/database/database.go b/internal/database/database.go index 4c34a427..96ffa3eb 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -7,6 +7,7 @@ import ( "github.com/openinfradev/tks-api/internal/delivery/api" + internal_gorm "github.com/openinfradev/tks-api/internal/gorm" "github.com/spf13/viper" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -37,9 +38,10 @@ func InitDB() (*gorm.DB, error) { default: level = logger.Silent } + newLogger := internal_gorm.NewGormLogger().LogMode(level) db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ - Logger: logger.Default.LogMode(level), + Logger: newLogger, }) if err != nil { return nil, err diff --git a/internal/gorm/gorm.go b/internal/gorm/gorm.go new file mode 100644 index 00000000..37bd2deb --- /dev/null +++ b/internal/gorm/gorm.go @@ -0,0 +1,152 @@ +// This file contains the custom Gorm logger +// Origin Source: https://github.com/go-gorm/gorm/blob/master/logger/logger.go +// Author: Jinzhu +// Changes: Modified functions related to logging +// Licensed under the MIT License +/* +The MIT License (MIT) + +Copyright (c) 2013-NOW Jinzhu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package gorm + +import ( + "context" + "fmt" + internalLogger "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" + "gorm.io/gorm/logger" + "gorm.io/gorm/utils" + "time" +) + +func (l *customGormLogger) LogMode(level logger.LogLevel) logger.Interface { + newlogger := *l + newlogger.LogLevel = level + return &newlogger +} + +func (l *customGormLogger) Info(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= logger.Info { + internalLogger.InfofWithContext(ctx, l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + } +} + +func (l *customGormLogger) Warn(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= logger.Warn { + internalLogger.WarnfWithContext(ctx, l.warnStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + } +} + +func (l *customGormLogger) Error(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= logger.Error { + internalLogger.ErrorfWithContext(ctx, l.errStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + } +} + +func (l *customGormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) { + if l.LogLevel <= logger.Silent { + return + } + + elapsed := time.Since(begin) + switch { + case err != nil && l.LogLevel >= logger.Error && (!errors.Is(err, logger.ErrRecordNotFound) || !l.IgnoreRecordNotFoundError): + sql, rows := fc() + if rows == -1 { + internalLogger.ErrorfWithContext(ctx, l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql) + //l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + internalLogger.ErrorfWithContext(ctx, l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql) + //l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= logger.Warn: + sql, rows := fc() + slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold) + if rows == -1 { + internalLogger.WarnfWithContext(ctx, l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql) + //l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + internalLogger.WarnfWithContext(ctx, l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql) + //l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + case l.LogLevel == logger.Info: + sql, rows := fc() + if rows == -1 { + internalLogger.InfofWithContext(ctx, l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql) + //l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + internalLogger.InfofWithContext(ctx, l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql) + //l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + default: + internalLogger.Info("Trace") + } +} + +type customGormLogger struct { + logger.Writer + logger.Config + infoStr, warnStr, errStr string + traceStr, traceErrStr, traceWarnStr string +} + +const ( + Reset = "\033[0m" + Red = "\033[31m" + Green = "\033[32m" + Yellow = "\033[33m" + Blue = "\033[34m" + Magenta = "\033[35m" + Cyan = "\033[36m" + White = "\033[37m" + BlueBold = "\033[34;1m" + MagentaBold = "\033[35;1m" + RedBold = "\033[31;1m" + YellowBold = "\033[33;1m" +) + +func NewGormLogger() logger.Interface { + infoStr := Green + "%s\n" + Reset + Green + "[info] " + Reset + warnStr := BlueBold + "%s\n" + Reset + Magenta + "[warn] " + Reset + errStr := Magenta + "%s\n" + Reset + Red + "[error] " + Reset + traceStr := Green + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s" + traceWarnStr := Green + "%s " + Yellow + "%s\n" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset + traceErrStr := RedBold + "%s " + MagentaBold + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s" + + return &customGormLogger{ + Writer: customGormLogger{}, + Config: logger.Config{ + SlowThreshold: time.Second, + LogLevel: logger.Silent, + IgnoreRecordNotFoundError: true, + ParameterizedQueries: true, + Colorful: false, + }, + infoStr: infoStr, + warnStr: warnStr, + errStr: errStr, + traceStr: traceStr, + traceErrStr: traceErrStr, + traceWarnStr: traceWarnStr, + } +} diff --git a/pkg/log/log.go b/pkg/log/log.go index 2a5bf3bc..a88eac18 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -2,6 +2,7 @@ package log import ( "context" + "fmt" "io" "os" "runtime" @@ -48,17 +49,65 @@ type CustomFormatter struct { logrus.Formatter } +var colors = map[logrus.Level]string{ + logrus.DebugLevel: "\033[36m", // Cyan + logrus.InfoLevel: "\033[32m", // Green + logrus.WarnLevel: "\033[33m", // Yellow + logrus.ErrorLevel: "\033[31m", // Red + logrus.FatalLevel: "\033[31m", // Red + logrus.PanicLevel: "\033[31m", // Red +} + +func getColor(level logrus.Level) string { + return colors[level] +} + func (f *CustomFormatter) Format(entry *logrus.Entry) ([]byte, error) { - //_, file := path.Split(entry.Caller.File) - //entry.Data["file"] = file - return f.Formatter.Format(entry) + levelColor := getColor(entry.Level) + resetColor := "\033[0m" + levelText := strings.ToUpper(entry.Level.String()) + + requestIDColorStart := "\033[34m" // 파란색 시작 + requestIDColorEnd := "\033[0m" // 색상 리셋 + + requestID := entry.Data[string(internal.ContextKeyRequestID)] + if requestID == nil { + requestID = "Unknown" + } else { + requestID = fmt.Sprintf("%s%v%s", requestIDColorStart, requestID, requestIDColorEnd) + } + file := entry.Data["file"] + if file == nil { + file = "-" + } + var logMessage string + + if file == "-" { + logMessage = fmt.Sprintf("%s%-7s%s %s %sREQUEST_ID=%v%s msg=%s\n", + levelColor, levelText, resetColor, + entry.Time.Format("2006-01-02 15:04:05"), + requestIDColorStart, requestID, requestIDColorEnd, + entry.Message, + ) + } else { + logMessage = fmt.Sprintf("%s%-7s%s %s %sREQUEST_ID=%v%s msg=%s file= %v\n", + levelColor, levelText, resetColor, + entry.Time.Format("2006-01-02 15:04:05"), + requestIDColorStart, requestID, requestIDColorEnd, + entry.Message, + file, + ) + } + + return []byte(logMessage), nil } // [TODO] more pretty func Info(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Info(v...) } else { logger.Info(v...) @@ -66,40 +115,26 @@ func Info(v ...interface{}) { } func Infof(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Infof(format, v...) } else { logger.Infof(format, v...) } } func InfoWithContext(ctx context.Context, v ...interface{}) { - reqID := ctx.Value(internal.ContextKeyRequestID) - if _, file, line, ok := runtime.Caller(1); ok { - logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), - string(internal.ContextKeyRequestID): reqID, - }).Info(v...) - } else { - logger.WithField(string(internal.ContextKeyRequestID), reqID).Info(v...) - } + logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Info(v...) } func InfofWithContext(ctx context.Context, format string, v ...interface{}) { - reqID := ctx.Value(internal.ContextKeyRequestID) - if _, file, line, ok := runtime.Caller(1); ok { - logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), - string(internal.ContextKeyRequestID): reqID, - }).Infof(format, v...) - } else { - logger.WithField(string(internal.ContextKeyRequestID), reqID).Infof(format, v...) - } + logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Infof(format, v...) } func Warn(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Warn(v...) } else { logger.Warn(v...) @@ -107,40 +142,26 @@ func Warn(v ...interface{}) { } func Warnf(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Warnf(format, v...) } else { logger.Warnf(format, v...) } } func WarnWithContext(ctx context.Context, v ...interface{}) { - reqID := ctx.Value(internal.ContextKeyRequestID) - if _, file, line, ok := runtime.Caller(1); ok { - logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), - string(internal.ContextKeyRequestID): reqID, - }).Warn(v...) - } else { - logger.WithField(string(internal.ContextKeyRequestID), reqID).Warn(v...) - } + logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Warn(v...) } func WarnfWithContext(ctx context.Context, format string, v ...interface{}) { - reqID := ctx.Value(internal.ContextKeyRequestID) - if _, file, line, ok := runtime.Caller(1); ok { - logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), - string(internal.ContextKeyRequestID): reqID, - }).Warnf(format, v...) - } else { - logger.WithField(string(internal.ContextKeyRequestID), reqID).Warnf(format, v...) - } + logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Warnf(format, v...) } func Debug(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Debug(v...) } else { logger.Debug(v...) @@ -148,40 +169,26 @@ func Debug(v ...interface{}) { } func Debugf(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Debugf(format, v...) } else { logger.Debugf(format, v...) } } func DebugWithContext(ctx context.Context, v ...interface{}) { - reqID := ctx.Value(internal.ContextKeyRequestID) - if _, file, line, ok := runtime.Caller(1); ok { - logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), - string(internal.ContextKeyRequestID): reqID, - }).Debug(v...) - } else { - logger.WithField(string(internal.ContextKeyRequestID), reqID).Debug(v...) - } + logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Debug(v...) } func DebugfWithContext(ctx context.Context, format string, v ...interface{}) { - reqID := ctx.Value(internal.ContextKeyRequestID) - if _, file, line, ok := runtime.Caller(1); ok { - logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), - string(internal.ContextKeyRequestID): reqID, - }).Debugf(format, v...) - } else { - logger.WithField(string(internal.ContextKeyRequestID), reqID).Debugf(format, v...) - } + logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Debugf(format, v...) } func Error(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Error(v...) } else { logger.Error(v...) @@ -189,40 +196,26 @@ func Error(v ...interface{}) { } func Errorf(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Errorf(format, v...) } else { logger.Errorf(format, v...) } } func ErrorWithContext(ctx context.Context, v ...interface{}) { - reqID := ctx.Value(internal.ContextKeyRequestID) - if _, file, line, ok := runtime.Caller(1); ok { - logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), - string(internal.ContextKeyRequestID): reqID, - }).Error(v...) - } else { - logger.WithField(string(internal.ContextKeyRequestID), reqID).Error(v...) - } + logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Error(v...) } func ErrorfWithContext(ctx context.Context, format string, v ...interface{}) { - reqID := ctx.Value(internal.ContextKeyRequestID) - if _, file, line, ok := runtime.Caller(1); ok { - logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), - string(internal.ContextKeyRequestID): reqID, - }).Errorf(format, v...) - } else { - logger.WithField(string(internal.ContextKeyRequestID), reqID).Errorf(format, v...) - } + logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Errorf(format, v...) } func Fatal(v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Fatal(v...) } else { logger.Fatal(v...) @@ -230,8 +223,9 @@ func Fatal(v ...interface{}) { } func Fatalf(format string, v ...interface{}) { if _, file, line, ok := runtime.Caller(1); ok { + relativePath := getRelativeFilePath(file) logger.WithFields(logrus.Fields{ - "file": file + ":" + strconv.Itoa(line), + "file": relativePath + ":" + strconv.Itoa(line), }).Fatalf(format, v...) } else { logger.Fatalf(format, v...) @@ -241,3 +235,18 @@ func Fatalf(format string, v ...interface{}) { func Disable() { logger.Out = io.Discard } + +func getRelativeFilePath(absolutePath string) string { + wd, err := os.Getwd() + if err != nil { + return absolutePath + } + + relativePath := strings.TrimPrefix(absolutePath, wd) + + if strings.HasPrefix(relativePath, "/") { + relativePath = relativePath[1:] + } + + return relativePath +} From 22e51521a7caff2b0d982d5c0d6a3b8d0b8fbff8 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 12 Mar 2024 17:20:30 +0900 Subject: [PATCH 122/502] fix conflict during rebase --- internal/database/database.go | 8 +- internal/delivery/http/app-serve-app.go | 37 +- internal/delivery/http/auth.go | 47 +- internal/delivery/http/organization.go | 30 +- internal/delivery/http/permission.go | 4 +- internal/delivery/http/role.go | 18 +- internal/delivery/http/user.go | 26 +- internal/middleware/audit/audit.go | 2 +- .../middleware/auth/authorizer/password.go | 2 +- internal/middleware/auth/authorizer/rbac.go | 24 + internal/repository/alert.go | 53 ++- internal/repository/app-group.go | 55 +-- internal/repository/app-serve-app.go | 102 ++-- internal/repository/audit.go | 23 +- internal/repository/auth.go | 25 +- internal/repository/cloud-account.go | 49 +- internal/repository/cluster.go | 73 +-- internal/repository/endpoint.go | 19 +- internal/repository/organization.go | 49 +- internal/repository/permission.go | 31 +- internal/repository/permission_test.go | 445 ------------------ internal/repository/project.go | 163 +++---- internal/repository/role.go | 69 +-- internal/repository/stack-template.go | 51 +- internal/repository/user.go | 166 +++---- internal/route/route.go | 1 - internal/usecase/alert.go | 24 +- internal/usecase/app-group.go | 28 +- internal/usecase/app-serve-app.go | 124 +++-- internal/usecase/audit.go | 8 +- internal/usecase/auth.go | 123 ++--- internal/usecase/auth_test.go | 9 - internal/usecase/cloud-account.go | 40 +- internal/usecase/cluster.go | 58 +-- internal/usecase/dashboard.go | 32 +- internal/usecase/organization.go | 54 +-- internal/usecase/permission.go | 58 ++- internal/usecase/project.go | 74 +-- internal/usecase/role.go | 36 +- internal/usecase/stack-template.go | 20 +- internal/usecase/stack.go | 62 +-- internal/usecase/user.go | 94 ++-- 42 files changed, 917 insertions(+), 1499 deletions(-) delete mode 100644 internal/repository/permission_test.go delete mode 100644 internal/usecase/auth_test.go diff --git a/internal/database/database.go b/internal/database/database.go index 96ffa3eb..37485621 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -1,6 +1,7 @@ package database import ( + "context" "fmt" "os" "strings" @@ -176,7 +177,10 @@ func EnsureDefaultRows(db *gorm.DB) error { } // - eps, err := repoFactory.Endpoint.List(nil) + + ctx := context.Background() + + eps, err := repoFactory.Endpoint.List(ctx, nil) if err != nil { return err } @@ -187,7 +191,7 @@ func EnsureDefaultRows(db *gorm.DB) error { } for _, ep := range api.ApiMap { if _, ok := storedEps[ep.Name]; !ok { - if err := repoFactory.Endpoint.Create(&model.Endpoint{ + if err := repoFactory.Endpoint.Create(ctx, &model.Endpoint{ Name: ep.Name, Group: ep.Group, }); err != nil { diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index aa6f92b1..de7cbe7f 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -152,7 +152,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re return } - exist, err := h.usecase.IsAppServeAppNameExist(organizationId, app.Name) + exist, err := h.usecase.IsAppServeAppNameExist(r.Context(), organizationId, app.Name) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -173,7 +173,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re r1 := rand.New(src) ns = fmt.Sprintf("%s-%s", app.Name, strconv.Itoa(r1.Intn(10000))) - nsExist, err = h.usecase.IsAppServeAppNamespaceExist(app.TargetClusterId, ns) + nsExist, err = h.usecase.IsAppServeAppNamespaceExist(r.Context(), app.TargetClusterId, ns) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -201,7 +201,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re return } - _, _, err = h.usecase.CreateAppServeApp(&app) + _, _, err = h.usecase.CreateAppServeApp(r.Context(), &app) if err != nil { ErrorJSON(w, r, err) return @@ -257,7 +257,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ return } pg := pagination.NewPagination(&urlParams) - apps, err := h.usecase.GetAppServeApps(organizationId, showAll, pg) + apps, err := h.usecase.GetAppServeApps(r.Context(), organizationId, showAll, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get Failed to get app-serve-apps ", err) ErrorJSON(w, r, err) @@ -314,7 +314,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid appId"), "C_INVALID_ASA_ID", "")) return } - app, err := h.usecase.GetAppServeAppById(appId) + app, err := h.usecase.GetAppServeAppById(r.Context(), appId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -376,7 +376,7 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid appId"), "", "")) return } - task, err := h.usecase.GetAppServeAppLatestTask(appId) + task, err := h.usecase.GetAppServeAppLatestTask(r.Context(), appId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -424,7 +424,7 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. } fmt.Printf("stackId = [%s]\n", stackId) - numApps, err := h.usecase.GetNumOfAppsOnStack(organizationId, stackId) + numApps, err := h.usecase.GetNumOfAppsOnStack(r.Context(), organizationId, stackId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -467,7 +467,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - tasks, err := h.usecase.GetAppServeAppTasks(appId, pg) + tasks, err := h.usecase.GetAppServeAppTasks(r.Context(), appId, pg) if err != nil { log.ErrorWithContext(r.Context(), "Failed to get app-serve-app-tasks ", err) ErrorJSON(w, r, err) @@ -535,7 +535,7 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * return } - task, app, err := h.usecase.GetAppServeAppTaskById(taskId) + task, app, err := h.usecase.GetAppServeAppTaskById(r.Context(), taskId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -693,7 +693,7 @@ func (h *AppServeAppHandler) IsAppServeAppExist(w http.ResponseWriter, r *http.R return } - exist, err := h.usecase.IsAppServeAppExist(appId) + exist, err := h.usecase.IsAppServeAppExist(r.Context(), appId) if err != nil { ErrorJSON(w, r, err) return @@ -734,7 +734,7 @@ func (h *AppServeAppHandler) IsAppServeAppNameExist(w http.ResponseWriter, r *ht return } - existed, err := h.usecase.IsAppServeAppNameExist(organizationId, appName) + existed, err := h.usecase.IsAppServeAppNameExist(r.Context(), organizationId, appName) if err != nil { ErrorJSON(w, r, err) return @@ -776,7 +776,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re return } - app, err := h.usecase.GetAppServeAppById(appId) + app, err := h.usecase.GetAppServeAppById(r.Context(), appId) if err != nil { ErrorJSON(w, r, err) return @@ -843,11 +843,11 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re var res string if appReq.Promote { - res, err = h.usecase.PromoteAppServeApp(appId) + res, err = h.usecase.PromoteAppServeApp(r.Context(), appId) } else if appReq.Abort { - res, err = h.usecase.AbortAppServeApp(appId) + res, err = h.usecase.AbortAppServeApp(r.Context(), appId) } else { - res, err = h.usecase.UpdateAppServeApp(app, &task) + res, err = h.usecase.UpdateAppServeApp(r.Context(), app, &task) } if err != nil { @@ -894,7 +894,7 @@ func (h *AppServeAppHandler) UpdateAppServeAppStatus(w http.ResponseWriter, r *h return } - res, err := h.usecase.UpdateAppServeAppStatus(appId, appStatusReq.TaskID, appStatusReq.Status, appStatusReq.Output) + res, err := h.usecase.UpdateAppServeAppStatus(r.Context(), appId, appStatusReq.TaskID, appStatusReq.Status, appStatusReq.Output) if err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -940,6 +940,7 @@ func (h *AppServeAppHandler) UpdateAppServeAppEndpoint(w http.ResponseWriter, r } res, err := h.usecase.UpdateAppServeAppEndpoint( + r.Context(), appId, appReq.TaskID, appReq.EndpointUrl, @@ -981,7 +982,7 @@ func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Re return } - res, err := h.usecase.DeleteAppServeApp(appId) + res, err := h.usecase.DeleteAppServeApp(r.Context(), appId) if err != nil { log.ErrorWithContext(r.Context(), "Failed to delete appId err : ", err) ErrorJSON(w, r, err) @@ -1031,7 +1032,7 @@ func (h *AppServeAppHandler) RollbackAppServeApp(w http.ResponseWriter, r *http. return } - res, err := h.usecase.RollbackAppServeApp(appId, appReq.TaskId) + res, err := h.usecase.RollbackAppServeApp(r.Context(), appId, appReq.TaskId) if err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index d2fea4d3..36359785 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -19,7 +19,6 @@ type IAuthHandler interface { Login(w http.ResponseWriter, r *http.Request) Logout(w http.ResponseWriter, r *http.Request) // Deprecated: PingToken is deprecated. Use VerifyToken instead. - PingToken(w http.ResponseWriter, r *http.Request) RefreshToken(w http.ResponseWriter, r *http.Request) FindId(w http.ResponseWriter, r *http.Request) FindPassword(w http.ResponseWriter, r *http.Request) @@ -59,7 +58,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { return } - user, err := h.usecase.Login(input.AccountId, input.Password, input.OrganizationId) + user, err := h.usecase.Login(r.Context(), input.AccountId, input.Password, input.OrganizationId) if err != nil { errorResponse, _ := httpErrors.ErrorResponse(err) _, _ = h.auditUsecase.Create(r.Context(), model.Audit{ @@ -85,7 +84,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { } var cookies []*http.Cookie - if targetCookies, err := h.usecase.SingleSignIn(input.OrganizationId, input.AccountId, input.Password); err != nil { + if targetCookies, err := h.usecase.SingleSignIn(r.Context(), input.OrganizationId, input.AccountId, input.Password); err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) } else { cookies = append(cookies, targetCookies...) @@ -132,7 +131,7 @@ func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { } organizationId := userInfo.GetOrganizationId() - err := h.usecase.Logout(sessionId, organizationId) + err := h.usecase.Logout(r.Context(), sessionId, organizationId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) @@ -140,7 +139,7 @@ func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { } var cookies []*http.Cookie - redirectUrl, targetCookies, err := h.usecase.SingleSignOut(organizationId) + redirectUrl, targetCookies, err := h.usecase.SingleSignOut(r.Context(), organizationId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) } @@ -184,7 +183,7 @@ func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { return } - accountId, err := h.usecase.FindId(input.Code, input.Email, input.UserName, input.OrganizationId) + accountId, err := h.usecase.FindId(r.Context(), input.Code, input.Email, input.UserName, input.OrganizationId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -216,7 +215,7 @@ func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { return } - err = h.usecase.FindPassword(input.Code, input.AccountId, input.Email, input.UserName, input.OrganizationId) + err = h.usecase.FindPassword(r.Context(), input.Code, input.AccountId, input.Email, input.UserName, input.OrganizationId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -245,7 +244,7 @@ func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Req return } - err = h.usecase.VerifyIdentity("", input.Email, input.UserName, input.OrganizationId) + err = h.usecase.VerifyIdentity(r.Context(), "", input.Email, input.UserName, input.OrganizationId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -276,7 +275,7 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht return } - err = h.usecase.VerifyIdentity(input.AccountId, input.Email, input.UserName, input.OrganizationId) + err = h.usecase.VerifyIdentity(r.Context(), input.AccountId, input.Email, input.UserName, input.OrganizationId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -288,34 +287,6 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht ResponseJSON(w, r, http.StatusOK, out) } -// Login godoc -// -// @Tags Auth -// @Summary ping with token -// @Description ping with token -// @Accept json -// @Produce json -// @Param body body domain.PingTokenRequest true "token info" -// @Success 200 {object} nil -// @Router /auth/ping [post] -func (h *AuthHandler) PingToken(w http.ResponseWriter, r *http.Request) { - input := domain.PingTokenRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - ErrorJSON(w, r, err) - return - } - - err = h.usecase.PingToken(input.Token, input.OrganizationId) - if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } - - ResponseJSON(w, r, http.StatusOK, nil) -} - // VerifyToken godoc // @Tags Auth // @Summary verify token @@ -332,7 +303,7 @@ func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { return } - isActive, err := h.usecase.VerifyToken(token) + isActive, err := h.usecase.VerifyToken(r.Context(), token) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index a588758d..77f77841 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -74,7 +74,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. Description: "admin", Type: string(domain.RoleTypeTks), } - adminRoleId, err := h.roleUsecase.CreateTksRole(&adminRole) + adminRoleId, err := h.roleUsecase.CreateTksRole(r.Context(), &adminRole) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -86,7 +86,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. Description: "user", Type: string(domain.RoleTypeTks), } - userRoleId, err := h.roleUsecase.CreateTksRole(&userRole) + userRoleId, err := h.roleUsecase.CreateTksRole(r.Context(), &userRole) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -94,18 +94,18 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } // Permission 생성 - adminPermissionSet := h.permissionUsecase.GetAllowedPermissionSet() - h.permissionUsecase.SetRoleIdToPermissionSet(adminRoleId, adminPermissionSet) - err = h.permissionUsecase.CreatePermissionSet(adminPermissionSet) + adminPermissionSet := h.permissionUsecase.GetAllowedPermissionSet(r.Context()) + h.permissionUsecase.SetRoleIdToPermissionSet(r.Context(), adminRoleId, adminPermissionSet) + err = h.permissionUsecase.CreatePermissionSet(r.Context(), adminPermissionSet) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } - userPermissionSet := h.permissionUsecase.GetUserPermissionSet() - h.permissionUsecase.SetRoleIdToPermissionSet(userRoleId, userPermissionSet) - err = h.permissionUsecase.CreatePermissionSet(userPermissionSet) + userPermissionSet := h.permissionUsecase.GetUserPermissionSet(r.Context()) + h.permissionUsecase.SetRoleIdToPermissionSet(r.Context(), userRoleId, userPermissionSet) + err = h.permissionUsecase.CreatePermissionSet(r.Context(), userPermissionSet) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -113,14 +113,14 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } // Admin user 생성 - admin, err := h.userUsecase.CreateAdmin(organizationId, input.AdminAccountId, input.AdminName, input.AdminEmail) + admin, err := h.userUsecase.CreateAdmin(r.Context(), organizationId, input.AdminAccountId, input.AdminName, input.AdminEmail) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } - err = h.usecase.ChangeAdminId(organizationId, admin.ID) + err = h.usecase.ChangeAdminId(r.Context(), organizationId, admin.ID) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -154,7 +154,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - organizations, err := h.usecase.Fetch(pg) + organizations, err := h.usecase.Fetch(r.Context(), pg) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -199,7 +199,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req return } - organization, err := h.usecase.Get(organizationId) + organization, err := h.usecase.Get(r.Context(), organizationId) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -269,7 +269,7 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. } // organization 삭제 - err = h.usecase.Delete(organizationId, token) + err = h.usecase.Delete(r.Context(), organizationId, token) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -313,7 +313,7 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. return } - organization, err := h.usecase.Update(organizationId, input) + organization, err := h.usecase.Update(r.Context(), organizationId, input) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -359,7 +359,7 @@ func (h *OrganizationHandler) UpdatePrimaryCluster(w http.ResponseWriter, r *htt return } - err = h.usecase.UpdatePrimaryClusterId(organizationId, input.PrimaryClusterId) + err = h.usecase.UpdatePrimaryClusterId(r.Context(), organizationId, input.PrimaryClusterId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index d7ca79d9..bdc65716 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -79,7 +79,7 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http roleId = v } - permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(roleId) + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), roleId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -143,7 +143,7 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h log.InfoWithContext(r.Context(), err) } - if err := h.permissionUsecase.UpdatePermission(&permission); err != nil { + if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 7fdb1157..3ada3dc3 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -78,15 +78,15 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { // create role var roleId string - if roleId, err = h.roleUsecase.CreateTksRole(&dto); err != nil { + if roleId, err = h.roleUsecase.CreateTksRole(r.Context(), &dto); err != nil { ErrorJSON(w, r, err) return } // create permission defaultPermissionSet := model.NewDefaultPermissionSet() - h.permissionUsecase.SetRoleIdToPermissionSet(roleId, defaultPermissionSet) - err = h.permissionUsecase.CreatePermissionSet(defaultPermissionSet) + h.permissionUsecase.SetRoleIdToPermissionSet(r.Context(), roleId, defaultPermissionSet) + err = h.permissionUsecase.CreatePermissionSet(r.Context(), defaultPermissionSet) if err != nil { ErrorJSON(w, r, err) return @@ -123,7 +123,7 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { pg := pagination.NewPagination(&urlParams) // list roles - roles, err := h.roleUsecase.ListTksRoles(organizationId, pg) + roles, err := h.roleUsecase.ListTksRoles(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) return @@ -173,7 +173,7 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { } // get role - role, err := h.roleUsecase.GetTksRole(roleId) + role, err := h.roleUsecase.GetTksRole(r.Context(), roleId) if err != nil { ErrorJSON(w, r, err) return @@ -216,7 +216,7 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { } // delete role - if err := h.roleUsecase.DeleteTksRole(roleId); err != nil { + if err := h.roleUsecase.DeleteTksRole(r.Context(), roleId); err != nil { ErrorJSON(w, r, err) return } @@ -264,7 +264,7 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { } // update role - if err := h.roleUsecase.UpdateTksRole(&dto); err != nil { + if err := h.roleUsecase.UpdateTksRole(r.Context(), &dto); err != nil { ErrorJSON(w, r, err) return } @@ -300,7 +300,7 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) pg := pagination.NewPagination(&urlParams) // list roles - roles, err := h.roleUsecase.ListTksRoles(organizationId, pg) + roles, err := h.roleUsecase.ListTksRoles(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) return @@ -350,7 +350,7 @@ func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { } // get role - role, err := h.roleUsecase.GetTksRole(roleId) + role, err := h.roleUsecase.GetTksRole(r.Context(), roleId) if err != nil { ErrorJSON(w, r, err) return diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 9fa3b8b7..f7ca4fce 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -95,7 +95,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { ID: organizationId, } - roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) + roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -309,7 +309,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } user.AccountId = accountId - roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) + roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -368,7 +368,7 @@ func (u UserHandler) ResetPassword(w http.ResponseWriter, r *http.Request) { return } - err := u.usecase.ResetPasswordByAccountId(accountId, organizationId) + err := u.usecase.ResetPasswordByAccountId(r.Context(), accountId, organizationId) if err != nil { ErrorJSON(w, r, err) return @@ -395,7 +395,7 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { return } - user, err := u.usecase.Get(requestUserInfo.GetUserId()) + user, err := u.usecase.Get(r.Context(), requestUserInfo.GetUserId()) if err != nil { ErrorJSON(w, r, err) } @@ -444,7 +444,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { return } - err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.Password, requestUserInfo.GetOrganizationId()) + err = u.usecase.ValidateAccount(r.Context(), requestUserInfo.GetUserId(), input.Password, requestUserInfo.GetOrganizationId()) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -506,7 +506,7 @@ func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { return } - user, err := u.usecase.Get(requestUserInfo.GetUserId()) + user, err := u.usecase.Get(r.Context(), requestUserInfo.GetUserId()) if err != nil { ErrorJSON(w, r, err) return @@ -577,7 +577,7 @@ func (u UserHandler) DeleteMyProfile(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request context"), "A_INVALID_TOKEN", "")) return } - if err := u.usecase.Delete(requestUserInfo.GetUserId(), requestUserInfo.GetOrganizationId()); err != nil { + if err := u.usecase.Delete(r.Context(), requestUserInfo.GetUserId(), requestUserInfo.GetOrganizationId()); err != nil { ErrorJSON(w, r, err) return } @@ -704,7 +704,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) return } - err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + err = u.usecase.ValidateAccount(r.Context(), requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) if err != nil { ErrorJSON(w, r, err) return @@ -719,7 +719,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { Description: input.Description, } - roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) + roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) @@ -737,7 +737,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { ID: organizationId, } - user.Password = u.usecase.GenerateRandomPassword() + user.Password = u.usecase.GenerateRandomPassword(r.Context()) resUser, err := u.usecase.Create(r.Context(), &user) if err != nil { @@ -901,7 +901,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) return } - err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + err = u.usecase.ValidateAccount(r.Context(), requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) if err != nil { ErrorJSON(w, r, err) return @@ -966,7 +966,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found in request"), "A_INVALID_TOKEN", "")) return } - err = u.usecase.ValidateAccount(requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) + err = u.usecase.ValidateAccount(r.Context(), requestUserInfo.GetUserId(), input.AdminPassword, requestUserInfo.GetOrganizationId()) if err != nil { ErrorJSON(w, r, err) return @@ -985,7 +985,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { ID: organizationId, } - roles, err := u.roleUsecase.ListTksRoles(organizationId, nil) + roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) if err != nil { log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 12360269..fc06c80f 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -67,7 +67,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han ClientIP: GetClientIpAddress(w, r), UserId: &userId, } - if _, err := a.repo.Create(dto); err != nil { + if _, err := a.repo.Create(r.Context(), dto); err != nil { log.Error(err) } } diff --git a/internal/middleware/auth/authorizer/password.go b/internal/middleware/auth/authorizer/password.go index 4fd9b980..d9dc083c 100644 --- a/internal/middleware/auth/authorizer/password.go +++ b/internal/middleware/auth/authorizer/password.go @@ -20,7 +20,7 @@ func PasswordFilter(handler http.Handler, repo repository.Repository) http.Handl return } - storedUser, err := repo.User.GetByUuid(requestUserInfo.GetUserId()) + storedUser, err := repo.User.GetByUuid(r.Context(), requestUserInfo.GetUserId()) if err != nil { internalHttp.ErrorJSON(w, r, err) return diff --git a/internal/middleware/auth/authorizer/rbac.go b/internal/middleware/auth/authorizer/rbac.go index 722ccd8f..9c16508b 100644 --- a/internal/middleware/auth/authorizer/rbac.go +++ b/internal/middleware/auth/authorizer/rbac.go @@ -117,6 +117,30 @@ func AdminApiFilter(handler http.Handler, repo repository.Repository) http.Handl }) } +func RequestOrganizationValidationFilter(handler http.Handler, repo repository.Repository) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + return + } + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + //internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("organizationId not found"), "", "")) + //return + log.Warn("RequestOrganizationValidationFilter: organizationId not found. Passing through unsafely.") + } + if organizationId != requestUserInfo.GetOrganizationId() { + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return + } + + handler.ServeHTTP(w, r) + }) +} + //type pair struct { // regexp string // method string diff --git a/internal/repository/alert.go b/internal/repository/alert.go index 2d35f536..ef25d7bf 100644 --- a/internal/repository/alert.go +++ b/internal/repository/alert.go @@ -1,6 +1,7 @@ package repository import ( + "context" "time" "github.com/google/uuid" @@ -14,15 +15,15 @@ import ( // Interfaces type IAlertRepository interface { - Get(alertId uuid.UUID) (model.Alert, error) - GetByName(organizationId string, name string) (model.Alert, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]model.Alert, error) - FetchPodRestart(organizationId string, start time.Time, end time.Time) ([]model.Alert, error) - Create(dto model.Alert) (alertId uuid.UUID, err error) - Update(dto model.Alert) (err error) - Delete(dto model.Alert) (err error) - - CreateAlertAction(dto model.AlertAction) (alertActionId uuid.UUID, err error) + Get(ctx context.Context, alertId uuid.UUID) (model.Alert, error) + GetByName(ctx context.Context, organizationId string, name string) (model.Alert, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Alert, error) + FetchPodRestart(ctx context.Context, organizationId string, start time.Time, end time.Time) ([]model.Alert, error) + Create(ctx context.Context, dto model.Alert) (alertId uuid.UUID, err error) + Update(ctx context.Context, dto model.Alert) (err error) + Delete(ctx context.Context, dto model.Alert) (err error) + + CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) } type AlertRepository struct { @@ -36,28 +37,28 @@ func NewAlertRepository(db *gorm.DB) IAlertRepository { } // Logics -func (r *AlertRepository) Get(alertId uuid.UUID) (out model.Alert, err error) { - res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "id = ?", alertId) +func (r *AlertRepository) Get(ctx context.Context, alertId uuid.UUID) (out model.Alert, err error) { + res := r.db.WithContext(ctx).Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "id = ?", alertId) if res.Error != nil { return model.Alert{}, res.Error } return } -func (r *AlertRepository) GetByName(organizationId string, name string) (out model.Alert, err error) { - res := r.db.Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) +func (r *AlertRepository) GetByName(ctx context.Context, organizationId string, name string) (out model.Alert, err error) { + res := r.db.WithContext(ctx).Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { return model.Alert{}, res.Error } return } -func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.Alert, err error) { +func (r *AlertRepository) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.Alert, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.Alert{}). + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.Alert{}). Preload("AlertActions", func(db *gorm.DB) *gorm.DB { return db.Order("created_at ASC") }).Preload("AlertActions.Taker"). @@ -72,8 +73,8 @@ func (r *AlertRepository) Fetch(organizationId string, pg *pagination.Pagination return } -func (r *AlertRepository) FetchPodRestart(organizationId string, start time.Time, end time.Time) (out []model.Alert, err error) { - res := r.db.Preload(clause.Associations).Order("created_at DESC"). +func (r *AlertRepository) FetchPodRestart(ctx context.Context, organizationId string, start time.Time, end time.Time) (out []model.Alert, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).Order("created_at DESC"). Where("organization_id = ? AND name = 'pod-restart-frequently' AND created_at BETWEEN ? AND ?", organizationId, start, end). Find(&out) if res.Error != nil { @@ -82,7 +83,7 @@ func (r *AlertRepository) FetchPodRestart(organizationId string, start time.Time return } -func (r *AlertRepository) Create(dto model.Alert) (alertId uuid.UUID, err error) { +func (r *AlertRepository) Create(ctx context.Context, dto model.Alert) (alertId uuid.UUID, err error) { alert := model.Alert{ OrganizationId: dto.OrganizationId, Name: dto.Name, @@ -98,15 +99,15 @@ func (r *AlertRepository) Create(dto model.Alert) (alertId uuid.UUID, err error) RawData: dto.RawData, Status: domain.AlertActionStatus_CREATED, } - res := r.db.Create(&alert) + res := r.db.WithContext(ctx).Create(&alert) if res.Error != nil { return uuid.Nil, res.Error } return alert.ID, nil } -func (r *AlertRepository) Update(dto model.Alert) (err error) { - res := r.db.Model(&model.Alert{}). +func (r *AlertRepository) Update(ctx context.Context, dto model.Alert) (err error) { + res := r.db.WithContext(ctx).Model(&model.Alert{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description}) if res.Error != nil { @@ -115,26 +116,26 @@ func (r *AlertRepository) Update(dto model.Alert) (err error) { return nil } -func (r *AlertRepository) Delete(dto model.Alert) (err error) { - res := r.db.Delete(&model.Alert{}, "id = ?", dto.ID) +func (r *AlertRepository) Delete(ctx context.Context, dto model.Alert) (err error) { + res := r.db.WithContext(ctx).Delete(&model.Alert{}, "id = ?", dto.ID) if res.Error != nil { return res.Error } return nil } -func (r *AlertRepository) CreateAlertAction(dto model.AlertAction) (alertActionId uuid.UUID, err error) { +func (r *AlertRepository) CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) { alert := model.AlertAction{ AlertId: dto.AlertId, Content: dto.Content, Status: dto.Status, TakerId: dto.TakerId, } - res := r.db.Create(&alert) + res := r.db.WithContext(ctx).Create(&alert) if res.Error != nil { return uuid.Nil, res.Error } - res = r.db.Model(&model.Alert{}). + res = r.db.WithContext(ctx).Model(&model.Alert{}). Where("id = ?", dto.AlertId). Update("status", dto.Status) if res.Error != nil { diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index bd824996..edaf6a37 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -1,6 +1,7 @@ package repository import ( + "context" "fmt" "gorm.io/datatypes" @@ -14,15 +15,15 @@ import ( // Interfaces type IAppGroupRepository interface { - Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (res []model.AppGroup, err error) - Get(id domain.AppGroupId) (model.AppGroup, error) - Create(dto model.AppGroup) (id domain.AppGroupId, err error) - Update(dto model.AppGroup) (err error) - Delete(id domain.AppGroupId) error - GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (applications []model.Application, err error) - UpsertApplication(dto model.Application) error - InitWorkflow(appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error - InitWorkflowDescription(clusterId domain.ClusterId) error + Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (res []model.AppGroup, err error) + Get(ctx context.Context, id domain.AppGroupId) (model.AppGroup, error) + Create(ctx context.Context, dto model.AppGroup) (id domain.AppGroupId, err error) + Update(ctx context.Context, dto model.AppGroup) (err error) + Delete(ctx context.Context, id domain.AppGroupId) error + GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (applications []model.Application, err error) + UpsertApplication(ctx context.Context, dto model.Application) error + InitWorkflow(ctx context.Context, appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error + InitWorkflowDescription(ctx context.Context, clusterId domain.ClusterId) error } type AppGroupRepository struct { @@ -36,12 +37,12 @@ func NewAppGroupRepository(db *gorm.DB) IAppGroupRepository { } // Logics -func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { +func (r *AppGroupRepository) Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.AppGroup{}). + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.AppGroup{}). Where("cluster_id = ?", clusterId), &out) if res.Error != nil { return nil, res.Error @@ -50,15 +51,15 @@ func (r *AppGroupRepository) Fetch(clusterId domain.ClusterId, pg *pagination.Pa return out, nil } -func (r *AppGroupRepository) Get(id domain.AppGroupId) (out model.AppGroup, err error) { - res := r.db.First(&out, "id = ?", id) +func (r *AppGroupRepository) Get(ctx context.Context, id domain.AppGroupId) (out model.AppGroup, err error) { + res := r.db.WithContext(ctx).First(&out, "id = ?", id) if res.RowsAffected == 0 || res.Error != nil { return model.AppGroup{}, fmt.Errorf("Not found appGroup for %s", id) } return out, nil } -func (r *AppGroupRepository) Create(dto model.AppGroup) (appGroupId domain.AppGroupId, err error) { +func (r *AppGroupRepository) Create(ctx context.Context, dto model.AppGroup) (appGroupId domain.AppGroupId, err error) { appGroup := model.AppGroup{ ClusterId: dto.ClusterId, AppGroupType: dto.AppGroupType, @@ -68,7 +69,7 @@ func (r *AppGroupRepository) Create(dto model.AppGroup) (appGroupId domain.AppGr CreatorId: dto.CreatorId, UpdatorId: nil, } - res := r.db.Create(&appGroup) + res := r.db.WithContext(ctx).Create(&appGroup) if res.Error != nil { log.Error(res.Error) return "", res.Error @@ -77,8 +78,8 @@ func (r *AppGroupRepository) Create(dto model.AppGroup) (appGroupId domain.AppGr return appGroup.ID, nil } -func (r *AppGroupRepository) Update(dto model.AppGroup) (err error) { - res := r.db.Model(&model.AppGroup{}). +func (r *AppGroupRepository) Update(ctx context.Context, dto model.AppGroup) (err error) { + res := r.db.WithContext(ctx).Model(&model.AppGroup{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ "ClusterId": dto.ClusterId, @@ -93,24 +94,24 @@ func (r *AppGroupRepository) Update(dto model.AppGroup) (err error) { return nil } -func (r *AppGroupRepository) Delete(id domain.AppGroupId) error { - res := r.db.Unscoped().Delete(&model.AppGroup{}, "id = ?", id) +func (r *AppGroupRepository) Delete(ctx context.Context, id domain.AppGroupId) error { + res := r.db.WithContext(ctx).Unscoped().Delete(&model.AppGroup{}, "id = ?", id) if res.Error != nil { return fmt.Errorf("could not delete appGroup %s", id) } return nil } -func (r *AppGroupRepository) GetApplications(id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { - res := r.db.Where("app_group_id = ? AND type = ?", id, applicationType).Find(&out) +func (r *AppGroupRepository) GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { + res := r.db.WithContext(ctx).Where("app_group_id = ? AND type = ?", id, applicationType).Find(&out) if res.Error != nil { return nil, res.Error } return out, nil } -func (r *AppGroupRepository) UpsertApplication(dto model.Application) error { - res := r.db.Where(model.Application{ +func (r *AppGroupRepository) UpsertApplication(ctx context.Context, dto model.Application) error { + res := r.db.WithContext(ctx).Where(model.Application{ AppGroupId: dto.AppGroupId, Type: dto.Type, }). @@ -125,8 +126,8 @@ func (r *AppGroupRepository) UpsertApplication(dto model.Application) error { return nil } -func (r *AppGroupRepository) InitWorkflow(appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error { - res := r.db.Model(&model.AppGroup{}). +func (r *AppGroupRepository) InitWorkflow(ctx context.Context, appGroupId domain.AppGroupId, workflowId string, status domain.AppGroupStatus) error { + res := r.db.WithContext(ctx).Model(&model.AppGroup{}). Where("ID = ?", appGroupId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId, "StatusDesc": ""}) @@ -137,8 +138,8 @@ func (r *AppGroupRepository) InitWorkflow(appGroupId domain.AppGroupId, workflow return nil } -func (r *AppGroupRepository) InitWorkflowDescription(clusterId domain.ClusterId) error { - res := r.db.Model(&model.AppGroup{}). +func (r *AppGroupRepository) InitWorkflowDescription(ctx context.Context, clusterId domain.ClusterId) error { + res := r.db.WithContext(ctx).Model(&model.AppGroup{}). Where("cluster_id = ?", clusterId). Updates(map[string]interface{}{"WorkflowId": "", "StatusDesc": ""}) diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index a1d3e291..d2089fe2 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -1,6 +1,7 @@ package repository import ( + "context" "fmt" "time" @@ -12,22 +13,22 @@ import ( ) type IAppServeAppRepository interface { - CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) - GetAppServeAppById(appId string) (*model.AppServeApp, error) - - GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) - GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) - - GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) - GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) - - IsAppServeAppExist(appId string) (int64, error) - IsAppServeAppNameExist(orgId string, appName string) (int64, error) - CreateTask(task *model.AppServeAppTask) (taskId string, err error) - UpdateStatus(appId string, taskId string, status string, output string) error - UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error - GetTaskCountById(appId string) (int64, error) + CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) + GetAppServeApps(ctx context.Context, organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) + GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) + + GetAppServeAppTasksByAppId(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) + GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) + + GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) + GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) + + IsAppServeAppExist(ctx context.Context, appId string) (int64, error) + IsAppServeAppNameExist(ctx context.Context, orgId string, appName string) (int64, error) + CreateTask(ctx context.Context, task *model.AppServeAppTask) (taskId string, err error) + UpdateStatus(ctx context.Context, appId string, taskId string, status string, output string) error + UpdateEndpoint(ctx context.Context, appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error + GetTaskCountById(ctx context.Context, appId string) (int64, error) } type AppServeAppRepository struct { @@ -40,9 +41,9 @@ func NewAppServeAppRepository(db *gorm.DB) IAppServeAppRepository { } } -func (r *AppServeAppRepository) CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) { +func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) { - res := r.db.Create(&app) + res := r.db.WithContext(ctx).Create(&app) if res.Error != nil { return "", "", res.Error } @@ -51,9 +52,8 @@ func (r *AppServeAppRepository) CreateAppServeApp(app *model.AppServeApp) (appId } // Update creates new appServeApp task for existing appServeApp. -func (r *AppServeAppRepository) CreateTask( - task *model.AppServeAppTask) (string, error) { - res := r.db.Create(task) +func (r *AppServeAppRepository) CreateTask(ctx context.Context, task *model.AppServeAppTask) (string, error) { + res := r.db.WithContext(ctx).Create(task) if res.Error != nil { return "", res.Error } @@ -61,14 +61,14 @@ func (r *AppServeAppRepository) CreateTask( return task.ID, nil } -func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) (apps []model.AppServeApp, err error) { +func (r *AppServeAppRepository) GetAppServeApps(ctx context.Context, organizationId string, showAll bool, pg *pagination.Pagination) (apps []model.AppServeApp, err error) { var clusters []model.Cluster if pg == nil { pg = pagination.NewPagination(nil) } // TODO: should return different records based on showAll param - _, res := pg.Fetch(r.db.Model(&model.AppServeApp{}). + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.AppServeApp{}). Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId), &apps) if res.Error != nil { return nil, fmt.Errorf("error while finding appServeApps with organizationId: %s", organizationId) @@ -81,7 +81,7 @@ func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll b // Add cluster names to apps list queryStr := fmt.Sprintf("organization_id = '%s' AND status <> '%d'", organizationId, domain.ClusterStatus_DELETED) - res = r.db.Find(&clusters, queryStr) + res = r.db.WithContext(ctx).Find(&clusters, queryStr) if res.Error != nil { return nil, fmt.Errorf("error while fetching clusters with organizationId: %s", organizationId) } @@ -98,11 +98,11 @@ func (r *AppServeAppRepository) GetAppServeApps(organizationId string, showAll b return } -func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*model.AppServeApp, error) { +func (r *AppServeAppRepository) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) { var app model.AppServeApp var cluster model.Cluster - res := r.db.Where("id = ?", appId).First(&app) + res := r.db.WithContext(ctx).Where("id = ?", appId).First(&app) if res.Error != nil { log.Debug(res.Error) return nil, res.Error @@ -112,24 +112,24 @@ func (r *AppServeAppRepository) GetAppServeAppById(appId string) (*model.AppServ } // Populate tasks into app object - if err := r.db.Model(&app).Order("created_at desc").Association("AppServeAppTasks").Find(&app.AppServeAppTasks); err != nil { + if err := r.db.WithContext(ctx).Model(&app).Order("created_at desc").Association("AppServeAppTasks").Find(&app.AppServeAppTasks); err != nil { log.Debug(err) return nil, err } // Add cluster name to app object - r.db.Select("name").Where("id = ?", app.TargetClusterId).First(&cluster) + r.db.WithContext(ctx).Select("name").Where("id = ?", app.TargetClusterId).First(&cluster) app.TargetClusterName = cluster.Name return &app, nil } -func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pagination.Pagination) (tasks []model.AppServeAppTask, err error) { +func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(ctx context.Context, appId string, pg *pagination.Pagination) (tasks []model.AppServeAppTask, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.AppServeAppTask{}). + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.AppServeAppTask{}). Where("app_serve_app_tasks.app_serve_app_id = ?", appId), &tasks) if res.Error != nil { return nil, fmt.Errorf("Error while finding tasks with appId: %s", appId) @@ -144,12 +144,12 @@ func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(appId string, pg *pag } // Return single task info along with its parent app info -func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { +func (r *AppServeAppRepository) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { var task model.AppServeAppTask var app model.AppServeApp // Retrieve task info - res := r.db.Where("id = ?", taskId).First(&task) + res := r.db.WithContext(ctx).Where("id = ?", taskId).First(&task) if res.Error != nil { log.Debug(res.Error) return nil, nil, res.Error @@ -159,7 +159,7 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*model.Ap } // Retrieve app info - res = r.db.Where("id = ?", task.AppServeAppId).First(&app) + res = r.db.WithContext(ctx).Where("id = ?", task.AppServeAppId).First(&app) if res.Error != nil { log.Debug(res.Error) return nil, nil, res.Error @@ -171,11 +171,11 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(taskId string) (*model.Ap return &task, &app, nil } -func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) { +func (r *AppServeAppRepository) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) { var task model.AppServeAppTask // TODO: Does this work?? where's app ID here? - res := r.db.Order("created_at desc").First(&task) + res := r.db.WithContext(ctx).Order("created_at desc").First(&task) if res.Error != nil { log.Debug(res.Error) return nil, res.Error @@ -187,11 +187,11 @@ func (r *AppServeAppRepository) GetAppServeAppLatestTask(appId string) (*model.A return &task, nil } -func (r *AppServeAppRepository) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) { +func (r *AppServeAppRepository) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) { var apps []model.AppServeApp queryStr := fmt.Sprintf("organization_id = '%s' AND target_cluster_id = '%s' AND status <> 'DELETE_SUCCESS'", organizationId, clusterId) - res := r.db.Find(&apps, queryStr) + res := r.db.WithContext(ctx).Find(&apps, queryStr) if res.Error != nil { return -1, fmt.Errorf("Error while finding appServeApps with organizationId: %s", organizationId) } @@ -199,10 +199,10 @@ func (r *AppServeAppRepository) GetNumOfAppsOnStack(organizationId string, clust return res.RowsAffected, nil } -func (r *AppServeAppRepository) IsAppServeAppExist(appId string) (int64, error) { +func (r *AppServeAppRepository) IsAppServeAppExist(ctx context.Context, appId string) (int64, error) { var result int64 - res := r.db.Table("app_serve_apps").Where("id = ? AND status <> 'DELETE_SUCCESS'", appId).Count(&result) + res := r.db.WithContext(ctx).Table("app_serve_apps").Where("id = ? AND status <> 'DELETE_SUCCESS'", appId).Count(&result) if res.Error != nil { log.Debug(res.Error) return 0, res.Error @@ -210,7 +210,7 @@ func (r *AppServeAppRepository) IsAppServeAppExist(appId string) (int64, error) return result, nil } -func (r *AppServeAppRepository) IsAppServeAppNameExist(orgId string, appName string) (int64, error) { +func (r *AppServeAppRepository) IsAppServeAppNameExist(ctx context.Context, orgId string, appName string) (int64, error) { var result int64 queryString := fmt.Sprintf("organization_id = '%v' "+ @@ -218,7 +218,7 @@ func (r *AppServeAppRepository) IsAppServeAppNameExist(orgId string, appName str "AND status <> 'DELETE_SUCCESS'", orgId, appName) log.Info("query = ", queryString) - res := r.db.Table("app_serve_apps").Where(queryString).Count(&result) + res := r.db.WithContext(ctx).Table("app_serve_apps").Where(queryString).Count(&result) if res.Error != nil { log.Debug(res.Error) return 0, res.Error @@ -226,14 +226,14 @@ func (r *AppServeAppRepository) IsAppServeAppNameExist(orgId string, appName str return result, nil } -func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status string, output string) error { +func (r *AppServeAppRepository) UpdateStatus(ctx context.Context, appId string, taskId string, status string, output string) error { now := time.Now() app := model.AppServeApp{ ID: appId, Status: status, UpdatedAt: &now, } - res := r.db.Model(&app).Select("Status", "UpdatedAt").Updates(app) + res := r.db.WithContext(ctx).Model(&app).Select("Status", "UpdatedAt").Updates(app) if res.Error != nil || res.RowsAffected == 0 { return fmt.Errorf("UpdateStatus: nothing updated in AppServeApp with ID %s", appId) } @@ -244,7 +244,7 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status Output: output, UpdatedAt: &now, } - res = r.db.Model(&task).Select("Status", "Output", "UpdatedAt").Updates(task) + res = r.db.WithContext(ctx).Model(&task).Select("Status", "Output", "UpdatedAt").Updates(task) if res.Error != nil || res.RowsAffected == 0 { return fmt.Errorf("UpdateStatus: nothing updated in AppServeAppTask with ID %s", taskId) } @@ -269,7 +269,7 @@ func (r *AppServeAppRepository) UpdateStatus(appId string, taskId string, status return nil } -func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error { +func (r *AppServeAppRepository) UpdateEndpoint(ctx context.Context, appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error { now := time.Now() app := model.AppServeApp{ ID: appId, @@ -287,13 +287,13 @@ func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endp var res *gorm.DB if endpoint != "" && previewEndpoint != "" { // Both endpoints are valid - res = r.db.Model(&app).Select("EndpointUrl", "PreviewEndpointUrl", "UpdatedAt").Updates(app) + res = r.db.WithContext(ctx).Model(&app).Select("EndpointUrl", "PreviewEndpointUrl", "UpdatedAt").Updates(app) } else if endpoint != "" { // endpoint-only case - res = r.db.Model(&app).Select("EndpointUrl", "UpdatedAt").Updates(app) + res = r.db.WithContext(ctx).Model(&app).Select("EndpointUrl", "UpdatedAt").Updates(app) } else if previewEndpoint != "" { // previewEndpoint-only case - res = r.db.Model(&app).Select("PreviewEndpointUrl", "UpdatedAt").Updates(app) + res = r.db.WithContext(ctx).Model(&app).Select("PreviewEndpointUrl", "UpdatedAt").Updates(app) } else { return fmt.Errorf("updateEndpoint: No endpoint provided. " + "At least one of [endpoint, preview_endpoint] should be provided") @@ -305,7 +305,7 @@ func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endp // Update helm revision // Ignore if the value is less than 0 if helmRevision > 0 { - res = r.db.Model(&task).Select("HelmRevision", "UpdatedAt").Updates(task) + res = r.db.WithContext(ctx).Model(&task).Select("HelmRevision", "UpdatedAt").Updates(task) if res.Error != nil || res.RowsAffected == 0 { return fmt.Errorf("UpdateEndpoint: "+ "helm revision was not updated for AppServeAppTask with task ID %s", taskId) @@ -315,9 +315,9 @@ func (r *AppServeAppRepository) UpdateEndpoint(appId string, taskId string, endp return nil } -func (r *AppServeAppRepository) GetTaskCountById(appId string) (int64, error) { +func (r *AppServeAppRepository) GetTaskCountById(ctx context.Context, appId string) (int64, error) { var count int64 - if err := r.db.Model(&model.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { + if err := r.db.WithContext(ctx).Model(&model.AppServeAppTask{}).Where("AppServeAppId = ?", appId).Count(&count); err != nil { return 0, fmt.Errorf("could not select count AppServeAppTask with ID: %s", appId) } return count, nil diff --git a/internal/repository/audit.go b/internal/repository/audit.go index f7e0c5dd..8d9a594f 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -1,6 +1,7 @@ package repository import ( + "context" "fmt" "github.com/google/uuid" @@ -13,10 +14,10 @@ import ( // Interfaces type IAuditRepository interface { - Get(auditId uuid.UUID) (model.Audit, error) - Fetch(pg *pagination.Pagination) ([]model.Audit, error) - Create(dto model.Audit) (auditId uuid.UUID, err error) - Delete(auditId uuid.UUID) (err error) + Get(ctx context.Context, auditId uuid.UUID) (model.Audit, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.Audit, error) + Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) + Delete(ctx context.Context, auditId uuid.UUID) (err error) } type AuditRepository struct { @@ -30,20 +31,20 @@ func NewAuditRepository(db *gorm.DB) IAuditRepository { } // Logics -func (r *AuditRepository) Get(auditId uuid.UUID) (out model.Audit, err error) { - res := r.db.Preload(clause.Associations).First(&out, "id = ?", auditId) +func (r *AuditRepository) Get(ctx context.Context, auditId uuid.UUID) (out model.Audit, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "id = ?", auditId) if res.Error != nil { return } return } -func (r *AuditRepository) Fetch(pg *pagination.Pagination) (out []model.Audit, err error) { +func (r *AuditRepository) Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.Audit, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - db := r.db.Model(&model.Audit{}).Preload(clause.Associations) + db := r.db.WithContext(ctx).Model(&model.Audit{}).Preload(clause.Associations) _, res := pg.Fetch(db, &out) if res.Error != nil { return nil, res.Error @@ -51,7 +52,7 @@ func (r *AuditRepository) Fetch(pg *pagination.Pagination) (out []model.Audit, e return } -func (r *AuditRepository) Create(dto model.Audit) (auditId uuid.UUID, err error) { +func (r *AuditRepository) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { audit := model.Audit{ OrganizationId: dto.OrganizationId, Group: dto.Group, @@ -59,13 +60,13 @@ func (r *AuditRepository) Create(dto model.Audit) (auditId uuid.UUID, err error) Description: dto.Description, ClientIP: dto.ClientIP, UserId: dto.UserId} - res := r.db.Create(&audit) + res := r.db.WithContext(ctx).Create(&audit) if res.Error != nil { return uuid.Nil, res.Error } return audit.ID, nil } -func (r *AuditRepository) Delete(auditId uuid.UUID) (err error) { +func (r *AuditRepository) Delete(ctx context.Context, auditId uuid.UUID) (err error) { return fmt.Errorf("to be implemented") } diff --git a/internal/repository/auth.go b/internal/repository/auth.go index 3c2c980a..d9c86a59 100644 --- a/internal/repository/auth.go +++ b/internal/repository/auth.go @@ -1,15 +1,16 @@ package repository import ( + "context" "github.com/google/uuid" "gorm.io/gorm" ) type IAuthRepository interface { - CreateEmailCode(userId uuid.UUID, code string) error - GetEmailCode(userId uuid.UUID) (CacheEmailCode, error) - UpdateEmailCode(userId uuid.UUID, code string) error - DeleteEmailCode(userId uuid.UUID) error + CreateEmailCode(ctx context.Context, userId uuid.UUID, code string) error + GetEmailCode(ctx context.Context, userId uuid.UUID) (CacheEmailCode, error) + UpdateEmailCode(ctx context.Context, userId uuid.UUID, code string) error + DeleteEmailCode(ctx context.Context, userId uuid.UUID) error } type AuthRepository struct { @@ -31,26 +32,26 @@ func NewAuthRepository(db *gorm.DB) IAuthRepository { } } -func (r *AuthRepository) CreateEmailCode(userId uuid.UUID, code string) error { +func (r *AuthRepository) CreateEmailCode(ctx context.Context, userId uuid.UUID, code string) error { cacheEmailCode := CacheEmailCode{ UserId: userId, Code: code, } - return r.db.Create(&cacheEmailCode).Error + return r.db.WithContext(ctx).Create(&cacheEmailCode).Error } -func (r *AuthRepository) GetEmailCode(userId uuid.UUID) (CacheEmailCode, error) { +func (r *AuthRepository) GetEmailCode(ctx context.Context, userId uuid.UUID) (CacheEmailCode, error) { var cacheEmailCode CacheEmailCode - if err := r.db.Where("user_id = ?", userId).First(&cacheEmailCode).Error; err != nil { + if err := r.db.WithContext(ctx).Where("user_id = ?", userId).First(&cacheEmailCode).Error; err != nil { return CacheEmailCode{}, err } return cacheEmailCode, nil } -func (r *AuthRepository) UpdateEmailCode(userId uuid.UUID, code string) error { - return r.db.Model(&CacheEmailCode{}).Where("user_id = ?", userId).Update("code", code).Error +func (r *AuthRepository) UpdateEmailCode(ctx context.Context, userId uuid.UUID, code string) error { + return r.db.WithContext(ctx).Model(&CacheEmailCode{}).Where("user_id = ?", userId).Update("code", code).Error } -func (r *AuthRepository) DeleteEmailCode(userId uuid.UUID) error { - return r.db.Unscoped().Where("user_id = ?", userId).Delete(&CacheEmailCode{}).Error +func (r *AuthRepository) DeleteEmailCode(ctx context.Context, userId uuid.UUID) error { + return r.db.WithContext(ctx).Unscoped().Where("user_id = ?", userId).Delete(&CacheEmailCode{}).Error } diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index 08f635c8..72508451 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -1,6 +1,7 @@ package repository import ( + "context" "fmt" "github.com/google/uuid" @@ -14,14 +15,14 @@ import ( // Interfaces type ICloudAccountRepository interface { - Get(cloudAccountId uuid.UUID) (model.CloudAccount, error) - GetByName(organizationId string, name string) (model.CloudAccount, error) - GetByAwsAccountId(awsAccountId string) (model.CloudAccount, error) - Fetch(organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) - Create(dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) - Update(dto model.CloudAccount) (err error) - Delete(cloudAccountId uuid.UUID) (err error) - InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) (err error) + Get(ctx context.Context, cloudAccountId uuid.UUID) (model.CloudAccount, error) + GetByName(ctx context.Context, organizationId string, name string) (model.CloudAccount, error) + GetByAwsAccountId(ctx context.Context, awsAccountId string) (model.CloudAccount, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) + Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) + Update(ctx context.Context, dto model.CloudAccount) (err error) + Delete(ctx context.Context, cloudAccountId uuid.UUID) (err error) + InitWorkflow(ctx context.Context, cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) (err error) } type CloudAccountRepository struct { @@ -35,35 +36,35 @@ func NewCloudAccountRepository(db *gorm.DB) ICloudAccountRepository { } // Logics -func (r *CloudAccountRepository) Get(cloudAccountId uuid.UUID) (out model.CloudAccount, err error) { - res := r.db.Preload(clause.Associations).First(&out, "id = ?", cloudAccountId) +func (r *CloudAccountRepository) Get(ctx context.Context, cloudAccountId uuid.UUID) (out model.CloudAccount, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "id = ?", cloudAccountId) if res.Error != nil { return model.CloudAccount{}, res.Error } return } -func (r *CloudAccountRepository) GetByName(organizationId string, name string) (out model.CloudAccount, err error) { - res := r.db.Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) +func (r *CloudAccountRepository) GetByName(ctx context.Context, organizationId string, name string) (out model.CloudAccount, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { return model.CloudAccount{}, res.Error } return } -func (r *CloudAccountRepository) GetByAwsAccountId(awsAccountId string) (out model.CloudAccount, err error) { - res := r.db.Preload(clause.Associations).First(&out, "aws_account_id = ? AND status != ?", awsAccountId, domain.CloudAccountStatus_DELETED) +func (r *CloudAccountRepository) GetByAwsAccountId(ctx context.Context, awsAccountId string) (out model.CloudAccount, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "aws_account_id = ? AND status != ?", awsAccountId, domain.CloudAccountStatus_DELETED) if res.Error != nil { return model.CloudAccount{}, res.Error } return } -func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pagination) (out []model.CloudAccount, err error) { +func (r *CloudAccountRepository) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.CloudAccount, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.CloudAccount{}). + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.CloudAccount{}). Preload(clause.Associations). Where("organization_id = ? AND status != ?", organizationId, domain.CloudAccountStatus_DELETED), &out) if res.Error != nil { @@ -72,7 +73,7 @@ func (r *CloudAccountRepository) Fetch(organizationId string, pg *pagination.Pag return } -func (r *CloudAccountRepository) Create(dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { +func (r *CloudAccountRepository) Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { cloudAccount := model.CloudAccount{ OrganizationId: dto.OrganizationId, Name: dto.Name, @@ -83,15 +84,15 @@ func (r *CloudAccountRepository) Create(dto model.CloudAccount) (cloudAccountId CreatedIAM: false, Status: domain.CloudAccountStatus_PENDING, CreatorId: dto.CreatorId} - res := r.db.Create(&cloudAccount) + res := r.db.WithContext(ctx).Create(&cloudAccount) if res.Error != nil { return uuid.Nil, res.Error } return cloudAccount.ID, nil } -func (r *CloudAccountRepository) Update(dto model.CloudAccount) (err error) { - res := r.db.Model(&model.CloudAccount{}). +func (r *CloudAccountRepository) Update(ctx context.Context, dto model.CloudAccount) (err error) { + res := r.db.WithContext(ctx).Model(&model.CloudAccount{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description, "Resource": dto.Resource, "UpdatorId": dto.UpdatorId}) if res.Error != nil { @@ -100,16 +101,16 @@ func (r *CloudAccountRepository) Update(dto model.CloudAccount) (err error) { return nil } -func (r *CloudAccountRepository) Delete(cloudAccountId uuid.UUID) (err error) { - res := r.db.Delete(&model.CloudAccount{}, "id = ?", cloudAccountId) +func (r *CloudAccountRepository) Delete(ctx context.Context, cloudAccountId uuid.UUID) (err error) { + res := r.db.WithContext(ctx).Delete(&model.CloudAccount{}, "id = ?", cloudAccountId) if res.Error != nil { return res.Error } return nil } -func (r *CloudAccountRepository) InitWorkflow(cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) error { - res := r.db.Model(&model.CloudAccount{}). +func (r *CloudAccountRepository) InitWorkflow(ctx context.Context, cloudAccountId uuid.UUID, workflowId string, status domain.CloudAccountStatus) error { + res := r.db.WithContext(ctx).Model(&model.CloudAccount{}). Where("ID = ?", cloudAccountId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 05d2cb00..7d92bdc5 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -1,6 +1,7 @@ package repository import ( + "context" "fmt" "github.com/google/uuid" @@ -17,20 +18,20 @@ import ( // Interfaces type IClusterRepository interface { WithTrx(*gorm.DB) IClusterRepository - Fetch(pg *pagination.Pagination) (res []model.Cluster, err error) - FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) - FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) - Get(id domain.ClusterId) (model.Cluster, error) - GetByName(organizationId string, name string) (model.Cluster, error) - Create(dto model.Cluster) (clusterId domain.ClusterId, err error) - Update(dto model.Cluster) (err error) - Delete(id domain.ClusterId) error + Fetch(ctx context.Context, pg *pagination.Pagination) (res []model.Cluster, err error) + FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) + FetchByOrganizationId(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) (res []model.Cluster, err error) + Get(ctx context.Context, id domain.ClusterId) (model.Cluster, error) + GetByName(ctx context.Context, organizationId string, name string) (model.Cluster, error) + Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) + Update(ctx context.Context, dto model.Cluster) (err error) + Delete(ctx context.Context, id domain.ClusterId) error - InitWorkflow(clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error - InitWorkflowDescription(clusterId domain.ClusterId) error + InitWorkflow(ctx context.Context, clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error + InitWorkflowDescription(ctx context.Context, clusterId domain.ClusterId) error - SetFavorite(clusterId domain.ClusterId, userId uuid.UUID) error - DeleteFavorite(clusterId domain.ClusterId, userId uuid.UUID) error + SetFavorite(ctx context.Context, clusterId domain.ClusterId, userId uuid.UUID) error + DeleteFavorite(ctx context.Context, clusterId domain.ClusterId, userId uuid.UUID) error } type ClusterRepository struct { @@ -55,12 +56,12 @@ func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { return r } -func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []model.Cluster, err error) { +func (r *ClusterRepository) Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.Cluster{}).Preload(clause.Associations), &out) + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.Cluster{}).Preload(clause.Associations), &out) if res.Error != nil { return nil, res.Error } @@ -68,12 +69,12 @@ func (r *ClusterRepository) Fetch(pg *pagination.Pagination) (out []model.Cluste return } -func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { +func (r *ClusterRepository) FetchByOrganizationId(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.Cluster{}). + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.Cluster{}). Preload(clause.Associations). Joins("left outer join cluster_favorites on clusters.id = cluster_favorites.cluster_id AND cluster_favorites.user_id = ?", userId). Where("organization_id = ? AND status != ?", organizationId, domain.ClusterStatus_DELETED). @@ -84,11 +85,11 @@ func (r *ClusterRepository) FetchByOrganizationId(organizationId string, userId return } -func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { +func (r *ClusterRepository) FetchByCloudAccountId(ctx context.Context, cloudAccountId uuid.UUID, pg *pagination.Pagination) (out []model.Cluster, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Model(&model.Cluster{}).Preload("CloudAccount"). + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.Cluster{}).Preload("CloudAccount"). Where("cloud_account_id = ?", cloudAccountId), &out) if res.Error != nil { return nil, res.Error @@ -96,23 +97,23 @@ func (r *ClusterRepository) FetchByCloudAccountId(cloudAccountId uuid.UUID, pg * return } -func (r *ClusterRepository) Get(id domain.ClusterId) (out model.Cluster, err error) { - res := r.db.Preload(clause.Associations).First(&out, "id = ?", id) +func (r *ClusterRepository) Get(ctx context.Context, id domain.ClusterId) (out model.Cluster, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "id = ?", id) if res.Error != nil { return model.Cluster{}, res.Error } return } -func (r *ClusterRepository) GetByName(organizationId string, name string) (out model.Cluster, err error) { - res := r.db.Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) +func (r *ClusterRepository) GetByName(ctx context.Context, organizationId string, name string) (out model.Cluster, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) if res.Error != nil { return model.Cluster{}, res.Error } return } -func (r *ClusterRepository) Create(dto model.Cluster) (clusterId domain.ClusterId, err error) { +func (r *ClusterRepository) Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { var cloudAccountId *uuid.UUID cloudAccountId = dto.CloudAccountId if dto.CloudService == domain.CloudService_BYOH || *dto.CloudAccountId == uuid.Nil { @@ -147,7 +148,7 @@ func (r *ClusterRepository) Create(dto model.Cluster) (clusterId domain.ClusterI cluster.ID = dto.ID } - res := r.db.Create(&cluster) + res := r.db.WithContext(ctx).Create(&cluster) if res.Error != nil { log.Error(res.Error) return "", res.Error @@ -156,16 +157,16 @@ func (r *ClusterRepository) Create(dto model.Cluster) (clusterId domain.ClusterI return cluster.ID, nil } -func (r *ClusterRepository) Delete(clusterId domain.ClusterId) error { - res := r.db.Unscoped().Delete(&model.Cluster{}, "id = ?", clusterId) +func (r *ClusterRepository) Delete(ctx context.Context, clusterId domain.ClusterId) error { + res := r.db.WithContext(ctx).Unscoped().Delete(&model.Cluster{}, "id = ?", clusterId) if res.Error != nil { return fmt.Errorf("could not delete cluster for clusterId %s", clusterId) } return nil } -func (r *ClusterRepository) Update(dto model.Cluster) error { - res := r.db.Model(&model.Cluster{}). +func (r *ClusterRepository) Update(ctx context.Context, dto model.Cluster) error { + res := r.db.WithContext(ctx).Model(&model.Cluster{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{"Description": dto.Description, "UpdatorId": dto.UpdatorId}) if res.Error != nil { @@ -174,8 +175,8 @@ func (r *ClusterRepository) Update(dto model.Cluster) error { return nil } -func (r *ClusterRepository) InitWorkflow(clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error { - res := r.db.Model(&model.Cluster{}). +func (r *ClusterRepository) InitWorkflow(ctx context.Context, clusterId domain.ClusterId, workflowId string, status domain.ClusterStatus) error { + res := r.db.WithContext(ctx).Model(&model.Cluster{}). Where("ID = ?", clusterId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId, "StatusDesc": ""}) @@ -186,8 +187,8 @@ func (r *ClusterRepository) InitWorkflow(clusterId domain.ClusterId, workflowId return nil } -func (r *ClusterRepository) InitWorkflowDescription(clusterId domain.ClusterId) error { - res := r.db.Model(&model.AppGroup{}). +func (r *ClusterRepository) InitWorkflowDescription(ctx context.Context, clusterId domain.ClusterId) error { + res := r.db.WithContext(ctx).Model(&model.AppGroup{}). Where("id = ?", clusterId). Updates(map[string]interface{}{"WorkflowId": "", "StatusDesc": ""}) @@ -198,9 +199,9 @@ func (r *ClusterRepository) InitWorkflowDescription(clusterId domain.ClusterId) return nil } -func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid.UUID) error { +func (r *ClusterRepository) SetFavorite(ctx context.Context, clusterId domain.ClusterId, userId uuid.UUID) error { var clusterFavorites []model.ClusterFavorite - res := r.db.Where("cluster_id = ? AND user_id = ?", clusterId, userId).Find(&clusterFavorites) + res := r.db.WithContext(ctx).Where("cluster_id = ? AND user_id = ?", clusterId, userId).Find(&clusterFavorites) if res.Error != nil { log.Info(res.Error) return res.Error @@ -223,8 +224,8 @@ func (r *ClusterRepository) SetFavorite(clusterId domain.ClusterId, userId uuid. return nil } -func (r *ClusterRepository) DeleteFavorite(clusterId domain.ClusterId, userId uuid.UUID) error { - res := r.db.Unscoped().Delete(&model.ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) +func (r *ClusterRepository) DeleteFavorite(ctx context.Context, clusterId domain.ClusterId, userId uuid.UUID) error { + res := r.db.WithContext(ctx).Unscoped().Delete(&model.ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) if res.Error != nil { log.Error(res.Error) return fmt.Errorf("could not delete cluster favorite for clusterId %s, userId %s", clusterId, userId) diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go index 2b290779..e1230aeb 100644 --- a/internal/repository/endpoint.go +++ b/internal/repository/endpoint.go @@ -1,6 +1,7 @@ package repository import ( + "context" "fmt" "math" @@ -10,9 +11,9 @@ import ( ) type IEndpointRepository interface { - Create(endpoint *model.Endpoint) error - List(pg *pagination.Pagination) ([]*model.Endpoint, error) - Get(id uint) (*model.Endpoint, error) + Create(ctx context.Context, endpoint *model.Endpoint) error + List(ctx context.Context, pg *pagination.Pagination) ([]*model.Endpoint, error) + Get(ctx context.Context, id uint) (*model.Endpoint, error) } type EndpointRepository struct { @@ -25,20 +26,20 @@ func NewEndpointRepository(db *gorm.DB) *EndpointRepository { } } -func (e *EndpointRepository) Create(endpoint *model.Endpoint) error { +func (e *EndpointRepository) Create(ctx context.Context, endpoint *model.Endpoint) error { obj := &model.Endpoint{ Name: endpoint.Name, Group: endpoint.Group, } - if err := e.db.Create(obj).Error; err != nil { + if err := e.db.WithContext(ctx).Create(obj).Error; err != nil { return err } return nil } -func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*model.Endpoint, error) { +func (e *EndpointRepository) List(ctx context.Context, pg *pagination.Pagination) ([]*model.Endpoint, error) { var endpoints []*model.Endpoint if pg == nil { @@ -51,7 +52,7 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*model.Endpoint, pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&endpoints) + res := db.WithContext(ctx).Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&endpoints) if res.Error != nil { return nil, res.Error } @@ -59,10 +60,10 @@ func (e *EndpointRepository) List(pg *pagination.Pagination) ([]*model.Endpoint, return endpoints, nil } -func (e *EndpointRepository) Get(id uint) (*model.Endpoint, error) { +func (e *EndpointRepository) Get(ctx context.Context, id uint) (*model.Endpoint, error) { var obj model.Endpoint - if err := e.db.Preload("Permission").First(&obj, "id = ?", id).Error; err != nil { + if err := e.db.WithContext(ctx).Preload("Permission").First(&obj, "id = ?", id).Error; err != nil { return nil, err } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 7b21fb77..072b2d6a 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -1,6 +1,7 @@ package repository import ( + "context" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -12,14 +13,14 @@ import ( // Interfaces type IOrganizationRepository interface { - Create(dto *model.Organization) (model.Organization, error) - Fetch(pg *pagination.Pagination) (res *[]model.Organization, err error) - Get(organizationId string) (res model.Organization, err error) - Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) - UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error - UpdateAdminId(organizationId string, adminId uuid.UUID) error - Delete(organizationId string) (err error) - InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error + Create(ctx context.Context, dto *model.Organization) (model.Organization, error) + Fetch(ctx context.Context, pg *pagination.Pagination) (res *[]model.Organization, err error) + Get(ctx context.Context, organizationId string) (res model.Organization, err error) + Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) + UpdatePrimaryClusterId(ctx context.Context, organizationId string, primaryClusterId string) error + UpdateAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error + Delete(ctx context.Context, organizationId string) (err error) + InitWorkflow(ctx context.Context, organizationId string, workflowId string, status domain.OrganizationStatus) error } type OrganizationRepository struct { @@ -53,7 +54,7 @@ func NewOrganizationRepository(db *gorm.DB) IOrganizationRepository { // return nil //} -func (r *OrganizationRepository) Create(dto *model.Organization) (model.Organization, error) { +func (r *OrganizationRepository) Create(ctx context.Context, dto *model.Organization) (model.Organization, error) { organization := model.Organization{ ID: dto.ID, Name: dto.Name, @@ -62,7 +63,7 @@ func (r *OrganizationRepository) Create(dto *model.Organization) (model.Organiza Status: domain.OrganizationStatus_PENDING, Phone: dto.Phone, } - res := r.db.Create(&organization) + res := r.db.WithContext(ctx).Create(&organization) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return model.Organization{}, res.Error @@ -71,20 +72,20 @@ func (r *OrganizationRepository) Create(dto *model.Organization) (model.Organiza return organization, nil } -func (r *OrganizationRepository) Fetch(pg *pagination.Pagination) (out *[]model.Organization, err error) { +func (r *OrganizationRepository) Fetch(ctx context.Context, pg *pagination.Pagination) (out *[]model.Organization, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations), &out) + _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations), &out) if res.Error != nil { return nil, res.Error } return } -func (r *OrganizationRepository) Get(id string) (out model.Organization, err error) { - res := r.db.Preload(clause.Associations). +func (r *OrganizationRepository) Get(ctx context.Context, id string) (out model.Organization, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations). First(&out, "id = ?", id) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) @@ -93,8 +94,8 @@ func (r *OrganizationRepository) Get(id string) (out model.Organization, err err return } -func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateOrganizationRequest) (out model.Organization, err error) { - res := r.db.Model(&model.Organization{}). +func (r *OrganizationRepository) Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (out model.Organization, err error) { + res := r.db.WithContext(ctx).Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "name": in.Name, @@ -114,8 +115,8 @@ func (r *OrganizationRepository) Update(organizationId string, in domain.UpdateO return } -func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, primaryClusterId string) error { - res := r.db.Model(&model.Organization{}). +func (r *OrganizationRepository) UpdatePrimaryClusterId(ctx context.Context, organizationId string, primaryClusterId string) error { + res := r.db.WithContext(ctx).Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "primary_cluster_id": primaryClusterId, @@ -128,8 +129,8 @@ func (r *OrganizationRepository) UpdatePrimaryClusterId(organizationId string, p return nil } -func (r *OrganizationRepository) UpdateAdminId(organizationId string, adminId uuid.UUID) (err error) { - res := r.db.Model(&model.Organization{}). +func (r *OrganizationRepository) UpdateAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) (err error) { + res := r.db.WithContext(ctx).Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "admin_id": adminId, @@ -142,8 +143,8 @@ func (r *OrganizationRepository) UpdateAdminId(organizationId string, adminId uu return nil } -func (r *OrganizationRepository) Delete(organizationId string) error { - res := r.db.Delete(&model.Organization{}, "id = ?", organizationId) +func (r *OrganizationRepository) Delete(ctx context.Context, organizationId string) error { + res := r.db.WithContext(ctx).Delete(&model.Organization{}, "id = ?", organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -152,8 +153,8 @@ func (r *OrganizationRepository) Delete(organizationId string) error { return nil } -func (r *OrganizationRepository) InitWorkflow(organizationId string, workflowId string, status domain.OrganizationStatus) error { - res := r.db.Model(&model.Organization{}). +func (r *OrganizationRepository) InitWorkflow(ctx context.Context, organizationId string, workflowId string, status domain.OrganizationStatus) error { + res := r.db.WithContext(ctx).Model(&model.Organization{}). Where("ID = ?", organizationId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) if res.Error != nil { diff --git a/internal/repository/permission.go b/internal/repository/permission.go index ebed52e6..335ce2e4 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -1,17 +1,18 @@ package repository import ( + "context" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "gorm.io/gorm" ) type IPermissionRepository interface { - Create(permission *model.Permission) error - List(roleId string) ([]*model.Permission, error) - Get(id uuid.UUID) (*model.Permission, error) - Delete(id uuid.UUID) error - Update(permission *model.Permission) error + Create(ctx context.Context, permission *model.Permission) error + List(ctx context.Context, roleId string) ([]*model.Permission, error) + Get(ctx context.Context, id uuid.UUID) (*model.Permission, error) + Delete(ctx context.Context, id uuid.UUID) error + Update(ctx context.Context, permission *model.Permission) error } type PermissionRepository struct { @@ -24,7 +25,7 @@ func NewPermissionRepository(db *gorm.DB) *PermissionRepository { } } -func (r PermissionRepository) Create(p *model.Permission) error { +func (r PermissionRepository) Create(ctx context.Context, p *model.Permission) error { //var parent *Permission //var children []*Permission // @@ -46,13 +47,13 @@ func (r PermissionRepository) Create(p *model.Permission) error { // } //} - return r.db.Create(p).Error + return r.db.WithContext(ctx).Create(p).Error } -func (r PermissionRepository) List(roleId string) ([]*model.Permission, error) { +func (r PermissionRepository) List(ctx context.Context, roleId string) ([]*model.Permission, error) { var permissions []*model.Permission - err := r.db.Preload("Children.Children.Children.Children").Where("parent_id IS NULL AND role_id = ?", roleId).Find(&permissions).Error + err := r.db.WithContext(ctx).Preload("Children.Children.Children.Children").Where("parent_id IS NULL AND role_id = ?", roleId).Find(&permissions).Error if err != nil { return nil, err } @@ -60,9 +61,9 @@ func (r PermissionRepository) List(roleId string) ([]*model.Permission, error) { return permissions, nil } -func (r PermissionRepository) Get(id uuid.UUID) (*model.Permission, error) { +func (r PermissionRepository) Get(ctx context.Context, id uuid.UUID) (*model.Permission, error) { permission := &model.Permission{} - result := r.db.Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) + result := r.db.WithContext(ctx).Preload("Children.Children.Children").Preload("Parent").First(&permission, "id = ?", id) if result.Error != nil { return nil, result.Error } @@ -70,11 +71,11 @@ func (r PermissionRepository) Get(id uuid.UUID) (*model.Permission, error) { return permission, nil } -func (r PermissionRepository) Delete(id uuid.UUID) error { - return r.db.Delete(&model.Permission{}, "id = ?", id).Error +func (r PermissionRepository) Delete(ctx context.Context, id uuid.UUID) error { + return r.db.WithContext(ctx).Delete(&model.Permission{}, "id = ?", id).Error } -func (r PermissionRepository) Update(p *model.Permission) error { +func (r PermissionRepository) Update(ctx context.Context, p *model.Permission) error { // update on is_allowed - return r.db.Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error + return r.db.WithContext(ctx).Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error } diff --git a/internal/repository/permission_test.go b/internal/repository/permission_test.go deleted file mode 100644 index dad9d96e..00000000 --- a/internal/repository/permission_test.go +++ /dev/null @@ -1,445 +0,0 @@ -package repository_test - -import ( - "encoding/json" - "fmt" - "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/driver/postgres" - "gorm.io/gorm" - "gorm_test/config" - "testing" -) - -func TestPermission(t *testing.T) { - db := db_connection() - - db.AutoMigrate(&repository.Permission{}) - - //model := domain.Permission{ - // Name: "대시보드", - //} - - repo := repository.NewPermissionRepository(db) - - permissions, err := repo.List() - if err != nil { - t.Fatal(err) - } - out, err := json.MarshalIndent(permissions, "", " ") - if err != nil { - t.Fatal(err) - } - t.Log("start") - t.Logf("permission: %s", string(out)) - t.Log("end") - - //t.Logf("permission: %+v", permissions) - - // - //for _, permission := range permissions { - // // encoding to json - // b, err := json.Marshal(permission) - // if err != nil { - // t.Fatal(err) - // } - // t.Logf("permission: %s", string(b)) - //} - // - ////create - - //if err := repo.Create(dashboard); err != nil { - // t.Fatal(err) - //} - //if err := repo.Create(stack); err != nil { - // t.Fatal(err) - //} - //if err := repo.Create(security_policy); err != nil { - // t.Fatal(err) - //} - //if err := repo.Create(projectManagement); err != nil { - // t.Fatal(err) - //} - //if err := repo.Create(notification); err != nil { - // t.Fatal(err) - //} - //if err := repo.Create(configuration); err != nil { - // t.Fatal(err) - //} - - // get - //permission, err := repo.Get(uuid.MustParse("fd4363a7-d1d2-4feb-b976-b87d99a775c4")) - //if err != nil { - // t.Fatal(err) - //} - //out, err := json.Marshal(permission) - //if err != nil { - // t.Fatal(err) - //} - //t.Logf("permission: %s", string(out)) - - // print json pretty - //out, err := json.MarshalIndent(permission, "", " ") - //if err != nil { - // t.Fatal(err) - //} - //t.Logf("permission: %s", string(out)) - -} - -func db_connection() *gorm.DB { - conf := config.NewDefaultConfig() - dsn := fmt.Sprintf( - "host=%s dbname=%s user=%s password=%s port=%d sslmode=disable TimeZone=Asia/Seoul", - conf.Address, conf.Database, conf.AdminId, conf.AdminPassword, conf.Port, - ) - - db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) - if err != nil { - panic(err) - } - - return db -} - -var dashboard = &domain.Permission{ - Name: "대시보드", - Children: []*domain.Permission{ - { - Name: "대시보드", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "대시보드 설정", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, -} - -var stack = &domain.Permission{ - Name: "스택 관리", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, -} - -var security_policy = &domain.Permission{ - Name: "보안/정책 관리", - Children: []*domain.Permission{ - { - Name: "보안/정책", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, -} - -var projectManagement = &domain.Permission{ - Name: "프로젝트 관리", - Children: []*domain.Permission{ - { - Name: "프로젝트", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "앱 서빙", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "빌드", - IsAllowed: helper.BoolP(false), - }, - { - Name: "배포", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "설정-일반", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "설정-멤버", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "설정-네임스페이스", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, -} - -var notification = &domain.Permission{ - Name: "알림", - Children: []*domain.Permission{ - { - Name: "시스템 경고", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "보안/정책 감사로그", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, -} - -var configuration = &domain.Permission{ - Name: "설정", - Children: []*domain.Permission{ - { - Name: "일반", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "클라우드 계정", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "스택 템플릿", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "프로젝트 관리", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "사용자", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "사용자 권한 관리", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - Name: "알림 설정", - Children: []*domain.Permission{ - { - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - { - Name: "생성", - IsAllowed: helper.BoolP(false), - }, - { - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, - }, - }, - }, -} diff --git a/internal/repository/project.go b/internal/repository/project.go index 198e89a4..4260ea6a 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -1,6 +1,7 @@ package repository import ( + "context" "database/sql" "github.com/google/uuid" @@ -14,33 +15,33 @@ import ( ) type IProjectRepository interface { - CreateProject(p *model.Project) (string, error) - GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) - GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) - GetAllProjects(organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) - GetProjectById(organizationId string, projectId string) (*model.Project, error) - GetProjectByIdAndLeader(organizationId string, projectId string) (*model.Project, error) - GetProjectByName(organizationId string, projectName string) (*model.Project, error) - UpdateProject(p *model.Project) error - GetAllProjectRoles() ([]model.ProjectRole, error) - GetProjectRoleByName(name string) (*model.ProjectRole, error) - GetProjectRoleById(id string) (*model.ProjectRole, error) - AddProjectMember(*model.ProjectMember) (string, error) - GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) ([]model.ProjectMember, error) - GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) ([]model.ProjectMember, error) - GetProjectMemberCountByProjectId(projectId string) (*domain.GetProjectMemberCountResponse, error) - GetProjectMemberById(projectMemberId string) (*model.ProjectMember, error) - GetProjectMemberByUserId(projectId string, projectUserId string) (pm *model.ProjectMember, err error) - RemoveProjectMember(projectMemberId string) error - UpdateProjectMemberRole(pm *model.ProjectMember) error - CreateProjectNamespace(organizationId string, pn *model.ProjectNamespace) error - GetProjectNamespaceByName(organizationId string, projectId string, stackId string, projectNamespace string) (*model.ProjectNamespace, error) - GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) ([]model.ProjectNamespace, error) - GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, projectNamespace string, stackId string) (*model.ProjectNamespace, error) - UpdateProjectNamespace(pn *model.ProjectNamespace) error - DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, stackId string) error - GetAppCountByProjectId(organizationId string, projectId string) (int, error) - GetAppCountByNamespace(organizationId string, projectId string, namespace string) (int, error) + CreateProject(ctx context.Context, p *model.Project) (string, error) + GetProjects(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProjectsByUserId(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetAllProjects(ctx context.Context, organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) + GetProjectById(ctx context.Context, organizationId string, projectId string) (*model.Project, error) + GetProjectByIdAndLeader(ctx context.Context, organizationId string, projectId string) (*model.Project, error) + GetProjectByName(ctx context.Context, organizationId string, projectName string) (*model.Project, error) + UpdateProject(ctx context.Context, p *model.Project) error + GetAllProjectRoles(ctx context.Context) ([]model.ProjectRole, error) + GetProjectRoleByName(ctx context.Context, name string) (*model.ProjectRole, error) + GetProjectRoleById(ctx context.Context, id string) (*model.ProjectRole, error) + AddProjectMember(context.Context, *model.ProjectMember) (string, error) + GetProjectMembersByProjectId(ctx context.Context, projectId string, pg *pagination.Pagination) ([]model.ProjectMember, error) + GetProjectMembersByProjectIdAndRoleName(ctx context.Context, projectId string, memberRole string, pg *pagination.Pagination) ([]model.ProjectMember, error) + GetProjectMemberCountByProjectId(ctx context.Context, projectId string) (*domain.GetProjectMemberCountResponse, error) + GetProjectMemberById(ctx context.Context, projectMemberId string) (*model.ProjectMember, error) + GetProjectMemberByUserId(ctx context.Context, projectId string, projectUserId string) (pm *model.ProjectMember, err error) + RemoveProjectMember(ctx context.Context, projectMemberId string) error + UpdateProjectMemberRole(ctx context.Context, pm *model.ProjectMember) error + CreateProjectNamespace(ctx context.Context, organizationId string, pn *model.ProjectNamespace) error + GetProjectNamespaceByName(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) (*model.ProjectNamespace, error) + GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]model.ProjectNamespace, error) + GetProjectNamespaceByPrimaryKey(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*model.ProjectNamespace, error) + UpdateProjectNamespace(ctx context.Context, pn *model.ProjectNamespace) error + DeleteProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) error + GetAppCountByProjectId(ctx context.Context, organizationId string, projectId string) (int, error) + GetAppCountByNamespace(ctx context.Context, organizationId string, projectId string, namespace string) (int, error) } type ProjectRepository struct { @@ -53,8 +54,8 @@ func NewProjectRepository(db *gorm.DB) IProjectRepository { } } -func (r *ProjectRepository) CreateProject(p *model.Project) (string, error) { - res := r.db.Create(&p) +func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) (string, error) { + res := r.db.WithContext(ctx).Create(&p) if res.Error != nil { return "", res.Error } @@ -62,11 +63,11 @@ func (r *ProjectRepository) CreateProject(p *model.Project) (string, error) { return p.ID, nil } -func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - res := r.db.Raw(""+ + res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ @@ -156,11 +157,11 @@ func (r *ProjectRepository) GetProjects(organizationId string, userId uuid.UUID, return pr, nil } -func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - res := r.db.Raw(""+ + res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ @@ -213,11 +214,11 @@ func (r *ProjectRepository) GetProjectsByUserId(organizationId string, userId uu return pr, nil } -func (r *ProjectRepository) GetAllProjects(organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - res := r.db.Raw(""+ + res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " false as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ @@ -266,8 +267,8 @@ func (r *ProjectRepository) GetAllProjects(organizationId string, pg *pagination return pr, nil } -func (r *ProjectRepository) GetProjectById(organizationId string, projectId string) (p *model.Project, err error) { - res := r.db.Limit(1).Where("organization_id = ? and id = ?", organizationId, projectId).First(&p) +func (r *ProjectRepository) GetProjectById(ctx context.Context, organizationId string, projectId string) (p *model.Project, err error) { + res := r.db.WithContext(ctx).Limit(1).Where("organization_id = ? and id = ?", organizationId, projectId).First(&p) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project") @@ -281,8 +282,8 @@ func (r *ProjectRepository) GetProjectById(organizationId string, projectId stri return p, nil } -func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, projectId string) (p *model.Project, err error) { - res := r.db.Limit(1). +func (r *ProjectRepository) GetProjectByIdAndLeader(ctx context.Context, organizationId string, projectId string) (p *model.Project, err error) { + res := r.db.WithContext(ctx).Limit(1). Preload("ProjectMembers", "is_project_leader = ?", true). Preload("ProjectMembers.ProjectRole"). Preload("ProjectMembers.ProjectUser"). @@ -301,8 +302,8 @@ func (r *ProjectRepository) GetProjectByIdAndLeader(organizationId string, proje return p, nil } -func (r *ProjectRepository) GetProjectByName(organizationId string, projectName string) (p *model.Project, err error) { - res := r.db.Limit(1). +func (r *ProjectRepository) GetProjectByName(ctx context.Context, organizationId string, projectName string) (p *model.Project, err error) { + res := r.db.WithContext(ctx).Limit(1). Where("organization_id = ? and name = ?", organizationId, projectName). First(&p) if res.Error != nil { @@ -318,8 +319,8 @@ func (r *ProjectRepository) GetProjectByName(organizationId string, projectName return p, nil } -func (r *ProjectRepository) UpdateProject(p *model.Project) error { - res := r.db.Model(&p).Updates(model.Project{Name: p.Name, Description: p.Description, UpdatedAt: p.UpdatedAt}) +func (r *ProjectRepository) UpdateProject(ctx context.Context, p *model.Project) error { + res := r.db.WithContext(ctx).Model(&p).Updates(model.Project{Name: p.Name, Description: p.Description, UpdatedAt: p.UpdatedAt}) if res.Error != nil { return res.Error } @@ -327,9 +328,9 @@ func (r *ProjectRepository) UpdateProject(p *model.Project) error { return nil } -func (r *ProjectRepository) GetProjectRoleById(id string) (*model.ProjectRole, error) { +func (r *ProjectRepository) GetProjectRoleById(ctx context.Context, id string) (*model.ProjectRole, error) { var pr = &model.ProjectRole{ID: id} - res := r.db.First(pr) + res := r.db.WithContext(ctx).First(pr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project role") @@ -343,8 +344,8 @@ func (r *ProjectRepository) GetProjectRoleById(id string) (*model.ProjectRole, e return pr, nil } -func (r *ProjectRepository) GetAllProjectRoles() (prs []model.ProjectRole, err error) { - res := r.db.Find(&prs) +func (r *ProjectRepository) GetAllProjectRoles(ctx context.Context) (prs []model.ProjectRole, err error) { + res := r.db.WithContext(ctx).Find(&prs) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project roles") @@ -358,8 +359,8 @@ func (r *ProjectRepository) GetAllProjectRoles() (prs []model.ProjectRole, err e return prs, nil } -func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *model.ProjectRole, err error) { - res := r.db.Where("name = ?", name).First(&pr) +func (r *ProjectRepository) GetProjectRoleByName(ctx context.Context, name string) (pr *model.ProjectRole, err error) { + res := r.db.WithContext(ctx).Where("name = ?", name).First(&pr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Info("Cannot find project roles") @@ -373,8 +374,8 @@ func (r *ProjectRepository) GetProjectRoleByName(name string) (pr *model.Project return pr, nil } -func (r *ProjectRepository) AddProjectMember(pm *model.ProjectMember) (string, error) { - res := r.db.Create(&pm) +func (r *ProjectRepository) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { + res := r.db.WithContext(ctx).Create(&pm) if res.Error != nil { return "", res.Error } @@ -382,11 +383,11 @@ func (r *ProjectRepository) AddProjectMember(pm *model.ProjectMember) (string, e return pm.ID, nil } -func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { +func (r *ProjectRepository) GetProjectMembersByProjectId(ctx context.Context, projectId string, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Joins("ProjectUser"). + _, res := pg.Fetch(r.db.WithContext(ctx).Joins("ProjectUser"). Joins("ProjectRole"). Where("project_members.project_id = ?", projectId). Order("project_members.created_at ASC"), &pms) @@ -403,11 +404,11 @@ func (r *ProjectRepository) GetProjectMembersByProjectId(projectId string, pg *p return pms, nil } -func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId string, memberRole string, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { +func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(ctx context.Context, projectId string, memberRole string, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Joins("ProjectUser"). + _, res := pg.Fetch(r.db.WithContext(ctx).Joins("ProjectUser"). InnerJoins("ProjectRole", r.db.Where(&model.ProjectRole{Name: memberRole})). Order("project_members.created_at ASC"). Where("project_members.project_id = ?", projectId), &pms) @@ -425,8 +426,8 @@ func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(projectId st return pms, nil } -func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { - res := r.db.Raw(""+ +func (r *ProjectRepository) GetProjectMemberCountByProjectId(ctx context.Context, projectId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { + res := r.db.WithContext(ctx).Raw(""+ "select (plc.count + pmc.count + pvc.count) as project_member_all_count,"+ " plc.count as project_leader_count,"+ " pmc.count as project_member_count,"+ @@ -460,8 +461,8 @@ func (r *ProjectRepository) GetProjectMemberCountByProjectId(projectId string) ( return pmcr, nil } -func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm *model.ProjectMember, err error) { - res := r.db.Preload("ProjectUser"). +func (r *ProjectRepository) GetProjectMemberById(ctx context.Context, projectMemberId string) (pm *model.ProjectMember, err error) { + res := r.db.WithContext(ctx).Preload("ProjectUser"). Joins("ProjectRole").Where("project_members.id = ?", projectMemberId).First(&pm) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -476,8 +477,8 @@ func (r *ProjectRepository) GetProjectMemberById(projectMemberId string) (pm *mo return pm, nil } -func (r *ProjectRepository) GetProjectMemberByUserId(projectId string, projectUserId string) (pm *model.ProjectMember, err error) { - res := r.db.Preload("ProjectUser"). +func (r *ProjectRepository) GetProjectMemberByUserId(ctx context.Context, projectId string, projectUserId string) (pm *model.ProjectMember, err error) { + res := r.db.WithContext(ctx).Preload("ProjectUser"). Joins("ProjectRole").Where("project_id = ? and project_user_id = ?", projectId, projectUserId).First(&pm) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -492,8 +493,8 @@ func (r *ProjectRepository) GetProjectMemberByUserId(projectId string, projectUs return pm, nil } -func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { - res := r.db.Delete(&model.ProjectMember{ID: projectMemberId}) +func (r *ProjectRepository) RemoveProjectMember(ctx context.Context, projectMemberId string) error { + res := r.db.WithContext(ctx).Delete(&model.ProjectMember{ID: projectMemberId}) if res.Error != nil { return res.Error } @@ -510,8 +511,8 @@ func (r *ProjectRepository) RemoveProjectMember(projectMemberId string) error { // return nil //} -func (r *ProjectRepository) UpdateProjectMemberRole(pm *model.ProjectMember) error { - res := r.db.Model(&pm).Updates( +func (r *ProjectRepository) UpdateProjectMemberRole(ctx context.Context, pm *model.ProjectMember) error { + res := r.db.WithContext(ctx).Model(&pm).Updates( model.ProjectMember{ ProjectRoleId: pm.ProjectRoleId, IsProjectLeader: pm.IsProjectLeader, @@ -524,8 +525,8 @@ func (r *ProjectRepository) UpdateProjectMemberRole(pm *model.ProjectMember) err return nil } -func (r *ProjectRepository) CreateProjectNamespace(organizationId string, pn *model.ProjectNamespace) error { - res := r.db.Create(&pn) +func (r *ProjectRepository) CreateProjectNamespace(ctx context.Context, organizationId string, pn *model.ProjectNamespace) error { + res := r.db.WithContext(ctx).Create(&pn) if res.Error != nil { return res.Error } @@ -534,9 +535,9 @@ func (r *ProjectRepository) CreateProjectNamespace(organizationId string, pn *mo return nil } -func (r *ProjectRepository) GetProjectNamespaceByName(organizationId string, projectId string, stackId string, +func (r *ProjectRepository) GetProjectNamespaceByName(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) (pn *model.ProjectNamespace, err error) { - res := r.db.Limit(1). + res := r.db.WithContext(ctx).Limit(1). Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). First(&pn) if res.Error != nil { @@ -552,11 +553,11 @@ func (r *ProjectRepository) GetProjectNamespaceByName(organizationId string, pro return pn, nil } -func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectId string, pg *pagination.Pagination) (pns []model.ProjectNamespace, err error) { +func (r *ProjectRepository) GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) (pns []model.ProjectNamespace, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Where("project_id = ?", projectId). + _, res := pg.Fetch(r.db.WithContext(ctx).Where("project_id = ?", projectId). Preload("Stack"), &pns) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -571,9 +572,9 @@ func (r *ProjectRepository) GetProjectNamespaces(organizationId string, projectI return pns, nil } -func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(organizationId string, projectId string, +func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (pn *model.ProjectNamespace, err error) { - res := r.db.Limit(1). + res := r.db.WithContext(ctx).Limit(1). Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). Preload("Stack"). First(&pn) @@ -590,8 +591,8 @@ func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(organizationId strin return pn, nil } -func (r *ProjectRepository) UpdateProjectNamespace(pn *model.ProjectNamespace) error { - res := r.db.Model(&pn).Updates(model.ProjectNamespace{Description: pn.Description, UpdatedAt: pn.UpdatedAt}) +func (r *ProjectRepository) UpdateProjectNamespace(ctx context.Context, pn *model.ProjectNamespace) error { + res := r.db.WithContext(ctx).Model(&pn).Updates(model.ProjectNamespace{Description: pn.Description, UpdatedAt: pn.UpdatedAt}) if res.Error != nil { return res.Error } @@ -599,9 +600,9 @@ func (r *ProjectRepository) UpdateProjectNamespace(pn *model.ProjectNamespace) e return nil } -func (r *ProjectRepository) DeleteProjectNamespace(organizationId string, projectId string, projectNamespace string, +func (r *ProjectRepository) DeleteProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) error { - res := r.db.Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). + res := r.db.WithContext(ctx).Where("stack_id = ? and namespace = ? and project_id = ?", stackId, projectNamespace, projectId). Delete(&model.ProjectNamespace{StackId: stackId, Namespace: projectNamespace}) if res.Error != nil { return res.Error @@ -610,8 +611,8 @@ func (r *ProjectRepository) DeleteProjectNamespace(organizationId string, projec return nil } -func (r *ProjectRepository) GetAppCountByProjectId(organizationId string, projectId string) (appCount int, err error) { - res := r.db.Select("count(*) as app_count"). +func (r *ProjectRepository) GetAppCountByProjectId(ctx context.Context, organizationId string, projectId string) (appCount int, err error) { + res := r.db.WithContext(ctx).Select("count(*) as app_count"). Table("app_serve_apps"). Where("organization_id = ? and project_Id = ?", organizationId, projectId). Find(&appCount) @@ -623,8 +624,8 @@ func (r *ProjectRepository) GetAppCountByProjectId(organizationId string, projec return appCount, nil } -func (r *ProjectRepository) GetAppCountByNamespace(organizationId string, projectId string, namespace string) (appCount int, err error) { - res := r.db.Select("count(*) as app_count"). +func (r *ProjectRepository) GetAppCountByNamespace(ctx context.Context, organizationId string, projectId string, namespace string) (appCount int, err error) { + res := r.db.WithContext(ctx).Select("count(*) as app_count"). Table("app_serve_apps"). Where("organization_id = ? and project_Id = ? and namespace = ?", organizationId, projectId, namespace). Find(&appCount) diff --git a/internal/repository/role.go b/internal/repository/role.go index ab5c7f50..b3b1aa12 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -3,6 +3,7 @@ package repository import ( "fmt" "math" + "context" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -10,41 +11,39 @@ import ( ) type IRoleRepository interface { - Create(roleObj *model.Role) (string, error) - List(pg *pagination.Pagination) ([]*model.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) - Get(id string) (*model.Role, error) - GetTksRole(id string) (*model.Role, error) - GetTksRoleByRoleName(roleName string) (*model.Role, error) - Delete(id string) error - Update(roleObj *model.Role) error + Create(ctx context.Context, roleObj *model.Role) (string, error) + ListTksRoles(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]*model.Role, error) + GetTksRole(ctx context.Context, id string) (*model.Role, error) + GetTksRoleByRoleName(ctx context.Context, roleName string) (*model.Role, error) + Delete(ctx context.Context, id string) error + Update(ctx context.Context, roleObj *model.Role) error } type RoleRepository struct { db *gorm.DB } -func (r RoleRepository) GetTksRoleByRoleName(roleName string) (*model.Role, error) { +func (r RoleRepository) GetTksRoleByRoleName(ctx context.Context, roleName string) (*model.Role, error) { var role model.Role - if err := r.db.Preload("Role").First(&role, "Role.name = ?", roleName).Error; err != nil { + if err := r.db.WithContext(ctx).Preload("Role").First(&role, "Role.name = ?", roleName).Error; err != nil { return nil, err } return &role, nil } -func (r RoleRepository) Create(roleObj *model.Role) (string, error) { +func (r RoleRepository) Create(ctx context.Context, roleObj *model.Role) (string, error) { if roleObj == nil { return "", fmt.Errorf("roleObj is nil") } - if err := r.db.Create(roleObj).Error; err != nil { + if err := r.db.WithContext(ctx).Create(roleObj).Error; err != nil { return "", err } return roleObj.ID, nil } -func (r RoleRepository) List(pg *pagination.Pagination) ([]*model.Role, error) { +func (r RoleRepository) ListTksRoles(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { var roles []*model.Role if pg == nil { @@ -57,29 +56,7 @@ func (r RoleRepository) List(pg *pagination.Pagination) ([]*model.Role, error) { pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&roles) - - if res.Error != nil { - return nil, res.Error - } - - return roles, nil -} - -func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { - var roles []*model.Role - - if pg == nil { - pg = pagination.NewPagination(nil) - } - filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&model.Role{})) - - db.Count(&pg.TotalRows) - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db. + res := db.WithContext(ctx). Offset(pg.GetOffset()). Limit(pg.GetLimit()). Order(orderQuery). @@ -92,30 +69,22 @@ func (r RoleRepository) ListTksRoles(organizationId string, pg *pagination.Pagin return roles, nil } -func (r RoleRepository) Get(id string) (*model.Role, error) { - var role model.Role - if err := r.db.First(&role, "id = ?", id).Error; err != nil { - return nil, err - } - - return &role, nil -} -func (r RoleRepository) GetTksRole(id string) (*model.Role, error) { +func (r RoleRepository) GetTksRole(ctx context.Context, id string) (*model.Role, error) { var role model.Role - if err := r.db.First(&role, "id = ?", id).Error; err != nil { + if err := r.db.WithContext(ctx).First(&role, "id = ?", id).Error; err != nil { return nil, err } return &role, nil } -func (r RoleRepository) Update(roleObj *model.Role) error { +func (r RoleRepository) Update(ctx context.Context, roleObj *model.Role) error { if roleObj == nil { return fmt.Errorf("roleObj is nil") } - err := r.db.Model(&model.Role{}).Where("id = ?", roleObj.ID).Updates(model.Role{ + err := r.db.WithContext(ctx).Model(&model.Role{}).Where("id = ?", roleObj.ID).Updates(model.Role{ Name: roleObj.Name, Description: roleObj.Description, }).Error @@ -127,8 +96,8 @@ func (r RoleRepository) Update(roleObj *model.Role) error { return nil } -func (r RoleRepository) Delete(id string) error { - if err := r.db.Delete(&model.Role{}, "id = ?", id).Error; err != nil { +func (r RoleRepository) Delete(ctx context.Context, id string) error { + if err := r.db.WithContext(ctx).Delete(&model.Role{}, "id = ?", id).Error; err != nil { return err } diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 7fdf1b4e..56dc5bd1 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -1,6 +1,7 @@ package repository import ( + "context" "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -11,14 +12,14 @@ import ( // Interfaces type IStackTemplateRepository interface { - Get(stackTemplateId uuid.UUID) (model.StackTemplate, error) - GetByName(name string) (model.StackTemplate, error) - Fetch(pg *pagination.Pagination) ([]model.StackTemplate, error) - FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) - Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) - Update(dto model.StackTemplate) (err error) - Delete(dto model.StackTemplate) (err error) - UpdateOrganizations(stackTemplateId uuid.UUID, organizationIds []model.Organization) (err error) + Get(ctx context.Context, stackTemplateId uuid.UUID) (model.StackTemplate, error) + GetByName(ctx context.Context, name string) (model.StackTemplate, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.StackTemplate, error) + FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) + Create(ctx context.Context, dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) + Update(ctx context.Context, dto model.StackTemplate) (err error) + Delete(ctx context.Context, dto model.StackTemplate) (err error) + UpdateOrganizations(ctx context.Context, stackTemplateId uuid.UUID, organizationIds []model.Organization) (err error) } type StackTemplateRepository struct { @@ -32,41 +33,41 @@ func NewStackTemplateRepository(db *gorm.DB) IStackTemplateRepository { } // Logics -func (r *StackTemplateRepository) Get(stackTemplateId uuid.UUID) (out model.StackTemplate, err error) { - res := r.db.Preload(clause.Associations).First(&out, "id = ?", stackTemplateId) +func (r *StackTemplateRepository) Get(ctx context.Context, stackTemplateId uuid.UUID) (out model.StackTemplate, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "id = ?", stackTemplateId) if res.Error != nil { return model.StackTemplate{}, res.Error } return } -func (r *StackTemplateRepository) GetByName(name string) (out model.StackTemplate, err error) { - res := r.db.First(&out, "name = ?", name) +func (r *StackTemplateRepository) GetByName(ctx context.Context, name string) (out model.StackTemplate, err error) { + res := r.db.WithContext(ctx).First(&out, "name = ?", name) if res.Error != nil { return out, res.Error } return } -func (r *StackTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.StackTemplate, err error) { +func (r *StackTemplateRepository) Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.StackTemplate, err error) { if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations), &out) + _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations), &out) if res.Error != nil { return nil, res.Error } return } -func (r *StackTemplateRepository) FetchWithOrganization(organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) { +func (r *StackTemplateRepository) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.StackTemplate, err error) { if pg == nil { pg = pagination.NewPagination(nil) } _, res := pg.Fetch( - r.db.Preload(clause.Associations). + r.db.WithContext(ctx).Preload(clause.Associations). Joins("JOIN stack_template_organizations ON stack_template_organizations.stack_template_id = stack_templates.id AND stack_template_organizations.organization_id = ?", organizationId), &out) if res.Error != nil { @@ -75,16 +76,16 @@ func (r *StackTemplateRepository) FetchWithOrganization(organizationId string, p return } -func (r *StackTemplateRepository) Create(dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { - res := r.db.Create(&dto) +func (r *StackTemplateRepository) Create(ctx context.Context, dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { + res := r.db.WithContext(ctx).Create(&dto) if res.Error != nil { return uuid.Nil, res.Error } return dto.ID, nil } -func (r *StackTemplateRepository) Update(dto model.StackTemplate) (err error) { - res := r.db.Model(&model.StackTemplate{}). +func (r *StackTemplateRepository) Update(ctx context.Context, dto model.StackTemplate) (err error) { + res := r.db.WithContext(ctx).Model(&model.StackTemplate{}). Where("id = ?", dto.ID). Updates(map[string]interface{}{ "Template": dto.Template, @@ -103,21 +104,21 @@ func (r *StackTemplateRepository) Update(dto model.StackTemplate) (err error) { return nil } -func (r *StackTemplateRepository) Delete(dto model.StackTemplate) (err error) { - res := r.db.Delete(&model.StackTemplate{}, "id = ?", dto.ID) +func (r *StackTemplateRepository) Delete(ctx context.Context, dto model.StackTemplate) (err error) { + res := r.db.WithContext(ctx).Delete(&model.StackTemplate{}, "id = ?", dto.ID) if res.Error != nil { return res.Error } return nil } -func (r *StackTemplateRepository) UpdateOrganizations(stackTemplateId uuid.UUID, organizations []model.Organization) (err error) { +func (r *StackTemplateRepository) UpdateOrganizations(ctx context.Context, stackTemplateId uuid.UUID, organizations []model.Organization) (err error) { var stackTemplate = model.StackTemplate{} - res := r.db.Preload("Organizations").First(&stackTemplate, "id = ?", stackTemplateId) + res := r.db.WithContext(ctx).Preload("Organizations").First(&stackTemplate, "id = ?", stackTemplateId) if res.Error != nil { return res.Error } - err = r.db.Model(&stackTemplate).Association("Organizations").Replace(organizations) + err = r.db.WithContext(ctx).Model(&stackTemplate).Association("Organizations").Replace(organizations) if err != nil { return err } diff --git a/internal/repository/user.go b/internal/repository/user.go index fcfd4981..99a4b98e 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -1,6 +1,7 @@ package repository import ( + "context" "time" "github.com/google/uuid" @@ -13,17 +14,17 @@ import ( // Interface type IUserRepository interface { - CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, + CreateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, email string, department string, description string, organizationId string, roleId string) (model.User, error) - List(filters ...FilterFunc) (out *[]model.User, err error) - ListWithPagination(pg *pagination.Pagination, organizationId string) (out *[]model.User, err error) - Get(accountId string, organizationId string) (model.User, error) - GetByUuid(userId uuid.UUID) (model.User, error) - UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, email string, + List(ctx context.Context, filters ...FilterFunc) (out *[]model.User, err error) + ListWithPagination(ctx context.Context, pg *pagination.Pagination, organizationId string) (out *[]model.User, err error) + Get(ctx context.Context, accountId string, organizationId string) (model.User, error) + GetByUuid(ctx context.Context, userId uuid.UUID) (model.User, error) + UpdateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, roleId string, email string, department string, description string) (model.User, error) - UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error - DeleteWithUuid(uuid uuid.UUID) error - Flush(organizationId string) error + UpdatePasswordAt(ctx context.Context, userId uuid.UUID, organizationId string, isTemporary bool) error + DeleteWithUuid(ctx context.Context, uuid uuid.UUID) error + Flush(ctx context.Context, organizationId string) error AccountIdFilter(accountId string) FilterFunc OrganizationFilter(organization string) FilterFunc @@ -35,8 +36,8 @@ type UserRepository struct { db *gorm.DB } -func (r *UserRepository) Flush(organizationId string) error { - res := r.db.Where("organization_id = ?", organizationId).Delete(&model.User{}) +func (r *UserRepository) Flush(ctx context.Context, organizationId string) error { + res := r.db.WithContext(ctx).Where("organization_id = ?", organizationId).Delete(&model.User{}) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -50,33 +51,7 @@ func NewUserRepository(db *gorm.DB) IUserRepository { } } -//// Models -//type User struct { -// gorm.Model -// -// ID uuid.UUID `gorm:"primarykey;type:uuid"` -// AccountId string -// Name string -// Password string -// AuthType string `gorm:"authType"` -// RoleId uuid.UUID -// Role Role `gorm:"foreignKey:RoleId;references:ID"` -// OrganizationId string -// Organization Organization `gorm:"foreignKey:OrganizationId;references:ID"` -// Creator uuid.UUID -// Email string -// Department string -// Description string -// -// PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` -//} - -//func (g *User) BeforeCreate(tx *gorm.DB) (err error) { -// g.PasswordUpdatedAt = time.Now() -// return nil -//} - -func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name string, email string, +func (r *UserRepository) CreateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, email string, department string, description string, organizationId string, roleId string) (model.User, error) { newUser := model.User{ @@ -89,45 +64,25 @@ func (r *UserRepository) CreateWithUuid(uuid uuid.UUID, accountId string, name s OrganizationId: organizationId, RoleId: roleId, } - res := r.db.Create(&newUser) + res := r.db.WithContext(ctx).Create(&newUser) if res.Error != nil { log.Error(res.Error.Error()) return model.User{}, res.Error } - user, err := r.getUserByAccountId(accountId, organizationId) + user, err := r.getUserByAccountId(nil, accountId, organizationId) if err != nil { return model.User{}, err } return user, nil } -func (r *UserRepository) AccountIdFilter(accountId string) FilterFunc { - return func(user *gorm.DB) *gorm.DB { - return user.Where("account_id = ?", accountId) - } -} -func (r *UserRepository) OrganizationFilter(organization string) FilterFunc { - return func(user *gorm.DB) *gorm.DB { - return user.Where("organization_id = ?", organization) - } -} -func (r *UserRepository) EmailFilter(email string) FilterFunc { - return func(user *gorm.DB) *gorm.DB { - return user.Where("email = ?", email) - } -} -func (r *UserRepository) NameFilter(name string) FilterFunc { - return func(user *gorm.DB) *gorm.DB { - return user.Where("name = ?", name) - } -} -func (r *UserRepository) List(filters ...FilterFunc) (*[]model.User, error) { +func (r *UserRepository) List(ctx context.Context, filters ...FilterFunc) (*[]model.User, error) { var users []model.User var res *gorm.DB if filters == nil { - res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Find(&users) + res = r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Role").Find(&users) } else { combinedFilter := func(filters ...FilterFunc) FilterFunc { return func(user *gorm.DB) *gorm.DB { @@ -157,14 +112,14 @@ func (r *UserRepository) List(filters ...FilterFunc) (*[]model.User, error) { return &out, nil } -func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizationId string) (*[]model.User, error) { +func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination.Pagination, organizationId string) (*[]model.User, error) { var users []model.User if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload("Organization").Preload("Role").Model(&model.User{}).Where("organization_id = ?", organizationId), &users) + _, res := pg.Fetch(r.db.WithContext(ctx).Preload("Organization").Preload("Role").Model(&model.User{}).Where("organization_id = ?", organizationId), &users) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error @@ -178,17 +133,18 @@ func (r *UserRepository) ListWithPagination(pg *pagination.Pagination, organizat return &out, nil } -func (r *UserRepository) Get(accountId string, organizationId string) (model.User, error) { - user, err := r.getUserByAccountId(accountId, organizationId) +func (r *UserRepository) Get(ctx context.Context, accountId string, organizationId string) (model.User, error) { + user, err := r.getUserByAccountId(ctx, accountId, organizationId) if err != nil { return model.User{}, err } return user, nil } -func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser model.User, err error) { + +func (r *UserRepository) GetByUuid(ctx context.Context, userId uuid.UUID) (respUser model.User, err error) { user := model.User{} - res := r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) + res := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) @@ -200,10 +156,10 @@ func (r *UserRepository) GetByUuid(userId uuid.UUID) (respUser model.User, err e return user, nil } -func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name string, roleId string, +func (r *UserRepository) UpdateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, roleId string, email string, department string, description string) (model.User, error) { var user model.User - res := r.db.Model(&model.User{}).Where("id = ?", uuid).Updates(model.User{ + res := r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", uuid).Updates(model.User{ AccountId: accountId, Name: name, Email: email, @@ -224,14 +180,15 @@ func (r *UserRepository) UpdateWithUuid(uuid uuid.UUID, accountId string, name s } return user, nil } -func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId string, isTemporary bool) error { + +func (r *UserRepository) UpdatePasswordAt(ctx context.Context, userId uuid.UUID, organizationId string, isTemporary bool) error { var updateUser = model.User{} if isTemporary { updateUser.PasswordUpdatedAt = time.Time{} } else { updateUser.PasswordUpdatedAt = time.Now() } - res := r.db.Model(&model.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). + res := r.db.WithContext(ctx).Model(&model.User{}).Where("id = ? AND organization_id = ?", userId, organizationId). Select("password_updated_at").Updates(updateUser) if res.RowsAffected == 0 || res.Error != nil { @@ -244,8 +201,9 @@ func (r *UserRepository) UpdatePasswordAt(userId uuid.UUID, organizationId strin return nil } -func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { - res := r.db.Unscoped().Delete(&model.User{}, "id = ?", uuid) + +func (r *UserRepository) DeleteWithUuid(ctx context.Context, uuid uuid.UUID) error { + res := r.db.WithContext(ctx).Unscoped().Delete(&model.User{}, "id = ?", uuid) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return res.Error @@ -253,28 +211,8 @@ func (r *UserRepository) DeleteWithUuid(uuid uuid.UUID) error { return nil } -//// Deprecated: -//type Policy struct { -// gorm.Model -// -// //ID uuid.UUID `gorm:"primarykey;type:uuid;"` -// RoleId uuid.UUID -// Role Role `gorm:"references:ID"` -// Name string -// Description string -// Create bool `gorm:"column:c"` -// CreatePriviledge string -// Update bool `gorm:"column:u"` -// UpdatePriviledge string -// Read bool `gorm:"column:r"` -// ReadPriviledge string -// Delete bool `gorm:"column:d"` -// DeletePriviledge string -// Creator uuid.UUID -//} - -func (r *UserRepository) GetRoleByName(roleName string) (model.Role, error) { - role, err := r.getRoleByName(roleName) +func (r *UserRepository) GetRoleByName(ctx context.Context, roleName string) (model.Role, error) { + role, err := r.getRoleByName(ctx, roleName) if err != nil { return model.Role{}, err } @@ -305,9 +243,9 @@ func (r *UserRepository) GetRoleByName(roleName string) (model.Role, error) { //} // private members -func (r *UserRepository) getUserByAccountId(accountId string, organizationId string) (model.User, error) { +func (r *UserRepository) getUserByAccountId(ctx context.Context, accountId string, organizationId string) (model.User, error) { user := model.User{} - res := r.db.Model(&model.User{}).Preload("Organization").Preload("Role"). + res := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Role"). Find(&user, "account_id = ? AND organization_id = ?", accountId, organizationId) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) @@ -320,9 +258,9 @@ func (r *UserRepository) getUserByAccountId(accountId string, organizationId str return user, nil } -func (r *UserRepository) getRoleByName(roleName string) (model.Role, error) { +func (r *UserRepository) getRoleByName(ctx context.Context, roleName string) (model.Role, error) { role := model.Role{} - res := r.db.First(&role, "name = ?", roleName) + res := r.db.WithContext(ctx).First(&role, "name = ?", roleName) if res.Error != nil { log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) return model.Role{}, res.Error @@ -331,9 +269,29 @@ func (r *UserRepository) getRoleByName(roleName string) (model.Role, error) { return model.Role{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } - //if res.RowsAffected == 0 { - // return Role{}, nil - //} - return role, nil } + +func (r *UserRepository) AccountIdFilter(accountId string) FilterFunc { + return func(user *gorm.DB) *gorm.DB { + return user.Where("account_id = ?", accountId) + } +} + +func (r *UserRepository) OrganizationFilter(organization string) FilterFunc { + return func(user *gorm.DB) *gorm.DB { + return user.Where("organization_id = ?", organization) + } +} + +func (r *UserRepository) EmailFilter(email string) FilterFunc { + return func(user *gorm.DB) *gorm.DB { + return user.Where("email = ?", email) + } +} + +func (r *UserRepository) NameFilter(name string) FilterFunc { + return func(user *gorm.DB) *gorm.DB { + return user.Where("name = ?", name) + } +} diff --git a/internal/route/route.go b/internal/route/route.go index 6c8f16a3..b7d0b827 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -90,7 +90,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa authHandler := delivery.NewAuthHandler(usecaseFactory) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/login", authHandler.Login).Methods(http.MethodPost) - r.HandleFunc(API_PREFIX+API_VERSION+"/auth/ping", authHandler.PingToken).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/auth/logout", customMiddleware.Handle(internalApi.Logout, http.HandlerFunc(authHandler.Logout))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/auth/refresh", customMiddleware.Handle(internalApi.RefreshToken, http.HandlerFunc(authHandler.RefreshToken))).Methods(http.MethodPost) r.HandleFunc(API_PREFIX+API_VERSION+"/auth/find-id/verification", authHandler.FindId).Methods(http.MethodPost) diff --git a/internal/usecase/alert.go b/internal/usecase/alert.go index de77595a..01e6929b 100644 --- a/internal/usecase/alert.go +++ b/internal/usecase/alert.go @@ -51,7 +51,7 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque return fmt.Errorf("No data found") } - allClusters, err := u.clusterRepo.Fetch(nil) + allClusters, err := u.clusterRepo.Fetch(ctx, nil) if err != nil { return fmt.Errorf("No clusters") } @@ -64,12 +64,12 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque continue } - organization, err := u.organizationRepo.Get(organizationId) + organization, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { log.ErrorWithContext(ctx, err) continue } - primaryCluster, err := u.clusterRepo.Get(domain.ClusterId(organization.PrimaryClusterId)) + primaryCluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(organization.PrimaryClusterId)) if err != nil { log.ErrorWithContext(ctx, err) continue @@ -116,7 +116,7 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque RawData: rawData, } - _, err = u.repo.Create(dto) + _, err = u.repo.Create(ctx, dto) if err != nil { continue } @@ -130,7 +130,7 @@ func (u *AlertUsecase) Update(ctx context.Context, dto model.Alert) error { } func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert model.Alert, err error) { - alert, err = u.repo.Get(alertId) + alert, err = u.repo.Get(ctx, alertId) if err != nil { return alert, err } @@ -140,7 +140,7 @@ func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert model. } func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Alert, err error) { - out, err = u.repo.GetByName(organizationId, name) + out, err = u.repo.GetByName(ctx, organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return out, httpErrors.NewNotFoundError(err, "", "") @@ -151,7 +151,7 @@ func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, nam } func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (alerts []model.Alert, err error) { - alerts, err = u.repo.Fetch(organizationId, pg) + alerts, err = u.repo.Fetch(ctx, organizationId, pg) if err != nil { return nil, err } @@ -174,7 +174,7 @@ func (u *AlertUsecase) Delete(ctx context.Context, dto model.Alert) (err error) return httpErrors.NewNotFoundError(err, "AL_NOT_FOUND_ALERT", "") } - err = u.repo.Delete(dto) + err = u.repo.Delete(ctx, dto) if err != nil { return err } @@ -188,7 +188,7 @@ func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto model.AlertAct return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") } - _, err = u.repo.Get(dto.AlertId) + _, err = u.repo.Get(ctx, dto.AlertId) if err != nil { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Not found alert"), "AL_NOT_FOUND_ALERT", "") } @@ -197,7 +197,7 @@ func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto model.AlertAct dto.TakerId = &userId dto.CreatedAt = time.Now() - alertActionId, err = u.repo.CreateAlertAction(dto) + alertActionId, err = u.repo.CreateAlertAction(ctx, dto) if err != nil { return uuid.Nil, err } @@ -242,11 +242,11 @@ func (u *AlertUsecase) makeAdditionalInfo(alert *model.Alert) { func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, alert domain.CreateAlertRequestAlert, clusterId domain.ClusterId) (url string) { primaryGrafanaEndpoint := "" - appGroups, err := u.appGroupRepo.Fetch(primaryCluster.ID, nil) + appGroups, err := u.appGroupRepo.Fetch(ctx, primaryCluster.ID, nil) if err == nil { for _, appGroup := range appGroups { if appGroup.AppGroupType == domain.AppGroupType_LMA { - applications, err := u.appGroupRepo.GetApplications(appGroup.ID, domain.ApplicationType_GRAFANA) + applications, err := u.appGroupRepo.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) if err != nil { return "" } diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index a73c0e6b..d492128d 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -43,7 +43,7 @@ func NewAppGroupUsecase(r repository.Repository, argoClient argowf.ArgoClient) I } func (u *AppGroupUsecase) Fetch(ctx context.Context, clusterId domain.ClusterId, pg *pagination.Pagination) (out []model.AppGroup, err error) { - out, err = u.repo.Fetch(clusterId, pg) + out, err = u.repo.Fetch(ctx, clusterId, pg) if err != nil { return nil, err } @@ -58,12 +58,12 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do userId := user.GetUserId() dto.CreatorId = &userId - cluster, err := u.clusterRepo.Get(dto.ClusterId) + cluster, err := u.clusterRepo.Get(ctx, dto.ClusterId) if err != nil { return "", httpErrors.NewBadRequestError(err, "AG_NOT_FOUND_CLUSTER", "") } - resAppGroups, err := u.repo.Fetch(dto.ClusterId, nil) + resAppGroups, err := u.repo.Fetch(ctx, dto.ClusterId, nil) if err != nil { return "", httpErrors.NewBadRequestError(err, "AG_NOT_FOUND_APPGROUP", "") } @@ -83,7 +83,7 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do tksObjectStore := "minio" if cluster.CloudService != domain.CloudService_BYOH { tksObjectStore = "s3" - cloudAccounts, err := u.cloudAccountRepo.Fetch(cluster.OrganizationId, nil) + cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, cluster.OrganizationId, nil) if err != nil { return "", httpErrors.NewBadRequestError(fmt.Errorf("Failed to get cloudAccounts"), "", "") } @@ -107,9 +107,9 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do } if dto.ID == "" { - dto.ID, err = u.repo.Create(dto) + dto.ID, err = u.repo.Create(ctx, dto) } else { - err = u.repo.Update(dto) + err = u.repo.Update(ctx, dto) } if err != nil { return "", httpErrors.NewInternalServerError(err, "AG_FAILED_TO_CREATE_APPGROUP", "") @@ -152,7 +152,7 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do return "", httpErrors.NewInternalServerError(err, "AG_FAILED_TO_CALL_WORKFLOW", "") } - if err := u.repo.InitWorkflow(dto.ID, workflowId, domain.AppGroupStatus_INSTALLING); err != nil { + if err := u.repo.InitWorkflow(ctx, dto.ID, workflowId, domain.AppGroupStatus_INSTALLING); err != nil { return "", errors.Wrap(err, "Failed to initialize appGroup status") } @@ -160,7 +160,7 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do } func (u *AppGroupUsecase) Get(ctx context.Context, id domain.AppGroupId) (out model.AppGroup, err error) { - appGroup, err := u.repo.Get(id) + appGroup, err := u.repo.Get(ctx, id) if err != nil { return model.AppGroup{}, err } @@ -168,11 +168,11 @@ func (u *AppGroupUsecase) Get(ctx context.Context, id domain.AppGroupId) (out mo } func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err error) { - appGroup, err := u.repo.Get(id) + appGroup, err := u.repo.Get(ctx, id) if err != nil { return fmt.Errorf("No appGroup for deletiing : %s", id) } - cluster, err := u.clusterRepo.Get(appGroup.ClusterId) + cluster, err := u.clusterRepo.Get(ctx, appGroup.ClusterId) if err != nil { return httpErrors.NewBadRequestError(err, "AG_NOT_FOUND_CLUSTER", "") } @@ -183,7 +183,7 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err tksObjectStore := "minio" if cluster.CloudService != domain.CloudService_BYOH { tksObjectStore = "s3" - cloudAccounts, err := u.cloudAccountRepo.Fetch(cluster.OrganizationId, nil) + cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, cluster.OrganizationId, nil) if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("Failed to get cloudAccounts"), "", "") } @@ -242,7 +242,7 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err log.DebugWithContext(ctx, "submited workflow name : ", workflowId) - if err := u.repo.InitWorkflow(id, workflowId, domain.AppGroupStatus_DELETING); err != nil { + if err := u.repo.InitWorkflow(ctx, id, workflowId, domain.AppGroupStatus_DELETING); err != nil { return fmt.Errorf("Failed to initialize appGroup status. err : %s", err) } @@ -257,7 +257,7 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err } func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGroupId, applicationType domain.ApplicationType) (out []model.Application, err error) { - out, err = u.repo.GetApplications(id, applicationType) + out, err = u.repo.GetApplications(ctx, id, applicationType) if err != nil { return nil, err } @@ -265,7 +265,7 @@ func (u *AppGroupUsecase) GetApplications(ctx context.Context, id domain.AppGrou } func (u *AppGroupUsecase) UpdateApplication(ctx context.Context, dto model.Application) (err error) { - err = u.repo.UpsertApplication(dto) + err = u.repo.UpsertApplication(ctx, dto) if err != nil { return err } diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 198b31a3..c58539c1 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -24,23 +24,23 @@ import ( ) type IAppServeAppUsecase interface { - CreateAppServeApp(app *model.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) - GetAppServeAppById(appId string) (*model.AppServeApp, error) - GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) - GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) - GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) - GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) - IsAppServeAppExist(appId string) (bool, error) - IsAppServeAppNameExist(orgId string, appName string) (bool, error) - IsAppServeAppNamespaceExist(clusterId string, namespace string) (bool, error) - UpdateAppServeAppStatus(appId string, taskId string, status string, output string) (ret string, err error) - DeleteAppServeApp(appId string) (res string, err error) - UpdateAppServeApp(app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) - UpdateAppServeAppEndpoint(appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) (string, error) - PromoteAppServeApp(appId string) (ret string, err error) - AbortAppServeApp(appId string) (ret string, err error) - RollbackAppServeApp(appId string, taskId string) (ret string, err error) + CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) + GetAppServeApps(ctx context.Context, organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) + GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) + GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) + GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) + GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) + GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) + IsAppServeAppExist(ctx context.Context, appId string) (bool, error) + IsAppServeAppNameExist(ctx context.Context, orgId string, appName string) (bool, error) + IsAppServeAppNamespaceExist(ctx context.Context, clusterId string, namespace string) (bool, error) + UpdateAppServeAppStatus(ctx context.Context, appId string, taskId string, status string, output string) (ret string, err error) + DeleteAppServeApp(ctx context.Context, appId string) (res string, err error) + UpdateAppServeApp(ctx context.Context, app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) + UpdateAppServeAppEndpoint(ctx context.Context, appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) (string, error) + PromoteAppServeApp(ctx context.Context, appId string) (ret string, err error) + AbortAppServeApp(ctx context.Context, appId string) (ret string, err error) + RollbackAppServeApp(ctx context.Context, appId string, taskId string) (ret string, err error) } type AppServeAppUsecase struct { @@ -59,7 +59,7 @@ func NewAppServeAppUsecase(r repository.Repository, argoClient argowf.ArgoClient } } -func (u *AppServeAppUsecase) CreateAppServeApp(app *model.AppServeApp) (string, string, error) { +func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (string, string, error) { if app == nil { return "", "", fmt.Errorf("invalid app obj") } @@ -125,7 +125,7 @@ func (u *AppServeAppUsecase) CreateAppServeApp(app *model.AppServeApp) (string, log.Debug("After transform, extraEnv: ", extEnv) } - appId, taskId, err := u.repo.CreateAppServeApp(app) + appId, taskId, err := u.repo.CreateAppServeApp(ctx, app) if err != nil { log.Error(err) return "", "", errors.Wrap(err, "Failed to create app.") @@ -180,8 +180,8 @@ func (u *AppServeAppUsecase) CreateAppServeApp(app *model.AppServeApp) (string, return appId, app.Name, nil } -func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) { - apps, err := u.repo.GetAppServeApps(organizationId, showAll, pg) +func (u *AppServeAppUsecase) GetAppServeApps(ctx context.Context, organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) { + apps, err := u.repo.GetAppServeApps(ctx, organizationId, showAll, pg) if err != nil { fmt.Println(apps) } @@ -189,8 +189,8 @@ func (u *AppServeAppUsecase) GetAppServeApps(organizationId string, showAll bool return apps, nil } -func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*model.AppServeApp, error) { - asa, err := u.repo.GetAppServeAppById(appId) +func (u *AppServeAppUsecase) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) { + asa, err := u.repo.GetAppServeAppById(ctx, appId) if err != nil { return nil, err } @@ -198,19 +198,19 @@ func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*model.AppServeAp /************************ * Construct grafana URL * ************************/ - organization, err := u.organizationRepo.Get(asa.OrganizationId) + organization, err := u.organizationRepo.Get(ctx, asa.OrganizationId) if err != nil { return asa, httpErrors.NewInternalServerError(errors.Wrap(err, fmt.Sprintf("Failed to get organization for app %s", asa.Name)), "S_FAILED_FETCH_ORGANIZATION", "") } - appGroupsInPrimaryCluster, err := u.appGroupRepo.Fetch(domain.ClusterId(organization.PrimaryClusterId), nil) + appGroupsInPrimaryCluster, err := u.appGroupRepo.Fetch(ctx, domain.ClusterId(organization.PrimaryClusterId), nil) if err != nil { return asa, err } for _, appGroup := range appGroupsInPrimaryCluster { if appGroup.AppGroupType == domain.AppGroupType_LMA { - applications, err := u.appGroupRepo.GetApplications(appGroup.ID, domain.ApplicationType_GRAFANA) + applications, err := u.appGroupRepo.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) if err != nil { return asa, err } @@ -223,8 +223,8 @@ func (u *AppServeAppUsecase) GetAppServeAppById(appId string) (*model.AppServeAp return asa, nil } -func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) { - tasks, err := u.repo.GetAppServeAppTasksByAppId(appId, pg) +func (u *AppServeAppUsecase) GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) { + tasks, err := u.repo.GetAppServeAppTasksByAppId(ctx, appId, pg) if err != nil { log.Debugf("Tasks: %v", tasks) } @@ -232,8 +232,8 @@ func (u *AppServeAppUsecase) GetAppServeAppTasks(appId string, pg *pagination.Pa return tasks, nil } -func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { - task, app, err := u.repo.GetAppServeAppTaskById(taskId) +func (u *AppServeAppUsecase) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { + task, app, err := u.repo.GetAppServeAppTaskById(ctx, taskId) if err != nil { return nil, nil, err } @@ -241,8 +241,8 @@ func (u *AppServeAppUsecase) GetAppServeAppTaskById(taskId string) (*model.AppSe return task, app, nil } -func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*model.AppServeAppTask, error) { - task, err := u.repo.GetAppServeAppLatestTask(appId) +func (u *AppServeAppUsecase) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) { + task, err := u.repo.GetAppServeAppLatestTask(ctx, appId) if err != nil { return nil, err } @@ -250,8 +250,8 @@ func (u *AppServeAppUsecase) GetAppServeAppLatestTask(appId string) (*model.AppS return task, nil } -func (u *AppServeAppUsecase) GetNumOfAppsOnStack(organizationId string, clusterId string) (int64, error) { - numApps, err := u.repo.GetNumOfAppsOnStack(organizationId, clusterId) +func (u *AppServeAppUsecase) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) { + numApps, err := u.repo.GetNumOfAppsOnStack(ctx, organizationId, clusterId) if err != nil { return -1, err } @@ -259,8 +259,8 @@ func (u *AppServeAppUsecase) GetNumOfAppsOnStack(organizationId string, clusterI return numApps, nil } -func (u *AppServeAppUsecase) IsAppServeAppExist(appId string) (bool, error) { - count, err := u.repo.IsAppServeAppExist(appId) +func (u *AppServeAppUsecase) IsAppServeAppExist(ctx context.Context, appId string) (bool, error) { + count, err := u.repo.IsAppServeAppExist(ctx, appId) if err != nil { return false, err } @@ -272,8 +272,8 @@ func (u *AppServeAppUsecase) IsAppServeAppExist(appId string) (bool, error) { return false, nil } -func (u *AppServeAppUsecase) IsAppServeAppNameExist(orgId string, appName string) (bool, error) { - count, err := u.repo.IsAppServeAppNameExist(orgId, appName) +func (u *AppServeAppUsecase) IsAppServeAppNameExist(ctx context.Context, orgId string, appName string) (bool, error) { + count, err := u.repo.IsAppServeAppNameExist(ctx, orgId, appName) if err != nil { return false, err } @@ -285,7 +285,7 @@ func (u *AppServeAppUsecase) IsAppServeAppNameExist(orgId string, appName string return false, nil } -func (u *AppServeAppUsecase) IsAppServeAppNamespaceExist(clusterId string, new_ns string) (bool, error) { +func (u *AppServeAppUsecase) IsAppServeAppNamespaceExist(ctx context.Context, clusterId string, new_ns string) (bool, error) { clientset, err := kubernetes.GetClientFromClusterId(clusterId) if err != nil { log.Error(err) @@ -307,15 +307,12 @@ func (u *AppServeAppUsecase) IsAppServeAppNamespaceExist(clusterId string, new_n return false, nil } -func (u *AppServeAppUsecase) UpdateAppServeAppStatus( - appId string, - taskId string, - status string, +func (u *AppServeAppUsecase) UpdateAppServeAppStatus(ctx context.Context, appId string, taskId string, status string, output string) (string, error) { log.Info("Starting status update process..") - err := u.repo.UpdateStatus(appId, taskId, status, output) + err := u.repo.UpdateStatus(ctx, appId, taskId, status, output) if err != nil { log.Info("appId = ", appId) log.Info("taskId = ", taskId) @@ -325,6 +322,7 @@ func (u *AppServeAppUsecase) UpdateAppServeAppStatus( } func (u *AppServeAppUsecase) UpdateAppServeAppEndpoint( + ctx context.Context, appId string, taskId string, endpoint string, @@ -333,7 +331,7 @@ func (u *AppServeAppUsecase) UpdateAppServeAppEndpoint( log.Info("Starting endpoint update process..") - err := u.repo.UpdateEndpoint(appId, taskId, endpoint, previewEndpoint, helmRevision) + err := u.repo.UpdateEndpoint(ctx, appId, taskId, endpoint, previewEndpoint, helmRevision) if err != nil { log.Info("appId = ", appId) log.Info("taskId = ", taskId) @@ -342,8 +340,8 @@ func (u *AppServeAppUsecase) UpdateAppServeAppEndpoint( return fmt.Sprintf("The appId '%s' endpoint is being updated.", appId), nil } -func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err error) { - app, err := u.repo.GetAppServeAppById(appId) +func (u *AppServeAppUsecase) DeleteAppServeApp(ctx context.Context, appId string) (res string, err error) { + app, err := u.repo.GetAppServeAppById(ctx, appId) if err != nil { return "", fmt.Errorf("error while getting ASA Info from DB. Err: %s", err) } @@ -373,7 +371,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er CreatedAt: time.Now(), } - taskId, err := u.repo.CreateTask(appTask) + taskId, err := u.repo.CreateTask(ctx, appTask) if err != nil { log.Error("taskId = ", taskId) log.Error("Failed to create delete task. Err:", err) @@ -382,7 +380,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er log.Info("Updating app status to 'DELETING'..") - err = u.repo.UpdateStatus(appId, taskId, "DELETING", "") + err = u.repo.UpdateStatus(ctx, appId, taskId, "DELETING", "") if err != nil { log.Debug("appId = ", appId) log.Debug("taskId = ", taskId) @@ -413,12 +411,12 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(appId string) (res string, err er "Confirm result by checking the app status after a while.", app.Name), nil } -func (u *AppServeAppUsecase) UpdateAppServeApp(app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) { +func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) { if appTask == nil { return "", errors.New("invalid parameters. appTask is nil") } - app_, err := u.repo.GetAppServeAppById(app.ID) + app_, err := u.repo.GetAppServeAppById(ctx, app.ID) if err != nil { return "", fmt.Errorf("error while getting ASA Info from DB. Err: %s", err) } @@ -480,7 +478,7 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(app *model.AppServeApp, appTask * log.Debug("After transform, extraEnv: ", extEnv) } - taskId, err := u.repo.CreateTask(appTask) + taskId, err := u.repo.CreateTask(ctx, appTask) if err != nil { log.Info("taskId = ", taskId) return "", fmt.Errorf("failed to update app-serve application. Err: %s", err) @@ -489,7 +487,7 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(app *model.AppServeApp, appTask * // Sync new task status to the parent app log.Info("Updating app status to 'PREPARING'..") - err = u.repo.UpdateStatus(app.ID, taskId, "PREPARING", "") + err = u.repo.UpdateStatus(ctx, app.ID, taskId, "PREPARING", "") if err != nil { log.Debug("appId = ", app.ID) log.Debug("taskId = ", taskId) @@ -547,8 +545,8 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(app *model.AppServeApp, appTask * return message, nil } -func (u *AppServeAppUsecase) PromoteAppServeApp(appId string) (ret string, err error) { - app, err := u.repo.GetAppServeAppById(appId) +func (u *AppServeAppUsecase) PromoteAppServeApp(ctx context.Context, appId string) (ret string, err error) { + app, err := u.repo.GetAppServeAppById(ctx, appId) if err != nil { return "", fmt.Errorf("error while getting ASA Info from DB. Err: %s", err) } @@ -565,7 +563,7 @@ func (u *AppServeAppUsecase) PromoteAppServeApp(appId string) (ret string, err e log.Info("Updating app status to 'PROMOTING'..") - err = u.repo.UpdateStatus(appId, latestTaskId, "PROMOTING", "") + err = u.repo.UpdateStatus(ctx, appId, latestTaskId, "PROMOTING", "") if err != nil { log.Debug("appId = ", appId) log.Debug("taskId = ", latestTaskId) @@ -599,8 +597,8 @@ func (u *AppServeAppUsecase) PromoteAppServeApp(appId string) (ret string, err e "Confirm result by checking the app status after a while.", app.Name), nil } -func (u *AppServeAppUsecase) AbortAppServeApp(appId string) (ret string, err error) { - app, err := u.repo.GetAppServeAppById(appId) +func (u *AppServeAppUsecase) AbortAppServeApp(ctx context.Context, appId string) (ret string, err error) { + app, err := u.repo.GetAppServeAppById(ctx, appId) if err != nil { return "", fmt.Errorf("error while getting ASA Info from DB. Err: %s", err) } @@ -617,7 +615,7 @@ func (u *AppServeAppUsecase) AbortAppServeApp(appId string) (ret string, err err log.Info("Updating app status to 'ABORTING'..") - err = u.repo.UpdateStatus(appId, latestTaskId, "ABORTING", "") + err = u.repo.UpdateStatus(ctx, appId, latestTaskId, "ABORTING", "") if err != nil { log.Debug("appId = ", appId) log.Debug("taskId = ", latestTaskId) @@ -651,10 +649,10 @@ func (u *AppServeAppUsecase) AbortAppServeApp(appId string) (ret string, err err "Confirm result by checking the app status after a while.", app.Name), nil } -func (u *AppServeAppUsecase) RollbackAppServeApp(appId string, taskId string) (ret string, err error) { +func (u *AppServeAppUsecase) RollbackAppServeApp(ctx context.Context, appId string, taskId string) (ret string, err error) { log.Info("Starting rollback process..") - app, err := u.repo.GetAppServeAppById(appId) + app, err := u.repo.GetAppServeAppById(ctx, appId) if err != nil { return "", err } @@ -683,7 +681,7 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(appId string, taskId string) (r task.RollbackVersion = targetVer // Creates new task record from the target task - newTaskId, err := u.repo.CreateTask(&task) + newTaskId, err := u.repo.CreateTask(ctx, &task) if err != nil { log.Info("taskId = ", newTaskId) return "", fmt.Errorf("failed to rollback app-serve application. Err: %s", err) @@ -691,7 +689,7 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(appId string, taskId string) (r log.Info("Updating app status to 'ROLLBACKING'..") - err = u.repo.UpdateStatus(appId, newTaskId, "ROLLBACKING", "") + err = u.repo.UpdateStatus(ctx, appId, newTaskId, "ROLLBACKING", "") if err != nil { log.Debug("appId = ", appId) log.Debug("taskId = ", newTaskId) diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index 0e3e5165..9a0f06cc 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -36,7 +36,7 @@ func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uui dto.UserId = &userId } } - auditId, err = u.repo.Create(dto) + auditId, err = u.repo.Create(ctx, dto) if err != nil { return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") } @@ -44,7 +44,7 @@ func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uui } func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res model.Audit, err error) { - res, err = u.repo.Get(auditId) + res, err = u.repo.Get(ctx, auditId) if err != nil { return model.Audit{}, err } @@ -52,7 +52,7 @@ func (u *AuditUsecase) Get(ctx context.Context, auditId uuid.UUID) (res model.Au } func (u *AuditUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (audits []model.Audit, err error) { - audits, err = u.repo.Fetch(pg) + audits, err = u.repo.Fetch(ctx, pg) if err != nil { return nil, err } @@ -60,7 +60,7 @@ func (u *AuditUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (au } func (u *AuditUsecase) Delete(ctx context.Context, dto model.Audit) (err error) { - err = u.repo.Delete(dto.ID) + err = u.repo.Delete(ctx, dto.ID) if err != nil { return httpErrors.NewNotFoundError(err, "", "") } diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 7213d1f2..a85c2c09 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -1,6 +1,7 @@ package usecase import ( + "context" "crypto/rand" "crypto/tls" "encoding/base64" @@ -19,7 +20,6 @@ import ( "golang.org/x/oauth2" "github.com/Nerzal/gocloak/v13" - "github.com/google/uuid" "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/keycloak" @@ -31,15 +31,14 @@ import ( ) type IAuthUsecase interface { - Login(accountId string, password string, organizationId string) (model.User, error) - Logout(accessToken string, organizationId string) error - PingToken(accessToken string, organizationId string) error - FindId(code string, email string, userName string, organizationId string) (string, error) - FindPassword(code string, accountId string, email string, userName string, organizationId string) error - VerifyIdentity(accountId string, email string, userName string, organizationId string) error - SingleSignIn(organizationId, accountId, password string) ([]*http.Cookie, error) - SingleSignOut(organizationId string) (string, []*http.Cookie, error) - VerifyToken(token string) (bool, error) + Login(ctx context.Context, accountId string, password string, organizationId string) (model.User, error) + Logout(ctx context.Context, accessToken string, organizationId string) error + FindId(ctx context.Context, code string, email string, userName string, organizationId string) (string, error) + FindPassword(ctx context.Context, code string, accountId string, email string, userName string, organizationId string) error + VerifyIdentity(ctx context.Context, accountId string, email string, userName string, organizationId string) error + SingleSignIn(ctx context.Context, organizationId, accountId, password string) ([]*http.Cookie, error) + SingleSignOut(ctx context.Context, organizationId string) (string, []*http.Cookie, error) + VerifyToken(ctx context.Context, token string) (bool, error) } const ( @@ -68,9 +67,9 @@ func NewAuthUsecase(r repository.Repository, kc keycloak.IKeycloak) IAuthUsecase } } -func (u *AuthUsecase) Login(accountId string, password string, organizationId string) (model.User, error) { +func (u *AuthUsecase) Login(ctx context.Context, accountId string, password string, organizationId string) (model.User, error) { // Authentication with DB - user, err := u.userRepository.Get(accountId, organizationId) + user, err := u.userRepository.Get(ctx, accountId, organizationId) if err != nil { return model.User{}, httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") } @@ -102,7 +101,7 @@ func (u *AuthUsecase) Login(accountId string, password string, organizationId st return user, nil } -func (u *AuthUsecase) Logout(accessToken string, organizationName string) error { +func (u *AuthUsecase) Logout(ctx context.Context, accessToken string, organizationName string) error { // [TODO] refresh token 을 추가하고, session timeout 을 줄이는 방향으로 고려할 것 err := u.kc.Logout(accessToken, organizationName) if err != nil { @@ -111,64 +110,8 @@ func (u *AuthUsecase) Logout(accessToken string, organizationName string) error return nil } -func (u *AuthUsecase) PingToken(accessToken string, organizationId string) error { - parsedToken, _, err := new(jwtWithouKey.Parser).ParseUnverified(accessToken, jwtWithouKey.MapClaims{}) - if err != nil { - return err - } - - if parsedToken.Method.Alg() != "RS256" { - return fmt.Errorf("invalid token") - } - - if parsedToken.Claims.Valid() != nil { - return fmt.Errorf("invalid token") - } - - isActive, err := u.kc.VerifyAccessToken(accessToken, organizationId) - if err != nil { - log.Errorf("failed to verify access token: %v", err) - return err - } - if !isActive { - return fmt.Errorf("token is not active") - } - - userId, err := uuid.Parse(parsedToken.Claims.(jwtWithouKey.MapClaims)["sub"].(string)) - if err != nil { - log.Errorf("failed to verify access token: %v", err) - - return err - } - requestSessionId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["sid"].(string) - if !ok { - return fmt.Errorf("session id is not found in token") - } - - sessionIds, err := u.kc.GetSessions(userId.String(), organizationId) - if err != nil { - log.Errorf("failed to get sessions: %v", err) - - return err - } - if len(*sessionIds) == 0 { - return fmt.Errorf("invalid session") - } - var matched bool = false - for _, id := range *sessionIds { - if id == requestSessionId { - matched = true - break - } - } - if !matched { - return fmt.Errorf("invalid session") - } - return nil -} - -func (u *AuthUsecase) FindId(code string, email string, userName string, organizationId string) (string, error) { - users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), +func (u *AuthUsecase) FindId(ctx context.Context, code string, email string, userName string, organizationId string) (string, error) { + users, err := u.userRepository.List(ctx, u.userRepository.OrganizationFilter(organizationId), u.userRepository.NameFilter(userName), u.userRepository.EmailFilter(email)) if err != nil && users == nil { return "", httpErrors.NewBadRequestError(err, "A_INVALID_ID", "") @@ -176,7 +119,7 @@ func (u *AuthUsecase) FindId(code string, email string, userName string, organiz if err != nil { return "", httpErrors.NewInternalServerError(err, "", "") } - emailCode, err := u.authRepository.GetEmailCode((*users)[0].ID) + emailCode, err := u.authRepository.GetEmailCode(ctx, (*users)[0].ID) if err != nil { return "", httpErrors.NewInternalServerError(err, "", "") } @@ -186,15 +129,15 @@ func (u *AuthUsecase) FindId(code string, email string, userName string, organiz if emailCode.Code != code { return "", httpErrors.NewBadRequestError(fmt.Errorf("invalid code"), "A_INVALID_CODE", "") } - if err := u.authRepository.DeleteEmailCode((*users)[0].ID); err != nil { + if err := u.authRepository.DeleteEmailCode(ctx, (*users)[0].ID); err != nil { return "", httpErrors.NewInternalServerError(err, "", "") } return (*users)[0].AccountId, nil } -func (u *AuthUsecase) FindPassword(code string, accountId string, email string, userName string, organizationId string) error { - users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), +func (u *AuthUsecase) FindPassword(ctx context.Context, code string, accountId string, email string, userName string, organizationId string) error { + users, err := u.userRepository.List(ctx, u.userRepository.OrganizationFilter(organizationId), u.userRepository.AccountIdFilter(accountId), u.userRepository.NameFilter(userName), u.userRepository.EmailFilter(email)) if err != nil && users == nil { @@ -204,7 +147,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, return httpErrors.NewInternalServerError(err, "", "") } user := (*users)[0] - emailCode, err := u.authRepository.GetEmailCode(user.ID) + emailCode, err := u.authRepository.GetEmailCode(ctx, user.ID) if err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -231,7 +174,7 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, return httpErrors.NewInternalServerError(err, "", "") } - if err = u.userRepository.UpdatePasswordAt(user.ID, organizationId, true); err != nil { + if err = u.userRepository.UpdatePasswordAt(ctx, user.ID, organizationId, true); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -247,22 +190,22 @@ func (u *AuthUsecase) FindPassword(code string, accountId string, email string, return httpErrors.NewInternalServerError(err, "", "") } - if err = u.authRepository.DeleteEmailCode(user.ID); err != nil { + if err = u.authRepository.DeleteEmailCode(ctx, user.ID); err != nil { return httpErrors.NewInternalServerError(err, "", "") } return nil } -func (u *AuthUsecase) VerifyIdentity(accountId string, email string, userName string, organizationId string) error { +func (u *AuthUsecase) VerifyIdentity(ctx context.Context, accountId string, email string, userName string, organizationId string) error { var users *[]model.User var err error if accountId == "" { - users, err = u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), + users, err = u.userRepository.List(ctx, u.userRepository.OrganizationFilter(organizationId), u.userRepository.NameFilter(userName), u.userRepository.EmailFilter(email)) } else { - users, err = u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), + users, err = u.userRepository.List(ctx, u.userRepository.OrganizationFilter(organizationId), u.userRepository.AccountIdFilter(accountId), u.userRepository.NameFilter(userName), u.userRepository.EmailFilter(email)) } @@ -277,13 +220,13 @@ func (u *AuthUsecase) VerifyIdentity(accountId string, email string, userName st if err != nil { return httpErrors.NewInternalServerError(err, "", "") } - _, err = u.authRepository.GetEmailCode((*users)[0].ID) + _, err = u.authRepository.GetEmailCode(ctx, (*users)[0].ID) if err != nil { - if err := u.authRepository.CreateEmailCode((*users)[0].ID, code); err != nil { + if err := u.authRepository.CreateEmailCode(ctx, (*users)[0].ID, code); err != nil { return httpErrors.NewInternalServerError(err, "", "") } } else { - if err := u.authRepository.UpdateEmailCode((*users)[0].ID, code); err != nil { + if err := u.authRepository.UpdateEmailCode(ctx, (*users)[0].ID, code); err != nil { return httpErrors.NewInternalServerError(err, "", "") } } @@ -304,7 +247,7 @@ func (u *AuthUsecase) VerifyIdentity(accountId string, email string, userName st return nil } -func (u *AuthUsecase) SingleSignIn(organizationId, accountId, password string) ([]*http.Cookie, error) { +func (u *AuthUsecase) SingleSignIn(ctx context.Context, organizationId, accountId, password string) ([]*http.Cookie, error) { cookies, err := makingCookie(organizationId, accountId, password) if err != nil { return nil, err @@ -316,22 +259,22 @@ func (u *AuthUsecase) SingleSignIn(organizationId, accountId, password string) ( return cookies, nil } -func (u *AuthUsecase) SingleSignOut(organizationId string) (string, []*http.Cookie, error) { +func (u *AuthUsecase) SingleSignOut(ctx context.Context, organizationId string) (string, []*http.Cookie, error) { var redirectUrl string - organization, err := u.organizationRepository.Get(organizationId) + organization, err := u.organizationRepository.Get(ctx, organizationId) if err != nil { return "", nil, err } - appGroupsInPrimaryCluster, err := u.appgroupRepository.Fetch(domain.ClusterId(organization.PrimaryClusterId), nil) + appGroupsInPrimaryCluster, err := u.appgroupRepository.Fetch(ctx, domain.ClusterId(organization.PrimaryClusterId), nil) if err != nil { return "", nil, err } for _, appGroup := range appGroupsInPrimaryCluster { if appGroup.AppGroupType == domain.AppGroupType_LMA { - applications, err := u.appgroupRepository.GetApplications(appGroup.ID, domain.ApplicationType_GRAFANA) + applications, err := u.appgroupRepository.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) if err != nil { return "", nil, err } @@ -366,7 +309,7 @@ func (u *AuthUsecase) SingleSignOut(organizationId string) (string, []*http.Cook return redirectUrl, cookies, nil } -func (u *AuthUsecase) VerifyToken(token string) (bool, error) { +func (u *AuthUsecase) VerifyToken(ctx context.Context, token string) (bool, error) { parsedToken, _, err := new(jwtWithouKey.Parser).ParseUnverified(token, jwtWithouKey.MapClaims{}) if err != nil { return false, err diff --git a/internal/usecase/auth_test.go b/internal/usecase/auth_test.go deleted file mode 100644 index 85a2c829..00000000 --- a/internal/usecase/auth_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package usecase_test - -import ( - "testing" -) - -func TestGet(t *testing.T) { - -} diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index b6719bbb..26e948e9 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -76,7 +76,7 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "", "사용 중인 AwsAccountId 입니다. 관리자에게 문의하세요.") } - cloudAccountId, err = u.repo.Create(dto) + cloudAccountId, err = u.repo.Create(ctx, dto) if err != nil { return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") } @@ -84,7 +84,7 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount // FOR TEST. ADD MAGIC KEYWORD if strings.Contains(dto.Name, domain.CLOUD_ACCOUNT_INCLUSTER) { - if err := u.repo.InitWorkflow(cloudAccountId, "", domain.CloudAccountStatus_CREATED); err != nil { + if err := u.repo.InitWorkflow(ctx, cloudAccountId, "", domain.CloudAccountStatus_CREATED); err != nil { return uuid.Nil, errors.Wrap(err, "Failed to initialize status") } return cloudAccountId, nil @@ -108,7 +108,7 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount } log.InfoWithContext(ctx, "submited workflow :", workflowId) - if err := u.repo.InitWorkflow(cloudAccountId, workflowId, domain.CloudAccountStatus_CREATING); err != nil { + if err := u.repo.InitWorkflow(ctx, cloudAccountId, workflowId, domain.CloudAccountStatus_CREATING); err != nil { return uuid.Nil, errors.Wrap(err, "Failed to initialize status") } @@ -124,7 +124,7 @@ func (u *CloudAccountUsecase) Update(ctx context.Context, dto model.CloudAccount dto.Resource = "TODO server result or additional information" dto.UpdatorId = &userId - err := u.repo.Update(dto) + err := u.repo.Update(ctx, dto) if err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -132,48 +132,48 @@ func (u *CloudAccountUsecase) Update(ctx context.Context, dto model.CloudAccount } func (u *CloudAccountUsecase) Get(ctx context.Context, cloudAccountId uuid.UUID) (res model.CloudAccount, err error) { - res, err = u.repo.Get(cloudAccountId) + res, err = u.repo.Get(ctx, cloudAccountId) if err != nil { return model.CloudAccount{}, err } - res.Clusters = u.getClusterCnt(cloudAccountId) + res.Clusters = u.getClusterCnt(ctx, cloudAccountId) return } func (u *CloudAccountUsecase) GetByName(ctx context.Context, organizationId string, name string) (res model.CloudAccount, err error) { - res, err = u.repo.GetByName(organizationId, name) + res, err = u.repo.GetByName(ctx, organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return model.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") } return model.CloudAccount{}, err } - res.Clusters = u.getClusterCnt(res.ID) + res.Clusters = u.getClusterCnt(ctx, res.ID) return } func (u *CloudAccountUsecase) GetByAwsAccountId(ctx context.Context, awsAccountId string) (res model.CloudAccount, err error) { - res, err = u.repo.GetByAwsAccountId(awsAccountId) + res, err = u.repo.GetByAwsAccountId(ctx, awsAccountId) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return model.CloudAccount{}, httpErrors.NewNotFoundError(err, "", "") } return model.CloudAccount{}, err } - res.Clusters = u.getClusterCnt(res.ID) + res.Clusters = u.getClusterCnt(ctx, res.ID) return } func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (cloudAccounts []model.CloudAccount, err error) { - cloudAccounts, err = u.repo.Fetch(organizationId, pg) + cloudAccounts, err = u.repo.Fetch(ctx, organizationId, pg) if err != nil { return nil, err } for i, cloudAccount := range cloudAccounts { - cloudAccounts[i].Clusters = u.getClusterCnt(cloudAccount.ID) + cloudAccounts[i].Clusters = u.getClusterCnt(ctx, cloudAccount.ID) } return } @@ -191,7 +191,7 @@ func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount } dto.UpdatorId = &userId - if u.getClusterCnt(dto.ID) > 0 { + if u.getClusterCnt(ctx, dto.ID) > 0 { return fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") } @@ -213,7 +213,7 @@ func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount } log.InfoWithContext(ctx, "submited workflow :", workflowId) - if err := u.repo.InitWorkflow(dto.ID, workflowId, domain.CloudAccountStatus_DELETING); err != nil { + if err := u.repo.InitWorkflow(ctx, dto.ID, workflowId, domain.CloudAccountStatus_DELETING); err != nil { return errors.Wrap(err, "Failed to initialize status") } @@ -221,7 +221,7 @@ func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount } func (u *CloudAccountUsecase) DeleteForce(ctx context.Context, cloudAccountId uuid.UUID) (err error) { - cloudAccount, err := u.repo.Get(cloudAccountId) + cloudAccount, err := u.repo.Get(ctx, cloudAccountId) if err != nil { return err } @@ -231,11 +231,11 @@ func (u *CloudAccountUsecase) DeleteForce(ctx context.Context, cloudAccountId uu return fmt.Errorf("The status is not CREATE_ERROR. %s", cloudAccount.Status) } - if u.getClusterCnt(cloudAccountId) > 0 { + if u.getClusterCnt(ctx, cloudAccountId) > 0 { return fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") } - err = u.repo.Delete(cloudAccountId) + err = u.repo.Delete(ctx, cloudAccountId) if err != nil { return err } @@ -244,7 +244,7 @@ func (u *CloudAccountUsecase) DeleteForce(ctx context.Context, cloudAccountId uu } func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccountId uuid.UUID) (available bool, out domain.ResourceQuota, err error) { - cloudAccount, err := u.repo.Get(cloudAccountId) + cloudAccount, err := u.repo.Get(ctx, cloudAccountId) if err != nil { return false, out, err } @@ -442,10 +442,10 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount return true, out, nil } -func (u *CloudAccountUsecase) getClusterCnt(cloudAccountId uuid.UUID) (cnt int) { +func (u *CloudAccountUsecase) getClusterCnt(ctx context.Context, cloudAccountId uuid.UUID) (cnt int) { cnt = 0 - clusters, err := u.clusterRepo.FetchByCloudAccountId(cloudAccountId, nil) + clusters, err := u.clusterRepo.FetchByCloudAccountId(ctx, cloudAccountId, nil) if err != nil { log.Error("Failed to get clusters by cloudAccountId. err : ", err) return cnt diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index e22233f3..b7f3df01 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -109,9 +109,9 @@ func (u *ClusterUsecase) Fetch(ctx context.Context, organizationId string, pg *p if organizationId == "" { // [TODO] 사용자가 속한 organization 리스트 - out, err = u.repo.Fetch(pg) + out, err = u.repo.Fetch(ctx, pg) } else { - out, err = u.repo.FetchByOrganizationId(organizationId, user.GetUserId(), pg) + out, err = u.repo.FetchByOrganizationId(ctx, organizationId, user.GetUserId(), pg) } if err != nil { @@ -125,7 +125,7 @@ func (u *ClusterUsecase) FetchByCloudAccountId(ctx context.Context, cloudAccount return nil, fmt.Errorf("Invalid cloudAccountId") } - out, err = u.repo.Fetch(pg) + out, err = u.repo.Fetch(ctx, pg) if err != nil { return nil, err @@ -139,13 +139,13 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - _, err = u.repo.GetByName(dto.OrganizationId, dto.Name) + _, err = u.repo.GetByName(ctx, dto.OrganizationId, dto.Name) if err == nil { return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "", "") } // check cloudAccount - cloudAccounts, err := u.cloudAccountRepo.Fetch(dto.OrganizationId, nil) + cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, dto.OrganizationId, nil) if err != nil { return "", httpErrors.NewBadRequestError(fmt.Errorf("Failed to get cloudAccounts"), "", "") } @@ -168,7 +168,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster } // check stackTemplate - stackTemplate, err := u.stackTemplateRepo.Get(dto.StackTemplateId) + stackTemplate, err := u.stackTemplateRepo.Get(ctx, dto.StackTemplateId) if err != nil { return "", httpErrors.NewBadRequestError(errors.Wrap(err, "Invalid stackTemplateId"), "", "") } @@ -178,7 +178,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster userId := user.GetUserId() dto.CreatorId = &userId - clusterId, err = u.repo.Create(dto) + clusterId, err = u.repo.Create(ctx, dto) if err != nil { return "", errors.Wrap(err, "Failed to create cluster") } @@ -206,7 +206,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster } log.InfoWithContext(ctx, "Successfully submited workflow: ", workflowId) - if err := u.repo.InitWorkflow(clusterId, workflowId, domain.ClusterStatus_INSTALLING); err != nil { + if err := u.repo.InitWorkflow(ctx, clusterId, workflowId, domain.ClusterStatus_INSTALLING); err != nil { return "", errors.Wrap(err, "Failed to initialize status") } @@ -219,18 +219,18 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - _, err = u.repo.GetByName(dto.OrganizationId, dto.Name) + _, err = u.repo.GetByName(ctx, dto.OrganizationId, dto.Name) if err == nil { return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "", "") } - _, err = u.organizationRepo.Get(dto.OrganizationId) + _, err = u.organizationRepo.Get(ctx, dto.OrganizationId) if err != nil { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "", "") } // check stackTemplate - stackTemplate, err := u.stackTemplateRepo.Get(dto.StackTemplateId) + stackTemplate, err := u.stackTemplateRepo.Get(ctx, dto.StackTemplateId) if err != nil { return "", httpErrors.NewBadRequestError(errors.Wrap(err, "Invalid stackTemplateId"), "", "") } @@ -241,7 +241,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster dto.ID = "tks-admin" dto.Name = "tks-admin" } - clusterId, err = u.repo.Create(dto) + clusterId, err = u.repo.Create(ctx, dto) if err != nil { return "", errors.Wrap(err, "Failed to create cluster") } @@ -268,7 +268,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster } log.InfoWithContext(ctx, "Successfully submited workflow: ", workflowId) - if err := u.repo.InitWorkflow(clusterId, workflowId, domain.ClusterStatus_INSTALLING); err != nil { + if err := u.repo.InitWorkflow(ctx, clusterId, workflowId, domain.ClusterStatus_INSTALLING); err != nil { return "", errors.Wrap(err, "Failed to initialize status") } @@ -281,12 +281,12 @@ func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clus return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - _, err = u.repo.GetByName(dto.OrganizationId, dto.Name) + _, err = u.repo.GetByName(ctx, dto.OrganizationId, dto.Name) if err == nil { return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "", "") } - stackTemplate, err := u.stackTemplateRepo.Get(dto.StackTemplateId) + stackTemplate, err := u.stackTemplateRepo.Get(ctx, dto.StackTemplateId) if err != nil { return "", httpErrors.NewBadRequestError(errors.Wrap(err, "Invalid stackTemplateId"), "", "") } @@ -297,7 +297,7 @@ func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clus userId := user.GetUserId() dto.CreatorId = &userId - clusterId, err = u.repo.Create(dto) + clusterId, err = u.repo.Create(ctx, dto) if err != nil { return "", errors.Wrap(err, "Failed to create cluster") } @@ -315,7 +315,7 @@ func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clus } log.InfoWithContext(ctx, "Successfully submited workflow: ", workflowId) - if err := u.repo.InitWorkflow(clusterId, workflowId, domain.ClusterStatus_BOOTSTRAPPING); err != nil { + if err := u.repo.InitWorkflow(ctx, clusterId, workflowId, domain.ClusterStatus_BOOTSTRAPPING); err != nil { return "", errors.Wrap(err, "Failed to initialize status") } @@ -328,7 +328,7 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - cluster, err := u.repo.Get(clusterId) + cluster, err := u.repo.Get(ctx, clusterId) if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid clusterId"), "C_INVALID_CLUSTER_ID", "") } @@ -336,7 +336,7 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId return httpErrors.NewBadRequestError(fmt.Errorf("Invalid cloudService"), "C_INVALID_CLOUD_SERVICE", "") } - stackTemplate, err := u.stackTemplateRepo.Get(cluster.StackTemplateId) + stackTemplate, err := u.stackTemplateRepo.Get(ctx, cluster.StackTemplateId) if err != nil { return httpErrors.NewBadRequestError(errors.Wrap(err, "Invalid stackTemplateId"), "", "") } @@ -367,7 +367,7 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId } log.InfoWithContext(ctx, "Successfully submited workflow: ", workflowId) - if err := u.repo.InitWorkflow(cluster.ID, workflowId, domain.ClusterStatus_INSTALLING); err != nil { + if err := u.repo.InitWorkflow(ctx, cluster.ID, workflowId, domain.ClusterStatus_INSTALLING); err != nil { return errors.Wrap(err, "Failed to initialize status") } @@ -375,7 +375,7 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId } func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) { - cluster, err := u.repo.Get(clusterId) + cluster, err := u.repo.Get(ctx, clusterId) if err != nil { return model.Cluster{}, err } @@ -384,7 +384,7 @@ func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (o } func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) (err error) { - cluster, err := u.repo.Get(clusterId) + cluster, err := u.repo.Get(ctx, clusterId) if err != nil { return httpErrors.NewNotFoundError(err, "", "") } @@ -393,7 +393,7 @@ func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) return fmt.Errorf("The cluster can not be deleted. cluster status : %s", cluster.Status) } - resAppGroups, err := u.appGroupRepo.Fetch(clusterId, nil) + resAppGroups, err := u.appGroupRepo.Fetch(ctx, clusterId, nil) if err != nil { return errors.Wrap(err, "Failed to get appgroup") } @@ -408,7 +408,7 @@ func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) // check cloudAccount tksCloudAccountId := "NULL" if cluster.CloudService != domain.CloudService_BYOH { - cloudAccount, err := u.cloudAccountRepo.Get(cluster.CloudAccount.ID) + cloudAccount, err := u.cloudAccountRepo.Get(ctx, cluster.CloudAccount.ID) if err != nil { return httpErrors.NewInternalServerError(fmt.Errorf("Failed to get cloudAccount"), "", "") } @@ -437,7 +437,7 @@ func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) log.DebugWithContext(ctx, "submited workflow name : ", workflowId) - if err := u.repo.InitWorkflow(clusterId, workflowId, domain.ClusterStatus_DELETING); err != nil { + if err := u.repo.InitWorkflow(ctx, clusterId, workflowId, domain.ClusterStatus_DELETING); err != nil { return errors.Wrap(err, "Failed to initialize status") } @@ -445,7 +445,7 @@ func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) } func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId domain.ClusterId) (out domain.ClusterSiteValuesResponse, err error) { - cluster, err := u.repo.Get(clusterId) + cluster, err := u.repo.Get(ctx, clusterId) if err != nil { return domain.ClusterSiteValuesResponse{}, errors.Wrap(err, "Failed to get cluster") } @@ -483,7 +483,7 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom } func (u *ClusterUsecase) CreateBootstrapKubeconfig(ctx context.Context, clusterId domain.ClusterId) (out domain.BootstrapKubeconfig, err error) { - _, err = u.repo.Get(clusterId) + _, err = u.repo.Get(ctx, clusterId) if err != nil { return out, httpErrors.NewNotFoundError(err, "", "") } @@ -528,7 +528,7 @@ func (u *ClusterUsecase) CreateBootstrapKubeconfig(ctx context.Context, clusterI } func (u *ClusterUsecase) GetBootstrapKubeconfig(ctx context.Context, clusterId domain.ClusterId) (out domain.BootstrapKubeconfig, err error) { - cluster, err := u.repo.Get(clusterId) + cluster, err := u.repo.Get(ctx, clusterId) if err != nil { return out, httpErrors.NewNotFoundError(err, "", "") } @@ -599,7 +599,7 @@ func (u *ClusterUsecase) GetBootstrapKubeconfig(ctx context.Context, clusterId d } func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterId) (out []domain.ClusterNode, err error) { - cluster, err := u.repo.Get(clusterId) + cluster, err := u.repo.Get(ctx, clusterId) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return out, httpErrors.NewNotFoundError(err, "S_FAILED_FETCH_CLUSTER", "") diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index a4f271a8..99ce9329 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -51,7 +51,7 @@ func NewDashboardUsecase(r repository.Repository, cache *gcache.Cache) IDashboar } func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (out []domain.DashboardChart, err error) { - _, err = u.organizationRepo.Get(organizationId) + _, err = u.organizationRepo.Get(ctx, organizationId) if err != nil { return nil, errors.Wrap(err, "invalid organization") } @@ -61,7 +61,7 @@ func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, continue } - chart, err := u.getChartFromPrometheus(organizationId, strType, duration, interval, year, month) + chart, err := u.getChartFromPrometheus(ctx, organizationId, strType, duration, interval, year, month) if err != nil { return nil, err } @@ -73,12 +73,12 @@ func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, } func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) { - clusters, err := u.clusterRepo.FetchByOrganizationId(organizationId, uuid.Nil, nil) + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, uuid.Nil, nil) if err != nil { return out, err } - thanosUrl, err := u.getThanosUrl(organizationId) + thanosUrl, err := u.getThanosUrl(ctx, organizationId) if err != nil { log.ErrorWithContext(ctx, err) return out, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") @@ -99,7 +99,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) } for _, cluster := range clusters { - appGroups, err := u.appGroupRepo.Fetch(cluster.ID, nil) + appGroups, err := u.appGroupRepo.Fetch(ctx, cluster.ID, nil) if err != nil { return nil, err } @@ -137,7 +137,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) } func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId string) (out domain.DashboardResource, err error) { - thanosUrl, err := u.getThanosUrl(organizationId) + thanosUrl, err := u.getThanosUrl(ctx, organizationId) if err != nil { log.ErrorWithContext(ctx, err) return out, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") @@ -149,7 +149,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri } // Stack - clusters, err := u.clusterRepo.FetchByOrganizationId(organizationId, uuid.Nil, nil) + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, uuid.Nil, nil) if err != nil { return out, err } @@ -222,8 +222,8 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri return } -func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartType string, duration string, interval string, year string, month string) (res domain.DashboardChart, err error) { - thanosUrl, err := u.getThanosUrl(organizationId) +func (u *DashboardUsecase) getChartFromPrometheus(ctx context.Context, organizationId string, chartType string, duration string, interval string, year string, month string) (res domain.DashboardChart, err error) { + thanosUrl, err := u.getThanosUrl(ctx, organizationId) if err != nil { log.Error(err) return res, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") @@ -286,12 +286,12 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy return res, fmt.Errorf("Invalid month") } - alerts, err := u.alertRepo.FetchPodRestart(organizationId, startDate, endDate) + alerts, err := u.alertRepo.FetchPodRestart(ctx, organizationId, startDate, endDate) if err != nil { return res, err } - organization, err := u.organizationRepo.Get(organizationId) + organization, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { return res, err } @@ -375,7 +375,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy yAxisData = append(yAxisData, u.getChartYValue(val.Values, xAxis, percentage)) } - clusterName, err := u.getClusterNameFromId(val.Metric.TacoCluster) + clusterName, err := u.getClusterNameFromId(ctx, val.Metric.TacoCluster) if err != nil { clusterName = val.Metric.TacoCluster } @@ -402,14 +402,14 @@ func (u *DashboardUsecase) getChartFromPrometheus(organizationId string, chartTy } -func (u *DashboardUsecase) getThanosUrl(organizationId string) (out string, err error) { +func (u *DashboardUsecase) getThanosUrl(ctx context.Context, organizationId string) (out string, err error) { const prefix = "CACHE_KEY_THANOS_URL" value, found := u.cache.Get(prefix + organizationId) if found { return value.(string), nil } - organization, err := u.organizationRepo.Get(organizationId) + organization, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { return out, errors.Wrap(err, "Failed to get organization") } @@ -530,14 +530,14 @@ func (u *DashboardUsecase) getStackCpu(result []thanos.MetricDataResult, cluster return } -func (u *DashboardUsecase) getClusterNameFromId(clusterId string) (clusterName string, err error) { +func (u *DashboardUsecase) getClusterNameFromId(ctx context.Context, clusterId string) (clusterName string, err error) { const prefix = "CACHE_KEY_CLUSTER_NAME_FROM_ID" value, found := u.cache.Get(prefix + clusterId) if found { return value.(string), nil } - cluster, err := u.clusterRepo.Get(domain.ClusterId(clusterId)) + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) if err != nil { return clusterName, errors.Wrap(err, "Failed to get cluster") } diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 7dafe447..67fa317a 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -22,12 +22,12 @@ import ( type IOrganizationUsecase interface { Create(context.Context, *model.Organization) (organizationId string, err error) - Fetch(pg *pagination.Pagination) (*[]model.Organization, error) - Get(organizationId string) (model.Organization, error) - Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) - UpdatePrimaryClusterId(organizationId string, clusterId string) (err error) - ChangeAdminId(organizationId string, adminId uuid.UUID) error - Delete(organizationId string, accessToken string) error + Fetch(ctx context.Context, pg *pagination.Pagination) (*[]model.Organization, error) + Get(ctx context.Context, organizationId string) (model.Organization, error) + Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) + UpdatePrimaryClusterId(ctx context.Context, organizationId string, clusterId string) (err error) + ChangeAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error + Delete(ctx context.Context, organizationId string, accessToken string) error } type OrganizationUsecase struct { @@ -63,7 +63,7 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization in.ID = organizationId // Create organization in DB - _, err = u.repo.Create(in) + _, err = u.repo.Create(ctx, in) if err != nil { return "", err } @@ -83,26 +83,26 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization } log.InfoWithContext(ctx, "submited workflow :", workflowId) - if err := u.repo.InitWorkflow(organizationId, workflowId, domain.OrganizationStatus_CREATING); err != nil { + if err := u.repo.InitWorkflow(ctx, organizationId, workflowId, domain.OrganizationStatus_CREATING); err != nil { return "", errors.Wrap(err, "Failed to init workflow") } return organizationId, nil } -func (u *OrganizationUsecase) Fetch(pg *pagination.Pagination) (out *[]model.Organization, err error) { - organizations, err := u.repo.Fetch(pg) +func (u *OrganizationUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (out *[]model.Organization, err error) { + organizations, err := u.repo.Fetch(ctx, pg) if err != nil { return nil, err } return organizations, nil } -func (u *OrganizationUsecase) Get(organizationId string) (out model.Organization, err error) { - out, err = u.repo.Get(organizationId) +func (u *OrganizationUsecase) Get(ctx context.Context, organizationId string) (out model.Organization, err error) { + out, err = u.repo.Get(ctx, organizationId) if err != nil { return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") } - clusters, err := u.clusterRepo.FetchByOrganizationId(organizationId, uuid.Nil, nil) + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, uuid.Nil, nil) if err != nil { log.Info(err) out.ClusterCount = 0 @@ -112,8 +112,8 @@ func (u *OrganizationUsecase) Get(organizationId string) (out model.Organization } -func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) (err error) { - _, err = u.Get(organizationId) +func (u *OrganizationUsecase) Delete(ctx context.Context, organizationId string, accessToken string) (err error) { + _, err = u.Get(ctx, organizationId) if err != nil { return err } @@ -124,18 +124,18 @@ func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) } // delete roles in DB - roles, err := u.roleRepo.ListTksRoles(organizationId, nil) + roles, err := u.roleRepo.ListTksRoles(ctx, organizationId, nil) if err != nil { return err } for _, role := range roles { - if err := u.roleRepo.Delete(role.ID); err != nil { + if err := u.roleRepo.Delete(ctx, role.ID); err != nil { return err } } // delete organization in DB - err = u.repo.Delete(organizationId) + err = u.repo.Delete(ctx, organizationId) if err != nil { return err } @@ -143,13 +143,13 @@ func (u *OrganizationUsecase) Delete(organizationId string, accessToken string) return nil } -func (u *OrganizationUsecase) Update(organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) { - _, err := u.Get(organizationId) +func (u *OrganizationUsecase) Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) { + _, err := u.Get(ctx, organizationId) if err != nil { return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") } - res, err := u.repo.Update(organizationId, in) + res, err := u.repo.Update(ctx, organizationId, in) if err != nil { return model.Organization{}, err } @@ -157,30 +157,30 @@ func (u *OrganizationUsecase) Update(organizationId string, in domain.UpdateOrga return res, nil } -func (u *OrganizationUsecase) UpdatePrimaryClusterId(organizationId string, clusterId string) (err error) { +func (u *OrganizationUsecase) UpdatePrimaryClusterId(ctx context.Context, organizationId string, clusterId string) (err error) { if clusterId != "" && !helper.ValidateClusterId(clusterId) { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid clusterId"), "", "") } - _, err = u.Get(organizationId) + _, err = u.Get(ctx, organizationId) if err != nil { return httpErrors.NewNotFoundError(err, "", "") } - err = u.repo.UpdatePrimaryClusterId(organizationId, clusterId) + err = u.repo.UpdatePrimaryClusterId(ctx, organizationId, clusterId) if err != nil { return err } return nil } -func (u *OrganizationUsecase) ChangeAdminId(organizationId string, adminId uuid.UUID) error { - _, err := u.Get(organizationId) +func (u *OrganizationUsecase) ChangeAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error { + _, err := u.Get(ctx, organizationId) if err != nil { return httpErrors.NewNotFoundError(err, "", "") } - err = u.repo.UpdateAdminId(organizationId, adminId) + err = u.repo.UpdateAdminId(ctx, organizationId, adminId) if err != nil { return err } diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index bcce7e95..32b6bf0d 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -1,22 +1,20 @@ package usecase import ( + "context" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" ) type IPermissionUsecase interface { - CreatePermissionSet(permissionSet *model.PermissionSet) error - GetPermissionSetByRoleId(roleId string) (*model.PermissionSet, error) - ListPermissions(roleId string) ([]*model.Permission, error) - //GetPermission(id uuid.UUID) (*model.Permission, error) - //DeletePermission(id uuid.UUID) error - //UpdatePermission(permission *model.Permission) error - SetRoleIdToPermissionSet(roleId string, permissionSet *model.PermissionSet) - GetAllowedPermissionSet() *model.PermissionSet - GetUserPermissionSet() *model.PermissionSet - UpdatePermission(permission *model.Permission) error + CreatePermissionSet(ctx context.Context, permissionSet *model.PermissionSet) error + GetPermissionSetByRoleId(ctx context.Context, roleId string) (*model.PermissionSet, error) + ListPermissions(ctx context.Context, roleId string) ([]*model.Permission, error) + SetRoleIdToPermissionSet(ctx context.Context, roleId string, permissionSet *model.PermissionSet) + GetAllowedPermissionSet(ctx context.Context) *model.PermissionSet + GetUserPermissionSet(ctx context.Context) *model.PermissionSet + UpdatePermission(ctx context.Context, permission *model.Permission) error } type PermissionUsecase struct { @@ -29,30 +27,30 @@ func NewPermissionUsecase(repo repository.Repository) *PermissionUsecase { } } -func (p PermissionUsecase) CreatePermissionSet(permissionSet *model.PermissionSet) error { +func (p PermissionUsecase) CreatePermissionSet(ctx context.Context, permissionSet *model.PermissionSet) error { var err error - if err = p.repo.Create(permissionSet.Dashboard); err != nil { + if err = p.repo.Create(ctx, permissionSet.Dashboard); err != nil { return err } - if err = p.repo.Create(permissionSet.Stack); err != nil { + if err = p.repo.Create(ctx, permissionSet.Stack); err != nil { return err } - if err = p.repo.Create(permissionSet.SecurityPolicy); err != nil { + if err = p.repo.Create(ctx, permissionSet.SecurityPolicy); err != nil { return err } - if err = p.repo.Create(permissionSet.ProjectManagement); err != nil { + if err = p.repo.Create(ctx, permissionSet.ProjectManagement); err != nil { return err } - if err = p.repo.Create(permissionSet.Notification); err != nil { + if err = p.repo.Create(ctx, permissionSet.Notification); err != nil { return err } - if err = p.repo.Create(permissionSet.Configuration); err != nil { + if err = p.repo.Create(ctx, permissionSet.Configuration); err != nil { return err } return nil } -func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*model.PermissionSet, error) { +func (p PermissionUsecase) GetPermissionSetByRoleId(ctx context.Context, roleId string) (*model.PermissionSet, error) { permissionSet := &model.PermissionSet{ Dashboard: nil, Stack: nil, @@ -62,7 +60,7 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*model.Permi Configuration: nil, } - permissionList, err := p.repo.List(roleId) + permissionList, err := p.repo.List(ctx, roleId) if err != nil { return nil, err } @@ -86,33 +84,33 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(roleId string) (*model.Permi return permissionSet, nil } -func (p PermissionUsecase) ListPermissions(roleId string) ([]*model.Permission, error) { - return p.repo.List(roleId) +func (p PermissionUsecase) ListPermissions(ctx context.Context, roleId string) ([]*model.Permission, error) { + return p.repo.List(ctx, roleId) } -func (p PermissionUsecase) GetPermission(id uuid.UUID) (*model.Permission, error) { - return p.repo.Get(id) +func (p PermissionUsecase) GetPermission(ctx context.Context, id uuid.UUID) (*model.Permission, error) { + return p.repo.Get(ctx, id) } -func (p PermissionUsecase) DeletePermission(id uuid.UUID) error { - return p.repo.Delete(id) +func (p PermissionUsecase) DeletePermission(ctx context.Context, id uuid.UUID) error { + return p.repo.Delete(ctx, id) } -func (p PermissionUsecase) UpdatePermission(permission *model.Permission) error { - return p.repo.Update(permission) +func (p PermissionUsecase) UpdatePermission(ctx context.Context, permission *model.Permission) error { + return p.repo.Update(ctx, permission) } -func (p PermissionUsecase) SetRoleIdToPermissionSet(roleId string, permissionSet *model.PermissionSet) { +func (p PermissionUsecase) SetRoleIdToPermissionSet(ctx context.Context, roleId string, permissionSet *model.PermissionSet) { permissionSet.SetRoleId(roleId) } -func (p PermissionUsecase) GetAllowedPermissionSet() *model.PermissionSet { +func (p PermissionUsecase) GetAllowedPermissionSet(ctx context.Context) *model.PermissionSet { permissionSet := model.NewDefaultPermissionSet() permissionSet.SetAllowedPermissionSet() return permissionSet } -func (p PermissionUsecase) GetUserPermissionSet() *model.PermissionSet { +func (p PermissionUsecase) GetUserPermissionSet(ctx context.Context) *model.PermissionSet { permissionSet := model.NewDefaultPermissionSet() permissionSet.SetUserPermissionSet() return permissionSet diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 756692a9..8422338a 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -87,7 +87,7 @@ func NewProjectUsecase(r repository.Repository, kc keycloak.IKeycloak, argoClien } func (u *ProjectUsecase) CreateProject(ctx context.Context, p *model.Project) (string, error) { - projectId, err := u.projectRepo.CreateProject(p) + projectId, err := u.projectRepo.CreateProject(ctx, p) if err != nil { log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to create project.") @@ -98,7 +98,7 @@ func (u *ProjectUsecase) CreateProject(ctx context.Context, p *model.Project) (s func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { if userId == "" { - pr, err = u.projectRepo.GetAllProjects(organizationId, pg) + pr, err = u.projectRepo.GetAllProjects(ctx, organizationId, pg) } else { userUuid, err := uuid.Parse(userId) if err != nil { @@ -106,9 +106,9 @@ func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, return nil, errors.Wrap(err, "Failed to parse uuid to string") } if onlyMyProject == false { - pr, err = u.projectRepo.GetProjects(organizationId, userUuid, pg) + pr, err = u.projectRepo.GetProjects(ctx, organizationId, userUuid, pg) } else { - pr, err = u.projectRepo.GetProjectsByUserId(organizationId, userUuid, pg) + pr, err = u.projectRepo.GetProjectsByUserId(ctx, organizationId, userUuid, pg) } } if err != nil { @@ -120,7 +120,7 @@ func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, } func (u *ProjectUsecase) GetProject(ctx context.Context, organizationId string, projectId string) (*model.Project, error) { - p, err := u.projectRepo.GetProjectById(organizationId, projectId) + p, err := u.projectRepo.GetProjectById(ctx, organizationId, projectId) if err != nil { log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") @@ -129,7 +129,7 @@ func (u *ProjectUsecase) GetProject(ctx context.Context, organizationId string, } func (u *ProjectUsecase) GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*model.Project, error) { - p, err := u.projectRepo.GetProjectByIdAndLeader(organizationId, projectId) + p, err := u.projectRepo.GetProjectByIdAndLeader(ctx, organizationId, projectId) if err != nil { log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") @@ -139,7 +139,7 @@ func (u *ProjectUsecase) GetProjectWithLeader(ctx context.Context, organizationI func (u *ProjectUsecase) IsProjectNameExist(ctx context.Context, organizationId string, projectName string) (bool, error) { exist := true - p, err := u.projectRepo.GetProjectByName(organizationId, projectName) + p, err := u.projectRepo.GetProjectByName(ctx, organizationId, projectName) if err != nil { log.ErrorWithContext(ctx, err) exist = false @@ -162,7 +162,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne p.ProjectNamespaces = nil p.ProjectMembers = nil - if err := u.projectRepo.UpdateProject(p); err != nil { + if err := u.projectRepo.UpdateProject(ctx, p); err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to update project.") } @@ -181,7 +181,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne return errors.Wrap(err, "No userid") } - pm, err := u.projectRepo.GetProjectMemberByUserId(p.ID, newLeaderId) + pm, err := u.projectRepo.GetProjectMemberByUserId(ctx, p.ID, newLeaderId) if err != nil { return err } @@ -218,7 +218,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne } func (u *ProjectUsecase) GetProjectRole(ctx context.Context, id string) (*model.ProjectRole, error) { - pr, err := u.projectRepo.GetProjectRoleById(id) + pr, err := u.projectRepo.GetProjectRoleById(ctx, id) if err != nil { log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to get project roles.") @@ -231,13 +231,13 @@ func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs [] var pr *model.ProjectRole if query == ProjectLeader { - pr, err = u.projectRepo.GetProjectRoleByName("project-leader") + pr, err = u.projectRepo.GetProjectRoleByName(ctx, "project-leader") } else if query == ProjectMember { - pr, err = u.projectRepo.GetProjectRoleByName("project-member") + pr, err = u.projectRepo.GetProjectRoleByName(ctx, "project-member") } else if query == ProjectViewer { - pr, err = u.projectRepo.GetProjectRoleByName("project-viewer") + pr, err = u.projectRepo.GetProjectRoleByName(ctx, "project-viewer") } else { - prs, err = u.projectRepo.GetAllProjectRoles() + prs, err = u.projectRepo.GetAllProjectRoles(ctx) } if err != nil { log.ErrorWithContext(ctx, err) @@ -252,7 +252,7 @@ func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs [] } func (u *ProjectUsecase) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { - projectMemberId, err := u.projectRepo.AddProjectMember(pm) + projectMemberId, err := u.projectRepo.AddProjectMember(ctx, pm) if err != nil { log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to add project member to project.") @@ -268,7 +268,7 @@ func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId strin return nil, errors.Wrap(err, "Failed to parse uuid to string") } - user, err := u.userRepository.GetByUuid(uid) + user, err := u.userRepository.GetByUuid(ctx, uid) if err != nil { log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve user by id") @@ -282,7 +282,7 @@ func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId strin } func (u *ProjectUsecase) GetProjectMember(ctx context.Context, projectMemberId string) (pm *model.ProjectMember, err error) { - pm, err = u.projectRepo.GetProjectMemberById(projectMemberId) + pm, err = u.projectRepo.GetProjectMemberById(ctx, projectMemberId) if err != nil { log.ErrorWithContext(ctx, err) return pm, errors.Wrap(err, "Failed to get project member.") @@ -293,13 +293,13 @@ func (u *ProjectUsecase) GetProjectMember(ctx context.Context, projectMemberId s func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { if query == ProjectLeader { - pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-leader", pg) + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(ctx, projectId, "project-leader", pg) } else if query == ProjectMember { - pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-member", pg) + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(ctx, projectId, "project-member", pg) } else if query == ProjectViewer { - pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(projectId, "project-viewer", pg) + pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(ctx, projectId, "project-viewer", pg) } else { - pms, err = u.projectRepo.GetProjectMembersByProjectId(projectId, pg) + pms, err = u.projectRepo.GetProjectMembersByProjectId(ctx, projectId, pg) } if err != nil { log.ErrorWithContext(ctx, err) @@ -310,7 +310,7 @@ func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string } func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMemberId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { - pmcr, err = u.projectRepo.GetProjectMemberCountByProjectId(projectMemberId) + pmcr, err = u.projectRepo.GetProjectMemberCountByProjectId(ctx, projectMemberId) if err != nil { log.ErrorWithContext(ctx, err) return pmcr, errors.Wrap(err, "Failed to get project member count.") @@ -320,7 +320,7 @@ func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMembe } func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, projectMemberId string) error { - if err := u.projectRepo.RemoveProjectMember(projectMemberId); err != nil { + if err := u.projectRepo.RemoveProjectMember(ctx, projectMemberId); err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to remove project member to project.") } @@ -329,7 +329,7 @@ func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, projectMemberI func (u *ProjectUsecase) UpdateProjectMemberRole(ctx context.Context, pm *model.ProjectMember) error { - if err := u.projectRepo.UpdateProjectMemberRole(pm); err != nil { + if err := u.projectRepo.UpdateProjectMemberRole(ctx, pm); err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to remove project member to project.") } @@ -337,7 +337,7 @@ func (u *ProjectUsecase) UpdateProjectMemberRole(ctx context.Context, pm *model. } func (u *ProjectUsecase) CreateProjectNamespace(ctx context.Context, organizationId string, pn *model.ProjectNamespace) error { - if err := u.projectRepo.CreateProjectNamespace(organizationId, pn); err != nil { + if err := u.projectRepo.CreateProjectNamespace(ctx, organizationId, pn); err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -346,7 +346,7 @@ func (u *ProjectUsecase) CreateProjectNamespace(ctx context.Context, organizatio func (u *ProjectUsecase) IsProjectNamespaceExist(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) { exist := true - pn, err := u.projectRepo.GetProjectNamespaceByName(organizationId, projectId, stackId, projectNamespace) + pn, err := u.projectRepo.GetProjectNamespaceByName(ctx, organizationId, projectId, stackId, projectNamespace) if err != nil { log.ErrorWithContext(ctx, err) exist = false @@ -359,7 +359,7 @@ func (u *ProjectUsecase) IsProjectNamespaceExist(ctx context.Context, organizati } func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]model.ProjectNamespace, error) { - pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, pg) + pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, pg) if err != nil { log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") @@ -369,7 +369,7 @@ func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationI } func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*model.ProjectNamespace, error) { - pn, err := u.projectRepo.GetProjectNamespaceByPrimaryKey(organizationId, projectId, projectNamespace, stackId) + pn, err := u.projectRepo.GetProjectNamespaceByPrimaryKey(ctx, organizationId, projectId, projectNamespace, stackId) if err != nil { log.ErrorWithContext(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve project namespace.") @@ -379,7 +379,7 @@ func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId } func (u *ProjectUsecase) UpdateProjectNamespace(ctx context.Context, pn *model.ProjectNamespace) error { - if err := u.projectRepo.UpdateProjectNamespace(pn); err != nil { + if err := u.projectRepo.UpdateProjectNamespace(ctx, pn); err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to update project namespace") } @@ -388,7 +388,7 @@ func (u *ProjectUsecase) UpdateProjectNamespace(ctx context.Context, pn *model.P func (u *ProjectUsecase) DeleteProjectNamespace(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) error { - if err := u.projectRepo.DeleteProjectNamespace(organizationId, projectId, projectNamespace, stackId); err != nil { + if err := u.projectRepo.DeleteProjectNamespace(ctx, organizationId, projectId, projectNamespace, stackId); err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to delete project namespace.") } @@ -397,9 +397,9 @@ func (u *ProjectUsecase) DeleteProjectNamespace(ctx context.Context, organizatio func (u *ProjectUsecase) GetAppCount(ctx context.Context, organizationId string, projectId string, namespace string) (appCount int, err error) { if namespace == "" { - appCount, err = u.projectRepo.GetAppCountByProjectId(organizationId, projectId) + appCount, err = u.projectRepo.GetAppCountByProjectId(ctx, organizationId, projectId) } else { - appCount, err = u.projectRepo.GetAppCountByNamespace(organizationId, projectId, namespace) + appCount, err = u.projectRepo.GetAppCountByNamespace(ctx, organizationId, projectId, namespace) } if err != nil { log.ErrorWithContext(ctx, err) @@ -410,7 +410,7 @@ func (u *ProjectUsecase) GetAppCount(ctx context.Context, organizationId string, } func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error { - pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) + pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -455,7 +455,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga return nil } func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error { - pns, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) + pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { log.ErrorWithContext(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -652,7 +652,7 @@ func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, } func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) { - projectNamespaces, err := u.projectRepo.GetProjectNamespaces(organizationId, projectId, nil) + projectNamespaces, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { log.ErrorWithContext(ctx, err) return "", errors.Wrap(err, "Failed to retrieve project namespaces.") @@ -709,7 +709,7 @@ func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationI } func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) { - _, err = u.clusterRepository.Get(domain.ClusterId(stackId)) + _, err = u.clusterRepository.Get(ctx, domain.ClusterId(stackId)) if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } @@ -781,7 +781,7 @@ func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId str } func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) { - _, err = u.clusterRepository.Get(domain.ClusterId(stackId)) + _, err = u.clusterRepository.Get(ctx, domain.ClusterId(stackId)) if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } diff --git a/internal/usecase/role.go b/internal/usecase/role.go index bc5d3734..63121e04 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -2,17 +2,17 @@ package usecase import ( "github.com/openinfradev/tks-api/internal/model" + "context" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" ) type IRoleUsecase interface { - CreateTksRole(role *model.Role) (string, error) - ListRoles(pg *pagination.Pagination) ([]*model.Role, error) - ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) - GetTksRole(id string) (*model.Role, error) - DeleteTksRole(id string) error - UpdateTksRole(role *model.Role) error + CreateTksRole(ctx context.Context, role *model.Role) (string, error) + ListTksRoles(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]*model.Role, error) + GetTksRole(ctx context.Context, id string) (*model.Role, error) + DeleteTksRole(ctx context.Context, id string) error + UpdateTksRole(ctx context.Context, role *model.Role) error } type RoleUsecase struct { @@ -25,12 +25,12 @@ func NewRoleUsecase(repo repository.Repository) *RoleUsecase { } } -func (r RoleUsecase) CreateTksRole(role *model.Role) (string, error) { - return r.repo.Create(role) +func (r RoleUsecase) CreateTksRole(ctx context.Context, role *model.Role) (string, error) { + return r.repo.Create(ctx, role) } -func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { - roles, err := r.repo.ListTksRoles(organizationId, pg) +func (r RoleUsecase) ListTksRoles(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]*model.Role, error) { + roles, err := r.repo.ListTksRoles(ctx, organizationId, pg) if err != nil { return nil, err } @@ -38,12 +38,8 @@ func (r RoleUsecase) ListTksRoles(organizationId string, pg *pagination.Paginati return roles, nil } -func (r RoleUsecase) ListRoles(pg *pagination.Pagination) ([]*model.Role, error) { - return r.repo.List(nil) -} - -func (r RoleUsecase) GetTksRole(id string) (*model.Role, error) { - role, err := r.repo.GetTksRole(id) +func (r RoleUsecase) GetTksRole(ctx context.Context, id string) (*model.Role, error) { + role, err := r.repo.GetTksRole(ctx, id) if err != nil { return nil, err } @@ -51,12 +47,12 @@ func (r RoleUsecase) GetTksRole(id string) (*model.Role, error) { return role, nil } -func (r RoleUsecase) DeleteTksRole(id string) error { - return r.repo.Delete(id) +func (r RoleUsecase) DeleteTksRole(ctx context.Context, id string) error { + return r.repo.Delete(ctx, id) } -func (r RoleUsecase) UpdateTksRole(role *model.Role) error { - err := r.repo.Update(role) +func (r RoleUsecase) UpdateTksRole(ctx context.Context, role *model.Role) error { + err := r.repo.Update(ctx, role) if err != nil { return err } diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 58edef83..cfc042f9 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -66,7 +66,7 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTempla services = services + "]" dto.Services = []byte(services) - stackTemplateId, err = u.repo.Create(dto) + stackTemplateId, err = u.repo.Create(ctx, dto) if err != nil { return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") } @@ -82,12 +82,12 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTempla } func (u *StackTemplateUsecase) Update(ctx context.Context, dto model.StackTemplate) error { - _, err := u.repo.Get(dto.ID) + _, err := u.repo.Get(ctx, dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") } - err = u.repo.Update(dto) + err = u.repo.Update(ctx, dto) if err != nil { return err } @@ -95,7 +95,7 @@ func (u *StackTemplateUsecase) Update(ctx context.Context, dto model.StackTempla } func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUID) (res model.StackTemplate, err error) { - res, err = u.repo.Get(stackTemplateId) + res, err = u.repo.Get(ctx, stackTemplateId) if err != nil { return res, err } @@ -103,7 +103,7 @@ func (u *StackTemplateUsecase) Get(ctx context.Context, stackTemplateId uuid.UUI } func (u *StackTemplateUsecase) GetByName(ctx context.Context, name string) (out model.StackTemplate, err error) { - out, err = u.repo.GetByName(name) + out, err = u.repo.GetByName(ctx, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return out, httpErrors.NewNotFoundError(err, "ST_FAILED_FETCH_STACK_TEMPLATE", "") @@ -115,7 +115,7 @@ func (u *StackTemplateUsecase) GetByName(ctx context.Context, name string) (out } func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (res []model.StackTemplate, err error) { - res, err = u.repo.Fetch(pg) + res, err = u.repo.Fetch(ctx, pg) if err != nil { return nil, err } @@ -123,7 +123,7 @@ func (u *StackTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Paginat } func (u *StackTemplateUsecase) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (res []model.StackTemplate, err error) { - res, err = u.repo.FetchWithOrganization(organizationId, pg) + res, err = u.repo.FetchWithOrganization(ctx, organizationId, pg) if err != nil { return nil, err } @@ -135,20 +135,20 @@ func (u *StackTemplateUsecase) Delete(ctx context.Context, dto model.StackTempla } func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error { - _, err := u.repo.Get(dto.ID) + _, err := u.repo.Get(ctx, dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") } organizations := make([]model.Organization, 0) for _, organizationId := range dto.OrganizationIds { - organization, err := u.organizationRepo.Get(organizationId) + organization, err := u.organizationRepo.Get(ctx, organizationId) if err == nil { organizations = append(organizations, organization) } } - err = u.repo.UpdateOrganizations(dto.ID, organizations) + err = u.repo.UpdateOrganizations(ctx, dto.ID, organizations) if err != nil { return httpErrors.NewBadRequestError(err, "ST_FAILED_UPDATE_ORGANIZATION", "") } diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 9daeea2a..906aa322 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -73,12 +73,12 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "S_CREATE_ALREADY_EXISTED_NAME", "") } - stackTemplate, err := u.stackTemplateRepo.Get(dto.StackTemplateId) + stackTemplate, err := u.stackTemplateRepo.Get(ctx, dto.StackTemplateId) if err != nil { return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Invalid stackTemplateId"), "S_INVALID_STACK_TEMPLATE", "") } - clusters, err := u.clusterRepo.FetchByOrganizationId(dto.OrganizationId, user.GetUserId(), nil) + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, dto.OrganizationId, user.GetUserId(), nil) if err != nil { return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Failed to get clusters"), "S_FAILED_GET_CLUSTERS", "") } @@ -97,7 +97,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid clusterEndpoint"), "S_INVALID_ADMINCLUSTER_URL", "") } } else { - if _, err = u.cloudAccountRepo.Get(dto.CloudAccountId); err != nil { + if _, err = u.cloudAccountRepo.Get(ctx, dto.CloudAccountId); err != nil { return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Invalid cloudAccountId"), "S_INVALID_CLOUD_ACCOUNT", "") } } @@ -157,7 +157,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom return "", fmt.Errorf("Invalid workflow status [%s]", workflow.Status.Phase) } - cluster, err := u.clusterRepo.GetByName(dto.OrganizationId, dto.Name) + cluster, err := u.clusterRepo.GetByName(ctx, dto.OrganizationId, dto.Name) if err != nil { continue } @@ -176,12 +176,12 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err return httpErrors.NewBadRequestError(fmt.Errorf("Invalid stackId"), "S_INVALID_STACK_ID", "") } - _, err = u.stackTemplateRepo.Get(cluster.StackTemplateId) + _, err = u.stackTemplateRepo.Get(ctx, cluster.StackTemplateId) if err != nil { return httpErrors.NewInternalServerError(errors.Wrap(err, "Invalid stackTemplateId"), "S_INVALID_STACK_TEMPLATE", "") } - clusters, err := u.clusterRepo.FetchByOrganizationId(cluster.OrganizationId, uuid.Nil, nil) + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, cluster.OrganizationId, uuid.Nil, nil) if err != nil { return httpErrors.NewInternalServerError(errors.Wrap(err, "Failed to get clusters"), "S_FAILED_GET_CLUSTERS", "") } @@ -223,7 +223,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err } func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out model.Stack, err error) { - cluster, err := u.clusterRepo.Get(domain.ClusterId(stackId)) + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(stackId)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return out, httpErrors.NewNotFoundError(err, "S_FAILED_FETCH_CLUSTER", "") @@ -231,12 +231,12 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod return out, err } - organization, err := u.organizationRepo.Get(cluster.OrganizationId) + organization, err := u.organizationRepo.Get(ctx, cluster.OrganizationId) if err != nil { return out, httpErrors.NewInternalServerError(errors.Wrap(err, fmt.Sprintf("Failed to get organization for clusterId %s", domain.ClusterId(stackId))), "S_FAILED_FETCH_ORGANIZATION", "") } - appGroups, err := u.appGroupRepo.Fetch(domain.ClusterId(stackId), nil) + appGroups, err := u.appGroupRepo.Fetch(ctx, domain.ClusterId(stackId), nil) if err != nil { return out, err } @@ -256,14 +256,14 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod } } - appGroupsInPrimaryCluster, err := u.appGroupRepo.Fetch(domain.ClusterId(organization.PrimaryClusterId), nil) + appGroupsInPrimaryCluster, err := u.appGroupRepo.Fetch(ctx, domain.ClusterId(organization.PrimaryClusterId), nil) if err != nil { return out, err } for _, appGroup := range appGroupsInPrimaryCluster { if appGroup.AppGroupType == domain.AppGroupType_LMA { - applications, err := u.appGroupRepo.GetApplications(appGroup.ID, domain.ApplicationType_GRAFANA) + applications, err := u.appGroupRepo.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) if err != nil { return out, err } @@ -277,7 +277,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod } func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Stack, err error) { - cluster, err := u.clusterRepo.GetByName(organizationId, name) + cluster, err := u.clusterRepo.GetByName(ctx, organizationId, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return out, httpErrors.NewNotFoundError(err, "S_FAILED_FETCH_CLUSTER", "") @@ -285,7 +285,7 @@ func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, nam return out, err } - appGroups, err := u.appGroupRepo.Fetch(cluster.ID, nil) + appGroups, err := u.appGroupRepo.Fetch(ctx, cluster.ID, nil) if err != nil { return out, err } @@ -300,12 +300,12 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return out, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") } - organization, err := u.organizationRepo.Get(organizationId) + organization, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { return out, httpErrors.NewInternalServerError(errors.Wrap(err, fmt.Sprintf("Failed to get organization for clusterId %s", organizationId)), "S_FAILED_FETCH_ORGANIZATION", "") } - clusters, err := u.clusterRepo.FetchByOrganizationId(organizationId, user.GetUserId(), pg) + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, user.GetUserId(), pg) if err != nil { return out, err } @@ -313,7 +313,7 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag stackResources, _ := u.dashbordUsecase.GetStacks(ctx, organizationId) for _, cluster := range clusters { - appGroups, err := u.appGroupRepo.Fetch(cluster.ID, nil) + appGroups, err := u.appGroupRepo.Fetch(ctx, cluster.ID, nil) if err != nil { return nil, err } @@ -325,7 +325,7 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag for _, appGroup := range appGroups { if appGroup.AppGroupType == domain.AppGroupType_LMA { - applications, err := u.appGroupRepo.GetApplications(appGroup.ID, domain.ApplicationType_GRAFANA) + applications, err := u.appGroupRepo.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) if err != nil { return nil, err } @@ -359,7 +359,7 @@ func (u *StackUsecase) Update(ctx context.Context, dto model.Stack) (err error) return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - _, err = u.clusterRepo.Get(domain.ClusterId(dto.ID)) + _, err = u.clusterRepo.Get(ctx, domain.ClusterId(dto.ID)) if err != nil { return httpErrors.NewNotFoundError(err, "S_FAILED_FETCH_CLUSTER", "") } @@ -371,7 +371,7 @@ func (u *StackUsecase) Update(ctx context.Context, dto model.Stack) (err error) UpdatorId: &updatorId, } - err = u.clusterRepo.Update(dtoCluster) + err = u.clusterRepo.Update(ctx, dtoCluster) if err != nil { return err } @@ -385,13 +385,13 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } - cluster, err := u.clusterRepo.Get(domain.ClusterId(dto.ID)) + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(dto.ID)) if err != nil { return httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to get cluster"), "S_FAILED_FETCH_CLUSTER", "") } // 지우려고 하는 stack 이 primary cluster 라면, organization 내에 cluster 가 자기 자신만 남아있을 경우이다. - organizations, err := u.organizationRepo.Fetch(nil) + organizations, err := u.organizationRepo.Fetch(ctx, nil) if err != nil { return errors.Wrap(err, "Failed to get organizations") } @@ -399,7 +399,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) for _, organization := range *organizations { if organization.PrimaryClusterId == cluster.ID.String() { - clusters, err := u.clusterRepo.FetchByOrganizationId(organization.ID, user.GetUserId(), nil) + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organization.ID, user.GetUserId(), nil) if err != nil { return errors.Wrap(err, "Failed to get organizations") } @@ -414,7 +414,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) break } } - appGroups, err := u.appGroupRepo.Fetch(domain.ClusterId(dto.ID), nil) + appGroups, err := u.appGroupRepo.Fetch(ctx, domain.ClusterId(dto.ID), nil) if err != nil { return errors.Wrap(err, "Failed to get appGroups") } @@ -426,7 +426,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) } } - appsCnt, err := u.appServeAppRepo.GetNumOfAppsOnStack(dto.OrganizationId, dto.ID.String()) + appsCnt, err := u.appServeAppRepo.GetNumOfAppsOnStack(ctx, dto.OrganizationId, dto.ID.String()) if err != nil { return errors.Wrap(err, "Failed to get numOfAppsOnStack") } @@ -453,10 +453,10 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) // Remove Cluster & AppGroup status description - if err := u.appGroupRepo.InitWorkflowDescription(cluster.ID); err != nil { + if err := u.appGroupRepo.InitWorkflowDescription(ctx, cluster.ID); err != nil { log.ErrorWithContext(ctx, err) } - if err := u.clusterRepo.InitWorkflowDescription(cluster.ID); err != nil { + if err := u.clusterRepo.InitWorkflowDescription(ctx, cluster.ID); err != nil { log.ErrorWithContext(ctx, err) } @@ -493,12 +493,12 @@ func (u *StackUsecase) GetKubeConfig(ctx context.Context, stackId domain.StackId // [TODO] need more pretty... func (u *StackUsecase) GetStepStatus(ctx context.Context, stackId domain.StackId) (out []domain.StackStepStatus, stackStatus string, err error) { - cluster, err := u.clusterRepo.Get(domain.ClusterId(stackId)) + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(stackId)) if err != nil { return out, "", err } - organization, err := u.organizationRepo.Get(cluster.OrganizationId) + organization, err := u.organizationRepo.Get(ctx, cluster.OrganizationId) if err != nil { return out, "", err } @@ -541,7 +541,7 @@ func (u *StackUsecase) GetStepStatus(ctx context.Context, stackId domain.StackId }) } - appGroups, err := u.appGroupRepo.Fetch(domain.ClusterId(stackId), nil) + appGroups, err := u.appGroupRepo.Fetch(ctx, domain.ClusterId(stackId), nil) for _, appGroup := range appGroups { for i, step := range out { if step.Stage == appGroup.AppGroupType.String() { @@ -596,7 +596,7 @@ func (u *StackUsecase) SetFavorite(ctx context.Context, stackId domain.StackId) return httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") } - err := u.clusterRepo.SetFavorite(domain.ClusterId(stackId), user.GetUserId()) + err := u.clusterRepo.SetFavorite(ctx, domain.ClusterId(stackId), user.GetUserId()) if err != nil { return err } @@ -610,7 +610,7 @@ func (u *StackUsecase) DeleteFavorite(ctx context.Context, stackId domain.StackI return httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") } - err := u.clusterRepo.DeleteFavorite(domain.ClusterId(stackId), user.GetUserId()) + err := u.clusterRepo.DeleteFavorite(ctx, domain.ClusterId(stackId), user.GetUserId()) if err != nil { return err } diff --git a/internal/usecase/user.go b/internal/usecase/user.go index b3ebef7d..92cb6fe4 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -19,18 +19,18 @@ import ( ) type IUserUsecase interface { - CreateAdmin(organizationId string, accountId string, accountName string, email string) (*model.User, error) - DeleteAdmin(organizationId string) error + CreateAdmin(ctx context.Context, organizationId string, accountId string, accountName string, email string) (*model.User, error) + DeleteAdmin(ctx context.Context, organizationId string) error DeleteAll(ctx context.Context, organizationId string) error Create(ctx context.Context, user *model.User) (*model.User, error) List(ctx context.Context, organizationId string) (*[]model.User, error) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.User, error) - Get(userId uuid.UUID) (*model.User, error) + Get(ctx context.Context, userId uuid.UUID) (*model.User, error) Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) - ResetPassword(userId uuid.UUID) error - ResetPasswordByAccountId(accountId string, organizationId string) error - GenerateRandomPassword() string - Delete(userId uuid.UUID, organizationId string) error + ResetPassword(ctx context.Context, userId uuid.UUID) error + ResetPasswordByAccountId(ctx context.Context, accountId string, organizationId string) error + GenerateRandomPassword(ctx context.Context, ) string + Delete(ctx context.Context, userId uuid.UUID, organizationId string) error GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error @@ -40,8 +40,8 @@ type IUserUsecase interface { RenewalPasswordExpiredTime(ctx context.Context, userId uuid.UUID) error RenewalPasswordExpiredTimeByAccountId(ctx context.Context, accountId string, organizationId string) error DeleteByAccountId(ctx context.Context, accountId string, organizationId string) error - ValidateAccount(userId uuid.UUID, password string, organizationId string) error - ValidateAccountByAccountId(accountId string, password string, organizationId string) error + ValidateAccount(ctx context.Context, userId uuid.UUID, password string, organizationId string) error + ValidateAccountByAccountId(ctx context.Context, accountId string, password string, organizationId string) error UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *model.User) (*model.User, error) } @@ -54,7 +54,7 @@ type UserUsecase struct { } func (u *UserUsecase) RenewalPasswordExpiredTime(ctx context.Context, userId uuid.UUID) error { - user, err := u.userRepository.GetByUuid(userId) + user, err := u.userRepository.GetByUuid(ctx, userId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status != http.StatusNotFound { return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") @@ -62,7 +62,7 @@ func (u *UserUsecase) RenewalPasswordExpiredTime(ctx context.Context, userId uui return httpErrors.NewInternalServerError(err, "", "") } - err = u.userRepository.UpdatePasswordAt(userId, user.Organization.ID, false) + err = u.userRepository.UpdatePasswordAt(ctx, userId, user.Organization.ID, false) if err != nil { log.ErrorfWithContext(ctx, "failed to update password expired time: %v", err) return httpErrors.NewInternalServerError(err, "", "") @@ -72,7 +72,7 @@ func (u *UserUsecase) RenewalPasswordExpiredTime(ctx context.Context, userId uui } func (u *UserUsecase) RenewalPasswordExpiredTimeByAccountId(ctx context.Context, accountId string, organizationId string) error { - user, err := u.userRepository.Get(accountId, organizationId) + user, err := u.userRepository.Get(ctx, accountId, organizationId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status != http.StatusNotFound { return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") @@ -82,8 +82,8 @@ func (u *UserUsecase) RenewalPasswordExpiredTimeByAccountId(ctx context.Context, return u.RenewalPasswordExpiredTime(ctx, user.ID) } -func (u *UserUsecase) ResetPassword(userId uuid.UUID) error { - user, err := u.userRepository.GetByUuid(userId) +func (u *UserUsecase) ResetPassword(ctx context.Context, userId uuid.UUID) error { + user, err := u.userRepository.GetByUuid(ctx, userId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") @@ -109,7 +109,7 @@ func (u *UserUsecase) ResetPassword(userId uuid.UUID) error { return httpErrors.NewInternalServerError(err, "", "") } - if err = u.userRepository.UpdatePasswordAt(userId, user.Organization.ID, true); err != nil { + if err = u.userRepository.UpdatePasswordAt(ctx, userId, user.Organization.ID, true); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -128,23 +128,23 @@ func (u *UserUsecase) ResetPassword(userId uuid.UUID) error { return nil } -func (u *UserUsecase) ResetPasswordByAccountId(accountId string, organizationId string) error { - user, err := u.userRepository.Get(accountId, organizationId) +func (u *UserUsecase) ResetPasswordByAccountId(ctx context.Context, accountId string, organizationId string) error { + user, err := u.userRepository.Get(ctx, accountId, organizationId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") } return httpErrors.NewInternalServerError(err, "", "") } - return u.ResetPassword(user.ID) + return u.ResetPassword(ctx, user.ID) } -func (u *UserUsecase) GenerateRandomPassword() string { +func (u *UserUsecase) GenerateRandomPassword(ctx context.Context) string { return helper.GenerateRandomString(passwordLength) } -func (u *UserUsecase) ValidateAccount(userId uuid.UUID, password string, organizationId string) error { - user, err := u.userRepository.GetByUuid(userId) +func (u *UserUsecase) ValidateAccount(ctx context.Context, userId uuid.UUID, password string, organizationId string) error { + user, err := u.userRepository.GetByUuid(ctx, userId) if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") } @@ -155,7 +155,7 @@ func (u *UserUsecase) ValidateAccount(userId uuid.UUID, password string, organiz return nil } -func (u *UserUsecase) ValidateAccountByAccountId(accountId string, password string, organizationId string) error { +func (u *UserUsecase) ValidateAccountByAccountId(ctx context.Context, accountId string, password string, organizationId string) error { _, err := u.kc.Login(organizationId, accountId, password) return err } @@ -164,7 +164,7 @@ func (u *UserUsecase) DeleteAll(ctx context.Context, organizationId string) erro // TODO: implement me as transaction // TODO: clean users in keycloak - err := u.userRepository.Flush(organizationId) + err := u.userRepository.Flush(ctx, organizationId) if err != nil { return err } @@ -172,7 +172,7 @@ func (u *UserUsecase) DeleteAll(ctx context.Context, organizationId string) erro return nil } -func (u *UserUsecase) DeleteAdmin(organizationId string) error { +func (u *UserUsecase) DeleteAdmin(ctx context.Context, organizationId string) error { user, err := u.kc.GetUser(organizationId, "admin") if err != nil { return errors.Wrap(err, "get user failed") @@ -188,7 +188,7 @@ func (u *UserUsecase) DeleteAdmin(organizationId string) error { return errors.Wrap(err, "parse user id failed") } - err = u.userRepository.DeleteWithUuid(userUuid) + err = u.userRepository.DeleteWithUuid(ctx, userUuid) if err != nil { return errors.Wrap(err, "delete user failed") } @@ -196,7 +196,7 @@ func (u *UserUsecase) DeleteAdmin(organizationId string) error { return nil } -func (u *UserUsecase) CreateAdmin(organizationId string, accountId string, accountName string, email string) (*model.User, error) { +func (u *UserUsecase) CreateAdmin(ctx context.Context, organizationId string, accountId string, accountName string, email string) (*model.User, error) { // Generate Admin user object randomPassword := helper.GenerateRandomString(passwordLength) user := model.User{ @@ -219,7 +219,7 @@ func (u *UserUsecase) CreateAdmin(organizationId string, accountId string, accou } // Send mail of temporary password - organizationInfo, err := u.organizationRepository.Get(organizationId) + organizationInfo, err := u.organizationRepository.Get(ctx, organizationId) if err != nil { return nil, err } @@ -236,7 +236,7 @@ func (u *UserUsecase) CreateAdmin(organizationId string, accountId string, accou } func (u *UserUsecase) SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error { - user, err := u.userRepository.Get(accountId, organizationId) + user, err := u.userRepository.Get(ctx, accountId, organizationId) if err != nil { return err } @@ -282,12 +282,12 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s } // update password UpdateAt in DB - user, err := u.userRepository.Get(accountId, organizationId) + user, err := u.userRepository.Get(ctx, accountId, organizationId) if err != nil { return errors.Wrap(err, "getting user from repository failed") } - err = u.userRepository.UpdatePasswordAt(user.ID, organizationId, false) + err = u.userRepository.UpdatePasswordAt(ctx, user.ID, organizationId, false) if err != nil { return errors.Wrap(err, "updating user in repository failed") } @@ -296,7 +296,7 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s } func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[]model.User, err error) { - users, err = u.userRepository.List(u.userRepository.OrganizationFilter(organizationId)) + users, err = u.userRepository.List(ctx, u.userRepository.OrganizationFilter(organizationId)) if err != nil { return nil, err } @@ -305,7 +305,7 @@ func (u *UserUsecase) List(ctx context.Context, organizationId string) (users *[ } func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (users *[]model.User, err error) { - users, err = u.userRepository.ListWithPagination(pg, organizationId) + users, err = u.userRepository.ListWithPagination(ctx, pg, organizationId) if err != nil { return nil, err } @@ -313,8 +313,8 @@ func (u *UserUsecase) ListWithPagination(ctx context.Context, organizationId str return } -func (u *UserUsecase) Get(userId uuid.UUID) (*model.User, error) { - user, err := u.userRepository.GetByUuid(userId) +func (u *UserUsecase) Get(ctx context.Context, userId uuid.UUID) (*model.User, error) { + user, err := u.userRepository.GetByUuid(ctx, userId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { return nil, httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") @@ -326,7 +326,7 @@ func (u *UserUsecase) Get(userId uuid.UUID) (*model.User, error) { } func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) { - users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), + users, err := u.userRepository.List(ctx, u.userRepository.OrganizationFilter(organizationId), u.userRepository.AccountIdFilter(accountId)) if err != nil { return nil, err @@ -336,7 +336,7 @@ func (u *UserUsecase) GetByAccountId(ctx context.Context, accountId string, orga } func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) { - users, err := u.userRepository.List(u.userRepository.OrganizationFilter(organizationId), + users, err := u.userRepository.List(ctx, u.userRepository.OrganizationFilter(organizationId), u.userRepository.EmailFilter(email)) if err != nil { return nil, err @@ -346,7 +346,7 @@ func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organization } func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) { - storedUser, err := u.Get(userId) + storedUser, err := u.Get(ctx, userId) if err != nil { return nil, err } @@ -372,7 +372,7 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u } } - users, err := u.userRepository.List(u.userRepository.OrganizationFilter(user.Organization.ID), + users, err := u.userRepository.List(ctx, u.userRepository.OrganizationFilter(user.Organization.ID), u.userRepository.AccountIdFilter(accountId)) if err != nil { if _, code := httpErrors.ErrorResponse(err); code == http.StatusNotFound { @@ -391,7 +391,7 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u return nil, err } - out, err = u.userRepository.UpdateWithUuid((*users)[0].ID, user.AccountId, user.Name, roleUuid, user.Email, user.Department, user.Description) + out, err = u.userRepository.UpdateWithUuid(ctx, (*users)[0].ID, user.AccountId, user.Name, roleUuid, user.Email, user.Department, user.Description) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") } @@ -399,13 +399,13 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u return &out, nil } -func (u *UserUsecase) Delete(userId uuid.UUID, organizationId string) error { - user, err := u.userRepository.GetByUuid(userId) +func (u *UserUsecase) Delete(ctx context.Context, userId uuid.UUID, organizationId string) error { + user, err := u.userRepository.GetByUuid(ctx, userId) if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("not found user"), "", "") } - err = u.userRepository.DeleteWithUuid(userId) + err = u.userRepository.DeleteWithUuid(ctx, userId) if err != nil { return err } @@ -419,12 +419,12 @@ func (u *UserUsecase) Delete(userId uuid.UUID, organizationId string) error { return nil } func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, organizationId string) error { - user, err := u.userRepository.Get(accountId, organizationId) + user, err := u.userRepository.Get(ctx, accountId, organizationId) if err != nil { return err } - err = u.userRepository.DeleteWithUuid(user.ID) + err = u.userRepository.DeleteWithUuid(ctx, user.ID) if err != nil { return err } @@ -460,7 +460,7 @@ func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User // Get user role var roleUuid string - roles, err := u.roleRepository.ListTksRoles(user.Organization.ID, nil) + roles, err := u.roleRepository.ListTksRoles(ctx, user.Organization.ID, nil) if err != nil { return nil, err } @@ -483,7 +483,7 @@ func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User } // Create user in DB - resUser, err := u.userRepository.CreateWithUuid(userUuid, user.AccountId, user.Name, user.Email, + resUser, err := u.userRepository.CreateWithUuid(ctx, userUuid, user.AccountId, user.Name, user.Email, user.Department, user.Description, user.Organization.ID, roleUuid) if err != nil { return nil, err @@ -512,7 +512,7 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st } } - *user, err = u.userRepository.UpdateWithUuid(user.ID, user.AccountId, user.Name, newUser.Role.ID, user.Email, + *user, err = u.userRepository.UpdateWithUuid(ctx, user.ID, user.AccountId, user.Name, newUser.Role.ID, user.Email, user.Department, user.Description) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") From 649e139690f0796f2884204ecf922ce5e61795cd Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 12 Mar 2024 17:48:30 +0900 Subject: [PATCH 123/502] Remove logWithContext, Make context as default parameter in logs(info,warn,...) --- pkg/log/log.go | 184 +++++++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 84 deletions(-) diff --git a/pkg/log/log.go b/pkg/log/log.go index a88eac18..1c532e15 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -103,133 +103,149 @@ func (f *CustomFormatter) Format(entry *logrus.Entry) ([]byte, error) { } // [TODO] more pretty -func Info(v ...interface{}) { +func Info(ctx context.Context, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Info(v...) - } else { - logger.Info(v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) + } + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) } + + logger.WithFields(fields).Info(v...) } -func Infof(format string, v ...interface{}) { +func Infof(ctx context.Context, format string, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Infof(format, v...) - } else { - logger.Infof(format, v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) } -} -func InfoWithContext(ctx context.Context, v ...interface{}) { - logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Info(v...) -} -func InfofWithContext(ctx context.Context, format string, v ...interface{}) { - logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Infof(format, v...) + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) + } + + logger.WithFields(fields).Infof(format, v...) } -func Warn(v ...interface{}) { +func Warn(ctx context.Context, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Warn(v...) - } else { - logger.Warn(v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) } + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) + } + + logger.WithFields(fields).Warn(v...) } -func Warnf(format string, v ...interface{}) { +func Warnf(ctx context.Context, format string, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Warnf(format, v...) - } else { - logger.Warnf(format, v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) } -} -func WarnWithContext(ctx context.Context, v ...interface{}) { - logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Warn(v...) -} -func WarnfWithContext(ctx context.Context, format string, v ...interface{}) { - logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Warnf(format, v...) + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) + } + + logger.WithFields(fields).Warnf(format, v...) } -func Debug(v ...interface{}) { +func Debug(ctx context.Context, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Debug(v...) - } else { - logger.Debug(v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) } + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) + } + + logger.WithFields(fields).Debug(v...) } -func Debugf(format string, v ...interface{}) { +func Debugf(ctx context.Context, format string, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Debugf(format, v...) - } else { - logger.Debugf(format, v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) } + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) + } + + logger.WithFields(fields).Debugf(format, v...) } -func DebugWithContext(ctx context.Context, v ...interface{}) { - logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Debug(v...) -} -func DebugfWithContext(ctx context.Context, format string, v ...interface{}) { - logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Debugf(format, v...) -} -func Error(v ...interface{}) { +func Error(ctx context.Context, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Error(v...) - } else { - logger.Error(v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) + } + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) } + + logger.WithFields(fields).Error(v...) } -func Errorf(format string, v ...interface{}) { +func Errorf(ctx context.Context, format string, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Errorf(format, v...) - } else { - logger.Errorf(format, v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) } -} -func ErrorWithContext(ctx context.Context, v ...interface{}) { - logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Error(v...) -} -func ErrorfWithContext(ctx context.Context, format string, v ...interface{}) { - logger.WithField(string(internal.ContextKeyRequestID), ctx.Value(internal.ContextKeyRequestID)).Errorf(format, v...) + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) + } + + logger.WithFields(fields).Errorf(format, v...) } -func Fatal(v ...interface{}) { +func Fatal(ctx context.Context, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Fatal(v...) - } else { - logger.Fatal(v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) + } + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) } + + logger.WithFields(fields).Fatal(v...) } -func Fatalf(format string, v ...interface{}) { +func Fatalf(ctx context.Context, format string, v ...interface{}) { + fields := logrus.Fields{} + if _, file, line, ok := runtime.Caller(1); ok { relativePath := getRelativeFilePath(file) - logger.WithFields(logrus.Fields{ - "file": relativePath + ":" + strconv.Itoa(line), - }).Fatalf(format, v...) - } else { - logger.Fatalf(format, v...) + fields["file"] = relativePath + ":" + strconv.Itoa(line) } + + if ctx != nil { + fields[string(internal.ContextKeyRequestID)] = ctx.Value(internal.ContextKeyRequestID) + } + + logger.WithFields(fields).Fatalf(format, v...) } func Disable() { From 575e15f02838a113020f6bcff0c4354002504f40 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 12 Mar 2024 17:49:49 +0900 Subject: [PATCH 124/502] fix conflict during rebase --- internal/delivery/http/alert.go | 18 +++++++++--------- internal/delivery/http/app-group.go | 12 ++++++------ internal/delivery/http/app-serve-app.go | 4 ++-- internal/delivery/http/audit.go | 6 +++--- internal/delivery/http/cloud-account.go | 14 +++++++------- internal/delivery/http/cluster.go | 12 ++++++------ internal/delivery/http/dashboard.go | 8 ++++---- internal/delivery/http/organization.go | 4 ++-- internal/delivery/http/project.go | 6 +++--- internal/delivery/http/role.go | 4 ++-- internal/delivery/http/stack-template.go | 16 ++++++++-------- internal/delivery/http/stack.go | 18 +++++++++--------- internal/delivery/http/user.go | 4 ++-- internal/middleware/logging/logging.go | 4 ++-- internal/usecase/alert.go | 2 +- internal/usecase/cloud-account.go | 8 ++++---- internal/usecase/cluster.go | 12 ++++++------ internal/usecase/dashboard.go | 2 +- internal/usecase/organization.go | 2 +- internal/usecase/stack-template.go | 2 +- internal/usecase/stack.go | 4 ++-- 21 files changed, 81 insertions(+), 81 deletions(-) diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index bf878aef..3cc24e7a 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -53,7 +53,7 @@ func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { log.ErrorWithContext(r.Context(),err) } bodyString := string(bodyBytes) - log.InfoWithContext(r.Context(),bodyString) + log.Info(r.Context(),bodyString) */ // 외부로부터(alert manager) 오는 데이터이므로, dto 변환없이 by-pass 처리한다. @@ -127,13 +127,13 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { out.Alerts = make([]domain.AlertResponse, len(alerts)) for i, alert := range alerts { if err := serializer.Map(alert, &out.Alerts[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } outAlertActions := make([]domain.AlertActionResponse, len(alert.AlertActions)) for j, alertAction := range alert.AlertActions { if err := serializer.Map(alertAction, &outAlertActions[j]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } } out.Alerts[i].AlertActions = outAlertActions @@ -143,7 +143,7 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -183,12 +183,12 @@ func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { var out domain.GetAlertResponse if err := serializer.Map(alert, &out.Alert); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } outAlertActions := make([]domain.AlertActionResponse, len(alert.AlertActions)) for j, alertAction := range alert.AlertActions { if err := serializer.Map(alertAction, &outAlertActions[j]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } @@ -236,7 +236,7 @@ func (h *AlertHandler) AlertTest(w http.ResponseWriter, r *http.Request) { return } - log.InfoWithContext(r.Context(), "TEST ", body) + log.Info(r.Context(), "TEST ", body) } // CreateAlertAction godoc @@ -271,11 +271,11 @@ func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) return } - log.InfoWithContext(r.Context(), "alert : ", helper.ModelToJson(input)) + log.Info(r.Context(), "alert : ", helper.ModelToJson(input)) var dto model.AlertAction if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.AlertId = alertId diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 27543035..180da7be 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -46,7 +46,7 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) var dto model.AppGroup if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } appGroupId, err := h.usecase.Create(r.Context(), dto) @@ -97,13 +97,13 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { out.AppGroups = make([]domain.AppGroupResponse, len(appGroups)) for i, appGroup := range appGroups { if err := serializer.Map(appGroup, &out.AppGroups[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -140,7 +140,7 @@ func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { var out domain.GetAppGroupResponse if err := serializer.Map(appGroup, &out.AppGroup); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -226,7 +226,7 @@ func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request out.Applications = make([]domain.ApplicationResponse, len(applications)) for i, application := range applications { if err := serializer.Map(application, &out.Applications[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } @@ -267,7 +267,7 @@ func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Reque var dto model.Application if err := serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.AppGroupId = appGroupId diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index de7cbe7f..d19bcb51 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -274,7 +274,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -484,7 +484,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 2a7b2b99..c04b46ea 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -69,12 +69,12 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { out.Audits = make([]domain.AuditResponse, len(audits)) for i, audit := range audits { if err := serializer.Map(audit, &out.Audits[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -114,7 +114,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { var out domain.GetAuditResponse if err := serializer.Map(audit, &out.Audit); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 5c29a04d..b4a78d3f 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -56,7 +56,7 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.OrganizationId = organizationId @@ -108,13 +108,13 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re out.CloudAccounts = make([]domain.CloudAccountResponse, len(cloudAccounts)) for i, cloudAccount := range cloudAccounts { if err := serializer.Map(cloudAccount, &out.CloudAccounts[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -154,7 +154,7 @@ func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Req var out domain.GetCloudAccountResponse if err := serializer.Map(cloudAccount, &out.CloudAccount); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -201,7 +201,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.ID = cloudAccountId dto.OrganizationId = organizationId @@ -251,7 +251,7 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. var dto model.CloudAccount if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.ID = parsedId @@ -417,7 +417,7 @@ func (h *CloudAccountHandler) GetResourceQuota(w http.ResponseWriter, r *http.Re var out domain.GetCloudAccountResourceQuotaResponse if err := serializer.Map(resourceQuota, &out.ResourceQuota); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } out.Available = available diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index d0811b04..70cd3d7f 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -55,7 +55,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { out.Clusters = make([]domain.ClusterResponse, len(clusters)) for i, cluster := range clusters { if err := serializer.Map(cluster, &out.Clusters[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } @@ -68,7 +68,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -101,7 +101,7 @@ func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { var out domain.GetClusterResponse if err := serializer.Map(cluster, &out.Cluster); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -159,7 +159,7 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { var dto model.Cluster if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.ClusterType = domain.ClusterType_USER @@ -213,7 +213,7 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { var dto model.Cluster if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.SetDefaultConf() @@ -872,7 +872,7 @@ func (h *ClusterHandler) SetIstioLabel(w http.ResponseWriter, r *http.Request) { return } - log.InfoWithContext(r.Context(),input) + log.Info(r.Context(),input) if input.Value != "enabled" && input.Value != "disabled" { ErrorJSON(w, r, "invalid value", http.StatusBadRequest) diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 5a5bdbd1..55c75cd5 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -75,7 +75,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { out.Charts = make([]domain.DashboardChartResponse, len(charts)) for i, chart := range charts { if err := serializer.Map(chart, &out.Charts[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } @@ -154,7 +154,7 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { var out domain.DashboardChartResponse if err := serializer.Map(charts[0], &out); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -194,7 +194,7 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { out.Stacks = make([]domain.DashboardStackResponse, len(stacks)) for i, stack := range stacks { if err := serializer.Map(stack, &out.Stacks[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } @@ -232,7 +232,7 @@ func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) } var out domain.GetDashboardResourcesResponse if err := serializer.Map(resources, &out.Resources); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 77f77841..7433c12c 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -170,11 +170,11 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re log.ErrorWithContext(r.Context(), err) } - log.InfoWithContext(r.Context(), organization) + log.Info(r.Context(), organization) } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 74e0d1f1..5913602b 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -190,7 +190,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { var out domain.GetProjectsResponse out.Projects = pr if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } if pr == nil { @@ -232,7 +232,7 @@ func (p ProjectHandler) Admin_GetProjects(w http.ResponseWriter, r *http.Request var out domain.GetProjectsResponse out.Projects = pr if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } if pr == nil { @@ -765,7 +765,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request out = domain.GetProjectMembersResponse{ProjectMembers: pmrs} if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 3ada3dc3..c760b9d2 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -144,7 +144,7 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { } if err := serializer.Map(*pg, &out.Pagination); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } // response @@ -321,7 +321,7 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) } if err := serializer.Map(*pg, &out.Pagination); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } // response diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 724f9907..5eab00fe 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -49,7 +49,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt var dto model.StackTemplate if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } id, err := h.usecase.Create(r.Context(), dto) @@ -92,13 +92,13 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. out.StackTemplates = make([]domain.StackTemplateResponse, len(stackTemplates)) for i, stackTemplate := range stackTemplates { if err := serializer.Map(stackTemplate, &out.StackTemplates[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } out.StackTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) for j, organization := range stackTemplate.Organizations { if err := serializer.Map(organization, &out.StackTemplates[i].Organizations[j]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } @@ -110,7 +110,7 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -149,13 +149,13 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R var out domain.GetStackTemplateResponse if err := serializer.Map(stackTemplate, &out.StackTemplate); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } out.StackTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) for i, organization := range stackTemplate.Organizations { if err := serializer.Map(organization, &out.StackTemplate.Organizations[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } @@ -195,7 +195,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt var dto model.StackTemplate if err := serializer.Map(r, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.ID = stackTemplateId @@ -290,7 +290,7 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW var dto model.StackTemplate if err := serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.ID = stackTemplateId diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 9a40cf22..be985e76 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -54,7 +54,7 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { var dto model.Stack if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) @@ -123,21 +123,21 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { out.Stacks = make([]domain.StackResponse, len(stacks)) for i, stack := range stacks { if err := serializer.Map(stack, &out.Stacks[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } if err := serializer.Map(stack.CreatedAt, &out.Stacks[i].CreatedAt); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } err = json.Unmarshal(stack.StackTemplate.Services, &out.Stacks[i].StackTemplate.Services) if err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -171,12 +171,12 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { var out domain.GetStackResponse if err := serializer.Map(stack, &out.Stack); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } err = json.Unmarshal(stack.StackTemplate.Services, &out.Stack.StackTemplate.Services) if err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -213,7 +213,7 @@ func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { out.StepStatus = make([]domain.StackStepStatus, len(steps)) for i, step := range steps { if err := serializer.Map(step, &out.StepStatus[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } } out.StackStatus = status @@ -262,7 +262,7 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { var dto model.Stack if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } dto.ID = stackId dto.OrganizationId = organizationId diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index f7ca4fce..d4c78d14 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -217,7 +217,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -807,7 +807,7 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/middleware/logging/logging.go b/internal/middleware/logging/logging.go index 3bda0874..da5fcc35 100644 --- a/internal/middleware/logging/logging.go +++ b/internal/middleware/logging/logging.go @@ -17,11 +17,11 @@ func LoggingMiddleware(next http.Handler) http.Handler { ctx := r.Context() r = r.WithContext(context.WithValue(ctx, internal.ContextKeyRequestID, uuid.New().String())) - log.InfoWithContext(r.Context(), fmt.Sprintf("***** START [%s %s] ***** ", r.Method, r.RequestURI)) + log.Infof(r.Context(), fmt.Sprintf("***** START [%s %s] ***** ", r.Method, r.RequestURI)) body, err := io.ReadAll(r.Body) if err == nil { - log.InfoWithContext(r.Context(), fmt.Sprintf("REQUEST BODY : %s", bytes.NewBuffer(body).String())) + log.Infof(r.Context(), fmt.Sprintf("REQUEST BODY : %s", bytes.NewBuffer(body).String())) } r.Body = io.NopCloser(bytes.NewBuffer(body)) lrw := NewLoggingResponseWriter(w) diff --git a/internal/usecase/alert.go b/internal/usecase/alert.go index 01e6929b..f79d7572 100644 --- a/internal/usecase/alert.go +++ b/internal/usecase/alert.go @@ -201,7 +201,7 @@ func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto model.AlertAct if err != nil { return uuid.Nil, err } - log.InfoWithContext(ctx, "newly created alertActionId:", alertActionId) + log.Info(ctx, "newly created alertActionId:", alertActionId) return } diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index 26e948e9..484b224a 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -80,7 +80,7 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount if err != nil { return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") } - log.InfoWithContext(ctx, "newly created CloudAccount ID:", cloudAccountId) + log.Info(ctx, "newly created CloudAccount ID:", cloudAccountId) // FOR TEST. ADD MAGIC KEYWORD if strings.Contains(dto.Name, domain.CLOUD_ACCOUNT_INCLUSTER) { @@ -106,7 +106,7 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) return uuid.Nil, fmt.Errorf("Failed to call argo workflow : %s", err) } - log.InfoWithContext(ctx, "submited workflow :", workflowId) + log.Info(ctx, "submited workflow :", workflowId) if err := u.repo.InitWorkflow(ctx, cloudAccountId, workflowId, domain.CloudAccountStatus_CREATING); err != nil { return uuid.Nil, errors.Wrap(err, "Failed to initialize status") @@ -211,7 +211,7 @@ func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) return fmt.Errorf("Failed to call argo workflow : %s", err) } - log.InfoWithContext(ctx, "submited workflow :", workflowId) + log.Info(ctx, "submited workflow :", workflowId) if err := u.repo.InitWorkflow(ctx, dto.ID, workflowId, domain.CloudAccountStatus_DELETING); err != nil { return errors.Wrap(err, "Failed to initialize status") @@ -268,7 +268,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount stsSvc := sts.NewFromConfig(cfg) if !strings.Contains(cloudAccount.Name, domain.CLOUD_ACCOUNT_INCLUSTER) { - log.InfoWithContext(ctx, "Use assume role. awsAccountId : ", cloudAccount.AwsAccountId) + log.Info(ctx, "Use assume role. awsAccountId : ", cloudAccount.AwsAccountId) creds := stscreds.NewAssumeRoleProvider(stsSvc, "arn:aws:iam::"+cloudAccount.AwsAccountId+":role/controllers.cluster-api-provider-aws.sigs.k8s.io") cfg.Credentials = aws.NewCredentialsCache(creds) } diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index b7f3df01..e0941c2b 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -204,7 +204,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) return "", err } - log.InfoWithContext(ctx, "Successfully submited workflow: ", workflowId) + log.Info(ctx, "Successfully submited workflow: ", workflowId) if err := u.repo.InitWorkflow(ctx, clusterId, workflowId, domain.ClusterStatus_INSTALLING); err != nil { return "", errors.Wrap(err, "Failed to initialize status") @@ -266,7 +266,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) return "", err } - log.InfoWithContext(ctx, "Successfully submited workflow: ", workflowId) + log.Info(ctx, "Successfully submited workflow: ", workflowId) if err := u.repo.InitWorkflow(ctx, clusterId, workflowId, domain.ClusterStatus_INSTALLING); err != nil { return "", errors.Wrap(err, "Failed to initialize status") @@ -313,7 +313,7 @@ func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clus log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) return "", err } - log.InfoWithContext(ctx, "Successfully submited workflow: ", workflowId) + log.Info(ctx, "Successfully submited workflow: ", workflowId) if err := u.repo.InitWorkflow(ctx, clusterId, workflowId, domain.ClusterStatus_BOOTSTRAPPING); err != nil { return "", errors.Wrap(err, "Failed to initialize status") @@ -365,7 +365,7 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) return err } - log.InfoWithContext(ctx, "Successfully submited workflow: ", workflowId) + log.Info(ctx, "Successfully submited workflow: ", workflowId) if err := u.repo.InitWorkflow(ctx, cluster.ID, workflowId, domain.ClusterStatus_INSTALLING); err != nil { return errors.Wrap(err, "Failed to initialize status") @@ -572,7 +572,7 @@ func (u *ClusterUsecase) GetBootstrapKubeconfig(ctx context.Context, clusterId d } token := kubeconfigData.Users[0].User.Token[:6] - log.InfoWithContext(ctx, "token : ", token) + log.Info(ctx, "token : ", token) secrets, err := client.CoreV1().Secrets("kube-system").Get(context.TODO(), "bootstrap-token-"+token, metav1.GetOptions{}) if err != nil { @@ -651,7 +651,7 @@ func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterI tksUserNodeRegistered, tksUserNodeRegistering, tksUserHosts := 0, 0, make([]domain.ClusterHost, 0) for _, host := range hosts.Items { label := host.Labels["role"] - log.InfoWithContext(ctx, "label : ", label) + log.Info(ctx, "label : ", label) if len(label) < 12 { continue } diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 99ce9329..dbbbe3af 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -106,7 +106,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) stack := reflectClusterToStack(cluster, appGroups) dashboardStack := domain.DashboardStack{} if err := serializer.Map(stack, &dashboardStack); err != nil { - log.InfoWithContext(ctx, err) + log.Info(ctx, err) } memory, disk := u.getStackMemoryDisk(stackMemoryDisk.Data.Result, cluster.ID.String()) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 67fa317a..d4096f73 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -81,7 +81,7 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) return "", errors.Wrap(err, "Failed to call argo workflow") } - log.InfoWithContext(ctx, "submited workflow :", workflowId) + log.Info(ctx, "submited workflow :", workflowId) if err := u.repo.InitWorkflow(ctx, organizationId, workflowId, domain.OrganizationStatus_CREATING); err != nil { return "", errors.Wrap(err, "Failed to init workflow") diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index cfc042f9..33dae263 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -70,7 +70,7 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTempla if err != nil { return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") } - log.InfoWithContext(ctx, "newly created StackTemplate ID:", stackTemplateId) + log.Info(ctx, "newly created StackTemplate ID:", stackTemplateId) dto.ID = stackTemplateId err = u.UpdateOrganizations(ctx, dto) diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 906aa322..ef37b438 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -105,7 +105,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom // Make stack nodes var stackConf domain.StackConfResponse if err = serializer.Map(dto, &stackConf); err != nil { - log.InfoWithContext(ctx, err) + log.Info(ctx, err) } if stackTemplate.CloudService == "AWS" && stackTemplate.KubeType == "AWS" { if stackConf.TksCpNode == 0 { @@ -198,7 +198,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err // Make stack nodes var stackConf domain.StackConfResponse if err = serializer.Map(cluster, &stackConf); err != nil { - log.InfoWithContext(ctx, err) + log.Info(ctx, err) } workflow := "tks-stack-install" From 08681489e798fa64363c0e519f20d70ba8629bef Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 12 Mar 2024 17:50:52 +0900 Subject: [PATCH 125/502] fix conflict during rebase --- internal/delivery/http/alert.go | 2 +- internal/delivery/http/app-group.go | 6 +- internal/delivery/http/app-serve-app.go | 8 +- internal/delivery/http/auth.go | 2 +- internal/delivery/http/cluster.go | 54 ++++----- internal/delivery/http/handler.go | 4 +- internal/delivery/http/organization.go | 10 +- internal/delivery/http/project.go | 38 +++---- internal/delivery/http/stack-template.go | 8 +- internal/delivery/http/user.go | 22 ++-- internal/usecase/alert.go | 6 +- internal/usecase/app-group.go | 4 +- internal/usecase/cloud-account.go | 10 +- internal/usecase/cluster.go | 26 ++--- internal/usecase/dashboard.go | 4 +- internal/usecase/organization.go | 2 +- internal/usecase/project.go | 134 +++++++++++------------ internal/usecase/stack.go | 10 +- 18 files changed, 175 insertions(+), 175 deletions(-) diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index 3cc24e7a..4829e8d3 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -50,7 +50,7 @@ func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { // webhook 으로 부터 받은 body parse bodyBytes, err := io.ReadAll(r.Body) if err != nil { - log.ErrorWithContext(r.Context(),err) + log.Error(r.Context(),err) } bodyString := string(bodyBytes) log.Info(r.Context(),bodyString) diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 180da7be..dd7142a3 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -173,7 +173,7 @@ func (h *AppGroupHandler) DeleteAppGroup(w http.ResponseWriter, r *http.Request) err := h.usecase.Delete(r.Context(), appGroupId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to delete appGroup err : ", err) + log.Error(r.Context(), "Failed to delete appGroup err : ", err) ErrorJSON(w, r, err) return } @@ -217,7 +217,7 @@ func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request applications, err := h.usecase.GetApplications(r.Context(), appGroupId, applicationType) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get applications err : ", err) + log.Error(r.Context(), "Failed to get applications err : ", err) ErrorJSON(w, r, err) return } @@ -273,7 +273,7 @@ func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Reque err = h.usecase.UpdateApplication(r.Context(), dto) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to update application err : ", err) + log.Error(r.Context(), "Failed to update application err : ", err) ErrorJSON(w, r, err) return } diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index d19bcb51..1d66ebf7 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -252,14 +252,14 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ showAll, err := strconv.ParseBool(showAllParam) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to convert showAll params. Err: ", err) + log.Error(r.Context(), "Failed to convert showAll params. Err: ", err) ErrorJSON(w, r, err) return } pg := pagination.NewPagination(&urlParams) apps, err := h.usecase.GetAppServeApps(r.Context(), organizationId, showAll, pg) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get Failed to get app-serve-apps ", err) + log.Error(r.Context(), "Failed to get Failed to get app-serve-apps ", err) ErrorJSON(w, r, err) return } @@ -469,7 +469,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r tasks, err := h.usecase.GetAppServeAppTasks(r.Context(), appId, pg) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get app-serve-app-tasks ", err) + log.Error(r.Context(), "Failed to get app-serve-app-tasks ", err) ErrorJSON(w, r, err) return } @@ -984,7 +984,7 @@ func (h *AppServeAppHandler) DeleteAppServeApp(w http.ResponseWriter, r *http.Re res, err := h.usecase.DeleteAppServeApp(r.Context(), appId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to delete appId err : ", err) + log.Error(r.Context(), "Failed to delete appId err : ", err) ErrorJSON(w, r, err) return } diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 36359785..801c9ec2 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -98,7 +98,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { var out domain.LoginResponse if err = serializer.Map(user, &out.User); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 70cd3d7f..7dea7c9e 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -395,12 +395,12 @@ func (h *ClusterHandler) GetKubernetesInfo(w http.ResponseWriter, r *http.Reques vars := mux.Vars(r) clusterId, ok := vars["clusterId"] if !ok { - log.ErrorWithContext(r.Context(),"Failed to get clusterId") + log.Error(r.Context(),"Failed to get clusterId") } clientset_user, err := h.GetClientFromClusterId(clusterId) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get clientset for clusterId ", clusterId) + log.Error(r.Context(),"Failed to get clientset for clusterId ", clusterId) InternalServerError(w) return } @@ -414,21 +414,21 @@ func (h *ClusterHandler) GetKubernetesInfo(w http.ResponseWriter, r *http.Reques if err == nil { out.KubeInfo.Pods = len(pods.Items) } else { - log.ErrorWithContext(r.Context(),"Failed to get pods. err : ", err) + log.Error(r.Context(),"Failed to get pods. err : ", err) } nodes, err := clientset_user.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) if err == nil { out.KubeInfo.Nodes = len(nodes.Items) } else { - log.ErrorWithContext(r.Context(),"Failed to get nodes. err : ", err) + log.Error(r.Context(),"Failed to get nodes. err : ", err) } services, err := clientset_user.CoreV1().Services("").List(context.TODO(), metav1.ListOptions{}) if err == nil { out.KubeInfo.Services = len(services.Items) } else { - log.ErrorWithContext(r.Context(),"Failed to get services. err : ", err) + log.Error(r.Context(),"Failed to get services. err : ", err) } @@ -436,7 +436,7 @@ func (h *ClusterHandler) GetKubernetesInfo(w http.ResponseWriter, r *http.Reques if err == nil { out.KubeInfo.Namespaces = len(namespaces.Items) } else { - log.ErrorWithContext(r.Context(),"Failed to get namespaces. err : ", err) + log.Error(r.Context(),"Failed to get namespaces. err : ", err) } @@ -444,7 +444,7 @@ func (h *ClusterHandler) GetKubernetesInfo(w http.ResponseWriter, r *http.Reques if err == nil { out.KubeInfo.Version = version } else { - log.ErrorWithContext(r.Context(),"Failed to get kubernetes version. err : ", err) + log.Error(r.Context(),"Failed to get kubernetes version. err : ", err) } ResponseJSON(w, r, http.StatusOK, out) @@ -465,14 +465,14 @@ func (h *ClusterHandler) GetClusterApplications(w http.ResponseWriter, r *http.R vars := mux.Vars(r) clusterId, ok := vars["clusterId"] if !ok { - log.ErrorWithContext(r.Context(),"Failed to get clusterId") + log.Error(r.Context(),"Failed to get clusterId") ErrorJSON(w, r, "invalid clusterId", http.StatusBadRequest) } var applications = []*pb.AppGroup{} res, err := appInfoClient.GetAppGroupsByClusterID(context.TODO(), &pb.IDRequest{ID: clusterId}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get appgroups err : ", err) + log.Error(r.Context(),"Failed to get appgroups err : ", err) InternalServerError(w) return } @@ -497,7 +497,7 @@ func (h *ClusterHandler) GetClusterApplicationsKubeInfo(w http.ResponseWriter, r vars := mux.Vars(r) clusterId, ok := vars["clusterId"] if !ok { - log.ErrorWithContext(r.Context(),"Failed to get clusterId") + log.Error(r.Context(),"Failed to get clusterId") ErrorJSON(w, r, "invalid clusterId", http.StatusBadRequest) } @@ -508,7 +508,7 @@ func (h *ClusterHandler) GetClusterApplicationsKubeInfo(w http.ResponseWriter, r res, err := appInfoClient.GetAppGroupsByClusterID(context.TODO(), &pb.IDRequest{Id: clusterId}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get appgroups err : ", err) + log.Error(r.Context(),"Failed to get appgroups err : ", err) InternalServerError(w) return } @@ -525,19 +525,19 @@ func (h *ClusterHandler) GetClusterApplicationsKubeInfo(w http.ResponseWriter, r clientset, err := h.GetClientFromClusterId(appGroup.GetClusterId()) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get clientset for clusterId", appGroup.GetClusterId()) + log.Error(r.Context(),"Failed to get clientset for clusterId", appGroup.GetClusterId()) continue } pods, err := clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get pods. ", err) + log.Error(r.Context(),"Failed to get pods. ", err) continue } services, err := clientset.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get service. ", err) + log.Error(r.Context(),"Failed to get service. ", err) continue } @@ -614,7 +614,7 @@ func (h *ClusterHandler) GetClusterKubeConfig(w http.ResponseWriter, r *http.Req vars := mux.Vars(r) clusterId, ok := vars["clusterId"] if !ok { - log.ErrorWithContext(r.Context(),"Failed to get clusterId") + log.Error(r.Context(),"Failed to get clusterId") ErrorJSON(w, r, "invalid clusterId", http.StatusBadRequest) return } @@ -653,48 +653,48 @@ func (h *ClusterHandler) GetClusterKubeResources(w http.ResponseWriter, r *http. vars := mux.Vars(r) clusterId, ok := vars["clusterId"] if !ok { - log.ErrorWithContext(r.Context(),"Failed to get clusterId") + log.Error(r.Context(),"Failed to get clusterId") ErrorJSON(w, r, "Invalid clusterId", http.StatusBadRequest) } clientset, err := h.GetClientFromClusterId(clusterId) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get clientset for clusterId", clusterId) + log.Error(r.Context(),"Failed to get clientset for clusterId", clusterId) InternalServerError(w) return } pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get pods", err) + log.Error(r.Context(),"Failed to get pods", err) InternalServerError(w) return } services, err := clientset.CoreV1().Services("").List(context.TODO(), metav1.ListOptions{}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get services", err) + log.Error(r.Context(),"Failed to get services", err) InternalServerError(w) return } namespaces, err := clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get namespaces", err) + log.Error(r.Context(),"Failed to get namespaces", err) InternalServerError(w) return } events, err := clientset.CoreV1().Events("").List(context.TODO(), metav1.ListOptions{}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get events", err) + log.Error(r.Context(),"Failed to get events", err) InternalServerError(w) return } nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get events", err) + log.Error(r.Context(),"Failed to get events", err) InternalServerError(w) return } @@ -846,13 +846,13 @@ func (h *ClusterHandler) SetIstioLabel(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) clusterId, ok := vars["clusterId"] if !ok { - log.ErrorWithContext(r.Context(),"Failed to get clusterId") + log.Error(r.Context(),"Failed to get clusterId") ErrorJSON(w, r, "invalid clusterId", http.StatusBadRequest) return } namespace, ok := vars["namespace"] if !ok { - log.ErrorWithContext(r.Context(),"Failed to get namespace") + log.Error(r.Context(),"Failed to get namespace") ErrorJSON(w, r, "invalid namespace", http.StatusBadRequest) return } @@ -862,12 +862,12 @@ func (h *ClusterHandler) SetIstioLabel(w http.ResponseWriter, r *http.Request) { } body, err := io.ReadAll(r.Body) if err != nil { - log.ErrorWithContext(r.Context(),err) + log.Error(r.Context(),err) return } err = json.Unmarshal(body, &input) if err != nil { - log.ErrorWithContext(r.Context(),err) + log.Error(r.Context(),err) ErrorJSON(w, r, "invalid json", http.StatusBadRequest) return } @@ -883,7 +883,7 @@ func (h *ClusterHandler) SetIstioLabel(w http.ResponseWriter, r *http.Request) { clientset, err := h.GetClientFromClusterId(clusterId) if err != nil { - log.ErrorWithContext(r.Context(),"Failed to get clientset for clusterId", clusterId) + log.Error(r.Context(),"Failed to get clientset for clusterId", clusterId) InternalServerError(w) return } diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index d2b6e180..1fc7de9f 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -41,7 +41,7 @@ func ResponseJSON(w http.ResponseWriter, r *http.Request, httpStatus int, data i w.WriteHeader(httpStatus) if err := json.NewEncoder(w).Encode(out); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } } @@ -110,7 +110,7 @@ func (h *APIHandler) AddHistory(r *http.Request, projectId string, historyType s err := h.Repository.AddHistory(userId, projectId, historyType, description) if err != nil { - log.ErrorWithContext(r.Context(),err) + log.Error(r.Context(),err) return err } diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 7433c12c..69face7e 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -56,7 +56,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. ctx := r.Context() var organization model.Organization if err = serializer.Map(input, &organization); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } organizationId, err := h.usecase.Create(ctx, &organization) @@ -130,7 +130,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. var out domain.CreateOrganizationResponse if err = serializer.Map(organization, &out); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -167,7 +167,7 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re for i, organization := range *organizations { if err = serializer.Map(organization, &out.Organizations[i]); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } log.Info(r.Context(), organization) @@ -212,7 +212,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req } var out domain.GetOrganizationResponse if err = serializer.Map(organization, &out.Organization); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } out.Organization.StackTemplates = make([]domain.SimpleStackTemplateResponse, len(organization.StackTemplates)) @@ -326,7 +326,7 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. var out domain.UpdateOrganizationResponse if err = serializer.Map(organization, &out); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 5913602b..d9215d42 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -182,7 +182,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { myUserId := requestUserInfo.GetUserId().String() pr, err := p.usecase.GetProjects(r.Context(), organizationId, myUserId, onlyMyProject, pg) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to retrieve projects ", err) + log.Error(r.Context(), "Failed to retrieve projects ", err) ErrorJSON(w, r, err) return } @@ -224,7 +224,7 @@ func (p ProjectHandler) Admin_GetProjects(w http.ResponseWriter, r *http.Request pg := pagination.NewPagination(&urlParams) pr, err := p.usecase.GetProjects(r.Context(), organizationId, "", false, pg) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to retrieve projects ", err) + log.Error(r.Context(), "Failed to retrieve projects ", err) ErrorJSON(w, r, err) return } @@ -271,14 +271,14 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { project, err := p.usecase.GetProjectWithLeader(r.Context(), organizationId, projectId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to retrieve project", err) + log.Error(r.Context(), "Failed to retrieve project", err) ErrorJSON(w, r, err) return } //appCount, err := p.usecase.GetAppCount(organizationId, projectId) //if err != nil { - // log.ErrorWithContext(r.Context(), "Failed to retrieve app count", err) + // log.Error(r.Context(), "Failed to retrieve app count", err) // ErrorJSON(w, r, err) // return //} @@ -455,7 +455,7 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { pr, err := p.usecase.GetProjectRole(r.Context(), projectRoleId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project roles ", err) + log.Error(r.Context(), "Failed to get project roles ", err) ErrorJSON(w, r, err) return } @@ -492,7 +492,7 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) } else if strings.EqualFold(queryParam, "viewer") { query = usecase.ProjectViewer } else { - log.ErrorWithContext(r.Context(), "Invalid query params. Err: ") + log.Error(r.Context(), "Invalid query params. Err: ") ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid query params"), "C_INVALID_QUERY_PARAM", "")) return @@ -500,7 +500,7 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) prs, err := p.usecase.GetProjectRoles(r.Context(), query) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project roles ", err) + log.Error(r.Context(), "Failed to get project roles ", err) ErrorJSON(w, r, err) return } @@ -653,7 +653,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) pm, err := p.usecase.GetProjectMember(r.Context(), projectMemberId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project member ", err) + log.Error(r.Context(), "Failed to get project member ", err) ErrorJSON(w, r, err) return } @@ -725,7 +725,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request } else if strings.EqualFold(queryParam, "viewer") { query = usecase.ProjectViewer } else { - log.ErrorWithContext(r.Context(), "Invalid query params. Err: ") + log.Error(r.Context(), "Invalid query params. Err: ") ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid query params"), "C_INVALID_QUERY_PARAM", "")) return @@ -734,7 +734,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request pg := pagination.NewPagination(&urlParams) pms, err := p.usecase.GetProjectMembers(r.Context(), projectId, query, pg) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project members ", err) + log.Error(r.Context(), "Failed to get project members ", err) ErrorJSON(w, r, err) return } @@ -802,7 +802,7 @@ func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Req pmcr, err := p.usecase.GetProjectMemberCount(r.Context(), projectId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project member count", err) + log.Error(r.Context(), "Failed to get project member count", err) ErrorJSON(w, r, err) return } @@ -1285,7 +1285,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ pg := pagination.NewPagination(&urlParams) pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, pg) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project namespaces.", err) + log.Error(r.Context(), "Failed to get project namespaces.", err) ErrorJSON(w, r, err) return } @@ -1305,7 +1305,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ } appCount, err := p.usecase.GetAppCount(r.Context(), organizationId, projectId, pn.Namespace) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to retrieve app count", err) + log.Error(r.Context(), "Failed to retrieve app count", err) ErrorJSON(w, r, err) return } @@ -1363,14 +1363,14 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque pn, err := p.usecase.GetProjectNamespace(r.Context(), organizationId, projectId, projectNamespace, stackId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project namespace.", err) + log.Error(r.Context(), "Failed to get project namespace.", err) ErrorJSON(w, r, err) return } appCount, err := p.usecase.GetAppCount(r.Context(), organizationId, projectId, projectNamespace) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to retrieve app count", err) + log.Error(r.Context(), "Failed to retrieve app count", err) ErrorJSON(w, r, err) return } @@ -1447,7 +1447,7 @@ func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Re now := time.Now() pn, err := p.usecase.GetProjectNamespace(r.Context(), organizationId, projectId, projectNamespace, stackId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project namespace.", err) + log.Error(r.Context(), "Failed to get project namespace.", err) ErrorJSON(w, r, err) return } @@ -1572,7 +1572,7 @@ func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Requ kubeconfig, err := p.usecase.GetProjectKubeconfig(r.Context(), organizationId, projectId) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project kubeconfig.", err) + log.Error(r.Context(), "Failed to get project kubeconfig.", err) ErrorJSON(w, r, err) return } @@ -1625,7 +1625,7 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r k8sResources, err := p.usecase.GetK8sResources(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) + log.Error(r.Context(), "Failed to get project resources.", err) ErrorJSON(w, r, err) return } @@ -1678,7 +1678,7 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, resourcesUsage, err := p.usecase.GetResourcesUsage(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) if err != nil { - log.ErrorWithContext(r.Context(), "Failed to get project resources.", err) + log.Error(r.Context(), "Failed to get project resources.", err) ErrorJSON(w, r, err) return } diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 5eab00fe..a03b41fd 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -105,7 +105,7 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. err := json.Unmarshal(stackTemplate.Services, &out.StackTemplates[i].Services) if err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } } @@ -162,7 +162,7 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R err = json.Unmarshal(stackTemplate.Services, &out.StackTemplate.Services) if err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -245,12 +245,12 @@ func (h *StackTemplateHandler) GetStackTemplateServices(w http.ResponseWriter, r out.Services = make([]domain.StackTemplateServiceResponse, 2) err := json.Unmarshal([]byte(internal.SERVICE_LMA), &out.Services[0]) if err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } err = json.Unmarshal([]byte(internal.SERVICE_SERVICE_MESH), &out.Services[1]) if err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index d4c78d14..bfe4d048 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -89,7 +89,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var user model.User if err = serializer.Map(input, &user); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } user.Organization = model.Organization{ ID: organizationId, @@ -122,7 +122,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { var out domain.CreateUserResponse if err = serializer.Map(*resUser, &out.User); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusCreated, out) @@ -169,7 +169,7 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { var out domain.GetUserResponse if err = serializer.Map(*user, &out.User); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -212,7 +212,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { out.Users = make([]domain.ListUserBody, len(*users)) for i, user := range *users { if err = serializer.Map(user, &out.Users[i]); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } } @@ -335,7 +335,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { var out domain.UpdateUserResponse if err = serializer.Map(*resUser, &out.User); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) ErrorJSON(w, r, err) return } @@ -402,7 +402,7 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { var out domain.GetMyProfileResponse if err = serializer.Map(*user, &out.User); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) ErrorJSON(w, r, err) return } @@ -454,7 +454,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var user model.User if err = serializer.Map(input, &user); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) ErrorJSON(w, r, err) return } @@ -472,7 +472,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { var out domain.UpdateMyProfileResponse if err = serializer.Map(*resUser, &out.User); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) ErrorJSON(w, r, err) return } @@ -802,7 +802,7 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { out.Users = make([]domain.ListUserBody, len(*users)) for i, user := range *users { if err = serializer.Map(user, &out.Users[i]); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } } @@ -852,7 +852,7 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { var out admin_domain.GetUserResponse if err = serializer.Map(*user, &out.User); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -1011,7 +1011,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { var out admin_domain.UpdateUserResponse if err = serializer.Map(*resUser, &out.User); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) ErrorJSON(w, r, err) return } diff --git a/internal/usecase/alert.go b/internal/usecase/alert.go index f79d7572..c8397d07 100644 --- a/internal/usecase/alert.go +++ b/internal/usecase/alert.go @@ -60,18 +60,18 @@ func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertReque clusterId := alert.Labels.TacoCluster organizationId, err := u.getOrganizationFromCluster(&allClusters, clusterId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) continue } organization, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) continue } primaryCluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(organization.PrimaryClusterId)) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) continue } diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index d492128d..8bf631ab 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -142,13 +142,13 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do workflowTemplate = "tks-service-mesh" default: - log.ErrorWithContext(ctx, "invalid appGroup type ", dto.AppGroupType.String()) + log.Error(ctx, "invalid appGroup type ", dto.AppGroupType.String()) return "", errors.Wrap(err, fmt.Sprintf("Invalid appGroup type. %s", dto.AppGroupType.String())) } workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflowTemplate, opts) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return "", httpErrors.NewInternalServerError(err, "AG_FAILED_TO_CALL_WORKFLOW", "") } diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index 484b224a..9763c2bd 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -103,7 +103,7 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount }, }) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return uuid.Nil, fmt.Errorf("Failed to call argo workflow : %s", err) } log.Info(ctx, "submited workflow :", workflowId) @@ -208,7 +208,7 @@ func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount }, }) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return fmt.Errorf("Failed to call argo workflow : %s", err) } log.Info(ctx, "submited workflow :", workflowId) @@ -251,7 +251,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount awsAccessKeyId, awsSecretAccessKey, _ := kubernetes.GetAwsSecret() if err != nil || awsAccessKeyId == "" || awsSecretAccessKey == "" { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return false, out, httpErrors.NewInternalServerError(fmt.Errorf("Invalid aws secret."), "", "") } @@ -262,7 +262,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount }, })) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) } stsSvc := sts.NewFromConfig(cfg) @@ -357,7 +357,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount o.Region = "ap-northeast-2" }) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return false, out, err } currentUsage.EIP = len(res.Addresses) diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index e0941c2b..4fdb01b5 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -201,7 +201,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster }, }) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return "", err } log.Info(ctx, "Successfully submited workflow: ", workflowId) @@ -263,7 +263,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster }, }) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return "", err } log.Info(ctx, "Successfully submited workflow: ", workflowId) @@ -310,7 +310,7 @@ func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clus }, }) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return "", err } log.Info(ctx, "Successfully submited workflow: ", workflowId) @@ -362,7 +362,7 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId }, }) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return err } log.Info(ctx, "Successfully submited workflow: ", workflowId) @@ -431,7 +431,7 @@ func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) }, }) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return errors.Wrap(err, "Failed to call argo workflow") } @@ -454,7 +454,7 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom out.ClusterRegion = "ap-northeast-2" if err := serializer.Map(cluster, &out); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) } if cluster.StackTemplate.CloudService == "AWS" && cluster.StackTemplate.KubeType == "AWS" { @@ -463,7 +463,7 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom } if err := serializer.Map(cluster, &out); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) } /* @@ -496,7 +496,7 @@ func (u *ClusterUsecase) CreateBootstrapKubeconfig(ctx context.Context, clusterI }, }) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return out, httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") } log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) @@ -576,7 +576,7 @@ func (u *ClusterUsecase) GetBootstrapKubeconfig(ctx context.Context, clusterId d secrets, err := client.CoreV1().Secrets("kube-system").Get(context.TODO(), "bootstrap-token-"+token, metav1.GetOptions{}) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return out, err } @@ -790,7 +790,7 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clust numOfAz = int(rawConf.NumOfAz) if numOfAz > 3 { - log.ErrorWithContext(ctx,"Error: numOfAz cannot exceed 3.") + log.Error(ctx,"Error: numOfAz cannot exceed 3.") temp_err := fmt.Errorf("Error: numOfAz cannot exceed 3.") return nil, temp_err } @@ -823,11 +823,11 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clust } if !found { - log.ErrorWithContext(ctx,"Couldn't find entry for region ", region) + log.Error(ctx,"Couldn't find entry for region ", region) } if numOfAz > maxAzForSelectedRegion { - log.ErrorWithContext(ctx,"Invalid numOfAz: exceeded the number of Az in region ", region) + log.Error(ctx,"Invalid numOfAz: exceeded the number of Az in region ", region) temp_err := fmt.Errorf("Invalid numOfAz: exceeded the number of Az in region %s", region) return nil, temp_err } @@ -838,7 +838,7 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clust log.DebugWithContext(ctx,"No machineReplicas param. Using default values..") } else { if remainder := replicas % numOfAz; remainder != 0 { - log.ErrorWithContext(ctx,"Invalid machineReplicas: it should be multiple of numOfAz ", numOfAz) + log.Error(ctx,"Invalid machineReplicas: it should be multiple of numOfAz ", numOfAz) temp_err := fmt.Errorf("Invalid machineReplicas: it should be multiple of numOfAz %d", numOfAz) return nil, temp_err } else { diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index dbbbe3af..0e40c7d2 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -80,7 +80,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) thanosUrl, err := u.getThanosUrl(ctx, organizationId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return out, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } address, port := helper.SplitAddress(thanosUrl) @@ -139,7 +139,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId string) (out domain.DashboardResource, err error) { thanosUrl, err := u.getThanosUrl(ctx, organizationId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return out, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } address, port := helper.SplitAddress(thanosUrl) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index d4096f73..72d30e3c 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -78,7 +78,7 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization }, }) if err != nil { - log.ErrorWithContext(ctx, "failed to submit argo workflow template. err : ", err) + log.Error(ctx, "failed to submit argo workflow template. err : ", err) return "", errors.Wrap(err, "Failed to call argo workflow") } log.Info(ctx, "submited workflow :", workflowId) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 8422338a..b3d0e1a3 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -89,7 +89,7 @@ func NewProjectUsecase(r repository.Repository, kc keycloak.IKeycloak, argoClien func (u *ProjectUsecase) CreateProject(ctx context.Context, p *model.Project) (string, error) { projectId, err := u.projectRepo.CreateProject(ctx, p) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return "", errors.Wrap(err, "Failed to create project.") } @@ -102,7 +102,7 @@ func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, } else { userUuid, err := uuid.Parse(userId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to parse uuid to string") } if onlyMyProject == false { @@ -112,7 +112,7 @@ func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, } } if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") } @@ -122,7 +122,7 @@ func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, func (u *ProjectUsecase) GetProject(ctx context.Context, organizationId string, projectId string) (*model.Project, error) { p, err := u.projectRepo.GetProjectById(ctx, organizationId, projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") } return p, err @@ -131,7 +131,7 @@ func (u *ProjectUsecase) GetProject(ctx context.Context, organizationId string, func (u *ProjectUsecase) GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*model.Project, error) { p, err := u.projectRepo.GetProjectByIdAndLeader(ctx, organizationId, projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") } return p, err @@ -141,7 +141,7 @@ func (u *ProjectUsecase) IsProjectNameExist(ctx context.Context, organizationId exist := true p, err := u.projectRepo.GetProjectByName(ctx, organizationId, projectName) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) exist = false return exist, errors.Wrap(err, "Failed to retrieve project name.") } @@ -163,13 +163,13 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne p.ProjectMembers = nil if err := u.projectRepo.UpdateProject(ctx, p); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to update project.") } if newLeaderId != "" && currentLeaderId != newLeaderId { if err := u.RemoveProjectMember(ctx, currentMemberId); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to remove project member.") } @@ -220,7 +220,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne func (u *ProjectUsecase) GetProjectRole(ctx context.Context, id string) (*model.ProjectRole, error) { pr, err := u.projectRepo.GetProjectRoleById(ctx, id) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to get project roles.") } @@ -240,7 +240,7 @@ func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs [] prs, err = u.projectRepo.GetAllProjectRoles(ctx) } if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to get project roles.") } @@ -254,7 +254,7 @@ func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs [] func (u *ProjectUsecase) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { projectMemberId, err := u.projectRepo.AddProjectMember(ctx, pm) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return "", errors.Wrap(err, "Failed to add project member to project.") } return projectMemberId, nil @@ -264,18 +264,18 @@ func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId strin var uid uuid.UUID uid, err := uuid.Parse(projectUserId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to parse uuid to string") } user, err := u.userRepository.GetByUuid(ctx, uid) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve user by id") } var pu model.ProjectUser if err = serializer.Map(user, &pu); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, err } return &pu, nil @@ -284,7 +284,7 @@ func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId strin func (u *ProjectUsecase) GetProjectMember(ctx context.Context, projectMemberId string) (pm *model.ProjectMember, err error) { pm, err = u.projectRepo.GetProjectMemberById(ctx, projectMemberId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return pm, errors.Wrap(err, "Failed to get project member.") } @@ -302,7 +302,7 @@ func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string pms, err = u.projectRepo.GetProjectMembersByProjectId(ctx, projectId, pg) } if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to get project members.") } @@ -312,7 +312,7 @@ func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMemberId string) (pmcr *domain.GetProjectMemberCountResponse, err error) { pmcr, err = u.projectRepo.GetProjectMemberCountByProjectId(ctx, projectMemberId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return pmcr, errors.Wrap(err, "Failed to get project member count.") } @@ -321,7 +321,7 @@ func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMembe func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, projectMemberId string) error { if err := u.projectRepo.RemoveProjectMember(ctx, projectMemberId); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to remove project member to project.") } return nil @@ -330,7 +330,7 @@ func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, projectMemberI func (u *ProjectUsecase) UpdateProjectMemberRole(ctx context.Context, pm *model.ProjectMember) error { if err := u.projectRepo.UpdateProjectMemberRole(ctx, pm); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to remove project member to project.") } return nil @@ -338,7 +338,7 @@ func (u *ProjectUsecase) UpdateProjectMemberRole(ctx context.Context, pm *model. func (u *ProjectUsecase) CreateProjectNamespace(ctx context.Context, organizationId string, pn *model.ProjectNamespace) error { if err := u.projectRepo.CreateProjectNamespace(ctx, organizationId, pn); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil @@ -348,7 +348,7 @@ func (u *ProjectUsecase) IsProjectNamespaceExist(ctx context.Context, organizati exist := true pn, err := u.projectRepo.GetProjectNamespaceByName(ctx, organizationId, projectId, stackId, projectNamespace) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) exist = false return exist, errors.Wrap(err, "Failed to retrieve project namespace.") } @@ -361,7 +361,7 @@ func (u *ProjectUsecase) IsProjectNamespaceExist(ctx context.Context, organizati func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationId string, projectId string, pg *pagination.Pagination) ([]model.ProjectNamespace, error) { pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, pg) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") } @@ -371,7 +371,7 @@ func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationI func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) (*model.ProjectNamespace, error) { pn, err := u.projectRepo.GetProjectNamespaceByPrimaryKey(ctx, organizationId, projectId, projectNamespace, stackId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve project namespace.") } @@ -380,7 +380,7 @@ func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId func (u *ProjectUsecase) UpdateProjectNamespace(ctx context.Context, pn *model.ProjectNamespace) error { if err := u.projectRepo.UpdateProjectNamespace(ctx, pn); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to update project namespace") } return nil @@ -389,7 +389,7 @@ func (u *ProjectUsecase) UpdateProjectNamespace(ctx context.Context, pn *model.P func (u *ProjectUsecase) DeleteProjectNamespace(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) error { if err := u.projectRepo.DeleteProjectNamespace(ctx, organizationId, projectId, projectNamespace, stackId); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to delete project namespace.") } return nil @@ -402,7 +402,7 @@ func (u *ProjectUsecase) GetAppCount(ctx context.Context, organizationId string, appCount, err = u.projectRepo.GetAppCountByNamespace(ctx, organizationId, projectId, namespace) } if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return 0, errors.Wrap(err, "Failed to retrieve app count.") } @@ -412,7 +412,7 @@ func (u *ProjectUsecase) GetAppCount(ctx context.Context, organizationId string, func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error { pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -430,24 +430,24 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga } if err := u.createK8SInitialResource(ctx, organizationId, projectId, stackId); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } if err := u.createKeycloakClientRoles(ctx, organizationId, projectId, stackId); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } projectMembers, err := u.GetProjectMembers(ctx, projectId, ProjectAll, nil) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } for _, pm := range projectMembers { err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } } @@ -457,7 +457,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error { pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } var nsCount int @@ -473,25 +473,25 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o } if err := u.deleteK8SInitialResource(ctx, organizationId, projectId, stackId); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } projectMembers, err := u.GetProjectMembers(ctx, projectId, ProjectAll, nil) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } for _, pm := range projectMembers { err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } } if err := u.deleteKeycloakClientRoles(ctx, organizationId, projectId, stackId); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -500,31 +500,31 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { kubeconfig, err := kubernetes.GetKubeConfig(stackId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } pr, err := u.GetProject(ctx, organizationId, projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.EnsureClusterRole(kubeconfig, pr.Name) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.EnsureCommonClusterRole(kubeconfig, pr.Name) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.EnsureCommonClusterRoleBinding(kubeconfig, pr.Name) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -533,31 +533,31 @@ func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizat func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { kubeconfig, err := kubernetes.GetKubeConfig(stackId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } pr, err := u.GetProject(ctx, organizationId, projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.RemoveClusterRole(kubeconfig, pr.Name) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.RemoveCommonClusterRole(kubeconfig, pr.Name) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.RemoveCommonClusterRoleBinding(kubeconfig, pr.Name) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -568,7 +568,7 @@ func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organiza for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { err := u.kc.EnsureClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } } @@ -581,7 +581,7 @@ func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organiza for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { err := u.kc.DeleteClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } } @@ -590,19 +590,19 @@ func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organiza func (u *ProjectUsecase) CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error { kubeconfig, err := kubernetes.GetKubeConfig(stackId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } pr, err := u.GetProject(ctx, organizationId, projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = kubernetes.EnsureRoleBinding(kubeconfig, pr.Name, namespace) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -616,7 +616,7 @@ func (u *ProjectUsecase) DeleteK8SNSRoleBinding(ctx context.Context, organizatio func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) @@ -626,7 +626,7 @@ func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, o func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { err := u.kc.AssignClientRoleToUser(organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil @@ -635,7 +635,7 @@ func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Contex func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) @@ -645,7 +645,7 @@ func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { err := u.kc.UnassignClientRoleToUser(organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } return nil @@ -654,7 +654,7 @@ func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) { projectNamespaces, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return "", errors.Wrap(err, "Failed to retrieve project namespaces.") } @@ -684,21 +684,21 @@ func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationI for _, pn := range projectNamespaces { kubeconfig, err := kubernetes.GetKubeConfig(pn.StackId) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return "", errors.Wrap(err, "Failed to retrieve kubeconfig.") } var config kubeConfigType err = yaml.Unmarshal(kubeconfig, &config) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return "", errors.Wrap(err, "Failed to unmarshal kubeconfig.") } config.Contexts[0].Context.Namespace = pn.Namespace kubeconfig, err = yaml.Marshal(config) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return "", errors.Wrap(err, "Failed to marshal kubeconfig.") } @@ -725,56 +725,56 @@ func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId str if err == nil { out.Pods = len(pods.Items) } else { - log.ErrorWithContext(ctx, "Failed to get pods. err : ", err) + log.Error(ctx, "Failed to get pods. err : ", err) } pvcs, err := clientset_user.CoreV1().PersistentVolumeClaims(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.PVCs = len(pvcs.Items) } else { - log.ErrorWithContext(ctx, "Failed to get pvcs. err : ", err) + log.Error(ctx, "Failed to get pvcs. err : ", err) } services, err := clientset_user.CoreV1().Services(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Services = len(services.Items) } else { - log.ErrorWithContext(ctx, "Failed to get services. err : ", err) + log.Error(ctx, "Failed to get services. err : ", err) } ingresses, err := clientset_user.NetworkingV1().Ingresses(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Ingresses = len(ingresses.Items) } else { - log.ErrorWithContext(ctx, "Failed to get ingresses. err : ", err) + log.Error(ctx, "Failed to get ingresses. err : ", err) } deployments, err := clientset_user.AppsV1().Deployments(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Deployments = len(deployments.Items) } else { - log.ErrorWithContext(ctx, "Failed to get deployments. err : ", err) + log.Error(ctx, "Failed to get deployments. err : ", err) } statefulsets, err := clientset_user.AppsV1().StatefulSets(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Statefulsets = len(statefulsets.Items) } else { - log.ErrorWithContext(ctx, "Failed to get statefulsets. err : ", err) + log.Error(ctx, "Failed to get statefulsets. err : ", err) } daemonsets, err := clientset_user.AppsV1().DaemonSets(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Daemonsets = len(daemonsets.Items) } else { - log.ErrorWithContext(ctx, "Failed to get daemonsets. err : ", err) + log.Error(ctx, "Failed to get daemonsets. err : ", err) } jobs, err := clientset_user.BatchV1().Jobs(namespace).List(ctx, metav1.ListOptions{}) if err == nil { out.Jobs = len(jobs.Items) } else { - log.ErrorWithContext(ctx, "Failed to get jobs. err : ", err) + log.Error(ctx, "Failed to get jobs. err : ", err) } return diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index ef37b438..e27bfd56 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -138,7 +138,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom }, }) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return "", httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") } log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) @@ -214,7 +214,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err }, }) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") } log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) @@ -447,17 +447,17 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) }, }) if err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) return err } log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) // Remove Cluster & AppGroup status description if err := u.appGroupRepo.InitWorkflowDescription(ctx, cluster.ID); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) } if err := u.clusterRepo.InitWorkflowDescription(ctx, cluster.ID); err != nil { - log.ErrorWithContext(ctx, err) + log.Error(ctx, err) } // wait & get clusterId ( max 1min ) From d1209d35fe4f878f06e33e73e256a1ce4adef5ba Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 13 Mar 2024 11:14:07 +0900 Subject: [PATCH 126/502] apply context to all the rest --- internal/repository/endpoint_test.go | 75 -------------------------- internal/repository/mapper_test.go | 79 ---------------------------- 2 files changed, 154 deletions(-) delete mode 100644 internal/repository/endpoint_test.go delete mode 100644 internal/repository/mapper_test.go diff --git a/internal/repository/endpoint_test.go b/internal/repository/endpoint_test.go deleted file mode 100644 index f27a9f06..00000000 --- a/internal/repository/endpoint_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package repository_test - -import ( - "fmt" - myRepository "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/driver/postgres" - "gorm.io/gorm" - "gorm_test/config" - "testing" -) - -func TestNewEndpointRepository(t *testing.T) { - conf := config.NewDefaultConfig() - dsn := fmt.Sprintf( - "host=%s dbname=%s user=%s password=%s port=%d sslmode=disable TimeZone=Asia/Seoul", - conf.Address, conf.Database, conf.AdminId, conf.AdminPassword, conf.Port, - ) - - t.Logf("dsn: %s", dsn) - - db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) - if err != nil { - panic(err) - } - - if err = db.AutoMigrate(&myRepository.Endpoint{}); err != nil { - panic(err) - } - - dbClient := myRepository.NewEndpointRepository(db) - - // create - endpoint := &domain.Endpoint{ - Name: "test", - Group: "test", - } - - if err := dbClient.Create(endpoint); err != nil { - panic(err) - } - - t.Log("list") - // list - endpoints, err := dbClient.List(nil) - if err != nil { - panic(err) - } - - for _, endpoint := range endpoints { - t.Logf("endpoint: %+v", endpoint) - } - - t.Log("get") - // get - for _, endpoint := range endpoints { - endpoint, err := dbClient.Get(endpoint.ID) - if err != nil { - panic(err) - } - t.Logf("endpoint: %+v", endpoint) - } - - t.Log("update") - // update - for _, endpoint := range endpoints { - endpoint.Name = "test2" - t.Logf("BeforeUpdate: %+v", endpoint) - if err := dbClient.Update(endpoint); err != nil { - panic(err) - } else { - t.Logf("AfterUpdate: %+v", endpoint) - } - } -} diff --git a/internal/repository/mapper_test.go b/internal/repository/mapper_test.go deleted file mode 100644 index bf040134..00000000 --- a/internal/repository/mapper_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package repository - -import ( - "fmt" - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" - "testing" - "time" -) - -// test case -func TestConvert(t *testing.T) { - genUuid, _ := uuid.NewRandom() - uuidStr := genUuid.String() - - type args struct { - src interface{} - dst interface{} - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "test case 1", - args: args{ - src: User{ - ID: genUuid, - AccountId: "testAccount", - Name: "testName", - Password: "testPassword", - RoleId: uuid.UUID{}, - Role: Role{}, - OrganizationId: "testOrganizationId", - Organization: Organization{}, - Creator: uuid.UUID{}, - Email: "testEmail", - Department: "testDepartment", - Description: "testDescription", - }, - dst: &domain.User{}, - }, - wantErr: false, - }, - { - name: "test case 2", - args: args{ - src: domain.User{ - ID: uuidStr, - AccountId: "testAccount", - Password: "testPassword", - Name: "testName", - Token: "testToken", - Role: domain.Role{}, - Organization: domain.Organization{}, - Creator: "testCreator", - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - Email: "test email", - Department: "testDepartment", - Description: "testDescription", - }, - dst: &User{}, - }, - wantErr: false, - }, - } - _ = tests - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := Map(tt.args.src, tt.args.dst); (err != nil) != tt.wantErr { - t.Errorf("Map() error = %v, wantErr %v", err, tt.wantErr) - } else { - fmt.Println(tt.args.dst) - } - }) - } -} From edfca2c245dc40bb880457f9d758bcd3a9b1aa32 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 13 Mar 2024 11:14:37 +0900 Subject: [PATCH 127/502] apply context to all the rest --- cmd/server/main.go | 28 +- internal/database/database.go | 10 +- internal/delivery/http/app-serve-app.go | 45 +-- internal/delivery/http/audit.go | 2 +- internal/delivery/http/auth.go | 24 +- internal/delivery/http/cloud-account.go | 2 +- internal/delivery/http/handler.go | 2 +- internal/delivery/http/organization.go | 24 +- internal/delivery/http/permission.go | 23 +- internal/delivery/http/project.go | 94 ++--- internal/delivery/http/user.go | 42 +-- internal/gorm/gorm.go | 20 +- internal/helper/ssh.go | 18 +- internal/helper/util.go | 20 +- internal/keycloak/keycloak.go | 348 ++++++++---------- internal/kubernetes/kubernetes.go | 138 +++---- internal/mail/content.go | 18 +- internal/mail/ses.go | 8 +- internal/mail/smtp.go | 27 +- internal/middleware/audit/audit-map.go | 75 ++-- internal/middleware/audit/audit.go | 8 +- .../auth/authenticator/authenticator.go | 2 +- .../auth/authenticator/keycloak/keycloak.go | 14 +- internal/middleware/auth/authorizer/rbac.go | 4 +- internal/middleware/auth/role/default.go | 11 +- internal/middleware/logging/logging.go | 4 +- internal/repository/app-group.go | 2 +- internal/repository/app-serve-app.go | 16 +- internal/repository/cluster.go | 10 +- internal/repository/mapper.go | 3 +- internal/repository/organization.go | 16 +- internal/repository/project.go | 70 ++-- internal/repository/user.go | 20 +- internal/route/route.go | 8 +- internal/usecase/alert.go | 2 +- internal/usecase/app-group.go | 6 +- internal/usecase/app-serve-app.go | 138 +++---- internal/usecase/auth.go | 39 +- internal/usecase/cloud-account.go | 18 +- internal/usecase/cluster.go | 38 +- internal/usecase/dashboard.go | 32 +- internal/usecase/organization.go | 5 +- internal/usecase/project.go | 34 +- internal/usecase/stack.go | 38 +- internal/usecase/user.go | 52 +-- pkg/argo-client/client-mock.go | 11 +- pkg/argo-client/client.go | 43 +-- pkg/domain/mapper.go | 0 pkg/httpErrors/httpErrors.go | 2 - pkg/thanos-client/client.go | 19 +- 50 files changed, 796 insertions(+), 837 deletions(-) create mode 100644 pkg/domain/mapper.go diff --git a/cmd/server/main.go b/cmd/server/main.go index bf6926f7..34d84fab 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "flag" "fmt" "net/http" @@ -72,7 +73,7 @@ func init() { flag.Parse() if err := viper.BindPFlags(pflag.CommandLine); err != nil { - log.Error(err) + log.Error(context.Background(), err) } address := viper.GetString("external-address") @@ -102,11 +103,12 @@ func init() { // @host tks-api-dev.taco-cat.xyz // @BasePath /api/1.0/ func main() { - log.Info("*** Arguments *** ") + ctx := context.Background() + log.Info(ctx, "*** Arguments *** ") for i, s := range viper.AllSettings() { - log.Info(fmt.Sprintf("%s : %v", i, s)) + log.Info(ctx, fmt.Sprintf("%s : %v", i, s)) } - log.Info("****************** ") + log.Info(ctx, "****************** ") // For web service asset := route.NewAssetHandler(viper.GetString("web-root")) @@ -114,7 +116,7 @@ func main() { // Initialize database db, err := database.InitDB() if err != nil { - log.Fatal("cannot connect gormDB") + log.Fatal(ctx, "cannot connect gormDB") } // Ensure default rows in database @@ -125,12 +127,12 @@ func main() { if viper.GetString("argo-address") == "" || viper.GetInt("argo-port") == 0 { argoClient, err = argowf.NewMock() if err != nil { - log.Fatal("failed to create argowf client : ", err) + log.Fatal(ctx, "failed to create argowf client : ", err) } } else { argoClient, err = argowf.New(viper.GetString("argo-address"), viper.GetInt("argo-port"), false, "") if err != nil { - log.Fatal("failed to create argowf client : ", err) + log.Fatal(ctx, "failed to create argowf client : ", err) } } @@ -141,20 +143,20 @@ func main() { ClientSecret: viper.GetString("keycloak-client-secret"), }) - err = keycloak.InitializeKeycloak() + err = keycloak.InitializeKeycloak(ctx) if err != nil { - log.Fatal("failed to initialize keycloak : ", err) + log.Fatal(ctx, "failed to initialize keycloak : ", err) } - err = mail.Initialize() + err = mail.Initialize(ctx) if err != nil { - log.Fatal("failed to initialize ses : ", err) + log.Fatal(ctx, "failed to initialize ses : ", err) } route := route.SetupRouter(db, argoClient, keycloak, asset) - log.Info("Starting server on ", viper.GetInt("port")) + log.Info(ctx, "Starting server on ", viper.GetInt("port")) err = http.ListenAndServe("0.0.0.0:"+strconv.Itoa(viper.GetInt("port")), route) if err != nil { - log.Fatal(err) + log.Fatal(ctx, err) } } diff --git a/internal/database/database.go b/internal/database/database.go index 37485621..043bd031 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -3,6 +3,8 @@ package database import ( "context" "fmt" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/log" "os" "strings" @@ -179,8 +181,9 @@ func EnsureDefaultRows(db *gorm.DB) error { // ctx := context.Background() - - eps, err := repoFactory.Endpoint.List(ctx, nil) + pg := pagination.NewPagination(nil) + pg.Limit = 1000 + eps, err := repoFactory.Endpoint.List(ctx, pg) if err != nil { return err } @@ -189,7 +192,10 @@ func EnsureDefaultRows(db *gorm.DB) error { for _, ep := range eps { storedEps[ep.Name] = struct{}{} } + log.Debugf(context.Background(), "storedEps: %+v", storedEps) for _, ep := range api.ApiMap { + log.Debug(context.Background(), "ep.Name", ep.Name) + log.Debug(context.Background(), "storedEps[ep.Name]", storedEps[ep.Name]) if _, ok := storedEps[ep.Name]; !ok { if err := repoFactory.Endpoint.Create(ctx, &model.Endpoint{ Name: ep.Name, diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 1d66ebf7..f75ff95c 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -1,6 +1,7 @@ package http import ( + "context" "fmt" "math/rand" "net/http" @@ -94,14 +95,14 @@ func NewAppServeAppHandler(h usecase.Usecase) *AppServeAppHandler { func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) return } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid projectId"), "C_INVALID_PROJECT_ID", "")) return @@ -122,7 +123,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re return } - log.Infof("Processing CREATE request for app '%s'...", app.Name) + log.Infof(r.Context(), "Processing CREATE request for app '%s'...", app.Name) now := time.Now() app.OrganizationId = organizationId @@ -180,10 +181,10 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re } } - log.Infof("Created new namespace: %s", ns) + log.Infof(r.Context(), "Created new namespace: %s", ns) app.Namespace = ns } else { - log.Infof("Using existing namespace: %s", app.Namespace) + log.Infof(r.Context(), "Using existing namespace: %s", app.Namespace) } // Validate port param for springboot app @@ -268,7 +269,7 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ out.AppServeApps = make([]domain.AppServeAppResponse, len(apps)) for i, app := range apps { if err := serializer.Map(app, &out.AppServeApps[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } @@ -338,7 +339,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque var out domain.GetAppServeAppResponse if err := serializer.Map(app, &out.AppServeApp); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } // NOTE: makeStages function's been changed to use task instead of app @@ -388,7 +389,7 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * var out domain.GetAppServeAppTaskResponse if err := serializer.Map(task, &out.AppServeAppTask); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -411,7 +412,7 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%s]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%s]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "", "")) return @@ -478,7 +479,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r out.AppServeAppTasks = make([]domain.AppServeAppTaskResponse, len(tasks)) for i, task := range tasks { if err := serializer.Map(task, &out.AppServeAppTasks[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } @@ -508,28 +509,28 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId: [%s]", organizationId), "C_INVALID_ORGANIZATION_ID", "")) return } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid projectId: [%s]", projectId), "C_INVALID_PROJECT_ID", "")) return } appId, ok := vars["appId"] - log.Debugf("appId = [%s]\n", appId) + log.Debugf(r.Context(), "appId = [%s]\n", appId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid appId: [%s]", appId), "C_INVALID_ASA_ID", "")) return } taskId, ok := vars["taskId"] - log.Debugf("taskId = [%s]\n", taskId) + log.Debugf(r.Context(), "taskId = [%s]\n", taskId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid taskId: [%s]", taskId), "C_INVALID_ASA_TASK_ID", "")) return @@ -552,18 +553,18 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * var out domain.GetAppServeAppTaskResponse if err := serializer.Map(app, &out.AppServeApp); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } if err := serializer.Map(task, &out.AppServeAppTask); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } - out.Stages = makeStages(task, app) + out.Stages = makeStages(r.Context(), task, app) ResponseJSON(w, r, http.StatusOK, out) } -func makeStages(task *model.AppServeAppTask, app *model.AppServeApp) []domain.StageResponse { +func makeStages(ctx context.Context, task *model.AppServeAppTask, app *model.AppServeApp) []domain.StageResponse { stages := make([]domain.StageResponse, 0) var stage domain.StageResponse @@ -592,20 +593,20 @@ func makeStages(task *model.AppServeAppTask, app *model.AppServeApp) []domain.St pipelines = []string{"deploy", "promote"} } } else { - log.Error("Unexpected case happened while making stages!") + log.Error(ctx, "Unexpected case happened while making stages!") } fmt.Printf("Pipeline stages: %v\n", pipelines) for _, pl := range pipelines { - stage = makeStage(task, app, pl) + stage = makeStage(ctx, task, app, pl) stages = append(stages, stage) } return stages } -func makeStage(task *model.AppServeAppTask, app *model.AppServeApp, pl string) domain.StageResponse { +func makeStage(ctx context.Context, task *model.AppServeAppTask, app *model.AppServeApp, pl string) domain.StageResponse { taskStatus := task.Status strategy := task.Strategy @@ -634,7 +635,7 @@ func makeStage(task *model.AppServeAppTask, app *model.AppServeApp, pl string) d actions = append(actions, action) } } else { - log.Error("Not supported strategy!") + log.Error(ctx, "Not supported strategy!") } } else if stage.Status == "PROMOTE_WAIT" && strategy == "blue-green" { diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index c04b46ea..5b8defff 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -110,7 +110,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } - log.Info(audit) + log.Info(r.Context(), audit) var out domain.GetAuditResponse if err := serializer.Map(audit, &out.Audit); err != nil { diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 801c9ec2..5208a42a 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -69,7 +69,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { ClientIP: audit.GetClientIpAddress(w, r), UserId: nil, }) - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } else { @@ -85,7 +85,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { var cookies []*http.Cookie if targetCookies, err := h.usecase.SingleSignIn(r.Context(), input.OrganizationId, input.AccountId, input.Password); err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) } else { cookies = append(cookies, targetCookies...) } @@ -119,13 +119,13 @@ func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { sessionId, ok := request.SessionFrom(ctx) if !ok { - log.ErrorfWithContext(r.Context(), "session id is not found") + log.Errorf(r.Context(), "session id is not found") ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("session id is not found"), "A_NO_SESSION", "")) return } userInfo, ok := request.UserFrom(ctx) if !ok { - log.ErrorfWithContext(r.Context(), "user info is not found") + log.Errorf(r.Context(), "user info is not found") ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user info is not found"), "A_NO_SESSION", "")) return } @@ -133,7 +133,7 @@ func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { err := h.usecase.Logout(r.Context(), sessionId, organizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } @@ -141,7 +141,7 @@ func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { var cookies []*http.Cookie redirectUrl, targetCookies, err := h.usecase.SingleSignOut(r.Context(), organizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) } cookies = append(cookies, targetCookies...) if len(cookies) > 0 { @@ -185,7 +185,7 @@ func (h *AuthHandler) FindId(w http.ResponseWriter, r *http.Request) { accountId, err := h.usecase.FindId(r.Context(), input.Code, input.Email, input.UserName, input.OrganizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -217,7 +217,7 @@ func (h *AuthHandler) FindPassword(w http.ResponseWriter, r *http.Request) { err = h.usecase.FindPassword(r.Context(), input.Code, input.AccountId, input.Email, input.UserName, input.OrganizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -246,7 +246,7 @@ func (h *AuthHandler) VerifyIdentityForLostId(w http.ResponseWriter, r *http.Req err = h.usecase.VerifyIdentity(r.Context(), "", input.Email, input.UserName, input.OrganizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -277,7 +277,7 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht err = h.usecase.VerifyIdentity(r.Context(), input.AccountId, input.Email, input.UserName, input.OrganizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -298,14 +298,14 @@ func (h *AuthHandler) VerifyIdentityForLostPassword(w http.ResponseWriter, r *ht func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { token, ok := request.TokenFrom(r.Context()) if !ok { - log.ErrorfWithContext(r.Context(), "token is not found") + log.Errorf(r.Context(), "token is not found") ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("token is not found"), "C_INTERNAL_ERROR", "")) return } isActive, err := h.usecase.VerifyToken(r.Context(), token) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index b4a78d3f..c2685eb8 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -184,7 +184,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) return } - log.DebugWithContext(r.Context(), "[TODO] organization check", organizationId) + log.Debug(r.Context(), "[TODO] organization check", organizationId) cloudAccountId, err := uuid.Parse(strId) if err != nil { diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index 1fc7de9f..a45435c9 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -27,7 +27,7 @@ func init() { } func ErrorJSON(w http.ResponseWriter, r *http.Request, err error) { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) errorResponse, status := httpErrors.ErrorResponse(err) ResponseJSON(w, r, status, errorResponse) } diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 69face7e..a224781d 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -48,7 +48,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -61,7 +61,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. organizationId, err := h.usecase.Create(ctx, &organization) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -76,7 +76,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } adminRoleId, err := h.roleUsecase.CreateTksRole(r.Context(), &adminRole) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -88,7 +88,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. } userRoleId, err := h.roleUsecase.CreateTksRole(r.Context(), &userRole) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -98,7 +98,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. h.permissionUsecase.SetRoleIdToPermissionSet(r.Context(), adminRoleId, adminPermissionSet) err = h.permissionUsecase.CreatePermissionSet(r.Context(), adminPermissionSet) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -107,7 +107,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. h.permissionUsecase.SetRoleIdToPermissionSet(r.Context(), userRoleId, userPermissionSet) err = h.permissionUsecase.CreatePermissionSet(r.Context(), userPermissionSet) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -115,7 +115,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. // Admin user 생성 admin, err := h.userUsecase.CreateAdmin(r.Context(), organizationId, input.AdminAccountId, input.AdminName, input.AdminEmail) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -156,7 +156,7 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re pg := pagination.NewPagination(&urlParams) organizations, err := h.usecase.Fetch(r.Context(), pg) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -201,7 +201,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req organization, err := h.usecase.Get(r.Context(), organizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -262,7 +262,7 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. err := h.userUsecase.DeleteAll(r.Context(), organizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -271,7 +271,7 @@ func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http. // organization 삭제 err = h.usecase.Delete(r.Context(), organizationId, token) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -315,7 +315,7 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. organization, err := h.usecase.Update(r.Context(), organizationId, input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index bdc65716..488c971a 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -43,7 +43,7 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http var premissionSetResponse domain.PermissionSetResponse if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } var out domain.GetPermissionTemplatesResponse @@ -87,7 +87,7 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http var premissionSetResponse domain.PermissionSetResponse if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } var out domain.GetPermissionsByRoleIdResponse @@ -115,7 +115,6 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http // @Security JWT func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { // path parameter - log.Debug("UpdatePermissionsByRoleId Called") var roleId string _ = roleId vars := mux.Vars(r) @@ -133,14 +132,11 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } - log.Debugf("input: %+v", input) for _, permissionResponse := range input.Permissions { - log.Debugf("permissionResponse: %+v", permissionResponse) - var permission model.Permission if err := serializer.Map(permissionResponse, &permission); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil { @@ -149,18 +145,5 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h } } - //var edgePermissions []*domain.Permission - //for _, permission := range input.Permissions { - // domain.GetEdgePermission(permission, edgePermissions, nil) - //} - //log.Debugf("edgePermissions: %+v", edgePermissions) - //for _, permission := range edgePermissions { - // err := h.permissionUsecase.UpdatePermission(permission) - // if err != nil { - // ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - // return - // } - //} - ResponseJSON(w, r, http.StatusOK, nil) } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index d9215d42..015c4c48 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -82,7 +82,7 @@ func NewProjectHandler(u usecase.Usecase) IProjectHandler { func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -101,7 +101,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { Description: projectReq.Description, CreatedAt: now, } - log.Infof("Processing CREATE request for project '%s'...", project.Name) + log.Infof(r.Context(), "Processing CREATE request for project '%s'...", project.Name) projectId, err := p.usecase.CreateProject(r.Context(), project) if err != nil { @@ -112,14 +112,14 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { project.ID = projectId ProjectLeaderId, err := uuid.Parse(projectReq.ProjectLeaderId) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to parse uuid to string")) return } prs, err := p.usecase.GetProjectRoles(r.Context(), usecase.ProjectLeader) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "Failed to retrieve project-leader id")) return } @@ -137,7 +137,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { projectMemberId, err := p.usecase.AddProjectMember(r.Context(), pm) if err != nil { - log.Errorf("projectMemberId: %v", projectMemberId) + log.Errorf(r.Context(), "projectMemberId: %v", projectMemberId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -302,7 +302,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { var pdr domain.ProjectDetailResponse if err = serializer.Map(*project, &pdr); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, err) return } @@ -371,14 +371,14 @@ func (p ProjectHandler) IsProjectNameExist(w http.ResponseWriter, r *http.Reques func (p ProjectHandler) UpdateProject(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) return } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), "C_INVALID_PROJECT_ID", "")) @@ -438,7 +438,7 @@ func (p ProjectHandler) DeleteProject(w http.ResponseWriter, r *http.Request) { func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -446,7 +446,7 @@ func (p ProjectHandler) GetProjectRole(w http.ResponseWriter, r *http.Request) { } projectRoleId, ok := vars["projectRoleId"] - log.Debugf("projectRoleId = [%v]\n", projectRoleId) + log.Debugf(r.Context(), "projectRoleId = [%v]\n", projectRoleId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectRoleId"), "C_INVALID_PROJECT_ROLE_ID", "")) @@ -529,7 +529,7 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -552,7 +552,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) pg := pagination.NewPagination(&urlParams) pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, pg) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -565,7 +565,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) for _, pmr := range projectMemberReq.ProjectMemberRequests { pu, err := p.usecase.GetProjectUser(r.Context(), pmr.ProjectUserId) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectUserId"), "C_INVALID_PROJECT_USER_ID", "")) return @@ -573,7 +573,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) pr, err := p.usecase.GetProjectRole(r.Context(), pmr.ProjectRoleId) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -593,7 +593,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) } pmId, err := p.usecase.AddProjectMember(r.Context(), pm) if err != nil { - log.Errorf("projectMemberId: %s", pmId) + log.Errorf(r.Context(), "projectMemberId: %s", pmId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -601,7 +601,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // tasks for keycloak & k8s for stackId := range stackIds { if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pmId); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -628,7 +628,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -636,7 +636,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), "C_INVALID_PROJECT_ID", "")) @@ -644,7 +644,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) } projectMemberId, ok := vars["projectMemberId"] - log.Debugf("projectMemberId = [%v]\n", projectMemberId) + log.Debugf(r.Context(), "projectMemberId = [%v]\n", projectMemberId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectMemberId"), "C_INVALID_PROJECT_MEMBER_ID", "")) @@ -698,7 +698,7 @@ func (p ProjectHandler) GetProjectMember(w http.ResponseWriter, r *http.Request) func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -786,7 +786,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -830,7 +830,7 @@ func (p ProjectHandler) GetProjectMemberCount(w http.ResponseWriter, r *http.Req func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -838,7 +838,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), "C_INVALID_PROJECT_ID", "")) @@ -846,7 +846,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } projectMemberId, ok := vars["projectMemberId"] - log.Debugf("projectMemberId = [%v]\n", projectMemberId) + log.Debugf(r.Context(), "projectMemberId = [%v]\n", projectMemberId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectMemberId"), "C_INVALID_PROJECT_MEMBER_ID", "")) @@ -856,7 +856,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque // tasks for keycloak & k8s pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -866,7 +866,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } for stackId := range stackIds { if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -896,7 +896,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -904,7 +904,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), "C_INVALID_PROJECT_ID", "")) @@ -920,7 +920,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // tasks for keycloak & k8s pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -934,7 +934,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // tasks for keycloak & k8s for stackId := range stackIds { if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ProjectMemberId); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -965,7 +965,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -973,7 +973,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), "C_INVALID_PROJECT_ID", "")) @@ -996,7 +996,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R now := time.Now() pm, err := p.usecase.GetProjectMember(r.Context(), projectMemberId) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1008,7 +1008,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1019,7 +1019,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R // tasks for keycloak & k8s. Unassign old role for stackId := range stackIds { if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1037,7 +1037,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R // tasks for keycloak & k8s. Assign new role for stackId := range stackIds { if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1062,7 +1062,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -1070,7 +1070,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } projectId, ok := vars["projectId"] - log.Debugf("projectId = [%v]\n", projectId) + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectId"), "C_INVALID_PROJECT_ID", "")) @@ -1086,7 +1086,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1098,7 +1098,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. for _, pmr := range projectMemberReq.ProjectMemberRoleRequests { pm, err := p.usecase.GetProjectMember(r.Context(), pmr.ProjectMemberId) if err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1110,7 +1110,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. for stackId := range stackIds { if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1128,7 +1128,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. for stackId := range stackIds { if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1299,7 +1299,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ for _, pn := range pns { var pnr domain.ProjectNamespaceResponse if err = serializer.Map(pn, &pnr); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, err) return } @@ -1383,7 +1383,7 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque var pnr domain.ProjectNamespaceResponse if err = serializer.Map(*pn, &pnr); err != nil { - log.Error(err) + log.Error(r.Context(), err) ErrorJSON(w, r, err) return } @@ -1413,7 +1413,7 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque func (p ProjectHandler) UpdateProjectNamespace(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] - log.Debugf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) @@ -1632,7 +1632,7 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r var out domain.GetProjectNamespaceK8sResourcesResponse if err = serializer.Map(k8sResources, &out.K8sResources); err != nil { - log.Error(err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) } @@ -1685,7 +1685,7 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, var out domain.GetProjectNamespaceResourcesUsageResponse if err = serializer.Map(resourcesUsage, &out.ResourcesUsage); err != nil { - log.Error(err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index bfe4d048..203194db 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -80,7 +80,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { input := domain.CreateUserRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -97,7 +97,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -110,7 +110,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { resUser, err := u.usecase.Create(ctx, &user) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusConflict { ErrorJSON(w, r, httpErrors.NewConflictError(err, "", "")) return @@ -156,7 +156,7 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { user, err := u.usecase.GetByAccountId(r.Context(), userId, organizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) @@ -203,7 +203,7 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { pg := pagination.NewPagination(&urlParams) users, err := u.usecase.ListWithPagination(r.Context(), organizationId, pg) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -254,7 +254,7 @@ func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -292,7 +292,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { input := domain.UpdateUserRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -311,7 +311,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -438,7 +438,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { input := domain.UpdateMyProfileRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -446,7 +446,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { err = u.usecase.ValidateAccount(r.Context(), requestUserInfo.GetUserId(), input.Password, requestUserInfo.GetOrganizationId()) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -522,7 +522,7 @@ func (u UserHandler) UpdateMyPassword(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -690,7 +690,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { input := admin_domain.CreateUserRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -721,7 +721,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -741,7 +741,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { resUser, err := u.usecase.Create(r.Context(), &user) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusConflict { ErrorJSON(w, r, httpErrors.NewConflictError(err, "", "")) return @@ -753,7 +753,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { err = u.usecase.SendEmailForTemporaryPassword(r.Context(), user.AccountId, organizationId, user.Password) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -793,7 +793,7 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { pg := pagination.NewPagination(&urlParams) users, err := u.usecase.ListWithPagination(r.Context(), organizationId, pg) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -839,7 +839,7 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { user, err := u.usecase.GetByAccountId(r.Context(), userId, organizationId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) @@ -889,7 +889,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { if organizationId != "master" { err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -914,7 +914,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -952,7 +952,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { input := admin_domain.UpdateUserRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -987,7 +987,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } diff --git a/internal/gorm/gorm.go b/internal/gorm/gorm.go index 37bd2deb..30b95d01 100644 --- a/internal/gorm/gorm.go +++ b/internal/gorm/gorm.go @@ -47,19 +47,19 @@ func (l *customGormLogger) LogMode(level logger.LogLevel) logger.Interface { func (l *customGormLogger) Info(ctx context.Context, msg string, data ...interface{}) { if l.LogLevel >= logger.Info { - internalLogger.InfofWithContext(ctx, l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + internalLogger.Infof(ctx, l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) } } func (l *customGormLogger) Warn(ctx context.Context, msg string, data ...interface{}) { if l.LogLevel >= logger.Warn { - internalLogger.WarnfWithContext(ctx, l.warnStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + internalLogger.Warnf(ctx, l.warnStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) } } func (l *customGormLogger) Error(ctx context.Context, msg string, data ...interface{}) { if l.LogLevel >= logger.Error { - internalLogger.ErrorfWithContext(ctx, l.errStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) + internalLogger.Errorf(ctx, l.errStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...) } } @@ -73,33 +73,33 @@ func (l *customGormLogger) Trace(ctx context.Context, begin time.Time, fc func() case err != nil && l.LogLevel >= logger.Error && (!errors.Is(err, logger.ErrRecordNotFound) || !l.IgnoreRecordNotFoundError): sql, rows := fc() if rows == -1 { - internalLogger.ErrorfWithContext(ctx, l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql) + internalLogger.Errorf(ctx, l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql) //l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql) } else { - internalLogger.ErrorfWithContext(ctx, l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql) + internalLogger.Errorf(ctx, l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql) //l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql) } case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= logger.Warn: sql, rows := fc() slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold) if rows == -1 { - internalLogger.WarnfWithContext(ctx, l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql) + internalLogger.Warnf(ctx, l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql) //l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql) } else { - internalLogger.WarnfWithContext(ctx, l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql) + internalLogger.Warnf(ctx, l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql) //l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql) } case l.LogLevel == logger.Info: sql, rows := fc() if rows == -1 { - internalLogger.InfofWithContext(ctx, l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql) + internalLogger.Infof(ctx, l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql) //l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql) } else { - internalLogger.InfofWithContext(ctx, l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql) + internalLogger.Infof(ctx, l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql) //l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql) } default: - internalLogger.Info("Trace") + internalLogger.Info(ctx, "Trace") } } diff --git a/internal/helper/ssh.go b/internal/helper/ssh.go index 7b65b929..08505708 100644 --- a/internal/helper/ssh.go +++ b/internal/helper/ssh.go @@ -7,7 +7,6 @@ import ( "time" "github.com/gorilla/websocket" - "github.com/openinfradev/tks-api/pkg/log" "golang.org/x/crypto/ssh" ) @@ -114,12 +113,12 @@ func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) { //read websocket msg _, wsData, err := wsConn.ReadMessage() if err != nil { - log.Error(err) - log.Error("reading webSocket message failed") + //log.Error(err) + //log.Error("reading webSocket message failed") return } - cmd := bytes.NewBuffer(wsData).String() - log.Debug(cmd) + //cmd := bytes.NewBuffer(wsData).String() + //log.Debug(cmd) //unmashal bytes into struct /* if err := json.Unmarshal(wsData, &msgObj); err != nil { @@ -140,7 +139,8 @@ func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) { // sendWebsocketInputCommandToSshSessionStdinPipe func (sws *LogicSshWsSession) sendWebsocketInputCommandToSshSessionStdinPipe(cmdBytes []byte) { if _, err := sws.stdinPipe.Write(cmdBytes); err != nil { - log.Error("ws cmd bytes write to ssh.stdin pipe failed") + + //log.Error("ws cmd bytes write to ssh.stdin pipe failed") } } @@ -162,11 +162,11 @@ func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) { if len(bs) > 0 { err := wsConn.WriteMessage(websocket.TextMessage, bs) if err != nil { - log.Error("ssh sending combo output to webSocket failed") + //log.Error("ssh sending combo output to webSocket failed") } _, err = sws.logBuff.Write(bs) if err != nil { - log.Error("combo output to log buffer failed") + //log.Error("combo output to log buffer failed") } sws.comboOutput.buffer.Reset() } @@ -179,7 +179,7 @@ func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) { func (sws *LogicSshWsSession) Wait(quitChan chan bool) { if err := sws.session.Wait(); err != nil { - log.Error("ssh session wait failed") + //log.Error("ssh session wait failed") setQuit(quitChan) } } diff --git a/internal/helper/util.go b/internal/helper/util.go index 5a7cae86..9e4e573a 100644 --- a/internal/helper/util.go +++ b/internal/helper/util.go @@ -1,7 +1,7 @@ package helper import ( - "bytes" + "context" "crypto/rand" "encoding/json" "fmt" @@ -37,20 +37,10 @@ func ModelToJson(in any) string { return s } -func Transcode(in, out interface{}) { - buf := new(bytes.Buffer) - if err := json.NewEncoder(buf).Encode(in); err != nil { - log.Error(err) - } - if err := json.NewDecoder(buf).Decode(out); err != nil { - log.Error(err) - } -} - -func GenerateEmailCode() (string, error) { +func GenerateEmailCode(ctx context.Context) (string, error) { num, err := rand.Int(rand.Reader, big.NewInt(900000)) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", err } num = num.Add(num, big.NewInt(100000)) @@ -64,7 +54,7 @@ func IsDurationExpired(targetTime time.Time, duration time.Duration) bool { return diff > duration } -func SplitAddress(url string) (address string, port int) { +func SplitAddress(ctx context.Context, url string) (address string, port int) { url = strings.TrimSuffix(url, "\n") arr := strings.Split(url, ":") address = arr[0] + ":" + arr[1] @@ -79,7 +69,7 @@ func SplitAddress(url string) (address string, port int) { } port = portNum - log.Infof("address : %s, port : %d", address, port) + log.Infof(ctx, "address : %s, port : %d", address, port) return } diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 610d59ad..277f1296 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -16,34 +16,34 @@ import ( ) type IKeycloak interface { - InitializeKeycloak() error + InitializeKeycloak(ctx context.Context) error - LoginAdmin(accountId string, password string) (*model.User, error) - Login(accountId string, password string, organizationId string) (*model.User, error) - Logout(sessionId string, organizationId string) error + LoginAdmin(ctx context.Context, accountId string, password string) (*model.User, error) + Login(ctx context.Context, accountId string, password string, organizationId string) (*model.User, error) + Logout(ctx context.Context, sessionId string, organizationId string) error - CreateRealm(organizationId string) (string, error) - GetRealm(organizationId string) (*model.Organization, error) - GetRealms() ([]*model.Organization, error) - DeleteRealm(organizationId string) error - UpdateRealm(organizationId string, organizationConfig model.Organization) error + CreateRealm(ctx context.Context, organizationId string) (string, error) + GetRealm(ctx context.Context, organizationId string) (*model.Organization, error) + GetRealms(ctx context.Context) ([]*model.Organization, error) + DeleteRealm(ctx context.Context, organizationId string) error + UpdateRealm(ctx context.Context, organizationId string, organizationConfig model.Organization) error - CreateUser(organizationId string, user *gocloak.User) (string, error) - GetUser(organizationId string, userAccountId string) (*gocloak.User, error) - GetUsers(organizationId string) ([]*gocloak.User, error) - DeleteUser(organizationId string, userAccountId string) error - UpdateUser(organizationId string, user *gocloak.User) error - JoinGroup(organizationId string, userId string, groupName string) error - LeaveGroup(organizationId string, userId string, groupName string) error + CreateUser(ctx context.Context, organizationId string, user *gocloak.User) (string, error) + GetUser(ctx context.Context, organizationId string, userAccountId string) (*gocloak.User, error) + GetUsers(ctx context.Context, organizationId string) ([]*gocloak.User, error) + DeleteUser(ctx context.Context, organizationId string, userAccountId string) error + UpdateUser(ctx context.Context, organizationId string, user *gocloak.User) error + JoinGroup(ctx context.Context, organizationId string, userId string, groupName string) error + LeaveGroup(ctx context.Context, organizationId string, userId string, groupName string) error - EnsureClientRoleWithClientName(organizationId string, clientName string, roleName string) error - DeleteClientRoleWithClientName(organizationId string, clientName string, roleName string) error + EnsureClientRoleWithClientName(ctx context.Context, organizationId string, clientName string, roleName string) error + DeleteClientRoleWithClientName(ctx context.Context, organizationId string, clientName string, roleName string) error - AssignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error - UnassignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error + AssignClientRoleToUser(ctx context.Context, organizationId string, userId string, clientName string, roleName string) error + UnassignClientRoleToUser(ctx context.Context, organizationId string, userId string, clientName string, roleName string) error - VerifyAccessToken(token string, organizationId string) (bool, error) - GetSessions(userId string, organizationId string) (*[]string, error) + VerifyAccessToken(ctx context.Context, token string, organizationId string) (bool, error) + GetSessions(ctx context.Context, userId string, organizationId string) (*[]string, error) } type Keycloak struct { config *Config @@ -51,22 +51,20 @@ type Keycloak struct { adminCliToken *gocloak.JWT } -func (k *Keycloak) LoginAdmin(accountId string, password string) (*model.User, error) { - ctx := context.Background() - JWTToken, err := k.client.LoginAdmin(ctx, accountId, password, DefaultMasterRealm) +func (k *Keycloak) LoginAdmin(ctx context.Context, accountId string, password string) (*model.User, error) { + JWTToken, err := k.client.LoginAdmin(context.Background(), accountId, password, DefaultMasterRealm) if err != nil { - log.Error(err) + log.Error(ctx, err) return nil, err } return &model.User{Token: JWTToken.AccessToken}, nil } -func (k *Keycloak) Login(accountId string, password string, organizationId string) (*model.User, error) { - ctx := context.Background() - JWTToken, err := k.client.Login(ctx, DefaultClientID, k.config.ClientSecret, organizationId, accountId, password) +func (k *Keycloak) Login(ctx context.Context, accountId string, password string, organizationId string) (*model.User, error) { + JWTToken, err := k.client.Login(context.Background(), DefaultClientID, k.config.ClientSecret, organizationId, accountId, password) if err != nil { - log.Error(err) + log.Error(ctx, err) return nil, err } return &model.User{Token: JWTToken.AccessToken}, nil @@ -77,16 +75,15 @@ func New(config *Config) IKeycloak { config: config, } } -func (k *Keycloak) InitializeKeycloak() error { +func (k *Keycloak) InitializeKeycloak(ctx context.Context) error { k.client = gocloak.NewClient(k.config.Address) - ctx := context.Background() restyClient := k.client.RestyClient() restyClient.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) var token *gocloak.JWT var err error - if token, err = k.client.LoginAdmin(ctx, k.config.AdminId, k.config.AdminPassword, DefaultMasterRealm); err != nil { - log.Fatal(err) + if token, err = k.client.LoginAdmin(context.Background(), k.config.AdminId, k.config.AdminPassword, DefaultMasterRealm); err != nil { + log.Fatal(ctx, err) return err } k.adminCliToken = token @@ -98,18 +95,18 @@ func (k *Keycloak) InitializeKeycloak() error { group, err := k.ensureGroupByName(ctx, token, DefaultMasterRealm, "tks-admin@master") if err != nil { - log.Fatal(err) + log.Fatal(ctx, err) return err } user, err := k.ensureUserByName(ctx, token, DefaultMasterRealm, k.config.AdminId, k.config.AdminPassword) if err != nil { - log.Fatal(err) + log.Fatal(ctx, err) return err } if err := k.addUserToGroup(ctx, token, DefaultMasterRealm, *user.ID, *group.ID); err != nil { - log.Fatal(err) + log.Fatal(ctx, err) return err } @@ -117,27 +114,27 @@ func (k *Keycloak) InitializeKeycloak() error { redirectURIs = append(redirectURIs, viper.GetString("external-address")+"/*") tksClient, err := k.ensureClient(ctx, token, DefaultMasterRealm, DefaultClientID, k.config.ClientSecret, &redirectURIs) if err != nil { - log.Fatal(err) + log.Fatal(ctx, err) return err } // for _, defaultMapper := range defaultProtocolTksMapper { if err := k.ensureClientProtocolMappers(ctx, token, DefaultMasterRealm, *tksClient.ClientID, "openid", defaultMapper); err != nil { - log.Fatal(err) + log.Fatal(ctx, err) return err } } adminCliClient, err := k.ensureClient(ctx, token, DefaultMasterRealm, AdminCliClientID, k.config.ClientSecret, nil) if err != nil { - log.Fatal(err) + log.Fatal(ctx, err) return err } for _, defaultMapper := range defaultProtocolTksMapper { if err := k.ensureClientProtocolMappers(ctx, token, DefaultMasterRealm, *adminCliClient.ClientID, "openid", defaultMapper); err != nil { - log.Fatal(err) + log.Fatal(ctx, err) return err } } @@ -147,11 +144,11 @@ func (k *Keycloak) InitializeKeycloak() error { go func() { for { if token, err := k.client.RefreshToken(context.Background(), k.adminCliToken.RefreshToken, AdminCliClientID, k.config.ClientSecret, DefaultMasterRealm); err != nil { - log.Errorf("[Refresh]error is :%s(%T)", err.Error(), err) - log.Info("[Do Keycloak Admin CLI Login]") + log.Errorf(ctx, "[Refresh]error is :%s(%T)", err.Error(), err) + log.Info(ctx, "[Do Keycloak Admin CLI Login]") k.adminCliToken, err = k.client.LoginAdmin(ctx, k.config.AdminId, k.config.AdminPassword, DefaultMasterRealm) if err != nil { - log.Errorf("[LoginAdmin]error is :%s(%T)", err.Error(), err) + log.Errorf(ctx, "[LoginAdmin]error is :%s(%T)", err.Error(), err) } } else { k.adminCliToken = token @@ -163,12 +160,11 @@ func (k *Keycloak) InitializeKeycloak() error { return nil } -func (k *Keycloak) CreateRealm(organizationId string) (string, error) { +func (k *Keycloak) CreateRealm(ctx context.Context, organizationId string) (string, error) { //TODO implement me - ctx := context.Background() token := k.adminCliToken - realmUUID, err := k.client.CreateRealm(ctx, token.AccessToken, defaultRealmSetting(organizationId)) + realmUUID, err := k.client.CreateRealm(context.Background(), token.AccessToken, defaultRealmSetting(organizationId)) if err != nil { return "", err } @@ -177,7 +173,7 @@ func (k *Keycloak) CreateRealm(organizationId string) (string, error) { redirectURIs = append(redirectURIs, viper.GetString("external-address")+"/*") clientUUID, err := k.createDefaultClient(context.Background(), token.AccessToken, organizationId, DefaultClientID, k.config.ClientSecret, &redirectURIs) if err != nil { - log.Error(err, "createDefaultClient") + log.Error(ctx, err, "createDefaultClient") return "", err } @@ -192,7 +188,7 @@ func (k *Keycloak) CreateRealm(organizationId string) (string, error) { "userinfo.token.claim": "false", } } - if _, err := k.createClientProtocolMapper(ctx, token.AccessToken, organizationId, clientUUID, defaultMapper); err != nil { + if _, err := k.createClientProtocolMapper(context.Background(), token.AccessToken, organizationId, clientUUID, defaultMapper); err != nil { return "", err } } @@ -249,10 +245,9 @@ func (k *Keycloak) CreateRealm(organizationId string) (string, error) { return realmUUID, nil } -func (k *Keycloak) GetRealm(organizationId string) (*model.Organization, error) { - ctx := context.Background() +func (k *Keycloak) GetRealm(ctx context.Context, organizationId string) (*model.Organization, error) { token := k.adminCliToken - realm, err := k.client.GetRealm(ctx, token.AccessToken, organizationId) + realm, err := k.client.GetRealm(context.Background(), token.AccessToken, organizationId) if err != nil { return nil, err } @@ -260,10 +255,9 @@ func (k *Keycloak) GetRealm(organizationId string) (*model.Organization, error) return k.reflectOrganization(*realm), nil } -func (k *Keycloak) GetRealms() ([]*model.Organization, error) { - ctx := context.Background() +func (k *Keycloak) GetRealms(ctx context.Context) ([]*model.Organization, error) { token := k.adminCliToken - realms, err := k.client.GetRealms(ctx, token.AccessToken) + realms, err := k.client.GetRealms(context.Background(), token.AccessToken) if err != nil { return nil, err } @@ -275,21 +269,19 @@ func (k *Keycloak) GetRealms() ([]*model.Organization, error) { return organization, nil } -func (k *Keycloak) UpdateRealm(organizationId string, organizationConfig model.Organization) error { - ctx := context.Background() +func (k *Keycloak) UpdateRealm(ctx context.Context, organizationId string, organizationConfig model.Organization) error { token := k.adminCliToken realm := k.reflectRealmRepresentation(organizationConfig) - err := k.client.UpdateRealm(ctx, token.AccessToken, *realm) + err := k.client.UpdateRealm(context.Background(), token.AccessToken, *realm) if err != nil { return err } return nil } -func (k *Keycloak) DeleteRealm(organizationId string) error { - ctx := context.Background() +func (k *Keycloak) DeleteRealm(ctx context.Context, organizationId string) error { token := k.adminCliToken - err := k.client.DeleteRealm(ctx, token.AccessToken, organizationId) + err := k.client.DeleteRealm(context.Background(), token.AccessToken, organizationId) if err != nil { return err } @@ -297,11 +289,10 @@ func (k *Keycloak) DeleteRealm(organizationId string) error { return nil } -func (k *Keycloak) CreateUser(organizationId string, user *gocloak.User) (string, error) { - ctx := context.Background() +func (k *Keycloak) CreateUser(ctx context.Context, organizationId string, user *gocloak.User) (string, error) { token := k.adminCliToken user.Enabled = gocloak.BoolP(true) - uuid, err := k.client.CreateUser(ctx, token.AccessToken, organizationId, *user) + uuid, err := k.client.CreateUser(context.Background(), token.AccessToken, organizationId, *user) if err != nil { return "", err } @@ -309,12 +300,11 @@ func (k *Keycloak) CreateUser(organizationId string, user *gocloak.User) (string return uuid, nil } -func (k *Keycloak) GetUser(organizationId string, accountId string) (*gocloak.User, error) { - ctx := context.Background() +func (k *Keycloak) GetUser(ctx context.Context, organizationId string, accountId string) (*gocloak.User, error) { token := k.adminCliToken //TODO: this is rely on the fact that username is the same as userAccountId and unique - users, err := k.client.GetUsers(ctx, token.AccessToken, organizationId, gocloak.GetUsersParams{ + users, err := k.client.GetUsers(context.Background(), token.AccessToken, organizationId, gocloak.GetUsersParams{ Username: gocloak.StringP(accountId), }) if err != nil { @@ -328,11 +318,10 @@ func (k *Keycloak) GetUser(organizationId string, accountId string) (*gocloak.Us return users[0], nil } -func (k *Keycloak) GetUsers(organizationId string) ([]*gocloak.User, error) { - ctx := context.Background() +func (k *Keycloak) GetUsers(ctx context.Context, organizationId string) ([]*gocloak.User, error) { token := k.adminCliToken //TODO: this is rely on the fact that username is the same as userAccountId and unique - users, err := k.client.GetUsers(ctx, token.AccessToken, organizationId, gocloak.GetUsersParams{}) + users, err := k.client.GetUsers(context.Background(), token.AccessToken, organizationId, gocloak.GetUsersParams{}) if err != nil { return nil, err } @@ -344,11 +333,10 @@ func (k *Keycloak) GetUsers(organizationId string) ([]*gocloak.User, error) { return users, nil } -func (k *Keycloak) UpdateUser(organizationId string, user *gocloak.User) error { - ctx := context.Background() +func (k *Keycloak) UpdateUser(ctx context.Context, organizationId string, user *gocloak.User) error { token := k.adminCliToken user.Enabled = gocloak.BoolP(true) - err := k.client.UpdateUser(ctx, token.AccessToken, organizationId, *user) + err := k.client.UpdateUser(context.Background(), token.AccessToken, organizationId, *user) if err != nil { return err } @@ -356,24 +344,22 @@ func (k *Keycloak) UpdateUser(organizationId string, user *gocloak.User) error { return nil } -func (k *Keycloak) DeleteUser(organizationId string, userAccountId string) error { - ctx := context.Background() +func (k *Keycloak) DeleteUser(ctx context.Context, organizationId string, userAccountId string) error { token := k.adminCliToken - u, err := k.GetUser(organizationId, userAccountId) + u, err := k.GetUser(ctx, organizationId, userAccountId) if err != nil { - log.Errorf("error is :%s(%T)", err.Error(), err) + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) return httpErrors.NewNotFoundError(err, "", "") } - err = k.client.DeleteUser(ctx, token.AccessToken, organizationId, *u.ID) + err = k.client.DeleteUser(context.Background(), token.AccessToken, organizationId, *u.ID) if err != nil { return err } return nil } -func (k *Keycloak) VerifyAccessToken(token string, organizationId string) (bool, error) { - ctx := context.Background() - rptResult, err := k.client.RetrospectToken(ctx, token, DefaultClientID, k.config.ClientSecret, organizationId) +func (k *Keycloak) VerifyAccessToken(ctx context.Context, token string, organizationId string) (bool, error) { + rptResult, err := k.client.RetrospectToken(context.Background(), token, DefaultClientID, k.config.ClientSecret, organizationId) if err != nil { return false, err } @@ -384,12 +370,11 @@ func (k *Keycloak) VerifyAccessToken(token string, organizationId string) (bool, return true, nil } -func (k *Keycloak) GetSessions(userId string, organizationId string) (*[]string, error) { - ctx := context.Background() +func (k *Keycloak) GetSessions(ctx context.Context, userId string, organizationId string) (*[]string, error) { token := k.adminCliToken - sessions, err := k.client.GetUserSessions(ctx, token.AccessToken, organizationId, userId) + sessions, err := k.client.GetUserSessions(context.Background(), token.AccessToken, organizationId, userId) if err != nil { - log.Errorf("error is :%s(%T)", err.Error(), err) + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) return nil, err } @@ -401,10 +386,9 @@ func (k *Keycloak) GetSessions(userId string, organizationId string) (*[]string, return &sessionIds, nil } -func (k *Keycloak) Logout(sessionId string, organizationId string) error { - ctx := context.Background() +func (k *Keycloak) Logout(ctx context.Context, sessionId string, organizationId string) error { token := k.adminCliToken - err := k.client.LogoutUserSession(ctx, token.AccessToken, organizationId, sessionId) + err := k.client.LogoutUserSession(context.Background(), token.AccessToken, organizationId, sessionId) if err != nil { return err } @@ -412,57 +396,54 @@ func (k *Keycloak) Logout(sessionId string, organizationId string) error { return nil } -func (k *Keycloak) JoinGroup(organizationId string, userId string, groupName string) error { - ctx := context.Background() +func (k *Keycloak) JoinGroup(ctx context.Context, organizationId string, userId string, groupName string) error { token := k.adminCliToken - groups, err := k.client.GetGroups(ctx, token.AccessToken, organizationId, gocloak.GetGroupsParams{ + groups, err := k.client.GetGroups(context.Background(), token.AccessToken, organizationId, gocloak.GetGroupsParams{ Search: &groupName, }) if err != nil { - log.Error(err) + log.Error(ctx, err) return httpErrors.NewInternalServerError(err, "", "") } if len(groups) == 0 { return httpErrors.NewNotFoundError(fmt.Errorf("group not found"), "", "") } if err := k.client.AddUserToGroup(ctx, token.AccessToken, organizationId, userId, *groups[0].ID); err != nil { - log.Error(err) + log.Error(ctx, err) return httpErrors.NewInternalServerError(err, "", "") } return nil } -func (k *Keycloak) LeaveGroup(organizationId string, userId string, groupName string) error { - ctx := context.Background() +func (k *Keycloak) LeaveGroup(ctx context.Context, organizationId string, userId string, groupName string) error { token := k.adminCliToken - groups, err := k.client.GetGroups(ctx, token.AccessToken, organizationId, gocloak.GetGroupsParams{ + groups, err := k.client.GetGroups(context.Background(), token.AccessToken, organizationId, gocloak.GetGroupsParams{ Search: &groupName, }) if err != nil { - log.Error(err) + log.Error(ctx, err) return httpErrors.NewInternalServerError(err, "", "") } if len(groups) == 0 { return httpErrors.NewNotFoundError(fmt.Errorf("group not found"), "", "") } - if err := k.client.DeleteUserFromGroup(ctx, token.AccessToken, organizationId, userId, *groups[0].ID); err != nil { - log.Error(err) + if err := k.client.DeleteUserFromGroup(context.Background(), token.AccessToken, organizationId, userId, *groups[0].ID); err != nil { + log.Error(ctx, err) return httpErrors.NewInternalServerError(err, "", "") } return nil } -func (k *Keycloak) EnsureClientRoleWithClientName(organizationId string, clientName string, roleName string) error { - ctx := context.Background() +func (k *Keycloak) EnsureClientRoleWithClientName(ctx context.Context, organizationId string, clientName string, roleName string) error { token := k.adminCliToken - clients, err := k.client.GetClients(ctx, token.AccessToken, organizationId, gocloak.GetClientsParams{ + clients, err := k.client.GetClients(context.Background(), token.AccessToken, organizationId, gocloak.GetClientsParams{ ClientID: &clientName, }) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) return err } @@ -472,126 +453,123 @@ func (k *Keycloak) EnsureClientRoleWithClientName(organizationId string, clientN Name: gocloak.StringP(roleName), } - _, err = k.client.CreateClientRole(ctx, token.AccessToken, organizationId, *targetClient.ID, role) + _, err = k.client.CreateClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, role) if err != nil { - log.Error("Creating Client Role is failed", err) + log.Error(ctx, "Creating Client Role is failed", err) return err } return nil } -func (k *Keycloak) DeleteClientRoleWithClientName(organizationId string, clientName string, roleName string) error { - ctx := context.Background() +func (k *Keycloak) DeleteClientRoleWithClientName(ctx context.Context, organizationId string, clientName string, roleName string) error { token := k.adminCliToken - clients, err := k.client.GetClients(ctx, token.AccessToken, organizationId, gocloak.GetClientsParams{ + clients, err := k.client.GetClients(context.Background(), token.AccessToken, organizationId, gocloak.GetClientsParams{ ClientID: &clientName, }) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) return err } targetClient := clients[0] - roles, err := k.client.GetClientRoles(ctx, token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ + roles, err := k.client.GetClientRoles(context.Background(), token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ Search: &roleName, }) if err != nil { - log.Error("Getting Client Role is failed", err) + log.Error(ctx, "Getting Client Role is failed", err) return err } if len(roles) == 0 { - log.Warn("Client Role not found", roleName) + log.Warn(ctx, "Client Role not found", roleName) return nil } - err = k.client.DeleteClientRole(ctx, token.AccessToken, organizationId, *targetClient.ID, *roles[0].ID) + err = k.client.DeleteClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, *roles[0].ID) if err != nil { - log.Error("Deleting Client Role is failed", err) + log.Error(ctx, "Deleting Client Role is failed", err) return err } return nil } -func (k *Keycloak) AssignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error { - ctx := context.Background() +func (k *Keycloak) AssignClientRoleToUser(ctx context.Context, organizationId string, userId string, clientName string, roleName string) error { token := k.adminCliToken - clients, err := k.client.GetClients(ctx, token.AccessToken, organizationId, gocloak.GetClientsParams{ + clients, err := k.client.GetClients(context.Background(), token.AccessToken, organizationId, gocloak.GetClientsParams{ ClientID: &clientName, }) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) return err } if len(clients) == 0 { - log.Warn("Client not found", clientName) + log.Warn(ctx, "Client not found", clientName) return nil } targetClient := clients[0] - roles, err := k.client.GetClientRoles(ctx, token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ + roles, err := k.client.GetClientRoles(context.Background(), token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ Search: &roleName, }) if err != nil { - log.Error("Getting Client Role is failed", err) + log.Error(ctx, "Getting Client Role is failed", err) return err } if len(roles) == 0 { - log.Warn("Client Role not found", roleName) + log.Warn(ctx, "Client Role not found", roleName) return nil } - err = k.client.AddClientRolesToUser(ctx, token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) + err = k.client.AddClientRolesToUser(context.Background(), token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) if err != nil { - log.Error("Assigning Client Role to User is failed", err) + log.Error(ctx, "Assigning Client Role to User is failed", err) return err } return nil } -func (k *Keycloak) UnassignClientRoleToUser(organizationId string, userId string, clientName string, roleName string) error { - ctx := context.Background() +func (k *Keycloak) UnassignClientRoleToUser(ctx context.Context, organizationId string, userId string, clientName string, roleName string) error { token := k.adminCliToken - clients, err := k.client.GetClients(ctx, token.AccessToken, organizationId, gocloak.GetClientsParams{ + clients, err := k.client.GetClients(context.Background(), token.AccessToken, organizationId, gocloak.GetClientsParams{ ClientID: &clientName, }) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) return err } if len(clients) == 0 { - log.Warn("Client not found", clientName) + log.Warn(ctx, "Client not found", clientName) return nil } targetClient := clients[0] - roles, err := k.client.GetClientRoles(ctx, token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ + roles, err := k.client.GetClientRoles(context.Background(), token.AccessToken, organizationId, *targetClient.ID, gocloak.GetRoleParams{ Search: &roleName, }) if err != nil { - log.Error("Getting Client Role is failed", err) + log.Error(ctx, "Getting Client Role is failed", err) return err } if len(roles) == 0 { - log.Warn("Client Role not found", roleName) + log.Warn(ctx, "Client Role not found", roleName) return nil } - err = k.client.DeleteClientRolesFromUser(ctx, token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) + err = k.client.DeleteClientRolesFromUser(context.Background(), token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) if err != nil { - log.Error("Unassigning Client Role to User is failed", err) + log.Error(ctx, "Unassigning Client Role to User is failed", err) return err } @@ -601,69 +579,69 @@ func (k *Keycloak) UnassignClientRoleToUser(organizationId string, userId string func (k *Keycloak) ensureClientProtocolMappers(ctx context.Context, token *gocloak.JWT, realm string, clientId string, scope string, mapper gocloak.ProtocolMapperRepresentation) error { //TODO: Check current logic(if exist, do nothing) is fine - clients, err := k.client.GetClients(ctx, token.AccessToken, realm, gocloak.GetClientsParams{ + clients, err := k.client.GetClients(context.Background(), token.AccessToken, realm, gocloak.GetClientsParams{ ClientID: &clientId, }) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) return err } if clients[0].ProtocolMappers != nil { for _, protocolMapper := range *clients[0].ProtocolMappers { if *protocolMapper.Name == *mapper.Name { - log.Warn("Protocol Mapper already exists", *protocolMapper.Name) + log.Warn(ctx, "Protocol Mapper already exists", *protocolMapper.Name) return nil } } } - if _, err := k.client.CreateClientProtocolMapper(ctx, token.AccessToken, realm, *clients[0].ID, mapper); err != nil { - log.Error("Creating Client Protocol Mapper is failed", err) + if _, err := k.client.CreateClientProtocolMapper(context.Background(), token.AccessToken, realm, *clients[0].ID, mapper); err != nil { + log.Error(ctx, "Creating Client Protocol Mapper is failed", err) return err } return nil } func (k *Keycloak) ensureClient(ctx context.Context, token *gocloak.JWT, realm string, clientId string, secret string, redirectURIs *[]string) (*gocloak.Client, error) { - keycloakClient, err := k.client.GetClients(ctx, token.AccessToken, realm, gocloak.GetClientsParams{ + keycloakClient, err := k.client.GetClients(context.Background(), token.AccessToken, realm, gocloak.GetClientsParams{ ClientID: &clientId, }) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) } if len(keycloakClient) == 0 { - _, err = k.client.CreateClient(ctx, token.AccessToken, realm, gocloak.Client{ + _, err = k.client.CreateClient(context.Background(), token.AccessToken, realm, gocloak.Client{ ClientID: gocloak.StringP(clientId), Enabled: gocloak.BoolP(true), DirectAccessGrantsEnabled: gocloak.BoolP(true), RedirectURIs: redirectURIs, }) if err != nil { - log.Error("Creating Client is failed", err) + log.Error(ctx, "Creating Client is failed", err) } - keycloakClient, err = k.client.GetClients(ctx, token.AccessToken, realm, gocloak.GetClientsParams{ + keycloakClient, err = k.client.GetClients(context.Background(), token.AccessToken, realm, gocloak.GetClientsParams{ ClientID: &clientId, }) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) } } else { - err = k.client.UpdateClient(ctx, token.AccessToken, realm, gocloak.Client{ + err = k.client.UpdateClient(context.Background(), token.AccessToken, realm, gocloak.Client{ ID: keycloakClient[0].ID, Enabled: gocloak.BoolP(true), DirectAccessGrantsEnabled: gocloak.BoolP(true), RedirectURIs: redirectURIs, }) if err != nil { - log.Error("Update Client is failed", err) + log.Error(ctx, "Update Client is failed", err) } } if keycloakClient[0].Secret == nil || *keycloakClient[0].Secret != secret { - log.Warn("Client secret is not matched. Overwrite it") + log.Warn(ctx, "Client secret is not matched. Overwrite it") keycloakClient[0].Secret = gocloak.StringP(secret) - if err := k.client.UpdateClient(ctx, token.AccessToken, realm, *keycloakClient[0]); err != nil { - log.Error("Updating Client is failed", err) + if err := k.client.UpdateClient(context.Background(), token.AccessToken, realm, *keycloakClient[0]); err != nil { + log.Error(ctx, "Updating Client is failed", err) } } @@ -671,9 +649,9 @@ func (k *Keycloak) ensureClient(ctx context.Context, token *gocloak.JWT, realm s } func (k *Keycloak) addUserToGroup(ctx context.Context, token *gocloak.JWT, realm string, userID string, groupID string) error { - groups, err := k.client.GetUserGroups(ctx, token.AccessToken, realm, userID, gocloak.GetGroupsParams{}) + groups, err := k.client.GetUserGroups(context.Background(), token.AccessToken, realm, userID, gocloak.GetGroupsParams{}) if err != nil { - log.Error("Getting User Groups is failed") + log.Error(ctx, "Getting User Groups is failed") } for _, group := range groups { if *group.ID == groupID { @@ -681,15 +659,15 @@ func (k *Keycloak) addUserToGroup(ctx context.Context, token *gocloak.JWT, realm } } - err = k.client.AddUserToGroup(ctx, token.AccessToken, realm, userID, groupID) + err = k.client.AddUserToGroup(context.Background(), token.AccessToken, realm, userID, groupID) if err != nil { - log.Error("Assigning User to Group is failed", err) + log.Error(ctx, "Assigning User to Group is failed", err) } return err } func (k *Keycloak) ensureUserByName(ctx context.Context, token *gocloak.JWT, realm string, userName string, password string) (*gocloak.User, error) { - user, err := k.ensureUser(ctx, token, realm, userName, password) + user, err := k.ensureUser(context.Background(), token, realm, userName, password) return user, err } @@ -697,9 +675,9 @@ func (k *Keycloak) ensureUser(ctx context.Context, token *gocloak.JWT, realm str searchParam := gocloak.GetUsersParams{ Search: gocloak.StringP(userName), } - users, err := k.client.GetUsers(ctx, token.AccessToken, realm, searchParam) + users, err := k.client.GetUsers(context.Background(), token.AccessToken, realm, searchParam) if err != nil { - log.Error("Getting User is failed", err) + log.Error(ctx, "Getting User is failed", err) } if len(users) == 0 { user := gocloak.User{ @@ -713,14 +691,14 @@ func (k *Keycloak) ensureUser(ctx context.Context, token *gocloak.JWT, realm str }, }, } - _, err = k.client.CreateUser(ctx, token.AccessToken, realm, user) + _, err = k.client.CreateUser(context.Background(), token.AccessToken, realm, user) if err != nil { - log.Error("Creating User is failed", err) + log.Error(ctx, "Creating User is failed", err) } - users, err = k.client.GetUsers(ctx, token.AccessToken, realm, searchParam) + users, err = k.client.GetUsers(context.Background(), token.AccessToken, realm, searchParam) if err != nil { - log.Error("Getting User is failed", err) + log.Error(ctx, "Getting User is failed", err) } } @@ -728,7 +706,7 @@ func (k *Keycloak) ensureUser(ctx context.Context, token *gocloak.JWT, realm str } func (k *Keycloak) ensureGroupByName(ctx context.Context, token *gocloak.JWT, realm string, groupName string, groupParam ...gocloak.Group) (*gocloak.Group, error) { - group, err := k.ensureGroup(ctx, token, realm, groupName) + group, err := k.ensureGroup(context.Background(), token, realm, groupName) return group, err } @@ -740,27 +718,27 @@ func (k *Keycloak) ensureGroup(ctx context.Context, token *gocloak.JWT, realm st Name: gocloak.StringP(groupName), } - groups, err := k.client.GetGroups(ctx, token.AccessToken, realm, searchParam) + groups, err := k.client.GetGroups(context.Background(), token.AccessToken, realm, searchParam) if err != nil { - log.Error("Getting Group is failed", err) + log.Error(ctx, "Getting Group is failed", err) } if len(groups) == 0 { - _, err = k.client.CreateGroup(ctx, token.AccessToken, realm, groupParam) + _, err = k.client.CreateGroup(context.Background(), token.AccessToken, realm, groupParam) if err != nil { - log.Error("Creating Group is failed", err) + log.Error(ctx, "Creating Group is failed", err) } - groups, err = k.client.GetGroups(ctx, token.AccessToken, realm, searchParam) + groups, err = k.client.GetGroups(context.Background(), token.AccessToken, realm, searchParam) if err != nil { - log.Error("Getting Group is failed", err) + log.Error(ctx, "Getting Group is failed", err) } } return groups[0], err } func (k *Keycloak) createGroup(ctx context.Context, accessToken string, realm string, groupName string) (string, error) { - id, err := k.client.CreateGroup(ctx, accessToken, realm, gocloak.Group{Name: gocloak.StringP(groupName)}) + id, err := k.client.CreateGroup(context.Background(), accessToken, realm, gocloak.Group{Name: gocloak.StringP(groupName)}) if err != nil { - log.Error("Creating Group is failed", err) + log.Error(ctx, "Creating Group is failed", err) return "", err } return id, nil @@ -768,9 +746,9 @@ func (k *Keycloak) createGroup(ctx context.Context, accessToken string, realm st func (k *Keycloak) getClientByClientId(ctx context.Context, accessToken string, realm string, clientId string) ( string, error) { - clients, err := k.client.GetClients(ctx, accessToken, realm, gocloak.GetClientsParams{ClientID: &clientId}) + clients, err := k.client.GetClients(context.Background(), accessToken, realm, gocloak.GetClientsParams{ClientID: &clientId}) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) return "", err } return *clients[0].ID, nil @@ -778,9 +756,9 @@ func (k *Keycloak) getClientByClientId(ctx context.Context, accessToken string, func (k *Keycloak) createClientRole(ctx context.Context, accessToken string, realm string, clientUuid string, roleName string) (string, error) { - id, err := k.client.CreateClientRole(ctx, accessToken, realm, clientUuid, gocloak.Role{Name: gocloak.StringP(roleName)}) + id, err := k.client.CreateClientRole(context.Background(), accessToken, realm, clientUuid, gocloak.Role{Name: gocloak.StringP(roleName)}) if err != nil { - log.Error("Creating Client Role is failed", err) + log.Error(ctx, "Creating Client Role is failed", err) return "", err } return id, nil @@ -788,9 +766,9 @@ func (k *Keycloak) createClientRole(ctx context.Context, accessToken string, rea func (k *Keycloak) getClientRole(ctx context.Context, accessToken string, realm string, clientUuid string, roleName string) (*gocloak.Role, error) { - role, err := k.client.GetClientRole(ctx, accessToken, realm, clientUuid, roleName) + role, err := k.client.GetClientRole(context.Background(), accessToken, realm, clientUuid, roleName) if err != nil { - log.Error("Getting Client Role is failed", err) + log.Error(ctx, "Getting Client Role is failed", err) return nil, err } return role, nil @@ -798,9 +776,9 @@ func (k *Keycloak) getClientRole(ctx context.Context, accessToken string, realm func (k *Keycloak) addClientRoleToGroup(ctx context.Context, accessToken string, realm string, clientUuid string, groupUuid string, role *gocloak.Role) error { - err := k.client.AddClientRolesToGroup(ctx, accessToken, realm, clientUuid, groupUuid, []gocloak.Role{*role}) + err := k.client.AddClientRolesToGroup(context.Background(), accessToken, realm, clientUuid, groupUuid, []gocloak.Role{*role}) if err != nil { - log.Error("Adding Client Role to Group is failed", err) + log.Error(ctx, "Adding Client Role to Group is failed", err) return err } return nil @@ -808,9 +786,9 @@ func (k *Keycloak) addClientRoleToGroup(ctx context.Context, accessToken string, func (k *Keycloak) createClientProtocolMapper(ctx context.Context, accessToken string, realm string, id string, mapper gocloak.ProtocolMapperRepresentation) (string, error) { - id, err := k.client.CreateClientProtocolMapper(ctx, accessToken, realm, id, mapper) + id, err := k.client.CreateClientProtocolMapper(context.Background(), accessToken, realm, id, mapper) if err != nil { - log.Error("Creating Client Protocol Mapper is failed", err) + log.Error(ctx, "Creating Client Protocol Mapper is failed", err) return "", err } @@ -819,7 +797,7 @@ func (k *Keycloak) createClientProtocolMapper(ctx context.Context, accessToken s func (k *Keycloak) createDefaultClient(ctx context.Context, accessToken string, realm string, clientId string, clientSecret string, redirectURIs *[]string) (string, error) { - id, err := k.client.CreateClient(ctx, accessToken, realm, gocloak.Client{ + id, err := k.client.CreateClient(context.Background(), accessToken, realm, gocloak.Client{ ClientID: gocloak.StringP(clientId), DirectAccessGrantsEnabled: gocloak.BoolP(true), Enabled: gocloak.BoolP(true), @@ -827,16 +805,16 @@ func (k *Keycloak) createDefaultClient(ctx context.Context, accessToken string, }) if err != nil { - log.Error("Creating Client is failed", err) + log.Error(ctx, "Creating Client is failed", err) return "", err } - client, err := k.client.GetClient(ctx, accessToken, realm, id) + client, err := k.client.GetClient(context.Background(), accessToken, realm, id) if err != nil { - log.Error("Getting Client is failed", err) + log.Error(ctx, "Getting Client is failed", err) return "", err } client.Secret = gocloak.StringP(clientSecret) - err = k.client.UpdateClient(ctx, accessToken, realm, *client) + err = k.client.UpdateClient(context.Background(), accessToken, realm, *client) if err != nil { return "", err } diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index 2af15b06..d709134b 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -22,30 +22,30 @@ import ( "github.com/openinfradev/tks-api/pkg/log" ) -func getAdminConfig() (*rest.Config, error) { +func getAdminConfig(ctx context.Context) (*rest.Config, error) { kubeconfigPath := viper.GetString("kubeconfig-path") if kubeconfigPath == "" { - log.Info("Use in-cluster config") + log.Info(ctx, "Use in-cluster config") config, err := rest.InClusterConfig() if err != nil { - log.Error("Failed to load incluster kubeconfig") + log.Error(ctx, "Failed to load incluster kubeconfig") return nil, err } return config, nil } else { config, err := clientcmd.BuildConfigFromFlags("", viper.GetString("kubeconfig-path")) if err != nil { - log.Error("Failed to local kubeconfig") + log.Error(ctx, "Failed to local kubeconfig") return nil, err } return config, nil } } -func GetClientAdminCluster() (*kubernetes.Clientset, error) { - config, err := getAdminConfig() +func GetClientAdminCluster(ctx context.Context) (*kubernetes.Clientset, error) { + config, err := getAdminConfig(ctx) if err != nil { - log.Error("Failed to load kubeconfig") + log.Error(ctx, "Failed to load kubeconfig") return nil, err } @@ -57,15 +57,15 @@ func GetClientAdminCluster() (*kubernetes.Clientset, error) { return clientset, nil } -func GetAwsSecret() (awsAccessKeyId string, awsSecretAccessKey string, err error) { - clientset, err := GetClientAdminCluster() +func GetAwsSecret(ctx context.Context) (awsAccessKeyId string, awsSecretAccessKey string, err error) { + clientset, err := GetClientAdminCluster(ctx) if err != nil { return "", "", err } secrets, err := clientset.CoreV1().Secrets("argo").Get(context.TODO(), "awsconfig-secret", metav1.GetOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", "", err } @@ -81,15 +81,15 @@ func GetAwsSecret() (awsAccessKeyId string, awsSecretAccessKey string, err error return } -func GetAwsAccountIdSecret() (awsAccountId string, err error) { - clientset, err := GetClientAdminCluster() +func GetAwsAccountIdSecret(ctx context.Context) (awsAccountId string, err error) { + clientset, err := GetClientAdminCluster(ctx) if err != nil { return "", err } secrets, err := clientset.CoreV1().Secrets("argo").Get(context.TODO(), "tks-aws-user", metav1.GetOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", err } @@ -97,36 +97,36 @@ func GetAwsAccountIdSecret() (awsAccountId string, err error) { return } -func GetKubeConfig(clusterId string) ([]byte, error) { - clientset, err := GetClientAdminCluster() +func GetKubeConfig(ctx context.Context, clusterId string) ([]byte, error) { + clientset, err := GetClientAdminCluster(ctx) if err != nil { return nil, err } secrets, err := clientset.CoreV1().Secrets(clusterId).Get(context.TODO(), clusterId+"-tks-user-kubeconfig", metav1.GetOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return nil, err } return secrets.Data["value"], nil } -func GetClientFromClusterId(clusterId string) (*kubernetes.Clientset, error) { - clientset, err := GetClientAdminCluster() +func GetClientFromClusterId(ctx context.Context, clusterId string) (*kubernetes.Clientset, error) { + clientset, err := GetClientAdminCluster(ctx) if err != nil { return nil, err } secrets, err := clientset.CoreV1().Secrets(clusterId).Get(context.TODO(), clusterId+"-tks-kubeconfig", metav1.GetOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return nil, err } config_user, err := clientcmd.RESTConfigFromKubeConfig(secrets.Data["value"]) if err != nil { - log.Error(err) + log.Error(ctx, err) return nil, err } clientset_user, err := kubernetes.NewForConfig(config_user) @@ -137,64 +137,64 @@ func GetClientFromClusterId(clusterId string) (*kubernetes.Clientset, error) { return clientset_user, nil } -func GetKubernetesVserionByClusterId(clusterId string) (string, error) { - clientset, err := GetClientAdminCluster() +func GetKubernetesVserionByClusterId(ctx context.Context, clusterId string) (string, error) { + clientset, err := GetClientAdminCluster(ctx) if err != nil { return "", err } secrets, err := clientset.CoreV1().Secrets(clusterId).Get(context.TODO(), clusterId+"-tks-kubeconfig", metav1.GetOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", err } config_user, err := clientcmd.RESTConfigFromKubeConfig(secrets.Data["value"]) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", err } discoveryClient, err := discovery.NewDiscoveryClientForConfig(config_user) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", err } information, err := discoveryClient.ServerVersion() if err != nil { - log.Error("Error while fetching server version information", err) + log.Error(ctx, "Error while fetching server version information", err) return "", err } return information.GitVersion, nil } -func GetKubernetesVserion() (string, error) { - config, err := getAdminConfig() +func GetKubernetesVserion(ctx context.Context) (string, error) { + config, err := getAdminConfig(ctx) if err != nil { - log.Error("Failed to load kubeconfig") + log.Error(ctx, "Failed to load kubeconfig") return "", err } discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", err } information, err := discoveryClient.ServerVersion() if err != nil { - log.Error("Error while fetching server version information", err) + log.Error(ctx, "Error while fetching server version information", err) return "", err } return information.GitVersion, nil } -func GetResourceApiVersion(kubeconfig []byte, kind string) (string, error) { +func GetResourceApiVersion(ctx context.Context, kubeconfig []byte, kind string) (string, error) { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", err } @@ -202,7 +202,7 @@ func GetResourceApiVersion(kubeconfig []byte, kind string) (string, error) { apiResourceList, err := clientset.Discovery().ServerPreferredResources() if err != nil { - log.Error(err) + log.Error(ctx, err) return "", err } @@ -217,10 +217,10 @@ func GetResourceApiVersion(kubeconfig []byte, kind string) (string, error) { return "", nil } -func EnsureClusterRole(kubeconfig []byte, projectName string) error { +func EnsureClusterRole(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -233,13 +233,13 @@ func EnsureClusterRole(kubeconfig []byte, projectName string) error { if _, err := clientset.RbacV1().ClusterRoles().Get(context.Background(), projectName+"-"+role, metav1.GetOptions{}); err != nil { _, err = clientset.RbacV1().ClusterRoles().Create(context.Background(), obj, metav1.CreateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } else { _, err = clientset.RbacV1().ClusterRoles().Update(context.Background(), obj, metav1.UpdateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } @@ -248,10 +248,10 @@ func EnsureClusterRole(kubeconfig []byte, projectName string) error { return nil } -func RemoveClusterRole(kubeconfig []byte, projectName string) error { +func RemoveClusterRole(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -260,17 +260,17 @@ func RemoveClusterRole(kubeconfig []byte, projectName string) error { // remove clusterrole object for _, role := range []string{leaderRole, memberRole, viewerRole} { if err := clientset.RbacV1().ClusterRoles().Delete(context.Background(), projectName+"-"+role, metav1.DeleteOptions{}); err != nil { - log.Error(err) + log.Error(ctx, err) } } return nil } -func EnsureClusterRoleBinding(kubeconfig []byte, projectName string) error { +func EnsureClusterRoleBinding(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -281,13 +281,13 @@ func EnsureClusterRoleBinding(kubeconfig []byte, projectName string) error { if _, err = clientset.RbacV1().ClusterRoleBindings().Get(context.Background(), projectName+"-"+role, metav1.GetOptions{}); err != nil { _, err = clientset.RbacV1().ClusterRoleBindings().Create(context.Background(), obj, metav1.CreateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } else { _, err = clientset.RbacV1().ClusterRoleBindings().Update(context.Background(), obj, metav1.UpdateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } @@ -296,10 +296,10 @@ func EnsureClusterRoleBinding(kubeconfig []byte, projectName string) error { return nil } -func RemoveClusterRoleBinding(kubeconfig []byte, projectName string) error { +func RemoveClusterRoleBinding(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -307,17 +307,17 @@ func RemoveClusterRoleBinding(kubeconfig []byte, projectName string) error { for _, role := range []string{leaderRole, memberRole, viewerRole} { if err := clientset.RbacV1().ClusterRoleBindings().Delete(context.Background(), projectName+"-"+role, metav1.DeleteOptions{}); err != nil { - log.Error(err) + log.Error(ctx, err) } } return nil } -func EnsureRoleBinding(kubeconfig []byte, projectName string, namespace string) error { +func EnsureRoleBinding(ctx context.Context, kubeconfig []byte, projectName string, namespace string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -328,13 +328,13 @@ func EnsureRoleBinding(kubeconfig []byte, projectName string, namespace string) if _, err = clientset.RbacV1().RoleBindings(namespace).Get(context.Background(), projectName+"-"+role, metav1.GetOptions{}); err != nil { _, err = clientset.RbacV1().RoleBindings(namespace).Create(context.Background(), obj, metav1.CreateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } else { _, err = clientset.RbacV1().RoleBindings(namespace).Update(context.Background(), obj, metav1.UpdateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } @@ -343,10 +343,10 @@ func EnsureRoleBinding(kubeconfig []byte, projectName string, namespace string) return nil } -func RemoveRoleBinding(kubeconfig []byte, projectName string, namespace string) error { +func RemoveRoleBinding(ctx context.Context, kubeconfig []byte, projectName string, namespace string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -354,7 +354,7 @@ func RemoveRoleBinding(kubeconfig []byte, projectName string, namespace string) for _, role := range []string{leaderRole, memberRole, viewerRole} { if err := clientset.RbacV1().RoleBindings(namespace).Delete(context.Background(), projectName+"-"+role, metav1.DeleteOptions{}); err != nil { - log.Error(err) + log.Error(ctx, err) } } @@ -396,10 +396,10 @@ func getClusterRole(role, objName string) *rbacV1.ClusterRole { return &clusterRole } -func EnsureCommonClusterRole(kubeconfig []byte, projectName string) error { +func EnsureCommonClusterRole(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -409,13 +409,13 @@ func EnsureCommonClusterRole(kubeconfig []byte, projectName string) error { if _, err = clientset.RbacV1().ClusterRoles().Get(context.Background(), projectName+"-common", metav1.GetOptions{}); err != nil { _, err = clientset.RbacV1().ClusterRoles().Create(context.Background(), obj, metav1.CreateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } else { _, err = clientset.RbacV1().ClusterRoles().Update(context.Background(), obj, metav1.UpdateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } @@ -423,27 +423,27 @@ func EnsureCommonClusterRole(kubeconfig []byte, projectName string) error { return nil } -func RemoveCommonClusterRole(kubeconfig []byte, projectName string) error { +func RemoveCommonClusterRole(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } clientset := kubernetes.NewForConfigOrDie(config_user) if err := clientset.RbacV1().ClusterRoles().Delete(context.Background(), projectName+"-common", metav1.DeleteOptions{}); err != nil { - log.Error(err) + log.Error(ctx, err) return err } return nil } -func EnsureCommonClusterRoleBinding(kubeconfig []byte, projectName string) error { +func EnsureCommonClusterRoleBinding(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -454,13 +454,13 @@ func EnsureCommonClusterRoleBinding(kubeconfig []byte, projectName string) error if _, err = clientset.RbacV1().ClusterRoleBindings().Get(context.Background(), projectName+"-common"+"-"+role, metav1.GetOptions{}); err != nil { _, err = clientset.RbacV1().ClusterRoleBindings().Create(context.Background(), obj, metav1.CreateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } else { _, err = clientset.RbacV1().ClusterRoleBindings().Update(context.Background(), obj, metav1.UpdateOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } } @@ -469,10 +469,10 @@ func EnsureCommonClusterRoleBinding(kubeconfig []byte, projectName string) error return nil } -func RemoveCommonClusterRoleBinding(kubeconfig []byte, projectName string) error { +func RemoveCommonClusterRoleBinding(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { - log.Error(err) + log.Error(ctx, err) return err } @@ -480,7 +480,7 @@ func RemoveCommonClusterRoleBinding(kubeconfig []byte, projectName string) error for _, role := range []string{leaderRole, memberRole, viewerRole} { if err := clientset.RbacV1().ClusterRoles().Delete(context.Background(), projectName+"-common-"+role, metav1.DeleteOptions{}); err != nil { - log.Error(err) + log.Error(ctx, err) return err } } diff --git a/internal/mail/content.go b/internal/mail/content.go index d8ac55c9..77a4950d 100644 --- a/internal/mail/content.go +++ b/internal/mail/content.go @@ -2,17 +2,18 @@ package mail import ( "bytes" + "context" "html/template" "github.com/openinfradev/tks-api/pkg/log" ) -func MakeVerityIdentityMessage(to, code string) (*MessageInfo, error) { +func MakeVerityIdentityMessage(ctx context.Context, to, code string) (*MessageInfo, error) { subject := "[TKS] [인증번호:" + code + "] 인증번호가 발급되었습니다." tmpl, err := template.ParseFS(templateFS, "contents/authcode.html") if err != nil { - log.Errorf("failed to parse template, %v", err) + log.Errorf(ctx, "failed to parse template, %v", err) return nil, err } @@ -20,7 +21,7 @@ func MakeVerityIdentityMessage(to, code string) (*MessageInfo, error) { var tpl bytes.Buffer if err := tmpl.Execute(&tpl, data); err != nil { - log.Errorf("failed to execute template, %v", err) + log.Errorf(ctx, "failed to execute template, %v", err) return nil, err } @@ -34,12 +35,12 @@ func MakeVerityIdentityMessage(to, code string) (*MessageInfo, error) { return m, nil } -func MakeTemporaryPasswordMessage(to, organizationId, accountId, randomPassword string) (*MessageInfo, error) { +func MakeTemporaryPasswordMessage(ctx context.Context, to, organizationId, accountId, randomPassword string) (*MessageInfo, error) { subject := "[TKS] 임시 비밀번호가 발급되었습니다." tmpl, err := template.ParseFS(templateFS, "contents/temporary_password.html") if err != nil { - log.Errorf("failed to parse template, %v", err) + log.Errorf(ctx, "failed to parse template, %v", err) return nil, err } @@ -47,7 +48,7 @@ func MakeTemporaryPasswordMessage(to, organizationId, accountId, randomPassword var tpl bytes.Buffer if err := tmpl.Execute(&tpl, data); err != nil { - log.Errorf("failed to execute template, %v", err) + log.Errorf(ctx, "failed to execute template, %v", err) return nil, err } @@ -62,13 +63,14 @@ func MakeTemporaryPasswordMessage(to, organizationId, accountId, randomPassword } func MakeGeneratingOrganizationMessage( + ctx context.Context, organizationId string, organizationName string, to string, userAccountId string, randomPassword string) (*MessageInfo, error) { subject := "[TKS] 조직이 생성되었습니다." tmpl, err := template.ParseFS(templateFS, "contents/organization_creation.html") if err != nil { - log.Errorf("failed to parse template, %v", err) + log.Errorf(ctx, "failed to parse template, %v", err) return nil, err } @@ -82,7 +84,7 @@ func MakeGeneratingOrganizationMessage( var tpl bytes.Buffer if err := tmpl.Execute(&tpl, data); err != nil { - log.Errorf("failed to execute template, %v", err) + log.Errorf(ctx, "failed to execute template, %v", err) return nil, err } diff --git a/internal/mail/ses.go b/internal/mail/ses.go index 98e9a429..eb7a4f0a 100644 --- a/internal/mail/ses.go +++ b/internal/mail/ses.go @@ -20,7 +20,7 @@ type AwsMailer struct { message *MessageInfo } -func (a *AwsMailer) SendMail() error { +func (a *AwsMailer) SendMail(ctx context.Context) error { input := &awsSes.SendEmailInput{ Destination: &types.Destination{ ToAddresses: []string{a.message.To}, @@ -39,16 +39,16 @@ func (a *AwsMailer) SendMail() error { } if _, err := a.client.SendEmail(context.Background(), input); err != nil { - log.Errorf("failed to send email, %v", err) + log.Errorf(ctx, "failed to send email, %v", err) return err } return nil } -func initialize() error { +func initialize(ctx context.Context) error { if viper.GetString("aws-access-key-id") != "" || viper.GetString("aws-secret-access-key") != "" { - log.Warn("aws access key information is used on env. Be aware of security") + log.Warn(ctx, "aws access key information is used on env. Be aware of security") } if viper.GetString("aws-access-key-id") != "" { err := os.Setenv("AWS_ACCESS_KEY_ID", viper.GetString("aws-access-key-id")) diff --git a/internal/mail/smtp.go b/internal/mail/smtp.go index 12a401ec..23714e50 100644 --- a/internal/mail/smtp.go +++ b/internal/mail/smtp.go @@ -2,6 +2,7 @@ package mail import ( "bytes" + "context" "crypto/tls" "embed" "errors" @@ -27,7 +28,7 @@ var ( ) type Mailer interface { - SendMail() error + SendMail(ctx context.Context) error } type MessageInfo struct { @@ -47,7 +48,7 @@ type SmtpMailer struct { message *MessageInfo } -func (s *SmtpMailer) SendMail() error { +func (s *SmtpMailer) SendMail(ctx context.Context) error { s.client.SetHeader("From", s.message.From) s.client.SetHeader("To", s.message.To) s.client.SetHeader("Subject", s.message.Subject) @@ -55,14 +56,14 @@ func (s *SmtpMailer) SendMail() error { d := NewDialer(s.Host, s.Port, s.Username, s.Password) if err := d.DialAndSend(s.client); err != nil { - log.Errorf("failed to send email, %v", err) + log.Errorf(ctx, "failed to send email, %v", err) return err } return nil } -func Initialize() error { +func Initialize(ctx context.Context) error { mailProvider = viper.GetString("mail-provider") if mailProvider != "smtp" { mailProvider = "aws" @@ -70,8 +71,8 @@ func Initialize() error { switch mailProvider { case "aws": - if err := initialize(); err != nil { - log.Errorf("aws config initialize error, %v", err) + if err := initialize(ctx); err != nil { + log.Errorf(ctx, "aws config initialize error, %v", err) return err } from = "tks-dev@sktelecom.com" @@ -83,23 +84,23 @@ func Initialize() error { from = viper.GetString("smtp-from-email") if host == "" { - log.Error("smtp-host is not set") + log.Error(ctx, "smtp-host is not set") return fmt.Errorf("smtp-host is not set") } if port == 0 { - log.Error("smtp-port is not set") + log.Error(ctx, "smtp-port is not set") return fmt.Errorf("smtp-port is not set") } if username == "" { - log.Error("smtp-username is not set") + log.Error(ctx, "smtp-username is not set") return fmt.Errorf("smtp-username is not set") } if password == "" { - log.Error("smtp-password is not set") + log.Error(ctx, "smtp-password is not set") return fmt.Errorf("smtp-password is not set") } if from == "" { - log.Error("smtp-from-email is not set") + log.Error(ctx, "smtp-from-email is not set") return fmt.Errorf("smtp-from-email is not set") } @@ -115,11 +116,11 @@ func New(m *MessageInfo) Mailer { switch mailProvider { case "aws": mailer = NewAwsMailer(m) - log.Infof("aws ses mailer, %v", mailer) + log.Infof(nil, "aws ses mailer, %v", mailer) case "smtp": mailer = NewSmtpMailer(m) - log.Infof("smtp mailer, %v", mailer) + log.Infof(nil, "smtp mailer, %v", mailer) } return mailer diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index 863b71fd..a5fead14 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -2,6 +2,7 @@ package audit import ( "bytes" + "context" "encoding/json" "fmt" @@ -11,127 +12,127 @@ import ( "github.com/openinfradev/tks-api/pkg/log" ) -type fnAudit = func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) +type fnAudit = func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) var auditMap = map[internalApi.Endpoint]fnAudit{ - internalApi.CreateStack: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + internalApi.CreateStack: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateStackRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } if isSuccess(statusCode) { return fmt.Sprintf("스택 [%s]을 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("스택 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return fmt.Sprintf("스택 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreateProject: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateProject: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateProjectRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } if isSuccess(statusCode) { return fmt.Sprintf("프로젝트 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("프로젝트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return fmt.Sprintf("프로젝트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreateCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateCloudAccount: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateCloudAccountRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } if isSuccess(statusCode) { return fmt.Sprintf("클라우드 어카운트 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("클라우드 어카운트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return fmt.Sprintf("클라우드 어카운트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.DeleteCloudAccount: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.DeleteCloudAccount: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { if isSuccess(statusCode) { output := domain.DeleteCloudAccountResponse{} if err := json.Unmarshal(in, &output); err != nil { - log.Error(err) + log.Error(ctx, err) } return fmt.Sprintf("클라우드어카운트 [ID:%s]를 삭제하였습니다.", output.ID), "" } else { - return "클라우드어카운트 [%s]를 삭제하는데 실패하였습니다. ", errorText(out) + return "클라우드어카운트 [%s]를 삭제하는데 실패하였습니다. ", errorText(ctx, out) } - }, internalApi.CreateUser: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateUser: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateUserRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } if isSuccess(statusCode) { return fmt.Sprintf("사용자 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("사용자 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return fmt.Sprintf("사용자 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreateOrganization: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateOrganization: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateOrganizationRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } if isSuccess(statusCode) { return fmt.Sprintf("조직 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("조직 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return fmt.Sprintf("조직 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.DeleteOrganization: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.DeleteOrganization: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { if isSuccess(statusCode) { output := domain.DeleteOrganizationResponse{} if err := json.Unmarshal(in, &output); err != nil { - log.Error(err) + log.Error(ctx, err) } return fmt.Sprintf("조직 [ID:%s]를 삭제하였습니다.", output.ID), "" } else { - return "조직 [%s]를 삭제하는데 실패하였습니다. ", errorText(out) + return "조직 [%s]를 삭제하는데 실패하였습니다. ", errorText(ctx, out) } - }, internalApi.CreateAppServeApp: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateAppServeApp: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateAppServeAppRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } if isSuccess(statusCode) { return fmt.Sprintf("앱서빙 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("앱서빙 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return fmt.Sprintf("앱서빙 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateStackTemplate: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateStackTemplate: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateStackTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } - log.Info(input) + log.Info(ctx, input) if isSuccess(statusCode) { return fmt.Sprintf("스택 템플릿 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("스택 템플릿 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return fmt.Sprintf("스택 템플릿 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateUser: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateUser: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateUserRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } if isSuccess(statusCode) { return fmt.Sprintf("어드민 [%s]를 생성하였습니다.", input.Name), "" } else { - return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(out) + return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreatePolicyTemplate: func(out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreatePolicyTemplate: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreatePolicyTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { - log.Error(err) + log.Error(ctx, err) } if isSuccess(statusCode) { return fmt.Sprintf("폴리시템플릿 [%s]를 생성하였습니다.", input.TemplateName), "" } else { - return fmt.Sprintf("폴리시템플릿 [%s]을 생성하는데 실패하였습니다.", input.TemplateName), errorText(out) + return fmt.Sprintf("폴리시템플릿 [%s]을 생성하는데 실패하였습니다.", input.TemplateName), errorText(ctx, out) } }, } -func errorText(out *bytes.Buffer) string { +func errorText(ctx context.Context, out *bytes.Buffer) string { var e httpErrors.RestError if err := json.NewDecoder(out).Decode(&e); err != nil { - log.Error(err) + log.Error(ctx, err) return "" } return e.Text() diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index fc06c80f..33162b5f 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -33,7 +33,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { user, ok := request.UserFrom(r.Context()) if !ok { - log.Error("Invalid user token") + log.Error(r.Context(), "Invalid user token") return } userId := user.GetUserId() @@ -54,9 +54,9 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han if endpoint != internalApi.PingToken { body, err := io.ReadAll(r.Body) if err != nil { - log.Error(err) + log.Error(r.Context(), err) } - message, description = fn(lrw.GetBody(), body, statusCode) + message, description = fn(r.Context(), lrw.GetBody(), body, statusCode) r.Body = io.NopCloser(bytes.NewBuffer(body)) dto := model.Audit{ @@ -68,7 +68,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han UserId: &userId, } if _, err := a.repo.Create(r.Context(), dto); err != nil { - log.Error(err) + log.Error(r.Context(), err) } } } diff --git a/internal/middleware/auth/authenticator/authenticator.go b/internal/middleware/auth/authenticator/authenticator.go index 976850ac..80ea6bba 100644 --- a/internal/middleware/auth/authenticator/authenticator.go +++ b/internal/middleware/auth/authenticator/authenticator.go @@ -32,7 +32,7 @@ func (a *defaultAuthenticator) WithAuthentication(handler http.Handler) http.Han return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp, ok, err := a.auth.AuthenticateRequest(r) if !ok { - log.Error(err) + log.Error(r.Context(), err) internalHttp.ErrorJSON(w, r, err) return } diff --git a/internal/middleware/auth/authenticator/keycloak/keycloak.go b/internal/middleware/auth/authenticator/keycloak/keycloak.go index 49c337be..8f0ee136 100644 --- a/internal/middleware/auth/authenticator/keycloak/keycloak.go +++ b/internal/middleware/auth/authenticator/keycloak/keycloak.go @@ -40,7 +40,7 @@ func (a *keycloakAuthenticator) AuthenticateRequest(r *http.Request) (*authentic if len(token) == 0 { // The space before the token case if len(parts) == 3 { - log.Warn("the provided Authorization header contains extra space before the bearer token, and is ignored") + log.Warn(r.Context(), "the provided Authorization header contains extra space before the bearer token, and is ignored") } return nil, false, fmt.Errorf("token is empty") } @@ -59,9 +59,9 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("organization is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } - isActive, err := a.kc.VerifyAccessToken(token, organizationId) + isActive, err := a.kc.VerifyAccessToken(r.Context(), token, organizationId) if err != nil { - log.Errorf("failed to verify access token: %v", err) + log.Errorf(r.Context(), "failed to verify access token: %v", err) return nil, false, httpErrors.NewUnauthorizedError(err, "C_INTERNAL_ERROR", "") } if !isActive { @@ -71,14 +71,14 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) // tks role extraction roleOrganizationMapping := make(map[string]string) if roles, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["tks-role"]; !ok { - log.Errorf("tks-role is not found in token") + log.Errorf(r.Context(), "tks-role is not found in token") return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("tks-role is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } else { for _, role := range roles.([]interface{}) { slice := strings.Split(role.(string), "@") if len(slice) != 2 { - log.Errorf("invalid tks-role format: %v", role) + log.Errorf(r.Context(), "invalid tks-role format: %v", role) return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid tks-role format"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } @@ -94,7 +94,7 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) for _, role := range roles.([]interface{}) { slice := strings.Split(role.(string), "@") if len(slice) != 2 { - log.Errorf("invalid project-role format: %v", role) + log.Errorf(r.Context(), "invalid project-role format: %v", role) return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid project-role format"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } @@ -106,7 +106,7 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) userId, err := uuid.Parse(parsedToken.Claims.(jwtWithouKey.MapClaims)["sub"].(string)) if err != nil { - log.Errorf("failed to verify access token: %v", err) + log.Errorf(r.Context(), "failed to verify access token: %v", err) return nil, false, httpErrors.NewUnauthorizedError(err, "C_INTERNAL_ERROR", "") } diff --git a/internal/middleware/auth/authorizer/rbac.go b/internal/middleware/auth/authorizer/rbac.go index 9c16508b..9813558e 100644 --- a/internal/middleware/auth/authorizer/rbac.go +++ b/internal/middleware/auth/authorizer/rbac.go @@ -38,7 +38,7 @@ func RBACFilter(handler http.Handler, repo repository.Repository) http.Handler { return } } else { - log.Warn("RBACFilter: organizationId not found. Passing through unsafely.") + log.Warn(r.Context(), "RBACFilter: organizationId not found. Passing through unsafely.") } } @@ -130,7 +130,7 @@ func RequestOrganizationValidationFilter(handler http.Handler, repo repository.R if !ok { //internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("organizationId not found"), "", "")) //return - log.Warn("RequestOrganizationValidationFilter: organizationId not found. Passing through unsafely.") + log.Warn(r.Context(), "RequestOrganizationValidationFilter: organizationId not found. Passing through unsafely.") } if organizationId != requestUserInfo.GetOrganizationId() { internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) diff --git a/internal/middleware/auth/role/default.go b/internal/middleware/auth/role/default.go index 41bf5652..9b69bdaa 100644 --- a/internal/middleware/auth/role/default.go +++ b/internal/middleware/auth/role/default.go @@ -109,13 +109,6 @@ var defaultPermissionOfAdmin = defaultPermission{ internalApi.DeleteForceCloudAccount, internalApi.GetResourceQuota, - // StackTemplate - internalApi.GetStackTemplates, - internalApi.CreateStackTemplate, - internalApi.GetStackTemplate, - internalApi.UpdateStackTemplate, - internalApi.DeleteStackTemplate, - // Dashboard internalApi.GetChartsDashboard, internalApi.GetChartDashboard, @@ -225,8 +218,8 @@ var defaultPermissionOfUser = defaultPermission{ internalApi.GetResourceQuota, // StackTemplate - internalApi.GetStackTemplates, - internalApi.GetStackTemplate, + internalApi.Admin_GetStackTemplates, + internalApi.Admin_GetStackTemplate, // Dashboard internalApi.GetChartsDashboard, diff --git a/internal/middleware/logging/logging.go b/internal/middleware/logging/logging.go index da5fcc35..feee3af4 100644 --- a/internal/middleware/logging/logging.go +++ b/internal/middleware/logging/logging.go @@ -29,7 +29,7 @@ func LoggingMiddleware(next http.Handler) http.Handler { next.ServeHTTP(lrw, r) statusCode := lrw.GetStatusCode() - log.InfofWithContext(r.Context(), "[API_RESPONSE] [%d][%s][%s]", statusCode, http.StatusText(statusCode), lrw.GetBody().String()) - log.InfofWithContext(r.Context(), "***** END [%s %s] *****", r.Method, r.RequestURI) + log.Infof(r.Context(), "[API_RESPONSE] [%d][%s][%s]", statusCode, http.StatusText(statusCode), lrw.GetBody().String()) + log.Infof(r.Context(), "***** END [%s %s] *****", r.Method, r.RequestURI) }) } diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index edaf6a37..df2b76af 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -71,7 +71,7 @@ func (r *AppGroupRepository) Create(ctx context.Context, dto model.AppGroup) (ap } res := r.db.WithContext(ctx).Create(&appGroup) if res.Error != nil { - log.Error(res.Error) + log.Error(ctx, res.Error) return "", res.Error } diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index d2089fe2..53460c70 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -104,7 +104,7 @@ func (r *AppServeAppRepository) GetAppServeAppById(ctx context.Context, appId st res := r.db.WithContext(ctx).Where("id = ?", appId).First(&app) if res.Error != nil { - log.Debug(res.Error) + log.Debug(ctx, res.Error) return nil, res.Error } if res.RowsAffected == 0 { @@ -113,7 +113,7 @@ func (r *AppServeAppRepository) GetAppServeAppById(ctx context.Context, appId st // Populate tasks into app object if err := r.db.WithContext(ctx).Model(&app).Order("created_at desc").Association("AppServeAppTasks").Find(&app.AppServeAppTasks); err != nil { - log.Debug(err) + log.Debug(ctx, err) return nil, err } @@ -151,7 +151,7 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(ctx context.Context, task // Retrieve task info res := r.db.WithContext(ctx).Where("id = ?", taskId).First(&task) if res.Error != nil { - log.Debug(res.Error) + log.Debug(ctx, res.Error) return nil, nil, res.Error } if res.RowsAffected == 0 { @@ -161,7 +161,7 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(ctx context.Context, task // Retrieve app info res = r.db.WithContext(ctx).Where("id = ?", task.AppServeAppId).First(&app) if res.Error != nil { - log.Debug(res.Error) + log.Debug(ctx, res.Error) return nil, nil, res.Error } if res.RowsAffected == 0 { @@ -177,7 +177,7 @@ func (r *AppServeAppRepository) GetAppServeAppLatestTask(ctx context.Context, ap // TODO: Does this work?? where's app ID here? res := r.db.WithContext(ctx).Order("created_at desc").First(&task) if res.Error != nil { - log.Debug(res.Error) + log.Debug(ctx, res.Error) return nil, res.Error } if res.RowsAffected == 0 { @@ -204,7 +204,7 @@ func (r *AppServeAppRepository) IsAppServeAppExist(ctx context.Context, appId st res := r.db.WithContext(ctx).Table("app_serve_apps").Where("id = ? AND status <> 'DELETE_SUCCESS'", appId).Count(&result) if res.Error != nil { - log.Debug(res.Error) + log.Debug(ctx, res.Error) return 0, res.Error } return result, nil @@ -217,10 +217,10 @@ func (r *AppServeAppRepository) IsAppServeAppNameExist(ctx context.Context, orgI "AND name = '%v' "+ "AND status <> 'DELETE_SUCCESS'", orgId, appName) - log.Info("query = ", queryString) + log.Info(ctx, "query = ", queryString) res := r.db.WithContext(ctx).Table("app_serve_apps").Where(queryString).Count(&result) if res.Error != nil { - log.Debug(res.Error) + log.Debug(ctx, res.Error) return 0, res.Error } return result, nil diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 7d92bdc5..02acaa2f 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -49,7 +49,7 @@ func NewClusterRepository(db *gorm.DB) IClusterRepository { // Logics func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { if trxHandle == nil { - log.Info("Transaction Database not found") + log.Info(nil, "Transaction Database not found") return r } r.tx = trxHandle @@ -150,7 +150,7 @@ func (r *ClusterRepository) Create(ctx context.Context, dto model.Cluster) (clus res := r.db.WithContext(ctx).Create(&cluster) if res.Error != nil { - log.Error(res.Error) + log.Error(ctx, res.Error) return "", res.Error } @@ -203,7 +203,7 @@ func (r *ClusterRepository) SetFavorite(ctx context.Context, clusterId domain.Cl var clusterFavorites []model.ClusterFavorite res := r.db.WithContext(ctx).Where("cluster_id = ? AND user_id = ?", clusterId, userId).Find(&clusterFavorites) if res.Error != nil { - log.Info(res.Error) + log.Info(ctx, res.Error) return res.Error } @@ -217,7 +217,7 @@ func (r *ClusterRepository) SetFavorite(ctx context.Context, clusterId domain.Cl } resCreate := r.db.Create(&clusterFavorite) if resCreate.Error != nil { - log.Error(resCreate.Error) + log.Error(ctx, resCreate.Error) return fmt.Errorf("could not create cluster favorite for clusterId %s, userId %s", clusterId, userId) } @@ -227,7 +227,7 @@ func (r *ClusterRepository) SetFavorite(ctx context.Context, clusterId domain.Cl func (r *ClusterRepository) DeleteFavorite(ctx context.Context, clusterId domain.ClusterId, userId uuid.UUID) error { res := r.db.WithContext(ctx).Unscoped().Delete(&model.ClusterFavorite{}, "cluster_id = ? AND user_id = ?", clusterId, userId) if res.Error != nil { - log.Error(res.Error) + log.Error(ctx, res.Error) return fmt.Errorf("could not delete cluster favorite for clusterId %s, userId %s", clusterId, userId) } return nil diff --git a/internal/repository/mapper.go b/internal/repository/mapper.go index c7f7583c..4436142b 100644 --- a/internal/repository/mapper.go +++ b/internal/repository/mapper.go @@ -6,7 +6,6 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) type ConverterMap map[compositeKey]func(interface{}) (interface{}, error) @@ -47,7 +46,7 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e dstField.Set(reflect.ValueOf(converted)) } } else { - log.Errorf("no converter found for %s -> %s", srcField.Type(), dstField.Type()) + //log.Errorf("no converter found for %s -> %s", srcField.Type(), dstField.Type()) continue } } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 072b2d6a..e98cd899 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -65,7 +65,7 @@ func (r *OrganizationRepository) Create(ctx context.Context, dto *model.Organiza } res := r.db.WithContext(ctx).Create(&organization) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return model.Organization{}, res.Error } @@ -88,7 +88,7 @@ func (r *OrganizationRepository) Get(ctx context.Context, id string) (out model. res := r.db.WithContext(ctx).Preload(clause.Associations). First(&out, "id = ?", id) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return model.Organization{}, res.Error } return @@ -104,12 +104,12 @@ func (r *OrganizationRepository) Update(ctx context.Context, organizationId stri }) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return model.Organization{}, res.Error } res = r.db.Model(&model.Organization{}).Where("id = ?", organizationId).Find(&out) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return model.Organization{}, res.Error } return @@ -123,7 +123,7 @@ func (r *OrganizationRepository) UpdatePrimaryClusterId(ctx context.Context, org }) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error } return nil @@ -137,7 +137,7 @@ func (r *OrganizationRepository) UpdateAdminId(ctx context.Context, organization }) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error } return nil @@ -146,7 +146,7 @@ func (r *OrganizationRepository) UpdateAdminId(ctx context.Context, organization func (r *OrganizationRepository) Delete(ctx context.Context, organizationId string) error { res := r.db.WithContext(ctx).Delete(&model.Organization{}, "id = ?", organizationId) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error } @@ -158,7 +158,7 @@ func (r *OrganizationRepository) InitWorkflow(ctx context.Context, organizationI Where("ID = ?", organizationId). Updates(map[string]interface{}{"Status": status, "WorkflowId": workflowId}) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error } return nil diff --git a/internal/repository/project.go b/internal/repository/project.go index 4260ea6a..ccd54b60 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -151,7 +151,7 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri Scan(&pr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project") + log.Info(ctx, "Cannot find project") } } return pr, nil @@ -203,10 +203,10 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project") + log.Info(ctx, "Cannot find project") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -256,10 +256,10 @@ func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId s if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project") + log.Info(ctx, "Cannot find project") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -271,10 +271,10 @@ func (r *ProjectRepository) GetProjectById(ctx context.Context, organizationId s res := r.db.WithContext(ctx).Limit(1).Where("organization_id = ? and id = ?", organizationId, projectId).First(&p) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project") + log.Info(ctx, "Cannot find project") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -291,10 +291,10 @@ func (r *ProjectRepository) GetProjectByIdAndLeader(ctx context.Context, organiz if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project") + log.Info(ctx, "Cannot find project") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -308,10 +308,10 @@ func (r *ProjectRepository) GetProjectByName(ctx context.Context, organizationId First(&p) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found project name") + log.Info(ctx, "Not found project name") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -333,10 +333,10 @@ func (r *ProjectRepository) GetProjectRoleById(ctx context.Context, id string) ( res := r.db.WithContext(ctx).First(pr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project role") + log.Info(ctx, "Cannot find project role") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -348,10 +348,10 @@ func (r *ProjectRepository) GetAllProjectRoles(ctx context.Context) (prs []model res := r.db.WithContext(ctx).Find(&prs) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project roles") + log.Info(ctx, "Cannot find project roles") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -363,10 +363,10 @@ func (r *ProjectRepository) GetProjectRoleByName(ctx context.Context, name strin res := r.db.WithContext(ctx).Where("name = ?", name).First(&pr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project roles") + log.Info(ctx, "Cannot find project roles") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -393,10 +393,10 @@ func (r *ProjectRepository) GetProjectMembersByProjectId(ctx context.Context, pr Order("project_members.created_at ASC"), &pms) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project member") + log.Info(ctx, "Cannot find project member") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -415,10 +415,10 @@ func (r *ProjectRepository) GetProjectMembersByProjectIdAndRoleName(ctx context. if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project member") + log.Info(ctx, "Cannot find project member") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -450,10 +450,10 @@ func (r *ProjectRepository) GetProjectMemberCountByProjectId(ctx context.Context Scan(&pmcr) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project member count") + log.Info(ctx, "Cannot find project member count") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -466,10 +466,10 @@ func (r *ProjectRepository) GetProjectMemberById(ctx context.Context, projectMem Joins("ProjectRole").Where("project_members.id = ?", projectMemberId).First(&pm) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project member") + log.Info(ctx, "Cannot find project member") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -482,10 +482,10 @@ func (r *ProjectRepository) GetProjectMemberByUserId(ctx context.Context, projec Joins("ProjectRole").Where("project_id = ? and project_user_id = ?", projectId, projectUserId).First(&pm) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Cannot find project member") + log.Info(ctx, "Cannot find project member") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -542,10 +542,10 @@ func (r *ProjectRepository) GetProjectNamespaceByName(ctx context.Context, organ First(&pn) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found project namespace") + log.Info(ctx, "Not found project namespace") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -561,10 +561,10 @@ func (r *ProjectRepository) GetProjectNamespaces(ctx context.Context, organizati Preload("Stack"), &pns) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found project namespaces") + log.Info(ctx, "Not found project namespaces") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -580,10 +580,10 @@ func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(ctx context.Context, First(&pn) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found project namespace") + log.Info(ctx, "Not found project namespace") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -617,7 +617,7 @@ func (r *ProjectRepository) GetAppCountByProjectId(ctx context.Context, organiza Where("organization_id = ? and project_Id = ?", organizationId, projectId). Find(&appCount) if res.Error != nil { - log.Error(res.Error) + log.Error(ctx, res.Error) return 0, res.Error } @@ -630,7 +630,7 @@ func (r *ProjectRepository) GetAppCountByNamespace(ctx context.Context, organiza Where("organization_id = ? and project_Id = ? and namespace = ?", organizationId, projectId, namespace). Find(&appCount) if res.Error != nil { - log.Error(res.Error) + log.Error(ctx, res.Error) return 0, res.Error } diff --git a/internal/repository/user.go b/internal/repository/user.go index 99a4b98e..59627743 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -39,7 +39,7 @@ type UserRepository struct { func (r *UserRepository) Flush(ctx context.Context, organizationId string) error { res := r.db.WithContext(ctx).Where("organization_id = ?", organizationId).Delete(&model.User{}) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error } return nil @@ -66,7 +66,7 @@ func (r *UserRepository) CreateWithUuid(ctx context.Context, uuid uuid.UUID, acc } res := r.db.WithContext(ctx).Create(&newUser) if res.Error != nil { - log.Error(res.Error.Error()) + log.Error(ctx, res.Error.Error()) return model.User{}, res.Error } user, err := r.getUserByAccountId(nil, accountId, organizationId) @@ -97,7 +97,7 @@ func (r *UserRepository) List(ctx context.Context, filters ...FilterFunc) (*[]mo } if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error } if res.RowsAffected == 0 { @@ -121,7 +121,7 @@ func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination. _, res := pg.Fetch(r.db.WithContext(ctx).Preload("Organization").Preload("Role").Model(&model.User{}).Where("organization_id = ?", organizationId), &users) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error } @@ -147,7 +147,7 @@ func (r *UserRepository) GetByUuid(ctx context.Context, userId uuid.UUID) (respU res := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return model.User{}, res.Error } if res.RowsAffected == 0 { @@ -171,7 +171,7 @@ func (r *UserRepository) UpdateWithUuid(ctx context.Context, uuid uuid.UUID, acc return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return model.User{}, res.Error } res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) @@ -195,7 +195,7 @@ func (r *UserRepository) UpdatePasswordAt(ctx context.Context, userId uuid.UUID, return httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") } if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error } @@ -205,7 +205,7 @@ func (r *UserRepository) UpdatePasswordAt(ctx context.Context, userId uuid.UUID, func (r *UserRepository) DeleteWithUuid(ctx context.Context, uuid uuid.UUID) error { res := r.db.WithContext(ctx).Unscoped().Delete(&model.User{}, "id = ?", uuid) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error } return nil @@ -248,7 +248,7 @@ func (r *UserRepository) getUserByAccountId(ctx context.Context, accountId strin res := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Role"). Find(&user, "account_id = ? AND organization_id = ?", accountId, organizationId) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return model.User{}, res.Error } if res.RowsAffected == 0 { @@ -262,7 +262,7 @@ func (r *UserRepository) getRoleByName(ctx context.Context, roleName string) (mo role := model.Role{} res := r.db.WithContext(ctx).First(&role, "name = ?", roleName) if res.Error != nil { - log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return model.Role{}, res.Error } if res.RowsAffected == 0 { diff --git a/internal/route/route.go b/internal/route/route.go index b7d0b827..5989edba 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -305,7 +305,7 @@ func transactionMiddleware(db *gorm.DB) mux.MiddlewareFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() txHandle := db.Begin() - log.DebugWithContext(r.Context(),"beginning database transaction") + log.Debug(r.Context(),"beginning database transaction") defer func() { if r := recover(); r != nil { @@ -322,12 +322,12 @@ func transactionMiddleware(db *gorm.DB) mux.MiddlewareFunc { next.ServeHTTP(recorder, r) if StatusInList(recorder.Status, []int{http.StatusOK}) { - log.DebugWithContext(r.Context(),"committing transactions") + log.Debug(r.Context(),"committing transactions") if err := txHandle.Commit().Error; err != nil { - log.DebugWithContext(r.Context(),"trx commit error: ", err) + log.Debug(r.Context(),"trx commit error: ", err) } } else { - log.DebugWithContext(r.Context(),"rolling back transaction due to status code: ", recorder.Status) + log.Debug(r.Context(),"rolling back transaction due to status code: ", recorder.Status) txHandle.Rollback() } }) diff --git a/internal/usecase/alert.go b/internal/usecase/alert.go index c8397d07..7632170f 100644 --- a/internal/usecase/alert.go +++ b/internal/usecase/alert.go @@ -274,7 +274,7 @@ func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model. case "pvc-full": url = primaryGrafanaEndpoint + "/d/tks_cluster_dashboard/tks-kubernetes-view-cluster-global?var-taco_cluster=" + clusterId.String() + "&kiosk" default: - log.ErrorfWithContext(ctx, "Invalid alert name %s", alert.Labels.AlertName) + log.Errorf(ctx, "Invalid alert name %s", alert.Labels.AlertName) } return diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index 8bf631ab..39d7c8ac 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -146,7 +146,7 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do return "", errors.Wrap(err, fmt.Sprintf("Invalid appGroup type. %s", dto.AppGroupType.String())) } - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflowTemplate, opts) + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflowTemplate, opts) if err != nil { log.Error(ctx, "failed to submit argo workflow template. err : ", err) return "", httpErrors.NewInternalServerError(err, "AG_FAILED_TO_CALL_WORKFLOW", "") @@ -235,12 +235,12 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err "object_store=" + tksObjectStore, } - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflowTemplate, opts) + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflowTemplate, opts) if err != nil { return fmt.Errorf("Failed to call argo workflow : %s", err) } - log.DebugWithContext(ctx, "submited workflow name : ", workflowId) + log.Debug(ctx, "submited workflow name : ", workflowId) if err := u.repo.InitWorkflow(ctx, id, workflowId, domain.AppGroupStatus_DELETING); err != nil { return fmt.Errorf("Failed to initialize appGroup status. err : %s", err) diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index c58539c1..4fb12686 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -103,15 +103,15 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A extEnv := app.AppServeAppTasks[0].ExtraEnv if extEnv != "" { /* Preprocess extraEnv param */ - log.Debug("extraEnv received: ", extEnv) + log.Debug(ctx, "extraEnv received: ", extEnv) tempMap := map[string]string{} err := json.Unmarshal([]byte(extEnv), &tempMap) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", "", errors.Wrap(err, "Failed to process extraEnv param.") } - log.Debugf("extraEnv marshalled: %v", tempMap) + log.Debugf(ctx, "extraEnv marshalled: %v", tempMap) newExtEnv := map[string]string{} for key, val := range tempMap { @@ -122,12 +122,12 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A mJson, _ := json.Marshal(newExtEnv) extEnv = string(mJson) - log.Debug("After transform, extraEnv: ", extEnv) + log.Debug(ctx, "After transform, extraEnv: ", extEnv) } appId, taskId, err := u.repo.CreateAppServeApp(ctx, app) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", "", errors.Wrap(err, "Failed to create app.") } @@ -168,14 +168,14 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A "tks_api_url=" + viper.GetString("external-address"), } - log.Info("Submitting workflow: ", workflow) + log.Info(ctx, "Submitting workflow: ", workflow) - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, opts) + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, opts) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", "", errors.Wrap(err, fmt.Sprintf("failed to submit workflow. %s", workflow)) } - log.Info("Successfully submitted workflow: ", workflowId) + log.Info(ctx, "Successfully submitted workflow: ", workflowId) return appId, app.Name, nil } @@ -226,7 +226,7 @@ func (u *AppServeAppUsecase) GetAppServeAppById(ctx context.Context, appId strin func (u *AppServeAppUsecase) GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) { tasks, err := u.repo.GetAppServeAppTasksByAppId(ctx, appId, pg) if err != nil { - log.Debugf("Tasks: %v", tasks) + log.Debugf(ctx, "Tasks: %v", tasks) } return tasks, nil @@ -286,36 +286,36 @@ func (u *AppServeAppUsecase) IsAppServeAppNameExist(ctx context.Context, orgId s } func (u *AppServeAppUsecase) IsAppServeAppNamespaceExist(ctx context.Context, clusterId string, new_ns string) (bool, error) { - clientset, err := kubernetes.GetClientFromClusterId(clusterId) + clientset, err := kubernetes.GetClientFromClusterId(ctx, clusterId) if err != nil { - log.Error(err) + log.Error(ctx, err) return false, err } namespaces, err := clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) if err != nil { - log.Error(err) + log.Error(ctx, err) return false, err } for _, ns := range namespaces.Items { if new_ns == ns.ObjectMeta.Name { - log.Debugf("Namespace %s already exists.", new_ns) + log.Debugf(ctx, "Namespace %s already exists.", new_ns) return true, nil } } - log.Debugf("Namespace %s is available", new_ns) + log.Debugf(ctx, "Namespace %s is available", new_ns) return false, nil } func (u *AppServeAppUsecase) UpdateAppServeAppStatus(ctx context.Context, appId string, taskId string, status string, output string) (string, error) { - log.Info("Starting status update process..") + log.Info(ctx, "Starting status update process..") err := u.repo.UpdateStatus(ctx, appId, taskId, status, output) if err != nil { - log.Info("appId = ", appId) - log.Info("taskId = ", taskId) + log.Info(ctx, "appId = ", appId) + log.Info(ctx, "taskId = ", taskId) return "", fmt.Errorf("failed to update app status. Err: %s", err) } return fmt.Sprintf("The appId '%s' status is being updated.", appId), nil @@ -329,12 +329,12 @@ func (u *AppServeAppUsecase) UpdateAppServeAppEndpoint( previewEndpoint string, helmRevision int32) (string, error) { - log.Info("Starting endpoint update process..") + log.Info(ctx, "Starting endpoint update process..") err := u.repo.UpdateEndpoint(ctx, appId, taskId, endpoint, previewEndpoint, helmRevision) if err != nil { - log.Info("appId = ", appId) - log.Info("taskId = ", taskId) + log.Info(ctx, "appId = ", appId) + log.Info(ctx, "taskId = ", taskId) return "", fmt.Errorf("failed to update endpoint. Err: %s", err) } return fmt.Sprintf("The appId '%s' endpoint is being updated.", appId), nil @@ -373,24 +373,24 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(ctx context.Context, appId string taskId, err := u.repo.CreateTask(ctx, appTask) if err != nil { - log.Error("taskId = ", taskId) - log.Error("Failed to create delete task. Err:", err) + log.Error(ctx, "taskId = ", taskId) + log.Error(ctx, "Failed to create delete task. Err:", err) return "", errors.Wrap(err, "Failed to create delete task.") } - log.Info("Updating app status to 'DELETING'..") + log.Info(ctx, "Updating app status to 'DELETING'..") err = u.repo.UpdateStatus(ctx, appId, taskId, "DELETING", "") if err != nil { - log.Debug("appId = ", appId) - log.Debug("taskId = ", taskId) + log.Debug(ctx, "appId = ", appId) + log.Debug(ctx, "taskId = ", taskId) return "", fmt.Errorf("failed to update app status on DeleteAppServeApp. Err: %s", err) } workflow := "delete-java-app" - log.Info("Submitting workflow: ", workflow) + log.Info(ctx, "Submitting workflow: ", workflow) - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ "target_cluster_id=" + app.TargetClusterId, "app_name=" + app.Name, @@ -402,10 +402,10 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(ctx context.Context, appId string }, }) if err != nil { - log.Error("Failed to submit workflow. Err:", err) + log.Error(ctx, "Failed to submit workflow. Err:", err) return "", errors.Wrap(err, "Failed to submit workflow.") } - log.Info("Successfully submitted workflow: ", workflowId) + log.Info(ctx, "Successfully submitted workflow: ", workflowId) return fmt.Sprintf("The app %s is being deleted. "+ "Confirm result by checking the app status after a while.", app.Name), nil @@ -426,7 +426,7 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, app *model.A return "승인대기 또는 프로모트 작업 중에는 업그레이드를 수행할 수 없습니다", fmt.Errorf("Update not possible. The app is waiting for promote or in the middle of promote process.") } - log.Info("Starting normal update process..") + log.Info(ctx, "Starting normal update process..") // TODO: for more strict validation, check if immutable fields are provided by user // and those values are changed or not. (name, type, app_type, target_cluster) @@ -456,15 +456,15 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, app *model.A extEnv := appTask.ExtraEnv if extEnv != "" { /* Preprocess extraEnv param */ - log.Debug("extraEnv received: ", extEnv) + log.Debug(ctx, "extraEnv received: ", extEnv) tempMap := map[string]string{} err = json.Unmarshal([]byte(extEnv), &tempMap) if err != nil { - log.Error(err) + log.Error(ctx, err) return "", errors.Wrap(err, "Failed to process extraEnv param.") } - log.Debugf("extraEnv marshalled: %v", tempMap) + log.Debugf(ctx, "extraEnv marshalled: %v", tempMap) newExtEnv := map[string]string{} for key, val := range tempMap { @@ -475,31 +475,31 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, app *model.A mJson, _ := json.Marshal(newExtEnv) extEnv = string(mJson) - log.Debug("After transform, extraEnv: ", extEnv) + log.Debug(ctx, "After transform, extraEnv: ", extEnv) } taskId, err := u.repo.CreateTask(ctx, appTask) if err != nil { - log.Info("taskId = ", taskId) + log.Info(ctx, "taskId = ", taskId) return "", fmt.Errorf("failed to update app-serve application. Err: %s", err) } // Sync new task status to the parent app - log.Info("Updating app status to 'PREPARING'..") + log.Info(ctx, "Updating app status to 'PREPARING'..") err = u.repo.UpdateStatus(ctx, app.ID, taskId, "PREPARING", "") if err != nil { - log.Debug("appId = ", app.ID) - log.Debug("taskId = ", taskId) + log.Debug(ctx, "appId = ", app.ID) + log.Debug(ctx, "taskId = ", taskId) return "", fmt.Errorf("failed to update app status on UpdateAppServeApp. Err: %s", err) } // Call argo workflow workflow := "serve-java-app" - log.Info("Submitting workflow: ", workflow) + log.Info(ctx, "Submitting workflow: ", workflow) - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ "type=" + app.Type, "strategy=" + appTask.Strategy, @@ -530,10 +530,10 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, app *model.A }, }) if err != nil { - log.Error("Failed to submit workflow. Err:", err) + log.Error(ctx, "Failed to submit workflow. Err:", err) return "", fmt.Errorf("failed to submit workflow. Err: %s", err) } - log.Info("Successfully submitted workflow: ", workflowId) + log.Info(ctx, "Successfully submitted workflow: ", workflowId) var message string if appTask.Strategy == "rolling-update" { @@ -558,24 +558,24 @@ func (u *AppServeAppUsecase) PromoteAppServeApp(ctx context.Context, appId strin // Get the latest task ID so that the task status can be modified inside workflow once the promotion is done. latestTaskId := app.AppServeAppTasks[0].ID strategy := app.AppServeAppTasks[0].Strategy - log.Info("latestTaskId = ", latestTaskId) - log.Info("strategy = ", strategy) + log.Info(ctx, "latestTaskId = ", latestTaskId) + log.Info(ctx, "strategy = ", strategy) - log.Info("Updating app status to 'PROMOTING'..") + log.Info(ctx, "Updating app status to 'PROMOTING'..") err = u.repo.UpdateStatus(ctx, appId, latestTaskId, "PROMOTING", "") if err != nil { - log.Debug("appId = ", appId) - log.Debug("taskId = ", latestTaskId) + log.Debug(ctx, "appId = ", appId) + log.Debug(ctx, "taskId = ", latestTaskId) return "", fmt.Errorf("failed to update app status on PromoteAppServeApp. Err: %s", err) } // Call argo workflow workflow := "promote-java-app" - log.Info("Submitting workflow: ", workflow) + log.Info(ctx, "Submitting workflow: ", workflow) - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ "organization_id=" + app.OrganizationId, "target_cluster_id=" + app.TargetClusterId, @@ -588,10 +588,10 @@ func (u *AppServeAppUsecase) PromoteAppServeApp(ctx context.Context, appId strin }, }) if err != nil { - log.Error("failed to submit workflow. Err:", err) + log.Error(ctx, "failed to submit workflow. Err:", err) return "", fmt.Errorf("failed to submit workflow. Err: %s", err) } - log.Info("Successfully submitted workflow: ", workflowId) + log.Info(ctx, "Successfully submitted workflow: ", workflowId) return fmt.Sprintf("The app '%s' is being promoted. "+ "Confirm result by checking the app status after a while.", app.Name), nil @@ -610,25 +610,25 @@ func (u *AppServeAppUsecase) AbortAppServeApp(ctx context.Context, appId string) // Get the latest task ID so that the task status can be modified inside workflow once the abort process is done. latestTaskId := app.AppServeAppTasks[0].ID strategy := app.AppServeAppTasks[0].Strategy - log.Info("latestTaskId = ", latestTaskId) - log.Info("strategy = ", strategy) + log.Info(ctx, "latestTaskId = ", latestTaskId) + log.Info(ctx, "strategy = ", strategy) - log.Info("Updating app status to 'ABORTING'..") + log.Info(ctx, "Updating app status to 'ABORTING'..") err = u.repo.UpdateStatus(ctx, appId, latestTaskId, "ABORTING", "") if err != nil { - log.Debug("appId = ", appId) - log.Debug("taskId = ", latestTaskId) + log.Debug(ctx, "appId = ", appId) + log.Debug(ctx, "taskId = ", latestTaskId) return "", fmt.Errorf("failed to update app status on AbortAppServeApp. Err: %s", err) } // Call argo workflow workflow := "abort-java-app" - log.Info("Submitting workflow: ", workflow) + log.Info(ctx, "Submitting workflow: ", workflow) // Call argo workflow - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ "organization_id=" + app.OrganizationId, "target_cluster_id=" + app.TargetClusterId, @@ -643,14 +643,14 @@ func (u *AppServeAppUsecase) AbortAppServeApp(ctx context.Context, appId string) if err != nil { return "", fmt.Errorf("failed to submit workflow. Err: %s", err) } - log.Info("Successfully submitted workflow: ", workflowId) + log.Info(ctx, "Successfully submitted workflow: ", workflowId) return fmt.Sprintf("The app '%s' is being promoted. "+ "Confirm result by checking the app status after a while.", app.Name), nil } func (u *AppServeAppUsecase) RollbackAppServeApp(ctx context.Context, appId string, taskId string) (ret string, err error) { - log.Info("Starting rollback process..") + log.Info(ctx, "Starting rollback process..") app, err := u.repo.GetAppServeAppById(ctx, appId) if err != nil { @@ -683,25 +683,25 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(ctx context.Context, appId stri // Creates new task record from the target task newTaskId, err := u.repo.CreateTask(ctx, &task) if err != nil { - log.Info("taskId = ", newTaskId) + log.Info(ctx, "taskId = ", newTaskId) return "", fmt.Errorf("failed to rollback app-serve application. Err: %s", err) } - log.Info("Updating app status to 'ROLLBACKING'..") + log.Info(ctx, "Updating app status to 'ROLLBACKING'..") err = u.repo.UpdateStatus(ctx, appId, newTaskId, "ROLLBACKING", "") if err != nil { - log.Debug("appId = ", appId) - log.Debug("taskId = ", newTaskId) + log.Debug(ctx, "appId = ", appId) + log.Debug(ctx, "taskId = ", newTaskId) return "", fmt.Errorf("failed to update app status on RollbackAppServeApp. Err: %s", err) } // Call argo workflow workflow := "rollback-java-app" - log.Info("Submitting workflow: ", workflow) + log.Info(ctx, "Submitting workflow: ", workflow) - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ "organization_id=" + app.OrganizationId, "target_cluster_id=" + app.TargetClusterId, @@ -714,10 +714,10 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(ctx context.Context, appId stri }, }) if err != nil { - log.Error("Failed to submit workflow. Err:", err) + log.Error(ctx, "Failed to submit workflow. Err:", err) return "", fmt.Errorf("failed to submit workflow. Err: %s", err) } - log.Info("Successfully submitted workflow: ", workflowId) + log.Info(ctx, "Successfully submitted workflow: ", workflowId) return fmt.Sprintf("Rollback app Request '%v' is successfully submitted", taskId), nil } diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index a85c2c09..485a60a6 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -75,7 +75,7 @@ func (u *AuthUsecase) Login(ctx context.Context, accountId string, password stri } var accountToken *model.User - accountToken, err = u.kc.Login(accountId, password, organizationId) + accountToken, err = u.kc.Login(ctx, accountId, password, organizationId) if err != nil { apiErr, ok := err.(*gocloak.APIError) if ok { @@ -85,11 +85,6 @@ func (u *AuthUsecase) Login(ctx context.Context, accountId string, password stri } return model.User{}, httpErrors.NewInternalServerError(err, "", "") } - log.Errorf("err: %v", err) - if err != nil { - //TODO: implement not found handling - return model.User{}, err - } // Insert token user.Token = accountToken.Token @@ -103,7 +98,7 @@ func (u *AuthUsecase) Login(ctx context.Context, accountId string, password stri func (u *AuthUsecase) Logout(ctx context.Context, accessToken string, organizationName string) error { // [TODO] refresh token 을 추가하고, session timeout 을 줄이는 방향으로 고려할 것 - err := u.kc.Logout(accessToken, organizationName) + err := u.kc.Logout(ctx, accessToken, organizationName) if err != nil { return err } @@ -159,7 +154,7 @@ func (u *AuthUsecase) FindPassword(ctx context.Context, code string, accountId s } randomPassword := helper.GenerateRandomString(passwordLength) - originUser, err := u.kc.GetUser(organizationId, accountId) + originUser, err := u.kc.GetUser(ctx, organizationId, accountId) if err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -170,7 +165,7 @@ func (u *AuthUsecase) FindPassword(ctx context.Context, code string, accountId s Temporary: gocloak.BoolP(false), }, } - if err = u.kc.UpdateUser(organizationId, originUser); err != nil { + if err = u.kc.UpdateUser(ctx, organizationId, originUser); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -178,15 +173,15 @@ func (u *AuthUsecase) FindPassword(ctx context.Context, code string, accountId s return httpErrors.NewInternalServerError(err, "", "") } - message, err := mail.MakeTemporaryPasswordMessage(email, organizationId, accountId, randomPassword) + message, err := mail.MakeTemporaryPasswordMessage(ctx, email, organizationId, accountId, randomPassword) if err != nil { - log.Errorf("mail.MakeVerityIdentityMessage error. %v", err) + log.Errorf(ctx, "mail.MakeVerityIdentityMessage error. %v", err) return httpErrors.NewInternalServerError(err, "", "") } mailer := mail.New(message) - if err := mailer.SendMail(); err != nil { + if err := mailer.SendMail(ctx); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -216,7 +211,7 @@ func (u *AuthUsecase) VerifyIdentity(ctx context.Context, accountId string, emai return httpErrors.NewInternalServerError(err, "", "") } - code, err := helper.GenerateEmailCode() + code, err := helper.GenerateEmailCode(ctx) if err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -231,16 +226,16 @@ func (u *AuthUsecase) VerifyIdentity(ctx context.Context, accountId string, emai } } - message, err := mail.MakeVerityIdentityMessage(email, code) + message, err := mail.MakeVerityIdentityMessage(ctx, email, code) if err != nil { - log.Errorf("mail.MakeVerityIdentityMessage error. %v", err) + log.Errorf(ctx, "mail.MakeVerityIdentityMessage error. %v", err) return httpErrors.NewInternalServerError(err, "", "") } mailer := mail.New(message) - if err := mailer.SendMail(); err != nil { - log.Errorf("mailer.SendMail error. %v", err) + if err := mailer.SendMail(ctx); err != nil { + log.Errorf(ctx, "mailer.SendMail error. %v", err) return httpErrors.NewInternalServerError(err, "", "") } @@ -248,7 +243,7 @@ func (u *AuthUsecase) VerifyIdentity(ctx context.Context, accountId string, emai } func (u *AuthUsecase) SingleSignIn(ctx context.Context, organizationId, accountId, password string) ([]*http.Cookie, error) { - cookies, err := makingCookie(organizationId, accountId, password) + cookies, err := makingCookie(ctx, organizationId, accountId, password) if err != nil { return nil, err } @@ -319,7 +314,7 @@ func (u *AuthUsecase) VerifyToken(ctx context.Context, token string) (bool, erro return false, fmt.Errorf("organization is not found in token") } - isActive, err := u.kc.VerifyAccessToken(token, org) + isActive, err := u.kc.VerifyAccessToken(ctx, token, org) if err != nil { return false, err } @@ -364,7 +359,7 @@ func extractFormAction(htmlContent string) (string, error) { return f(doc), nil } -func makingCookie(organizationId, userName, password string) ([]*http.Cookie, error) { +func makingCookie(ctx context.Context, organizationId, userName, password string) ([]*http.Cookie, error) { stateCode, err := genStateString() if err != nil { return nil, err @@ -394,7 +389,7 @@ func makingCookie(organizationId, userName, password string) ([]*http.Cookie, er req.Header.Add("Accept", "text/html") resp, err := client.Do(req) if err != nil { - log.Errorf("Error while creating new request: %v", err) + log.Errorf(ctx, "Error while creating new request: %v", err) return nil, err } cookies := resp.Cookies() @@ -410,7 +405,7 @@ func makingCookie(organizationId, userName, password string) ([]*http.Cookie, er s, err := extractFormAction(htmlContent) if err != nil { - log.Errorf("Error while creating new request: %v", err) + log.Errorf(ctx, "Error while creating new request: %v", err) return nil, err } diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index 9763c2bd..5de5c4f2 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -91,6 +91,7 @@ func (u *CloudAccountUsecase) Create(ctx context.Context, dto model.CloudAccount } workflowId, err := u.argo.SumbitWorkflowFromWftpl( + ctx, "tks-create-aws-cloud-account", argowf.SubmitOptions{ Parameters: []string{ @@ -196,6 +197,7 @@ func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount } workflowId, err := u.argo.SumbitWorkflowFromWftpl( + ctx, "tks-delete-aws-cloud-account", argowf.SubmitOptions{ Parameters: []string{ @@ -249,7 +251,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount return false, out, err } - awsAccessKeyId, awsSecretAccessKey, _ := kubernetes.GetAwsSecret() + awsAccessKeyId, awsSecretAccessKey, _ := kubernetes.GetAwsSecret(ctx) if err != nil || awsAccessKeyId == "" || awsSecretAccessKey == "" { log.Error(ctx, err) return false, out, httpErrors.NewInternalServerError(fmt.Errorf("Invalid aws secret."), "", "") @@ -368,7 +370,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount if err != nil { return false, out, err } - log.DebugfWithContext(ctx, "%s %s %v", *res.Quota.QuotaName, *res.Quota.QuotaCode, *res.Quota.Value) + log.Debugf(ctx, "%s %s %v", *res.Quota.QuotaName, *res.Quota.QuotaCode, *res.Quota.Value) quotaValue := int(*res.Quota.Value) @@ -380,7 +382,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount // Cluster 1 switch key { case "L-69A177A2": // NLB - log.InfofWithContext(ctx, "NLB : usage %d, quota %d", currentUsage.NLB, quotaValue) + log.Infof(ctx, "NLB : usage %d, quota %d", currentUsage.NLB, quotaValue) out.Quotas = append(out.Quotas, domain.ResourceQuotaAttr{ Type: "NLB", Usage: currentUsage.NLB, @@ -391,7 +393,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount available = false } case "L-E9E9831D": // Classic - log.InfofWithContext(ctx, "CLB : usage %d, quota %d", currentUsage.CLB, quotaValue) + log.Infof(ctx, "CLB : usage %d, quota %d", currentUsage.CLB, quotaValue) out.Quotas = append(out.Quotas, domain.ResourceQuotaAttr{ Type: "CLB", Usage: currentUsage.CLB, @@ -402,7 +404,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount available = false } case "L-A4707A72": // IGW - log.InfofWithContext(ctx, "IGW : usage %d, quota %d", currentUsage.IGW, quotaValue) + log.Infof(ctx, "IGW : usage %d, quota %d", currentUsage.IGW, quotaValue) out.Quotas = append(out.Quotas, domain.ResourceQuotaAttr{ Type: "IGW", Usage: currentUsage.IGW, @@ -413,7 +415,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount available = false } case "L-1194D53C": // Cluster - log.InfofWithContext(ctx, "Cluster : usage %d, quota %d", currentUsage.Cluster, quotaValue) + log.Infof(ctx, "Cluster : usage %d, quota %d", currentUsage.Cluster, quotaValue) out.Quotas = append(out.Quotas, domain.ResourceQuotaAttr{ Type: "EKS", Usage: currentUsage.Cluster, @@ -424,7 +426,7 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount available = false } case "L-0263D0A3": // Elastic IP - log.InfofWithContext(ctx, "Elastic IP : usage %d, quota %d", currentUsage.EIP, quotaValue) + log.Infof(ctx, "Elastic IP : usage %d, quota %d", currentUsage.EIP, quotaValue) out.Quotas = append(out.Quotas, domain.ResourceQuotaAttr{ Type: "EIP", Usage: currentUsage.EIP, @@ -447,7 +449,7 @@ func (u *CloudAccountUsecase) getClusterCnt(ctx context.Context, cloudAccountId clusters, err := u.clusterRepo.FetchByCloudAccountId(ctx, cloudAccountId, nil) if err != nil { - log.Error("Failed to get clusters by cloudAccountId. err : ", err) + log.Error(ctx, "Failed to get clusters by cloudAccountId. err : ", err) return cnt } diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index 4fdb01b5..52fb3287 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -184,6 +184,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster } workflowId, err := u.argo.SumbitWorkflowFromWftpl( + ctx, "create-tks-usercluster", argowf.SubmitOptions{ Parameters: []string{ @@ -249,6 +250,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster kubeconfigBase64 := base64.StdEncoding.EncodeToString([]byte(dto.Kubeconfig)) workflowId, err := u.argo.SumbitWorkflowFromWftpl( + ctx, "import-tks-usercluster", argowf.SubmitOptions{ Parameters: []string{ @@ -290,7 +292,7 @@ func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clus if err != nil { return "", httpErrors.NewBadRequestError(errors.Wrap(err, "Invalid stackTemplateId"), "", "") } - log.InfofWithContext(ctx, "%s %s", stackTemplate.CloudService, dto.CloudService) + log.Infof(ctx, "%s %s", stackTemplate.CloudService, dto.CloudService) if stackTemplate.CloudService != dto.CloudService { return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid cloudService for stackTemplate "), "", "") } @@ -303,7 +305,7 @@ func (u *ClusterUsecase) Bootstrap(ctx context.Context, dto model.Cluster) (clus } workflow := "create-byoh-bootstrapkubeconfig" - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ fmt.Sprintf("tks_api_url=%s", viper.GetString("external-address")), "cluster_id=" + clusterId.String(), @@ -345,6 +347,7 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId } workflowId, err := u.argo.SumbitWorkflowFromWftpl( + ctx, "create-tks-usercluster", argowf.SubmitOptions{ Parameters: []string{ @@ -419,6 +422,7 @@ func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) } workflowId, err := u.argo.SumbitWorkflowFromWftpl( + ctx, "tks-remove-usercluster", argowf.SubmitOptions{ Parameters: []string{ @@ -435,7 +439,7 @@ func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) return errors.Wrap(err, "Failed to call argo workflow") } - log.DebugWithContext(ctx, "submited workflow name : ", workflowId) + log.Debug(ctx, "submited workflow name : ", workflowId) if err := u.repo.InitWorkflow(ctx, clusterId, workflowId, domain.ClusterStatus_DELETING); err != nil { return errors.Wrap(err, "Failed to initialize status") @@ -489,7 +493,7 @@ func (u *ClusterUsecase) CreateBootstrapKubeconfig(ctx context.Context, clusterI } workflow := "create-byoh-bootstrapkubeconfig" - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ fmt.Sprintf("tks_api_url=%s", viper.GetString("external-address")), "cluster_id=" + clusterId.String(), @@ -499,17 +503,17 @@ func (u *ClusterUsecase) CreateBootstrapKubeconfig(ctx context.Context, clusterI log.Error(ctx, err) return out, httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") } - log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) + log.Debug(ctx, "Submitted workflow: ", workflowId) // wait & get clusterId ( max 1min ) for i := 0; i < 60; i++ { time.Sleep(time.Second * 3) - workflow, err := u.argo.GetWorkflow("argo", workflowId) + workflow, err := u.argo.GetWorkflow(ctx, "argo", workflowId) if err != nil { return out, err } - log.DebugWithContext(ctx, "workflow ", workflow) + log.Debug(ctx, "workflow ", workflow) if workflow.Status.Phase == "Succeeded" { break @@ -532,7 +536,7 @@ func (u *ClusterUsecase) GetBootstrapKubeconfig(ctx context.Context, clusterId d if err != nil { return out, httpErrors.NewNotFoundError(err, "", "") } - client, err := kubernetes.GetClientAdminCluster() + client, err := kubernetes.GetClientAdminCluster(ctx) if err != nil { return out, err } @@ -553,7 +557,7 @@ func (u *ClusterUsecase) GetBootstrapKubeconfig(ctx context.Context, clusterId d return out, err } - log.DebugWithContext(ctx, helper.ModelToJson(kubeconfig.Status.BootstrapKubeconfigData)) + log.Debug(ctx, helper.ModelToJson(kubeconfig.Status.BootstrapKubeconfigData)) type BootstrapKubeconfigUser struct { Users []struct { @@ -580,7 +584,7 @@ func (u *ClusterUsecase) GetBootstrapKubeconfig(ctx context.Context, clusterId d return out, err } - log.Info(secrets.Data["expiration"][:]) + log.Info(ctx, secrets.Data["expiration"][:]) // 2023-10-17T11:05:33Z now := time.Now() @@ -610,7 +614,7 @@ func (u *ClusterUsecase) GetNodes(ctx context.Context, clusterId domain.ClusterI return out, httpErrors.NewBadRequestError(fmt.Errorf("Invalid cloud service"), "", "") } - client, err := kubernetes.GetClientAdminCluster() + client, err := kubernetes.GetClientAdminCluster(ctx) if err != nil { return out, err } @@ -815,9 +819,9 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clust var found bool = false for key, val := range azPerRegion { if strings.Contains(key, region) { - log.DebugWithContext(ctx,"Found region : ", key) + log.Debug(ctx,"Found region : ", key) maxAzForSelectedRegion = val - log.DebugWithContext(ctx,"Trimmed azNum var: ", maxAzForSelectedRegion) + log.Debug(ctx,"Trimmed azNum var: ", maxAzForSelectedRegion) found = true } } @@ -835,14 +839,14 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clust // Validate if machineReplicas is multiple of number of AZ replicas := int(rawConf.MachineReplicas) if replicas == 0 { - log.DebugWithContext(ctx,"No machineReplicas param. Using default values..") + log.Debug(ctx,"No machineReplicas param. Using default values..") } else { if remainder := replicas % numOfAz; remainder != 0 { log.Error(ctx,"Invalid machineReplicas: it should be multiple of numOfAz ", numOfAz) temp_err := fmt.Errorf("Invalid machineReplicas: it should be multiple of numOfAz %d", numOfAz) return nil, temp_err } else { - log.DebugWithContext(ctx,"Valid replicas and numOfAz. Caculating minSize & maxSize..") + log.Debug(ctx,"Valid replicas and numOfAz. Caculating minSize & maxSize..") minSizePerAz = int(replicas / numOfAz) maxSizePerAz = minSizePerAz * 5 @@ -851,8 +855,8 @@ func (u *ClusterUsecase) constructClusterConf(rawConf *model.ClusterConf) (clust fmt.Printf("maxSizePerAz exceeded maximum value %d, so adjusted to %d", MAX_SIZE_PER_AZ, MAX_SIZE_PER_AZ) maxSizePerAz = MAX_SIZE_PER_AZ } - log.DebugWithContext(ctx,"Derived minSizePerAz: ", minSizePerAz) - log.DebugWithContext(ctx,"Derived maxSizePerAz: ", maxSizePerAz) + log.Debug(ctx,"Derived minSizePerAz: ", minSizePerAz) + log.Debug(ctx,"Derived maxSizePerAz: ", maxSizePerAz) } } diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 0e40c7d2..12d15d91 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -83,17 +83,17 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) log.Error(ctx, err) return out, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } - address, port := helper.SplitAddress(thanosUrl) + address, port := helper.SplitAddress(ctx, thanosUrl) thanosClient, err := thanos.New(address, port, false, "") if err != nil { return out, errors.Wrap(err, "failed to create thanos client") } - stackMemoryDisk, err := thanosClient.Get("sum by (__name__, taco_cluster) ({__name__=~\"node_memory_MemFree_bytes|machine_memory_bytes|kubelet_volume_stats_used_bytes|kubelet_volume_stats_capacity_bytes\"})") + stackMemoryDisk, err := thanosClient.Get(ctx, "sum by (__name__, taco_cluster) ({__name__=~\"node_memory_MemFree_bytes|machine_memory_bytes|kubelet_volume_stats_used_bytes|kubelet_volume_stats_capacity_bytes\"})") if err != nil { return out, err } - stackCpu, err := thanosClient.Get("avg by (taco_cluster) (instance:node_cpu:ratio*100)") + stackCpu, err := thanosClient.Get(ctx, "avg by (taco_cluster) (instance:node_cpu:ratio*100)") if err != nil { return out, err } @@ -103,7 +103,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) if err != nil { return nil, err } - stack := reflectClusterToStack(cluster, appGroups) + stack := reflectClusterToStack(ctx, cluster, appGroups) dashboardStack := domain.DashboardStack{} if err := serializer.Map(stack, &dashboardStack); err != nil { log.Info(ctx, err) @@ -142,7 +142,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri log.Error(ctx, err) return out, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } - address, port := helper.SplitAddress(thanosUrl) + address, port := helper.SplitAddress(ctx, thanosUrl) thanosClient, err := thanos.New(address, port, false, "") if err != nil { return out, errors.Wrap(err, "failed to create thanos client") @@ -167,7 +167,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri /* {"data":{"result":[{"metric":{"taco_cluster":"cmsai5k5l"},"value":[1683608185.65,"32"]},{"metric":{"taco_cluster":"crjfh12oc"},"value":[1683608185.65,"12"]}],"vector":""},"status":"success"} */ - result, err := thanosClient.Get("sum by (taco_cluster) (machine_cpu_cores)") + result, err := thanosClient.Get(ctx, "sum by (taco_cluster) (machine_cpu_cores)") if err != nil { return out, err } @@ -184,7 +184,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri out.Cpu = fmt.Sprintf("%d 개", cpu) // Memory - result, err = thanosClient.Get("sum by (taco_cluster) (machine_memory_bytes)") + result, err = thanosClient.Get(ctx, "sum by (taco_cluster) (machine_memory_bytes)") if err != nil { return out, err } @@ -202,7 +202,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri out.Memory = fmt.Sprintf("%v GiB", math.Round(memory)) // Storage - result, err = thanosClient.Get("sum by (taco_cluster) (kubelet_volume_stats_capacity_bytes)") + result, err = thanosClient.Get(ctx, "sum by (taco_cluster) (kubelet_volume_stats_capacity_bytes)") if err != nil { return out, err } @@ -225,10 +225,10 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri func (u *DashboardUsecase) getChartFromPrometheus(ctx context.Context, organizationId string, chartType string, duration string, interval string, year string, month string) (res domain.DashboardChart, err error) { thanosUrl, err := u.getThanosUrl(ctx, organizationId) if err != nil { - log.Error(err) + log.Error(ctx, err) return res, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } - address, port := helper.SplitAddress(thanosUrl) + address, port := helper.SplitAddress(ctx, thanosUrl) thanosClient, err := thanos.New(address, port, false, "") if err != nil { return res, errors.Wrap(err, "failed to create thanos client") @@ -296,7 +296,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(ctx context.Context, organizat return res, err } - log.Info(organization.CreatedAt.Format("2006-01-02")) + log.Info(ctx, organization.CreatedAt.Format("2006-01-02")) podCounts := []domain.PodCount{} for day := rangeDate(startDate, endDate); ; { @@ -341,7 +341,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(ctx context.Context, organizat return domain.DashboardChart{}, fmt.Errorf("No data") } - result, err := thanosClient.FetchRange(query, int(now.Unix())-durationSec, int(now.Unix()), intervalSec) + result, err := thanosClient.FetchRange(ctx, query, int(now.Unix())-durationSec, int(now.Unix()), intervalSec) if err != nil { return res, err } @@ -419,7 +419,7 @@ func (u *DashboardUsecase) getThanosUrl(ctx context.Context, organizationId stri return out, fmt.Errorf("Invalid primary clusterId") } - clientset_admin, err := kubernetes.GetClientAdminCluster() + clientset_admin, err := kubernetes.GetClientAdminCluster(ctx) if err != nil { return out, errors.Wrap(err, "Failed to get client set for user cluster") } @@ -427,9 +427,9 @@ func (u *DashboardUsecase) getThanosUrl(ctx context.Context, organizationId stri // tks-endpoint-secret 이 있다면 그 secret 내의 endpoint 를 사용한다. secrets, err := clientset_admin.CoreV1().Secrets(organization.PrimaryClusterId).Get(context.TODO(), "tks-endpoint-secret", metav1.GetOptions{}) if err != nil { - log.Info("cannot found tks-endpoint-secret. so use LoadBalancer...") + log.Info(ctx, "cannot found tks-endpoint-secret. so use LoadBalancer...") - clientset_user, err := kubernetes.GetClientFromClusterId(organization.PrimaryClusterId) + clientset_user, err := kubernetes.GetClientFromClusterId(ctx, organization.PrimaryClusterId) if err != nil { return out, errors.Wrap(err, "Failed to get client set for user cluster") } @@ -456,7 +456,7 @@ func (u *DashboardUsecase) getThanosUrl(ctx context.Context, organizationId stri } } else { out = "http://" + string(secrets.Data["thanos"]) - log.Info("thanosUrl : ", out) + log.Info(ctx, "thanosUrl : ", out) u.cache.Set(prefix+organizationId, out, gcache.DefaultExpiration) return out, nil } diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 72d30e3c..7fe6ea4f 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -57,7 +57,7 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization in.CreatorId = &userId // Create realm in keycloak - if organizationId, err = u.kc.CreateRealm(helper.GenerateOrganizationId()); err != nil { + if organizationId, err = u.kc.CreateRealm(ctx, helper.GenerateOrganizationId()); err != nil { return "", err } in.ID = organizationId @@ -69,6 +69,7 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization } workflowId, err := u.argo.SumbitWorkflowFromWftpl( + ctx, "tks-create-contract-repo", argowf.SubmitOptions{ Parameters: []string{ @@ -119,7 +120,7 @@ func (u *OrganizationUsecase) Delete(ctx context.Context, organizationId string, } // Delete realm in keycloak - if err := u.kc.DeleteRealm(organizationId); err != nil { + if err := u.kc.DeleteRealm(ctx, organizationId); err != nil { return err } diff --git a/internal/usecase/project.go b/internal/usecase/project.go index b3d0e1a3..2fa7d364 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -199,7 +199,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne if err != nil { return err } - log.Infof("Added project member: %s", res) + log.Infof(ctx, "Added project member: %s", res) } else { pm.ProjectUserId = pu.ID pm.ProjectRoleId = projectRoleId @@ -498,7 +498,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o return nil } func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { - kubeconfig, err := kubernetes.GetKubeConfig(stackId) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -510,19 +510,19 @@ func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizat return errors.Wrap(err, "Failed to create project namespace.") } - err = kubernetes.EnsureClusterRole(kubeconfig, pr.Name) + err = kubernetes.EnsureClusterRole(ctx, kubeconfig, pr.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = kubernetes.EnsureCommonClusterRole(kubeconfig, pr.Name) + err = kubernetes.EnsureCommonClusterRole(ctx, kubeconfig, pr.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = kubernetes.EnsureCommonClusterRoleBinding(kubeconfig, pr.Name) + err = kubernetes.EnsureCommonClusterRoleBinding(ctx, kubeconfig, pr.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -531,7 +531,7 @@ func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizat return nil } func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { - kubeconfig, err := kubernetes.GetKubeConfig(stackId) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -543,19 +543,19 @@ func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizat return errors.Wrap(err, "Failed to create project namespace.") } - err = kubernetes.RemoveClusterRole(kubeconfig, pr.Name) + err = kubernetes.RemoveClusterRole(ctx, kubeconfig, pr.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = kubernetes.RemoveCommonClusterRole(kubeconfig, pr.Name) + err = kubernetes.RemoveCommonClusterRole(ctx, kubeconfig, pr.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = kubernetes.RemoveCommonClusterRoleBinding(kubeconfig, pr.Name) + err = kubernetes.RemoveCommonClusterRoleBinding(ctx, kubeconfig, pr.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -566,7 +566,7 @@ func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizat func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, stackId string) error { // create Roles in keycloak for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { - err := u.kc.EnsureClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) + err := u.kc.EnsureClientRoleWithClientName(ctx, organizationId, stackId+"-k8s-api", role+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -579,7 +579,7 @@ func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organiza // delete Roles in keycloak for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { - err := u.kc.DeleteClientRoleWithClientName(organizationId, stackId+"-k8s-api", role+"@"+projectId) + err := u.kc.DeleteClientRoleWithClientName(ctx, organizationId, stackId+"-k8s-api", role+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -588,7 +588,7 @@ func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organiza return nil } func (u *ProjectUsecase) CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error { - kubeconfig, err := kubernetes.GetKubeConfig(stackId) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -600,7 +600,7 @@ func (u *ProjectUsecase) CreateK8SNSRoleBinding(ctx context.Context, organizatio return errors.Wrap(err, "Failed to create project namespace.") } - err = kubernetes.EnsureRoleBinding(kubeconfig, pr.Name, namespace) + err = kubernetes.EnsureRoleBinding(ctx, kubeconfig, pr.Name, namespace) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -624,7 +624,7 @@ func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, o } func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { - err := u.kc.AssignClientRoleToUser(organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) + err := u.kc.AssignClientRoleToUser(ctx, organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -643,7 +643,7 @@ func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, } func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { - err := u.kc.UnassignClientRoleToUser(organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) + err := u.kc.UnassignClientRoleToUser(ctx, organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -682,7 +682,7 @@ func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationI kubeconfigs := make([]string, 0) for _, pn := range projectNamespaces { - kubeconfig, err := kubernetes.GetKubeConfig(pn.StackId) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, pn.StackId) if err != nil { log.Error(ctx, err) return "", errors.Wrap(err, "Failed to retrieve kubeconfig.") @@ -714,7 +714,7 @@ func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId str return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } - clientset_user, err := kubernetes.GetClientFromClusterId(stackId.String()) + clientset_user, err := kubernetes.GetClientFromClusterId(ctx, stackId.String()) if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get clientset : stackId %s", stackId)) } diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index e27bfd56..f49dc70c 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -86,7 +86,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom if len(clusters) == 0 { isPrimary = true } - log.DebugWithContext(ctx, "isPrimary ", isPrimary) + log.Debug(ctx, "isPrimary ", isPrimary) if dto.CloudService == domain.CloudService_BYOH { if dto.ClusterEndpoint == "" { @@ -122,7 +122,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom } workflow := "tks-stack-create" - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ fmt.Sprintf("tks_api_url=%s", viper.GetString("external-address")), "cluster_name=" + dto.Name, @@ -141,18 +141,18 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom log.Error(ctx, err) return "", httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") } - log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) + log.Debug(ctx, "Submitted workflow: ", workflowId) // wait & get clusterId ( max 1min ) dto.ID = domain.StackId("") for i := 0; i < 60; i++ { time.Sleep(time.Second * 5) - workflow, err := u.argo.GetWorkflow("argo", workflowId) + workflow, err := u.argo.GetWorkflow(ctx, "argo", workflowId) if err != nil { return "", err } - log.DebugWithContext(ctx, "workflow ", workflow) + log.Debug(ctx, "workflow ", workflow) if workflow.Status.Phase != "" && workflow.Status.Phase != "Running" { return "", fmt.Errorf("Invalid workflow status [%s]", workflow.Status.Phase) } @@ -189,7 +189,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err if len(clusters) == 0 { isPrimary = true } - log.DebugWithContext(ctx, "isPrimary ", isPrimary) + log.Debug(ctx, "isPrimary ", isPrimary) if cluster.CloudService != domain.CloudService_BYOH { return httpErrors.NewBadRequestError(fmt.Errorf("Invalid cloud service"), "S_INVALID_CLOUD_SERVICE", "") @@ -202,7 +202,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err } workflow := "tks-stack-install" - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ fmt.Sprintf("tks_api_url=%s", viper.GetString("external-address")), "cluster_id=" + cluster.ID.String(), @@ -217,7 +217,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err log.Error(ctx, err) return httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") } - log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) + log.Debug(ctx, "Submitted workflow: ", workflowId) return nil } @@ -242,7 +242,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod } stackResources, _ := u.dashbordUsecase.GetStacks(ctx, cluster.OrganizationId) - out = reflectClusterToStack(cluster, appGroups) + out = reflectClusterToStack(ctx, cluster, appGroups) if organization.PrimaryClusterId == cluster.ID.String() { out.PrimaryCluster = true @@ -251,7 +251,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod for _, resource := range stackResources { if resource.ID == domain.StackId(cluster.ID) { if err := serializer.Map(resource, &out.Resource); err != nil { - log.Error(err) + log.Error(ctx, err) } } } @@ -290,7 +290,7 @@ func (u *StackUsecase) GetByName(ctx context.Context, organizationId string, nam return out, err } - out = reflectClusterToStack(cluster, appGroups) + out = reflectClusterToStack(ctx, cluster, appGroups) return } @@ -318,7 +318,7 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag return nil, err } - outStack := reflectClusterToStack(cluster, appGroups) + outStack := reflectClusterToStack(ctx, cluster, appGroups) if organization.PrimaryClusterId == cluster.ID.String() { outStack.PrimaryCluster = true } @@ -338,7 +338,7 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag for _, resource := range stackResources { if resource.ID == domain.StackId(cluster.ID) { if err := serializer.Map(resource, &outStack.Resource); err != nil { - log.Error(err) + log.Error(ctx, err) } } } @@ -437,7 +437,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) // [TODO] BYOH 삭제는 어떻게 처리하는게 좋은가? workflow := "tks-stack-delete" - workflowId, err := u.argo.SumbitWorkflowFromWftpl(workflow, argowf.SubmitOptions{ + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ fmt.Sprintf("tks_api_url=%s", viper.GetString("external-address")), "organization_id=" + dto.OrganizationId, @@ -450,7 +450,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) log.Error(ctx, err) return err } - log.DebugWithContext(ctx, "Submitted workflow: ", workflowId) + log.Debug(ctx, "Submitted workflow: ", workflowId) // Remove Cluster & AppGroup status description if err := u.appGroupRepo.InitWorkflowDescription(ctx, cluster.ID); err != nil { @@ -463,7 +463,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) // wait & get clusterId ( max 1min ) for i := 0; i < 60; i++ { time.Sleep(time.Second * 2) - workflow, err := u.argo.GetWorkflow("argo", workflowId) + workflow, err := u.argo.GetWorkflow(ctx, "argo", workflowId) if err != nil { return err } @@ -482,7 +482,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) } func (u *StackUsecase) GetKubeConfig(ctx context.Context, stackId domain.StackId) (kubeConfig string, err error) { - kubeconfig, err := kubernetes.GetKubeConfig(stackId.String()) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId.String()) //kubeconfig, err := kubernetes.GetKubeConfig("cmsai5k5l") if err != nil { return "", err @@ -618,9 +618,9 @@ func (u *StackUsecase) DeleteFavorite(ctx context.Context, stackId domain.StackI return nil } -func reflectClusterToStack(cluster model.Cluster, appGroups []model.AppGroup) (out model.Stack) { +func reflectClusterToStack(ctx context.Context, cluster model.Cluster, appGroups []model.AppGroup) (out model.Stack) { if err := serializer.Map(cluster, &out); err != nil { - log.Error(err) + log.Error(ctx, err) } status, statusDesc := getStackStatus(cluster, appGroups) diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 92cb6fe4..5730e87d 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -64,7 +64,7 @@ func (u *UserUsecase) RenewalPasswordExpiredTime(ctx context.Context, userId uui err = u.userRepository.UpdatePasswordAt(ctx, userId, user.Organization.ID, false) if err != nil { - log.ErrorfWithContext(ctx, "failed to update password expired time: %v", err) + log.Errorf(ctx, "failed to update password expired time: %v", err) return httpErrors.NewInternalServerError(err, "", "") } @@ -89,7 +89,7 @@ func (u *UserUsecase) ResetPassword(ctx context.Context, userId uuid.UUID) error return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") } } - userInKeycloak, err := u.kc.GetUser(user.Organization.ID, user.AccountId) + userInKeycloak, err := u.kc.GetUser(ctx, user.Organization.ID, user.AccountId) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") @@ -105,7 +105,7 @@ func (u *UserUsecase) ResetPassword(ctx context.Context, userId uuid.UUID) error Temporary: gocloak.BoolP(false), }, } - if err = u.kc.UpdateUser(user.Organization.ID, userInKeycloak); err != nil { + if err = u.kc.UpdateUser(ctx, user.Organization.ID, userInKeycloak); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -113,15 +113,15 @@ func (u *UserUsecase) ResetPassword(ctx context.Context, userId uuid.UUID) error return httpErrors.NewInternalServerError(err, "", "") } - message, err := mail.MakeTemporaryPasswordMessage(user.Email, user.Organization.ID, user.AccountId, randomPassword) + message, err := mail.MakeTemporaryPasswordMessage(ctx, user.Email, user.Organization.ID, user.AccountId, randomPassword) if err != nil { - log.Errorf("mail.MakeVerityIdentityMessage error. %v", err) + log.Errorf(ctx, "mail.MakeVerityIdentityMessage error. %v", err) return httpErrors.NewInternalServerError(err, "", "") } mailer := mail.New(message) - if err := mailer.SendMail(); err != nil { + if err := mailer.SendMail(ctx); err != nil { return httpErrors.NewInternalServerError(err, "", "") } @@ -148,7 +148,7 @@ func (u *UserUsecase) ValidateAccount(ctx context.Context, userId uuid.UUID, pas if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") } - _, err = u.kc.Login(user.AccountId, password, organizationId) + _, err = u.kc.Login(ctx, user.AccountId, password, organizationId) if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("invalid password"), "A_INVALID_PASSWORD", "") } @@ -156,7 +156,7 @@ func (u *UserUsecase) ValidateAccount(ctx context.Context, userId uuid.UUID, pas } func (u *UserUsecase) ValidateAccountByAccountId(ctx context.Context, accountId string, password string, organizationId string) error { - _, err := u.kc.Login(organizationId, accountId, password) + _, err := u.kc.Login(ctx, organizationId, accountId, password) return err } @@ -173,12 +173,12 @@ func (u *UserUsecase) DeleteAll(ctx context.Context, organizationId string) erro } func (u *UserUsecase) DeleteAdmin(ctx context.Context, organizationId string) error { - user, err := u.kc.GetUser(organizationId, "admin") + user, err := u.kc.GetUser(ctx, organizationId, "admin") if err != nil { return errors.Wrap(err, "get user failed") } - err = u.kc.DeleteUser(organizationId, "admin") + err = u.kc.DeleteUser(ctx, organizationId, "admin") if err != nil { return errors.Wrap(err, "delete user failed") } @@ -223,12 +223,12 @@ func (u *UserUsecase) CreateAdmin(ctx context.Context, organizationId string, ac if err != nil { return nil, err } - message, err := mail.MakeGeneratingOrganizationMessage(organizationId, organizationInfo.Name, user.Email, user.AccountId, randomPassword) + message, err := mail.MakeGeneratingOrganizationMessage(ctx, organizationId, organizationInfo.Name, user.Email, user.AccountId, randomPassword) if err != nil { return nil, httpErrors.NewInternalServerError(err, "", "") } mailer := mail.New(message) - if err := mailer.SendMail(); err != nil { + if err := mailer.SendMail(ctx); err != nil { return nil, httpErrors.NewInternalServerError(err, "", "") } @@ -241,14 +241,14 @@ func (u *UserUsecase) SendEmailForTemporaryPassword(ctx context.Context, account return err } - message, err := mail.MakeTemporaryPasswordMessage(user.Email, organizationId, accountId, password) + message, err := mail.MakeTemporaryPasswordMessage(ctx, user.Email, organizationId, accountId, password) if err != nil { return err } mailer := mail.New(message) - if err := mailer.SendMail(); err != nil { + if err := mailer.SendMail(ctx); err != nil { return err } @@ -261,10 +261,10 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s if originPassword == newPassword { return httpErrors.NewBadRequestError(fmt.Errorf("new password is same with origin password"), "A_SAME_OLD_PASSWORD", "") } - if _, err := u.kc.Login(accountId, originPassword, organizationId); err != nil { + if _, err := u.kc.Login(ctx, accountId, originPassword, organizationId); err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("invalid origin password"), "A_INVALID_PASSWORD", "") } - originUser, err := u.kc.GetUser(organizationId, accountId) + originUser, err := u.kc.GetUser(ctx, organizationId, accountId) if err != nil { return err } @@ -276,7 +276,7 @@ func (u *UserUsecase) UpdatePasswordByAccountId(ctx context.Context, accountId s }, } - err = u.kc.UpdateUser(organizationId, originUser) + err = u.kc.UpdateUser(ctx, organizationId, originUser) if err != nil { return errors.Wrap(err, "updating user in keycloak failed") } @@ -358,7 +358,7 @@ func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *model. func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) { var out model.User - originUser, err := u.kc.GetUser(user.Organization.ID, accountId) + originUser, err := u.kc.GetUser(ctx, user.Organization.ID, accountId) if err != nil { return nil, err } @@ -366,7 +366,7 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u if (originUser.Email == nil || *originUser.Email != user.Email) || (originUser.FirstName == nil || *originUser.FirstName != user.Name) { originUser.Email = gocloak.StringP(user.Email) originUser.FirstName = gocloak.StringP(user.Name) - err = u.kc.UpdateUser(user.Organization.ID, originUser) + err = u.kc.UpdateUser(ctx, user.Organization.ID, originUser) if err != nil { return nil, err } @@ -411,7 +411,7 @@ func (u *UserUsecase) Delete(ctx context.Context, userId uuid.UUID, organization } // Delete user in keycloak - err = u.kc.DeleteUser(organizationId, user.AccountId) + err = u.kc.DeleteUser(ctx, organizationId, user.AccountId) if err != nil { return err } @@ -430,7 +430,7 @@ func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, o } // Delete user in keycloak - err = u.kc.DeleteUser(organizationId, accountId) + err = u.kc.DeleteUser(ctx, organizationId, accountId) if err != nil { return err } @@ -441,7 +441,7 @@ func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, o func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User, error) { // Create user in keycloak groups := []string{fmt.Sprintf("%s@%s", user.Role.Name, user.Organization.ID)} - userUuidStr, err := u.kc.CreateUser(user.Organization.ID, &gocloak.User{ + userUuidStr, err := u.kc.CreateUser(ctx, user.Organization.ID, &gocloak.User{ Username: gocloak.StringP(user.AccountId), Credentials: &[]gocloak.CredentialRepresentation{ { @@ -502,12 +502,12 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st if newUser.Role.Name != user.Role.Name { originGroupName := fmt.Sprintf("%s@%s", user.Role.Name, newUser.Organization.ID) newGroupName := fmt.Sprintf("%s@%s", newUser.Role.Name, newUser.Organization.ID) - if err := u.kc.LeaveGroup(newUser.Organization.ID, user.ID.String(), originGroupName); err != nil { - log.ErrorfWithContext(ctx, "leave group in keycloak failed: %v", err) + if err := u.kc.LeaveGroup(ctx, newUser.Organization.ID, user.ID.String(), originGroupName); err != nil { + log.Errorf(ctx, "leave group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } - if err := u.kc.JoinGroup(newUser.Organization.ID, user.ID.String(), newGroupName); err != nil { - log.ErrorfWithContext(ctx, "join group in keycloak failed: %v", err) + if err := u.kc.JoinGroup(ctx, newUser.Organization.ID, user.ID.String(), newGroupName); err != nil { + log.Errorf(ctx, "join group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } } diff --git a/pkg/argo-client/client-mock.go b/pkg/argo-client/client-mock.go index d3a22de5..47891107 100644 --- a/pkg/argo-client/client-mock.go +++ b/pkg/argo-client/client-mock.go @@ -1,6 +1,7 @@ package argowf import ( + "context" "net/http" "time" ) @@ -23,22 +24,22 @@ func NewMock() (ArgoClient, error) { }, nil } -func (c *ArgoClientMockImpl) GetWorkflowTemplates(namespace string) (*GetWorkflowTemplatesResponse, error) { +func (c *ArgoClientMockImpl) GetWorkflowTemplates(ctx context.Context, namespace string) (*GetWorkflowTemplatesResponse, error) { return nil, nil } -func (c *ArgoClientMockImpl) GetWorkflow(namespace string, workflowName string) (*Workflow, error) { +func (c *ArgoClientMockImpl) GetWorkflow(ctx context.Context, namespace string, workflowName string) (*Workflow, error) { return nil, nil } -func (c *ArgoClientMockImpl) GetWorkflowLog(namespace string, container string, workflowName string) (string, error) { +func (c *ArgoClientMockImpl) GetWorkflowLog(ctx context.Context, namespace string, container string, workflowName string) (string, error) { return "", nil } -func (c *ArgoClientMockImpl) GetWorkflows(namespace string) (*GetWorkflowsResponse, error) { +func (c *ArgoClientMockImpl) GetWorkflows(ctx context.Context, namespace string) (*GetWorkflowsResponse, error) { return nil, nil } -func (c *ArgoClientMockImpl) SumbitWorkflowFromWftpl(wftplName string, opts SubmitOptions) (string, error) { +func (c *ArgoClientMockImpl) SumbitWorkflowFromWftpl(ctx context.Context, wftplName string, opts SubmitOptions) (string, error) { return "", nil } diff --git a/pkg/argo-client/client.go b/pkg/argo-client/client.go index b100b5a4..3b10eb50 100644 --- a/pkg/argo-client/client.go +++ b/pkg/argo-client/client.go @@ -2,6 +2,7 @@ package argowf import ( "bytes" + "context" "encoding/json" "fmt" "io" @@ -12,11 +13,11 @@ import ( ) type ArgoClient interface { - GetWorkflowTemplates(namespace string) (*GetWorkflowTemplatesResponse, error) - GetWorkflow(namespace string, workflowName string) (*Workflow, error) - GetWorkflowLog(namespace string, container string, workflowName string) (logs string, err error) - GetWorkflows(namespace string) (*GetWorkflowsResponse, error) - SumbitWorkflowFromWftpl(wftplName string, opts SubmitOptions) (string, error) + GetWorkflowTemplates(ctx context.Context, namespace string) (*GetWorkflowTemplatesResponse, error) + GetWorkflow(ctx context.Context, namespace string, workflowName string) (*Workflow, error) + GetWorkflowLog(ctx context.Context, namespace string, container string, workflowName string) (logs string, err error) + GetWorkflows(ctx context.Context, namespace string) (*GetWorkflowsResponse, error) + SumbitWorkflowFromWftpl(ctx context.Context, wftplName string, opts SubmitOptions) (string, error) } type ArgoClientImpl struct { @@ -46,7 +47,7 @@ func New(host string, port int, ssl bool, token string) (ArgoClient, error) { }, nil } -func (c *ArgoClientImpl) GetWorkflowTemplates(namespace string) (*GetWorkflowTemplatesResponse, error) { +func (c *ArgoClientImpl) GetWorkflowTemplates(ctx context.Context, namespace string) (*GetWorkflowTemplatesResponse, error) { res, err := c.client.Get(fmt.Sprintf("%s/api/v1/workflow-templates/%s", c.url, namespace)) if err != nil { return nil, err @@ -60,7 +61,7 @@ func (c *ArgoClientImpl) GetWorkflowTemplates(namespace string) (*GetWorkflowTem defer func() { if err := res.Body.Close(); err != nil { - log.Error("error closing http body") + log.Error(ctx, "error closing http body") } }() @@ -71,13 +72,13 @@ func (c *ArgoClientImpl) GetWorkflowTemplates(namespace string) (*GetWorkflowTem wftplRes := GetWorkflowTemplatesResponse{} if err := json.Unmarshal(body, &wftplRes); err != nil { - log.Error("an error was unexpected while parsing response from api /workflow template.") + log.Error(ctx, "an error was unexpected while parsing response from api /workflow template.") return nil, err } return &wftplRes, nil } -func (c *ArgoClientImpl) GetWorkflow(namespace string, workflowName string) (*Workflow, error) { +func (c *ArgoClientImpl) GetWorkflow(ctx context.Context, namespace string, workflowName string) (*Workflow, error) { res, err := c.client.Get(fmt.Sprintf("%s/api/v1/workflows/%s/%s", c.url, namespace, workflowName)) if err != nil { return nil, err @@ -91,7 +92,7 @@ func (c *ArgoClientImpl) GetWorkflow(namespace string, workflowName string) (*Wo defer func() { if err := res.Body.Close(); err != nil { - log.Error("error closing http body") + log.Error(ctx, "error closing http body") } }() @@ -102,15 +103,15 @@ func (c *ArgoClientImpl) GetWorkflow(namespace string, workflowName string) (*Wo workflowRes := Workflow{} if err := json.Unmarshal(body, &workflowRes); err != nil { - log.Error("an error was unexpected while parsing response from api /workflow template.") + log.Error(ctx, "an error was unexpected while parsing response from api /workflow template.") return nil, err } return &workflowRes, nil } -func (c *ArgoClientImpl) GetWorkflowLog(namespace string, container string, workflowName string) (logs string, err error) { - log.Info(fmt.Sprintf("%s/api/v1/workflows/%s/%s/log?logOptions.container=%s", c.url, namespace, workflowName, container)) +func (c *ArgoClientImpl) GetWorkflowLog(ctx context.Context, namespace string, container string, workflowName string) (logs string, err error) { + log.Info(ctx, fmt.Sprintf("%s/api/v1/workflows/%s/%s/log?logOptions.container=%s", c.url, namespace, workflowName, container)) res, err := c.client.Get(fmt.Sprintf("%s/api/v1/workflows/%s/%s/log?logOptions.container=%s", c.url, namespace, workflowName, container)) if err != nil { return logs, err @@ -124,7 +125,7 @@ func (c *ArgoClientImpl) GetWorkflowLog(namespace string, container string, work defer func() { if err := res.Body.Close(); err != nil { - log.Error("error closing http body") + log.Error(ctx, "error closing http body") } }() @@ -136,7 +137,7 @@ func (c *ArgoClientImpl) GetWorkflowLog(namespace string, container string, work return string(body[:]), nil } -func (c *ArgoClientImpl) GetWorkflows(namespace string) (*GetWorkflowsResponse, error) { +func (c *ArgoClientImpl) GetWorkflows(ctx context.Context, namespace string) (*GetWorkflowsResponse, error) { res, err := c.client.Get(fmt.Sprintf("%s/api/v1/workflows/%s", c.url, namespace)) if err != nil { return nil, err @@ -150,7 +151,7 @@ func (c *ArgoClientImpl) GetWorkflows(namespace string) (*GetWorkflowsResponse, defer func() { if err := res.Body.Close(); err != nil { - log.Error("error closing http body") + log.Error(ctx, "error closing http body") } }() @@ -161,21 +162,21 @@ func (c *ArgoClientImpl) GetWorkflows(namespace string) (*GetWorkflowsResponse, workflowsRes := GetWorkflowsResponse{} if err := json.Unmarshal(body, &workflowsRes); err != nil { - log.Error("an error was unexpected while parsing response from api /workflow template.") + log.Error(ctx, "an error was unexpected while parsing response from api /workflow template.") return nil, err } return &workflowsRes, nil } -func (c *ArgoClientImpl) SumbitWorkflowFromWftpl(wftplName string, opts SubmitOptions) (string, error) { +func (c *ArgoClientImpl) SumbitWorkflowFromWftpl(ctx context.Context, wftplName string, opts SubmitOptions) (string, error) { reqBody := submitWorkflowRequestBody{ Namespace: "argo", ResourceKind: "WorkflowTemplate", ResourceName: wftplName, SubmitOptions: opts, } - log.Debug("SumbitWorkflowFromWftpl reqBody ", reqBody) + log.Debug(ctx, "SumbitWorkflowFromWftpl reqBody ", reqBody) reqBodyBytes, err := json.Marshal(reqBody) if err != nil { @@ -199,7 +200,7 @@ func (c *ArgoClientImpl) SumbitWorkflowFromWftpl(wftplName string, opts SubmitOp defer func() { if res != nil { if err := res.Body.Close(); err != nil { - log.Error("error closing http body") + log.Error(ctx, "error closing http body") } } }() @@ -211,7 +212,7 @@ func (c *ArgoClientImpl) SumbitWorkflowFromWftpl(wftplName string, opts SubmitOp submitRes := SubmitWorkflowResponse{} if err := json.Unmarshal(body, &submitRes); err != nil { - log.Error("an error was unexpected while parsing response from api /submit.") + log.Error(ctx, "an error was unexpected while parsing response from api /submit.") return "", err } return submitRes.Metadata.Name, nil diff --git a/pkg/domain/mapper.go b/pkg/domain/mapper.go new file mode 100644 index 00000000..e69de29b diff --git a/pkg/httpErrors/httpErrors.go b/pkg/httpErrors/httpErrors.go index 6e5b4464..bde4fd68 100644 --- a/pkg/httpErrors/httpErrors.go +++ b/pkg/httpErrors/httpErrors.go @@ -4,7 +4,6 @@ import ( "net/http" "strings" - "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" ) @@ -71,7 +70,6 @@ func NewRestError(status int, err error, code ErrorCode, text string) IRestError if text != "" { t = text } - log.Info(t) return RestError{ ErrStatus: status, diff --git a/pkg/thanos-client/client.go b/pkg/thanos-client/client.go index 1a6994a5..bb9e360c 100644 --- a/pkg/thanos-client/client.go +++ b/pkg/thanos-client/client.go @@ -1,6 +1,7 @@ package thanos import ( + "context" "encoding/json" "fmt" "io" @@ -13,8 +14,8 @@ import ( ) type ThanosClient interface { - Get(query string) (Metric, error) - FetchRange(query string, start int, end int, step int) (out Metric, err error) + Get(ctx context.Context, query string) (Metric, error) + FetchRange(ctx context.Context, query string, start int, end int, step int) (out Metric, err error) } type ThanosClientImpl struct { @@ -44,10 +45,10 @@ func New(host string, port int, ssl bool, token string) (ThanosClient, error) { }, nil } -func (c *ThanosClientImpl) Get(query string) (out Metric, err error) { +func (c *ThanosClientImpl) Get(ctx context.Context, query string) (out Metric, err error) { url := c.url + "/api/v1/query?query=" + url.QueryEscape(query) - log.Info("url : ", url) + log.Info(ctx, "url : ", url) res, err := c.client.Get(url) if err != nil { return out, err @@ -61,7 +62,7 @@ func (c *ThanosClientImpl) Get(query string) (out Metric, err error) { defer func() { if err := res.Body.Close(); err != nil { - log.Error("error closing http body") + log.Error(ctx, "error closing http body") } }() @@ -75,16 +76,16 @@ func (c *ThanosClientImpl) Get(query string) (out Metric, err error) { return out, err } - log.Info(helper.ModelToJson(out)) + log.Info(ctx, helper.ModelToJson(out)) return } -func (c *ThanosClientImpl) FetchRange(query string, start int, end int, step int) (out Metric, err error) { +func (c *ThanosClientImpl) FetchRange(ctx context.Context, query string, start int, end int, step int) (out Metric, err error) { rangeParam := fmt.Sprintf("&dedup=true&partial_response=false&start=%d&end=%d&step=%d&max_source_resolution=0s", start, end, step) query = url.QueryEscape(query) + rangeParam url := c.url + "/api/v1/query_range?query=" + query - log.Info("url : ", url) + log.Info(ctx, "url : ", url) res, err := c.client.Get(url) if err != nil { return out, err @@ -98,7 +99,7 @@ func (c *ThanosClientImpl) FetchRange(query string, start int, end int, step int defer func() { if err := res.Body.Close(); err != nil { - log.Error("error closing http body") + log.Error(ctx, "error closing http body") } }() From d63313ee5e3025bcec3bccc156d12407922afcd2 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 13 Mar 2024 11:25:02 +0900 Subject: [PATCH 128/502] apply context to policy-template APIs --- internal/delivery/http/policy-template.go | 44 ++++---- internal/repository/policy-template.go | 129 +++++++++++----------- internal/usecase/policy-template.go | 40 +++---- 3 files changed, 107 insertions(+), 106 deletions(-) diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index e747a98f..20590ece 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -63,14 +63,14 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } var dto model.PolicyTemplate if err = serializer.Map(input, &dto); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } policyTemplateId, err := h.usecase.Create(r.Context(), dto) @@ -107,7 +107,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h id, err := uuid.Parse(policyTemplateId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -117,7 +117,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h err = UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -125,7 +125,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h err = h.usecase.Update(r.Context(), id, input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -159,7 +159,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *h id, err := uuid.Parse(policyTemplateId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -172,7 +172,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *h err = h.usecase.Delete(r.Context(), id) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return @@ -206,7 +206,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http id, err := uuid.Parse(policyTemplateId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) return @@ -218,7 +218,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http policyTemplate, err := h.usecase.Get(r.Context(), id) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE", "")) return @@ -230,7 +230,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http var out domain.GetPolicyTemplateResponse if err = serializer.Map(*policyTemplate, &out.PolicyTemplate); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -266,13 +266,13 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt out.PolicyTemplates = make([]domain.PolicyTemplateResponse, len(policyTemplates)) for i, policyTemplate := range policyTemplates { if err := serializer.Map(policyTemplate, &out.PolicyTemplates[i]); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) continue } } if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -300,7 +300,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter id, err := uuid.Parse(policyTemplateId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) return } @@ -308,7 +308,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter policyTemplateVersions, err := h.usecase.ListPolicyTemplateVersions(r.Context(), id) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) return @@ -320,7 +320,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter var out domain.ListPolicyTemplateVersionsResponse if err = serializer.Map(*policyTemplateVersions, &out); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -415,7 +415,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, policyTemplate, err := h.usecase.GetPolicyTemplateVersion(r.Context(), id, version) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) return @@ -427,7 +427,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, var out domain.GetPolicyTemplateVersionResponse if err = serializer.Map(*policyTemplate, &out.PolicyTemplate); err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -464,7 +464,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite err = UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -537,7 +537,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite id, err := uuid.Parse(policyTemplateId) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) return } @@ -545,7 +545,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite err = h.usecase.DeletePolicyTemplateVersion(r.Context(), id, version) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) return @@ -651,7 +651,7 @@ func (h *PolicyTemplateHandler) RegoCompile(w http.ResponseWriter, r *http.Reque input := domain.RegoCompileRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return @@ -659,7 +659,7 @@ func (h *PolicyTemplateHandler) RegoCompile(w http.ResponseWriter, r *http.Reque response, err := h.usecase.RegoCompile(&input, parseParameter) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 7500369b..dcd45c22 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -1,6 +1,7 @@ package repository import ( + "context" "encoding/json" "fmt" "strings" @@ -17,20 +18,20 @@ import ( ) type IPolicyTemplateRepository interface { - Create(dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) - Update(dto domain.UpdatePolicyTemplateUpdate) (err error) - Fetch(pg *pagination.Pagination) (out []model.PolicyTemplate, err error) - GetByName(policyTemplateName string) (out *model.PolicyTemplate, err error) - GetByKind(policyTemplateKind string) (out *model.PolicyTemplate, err error) - GetByID(policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) - Delete(policyTemplateId uuid.UUID) (err error) - ExistByName(policyTemplateName string) (exist bool, err error) - ExistByKind(policyTemplateKind string) (exist bool, err error) - ExistByID(policyTemplateId uuid.UUID) (exist bool, err error) - ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) - GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) - DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) - CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) + Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) + Update(ctx context.Context, dto domain.UpdatePolicyTemplateUpdate) (err error) + Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.PolicyTemplate, err error) + GetByName(ctx context.Context, policyTemplateName string) (out *model.PolicyTemplate, err error) + GetByKind(ctx context.Context, policyTemplateKind string) (out *model.PolicyTemplate, err error) + GetByID(ctx context.Context, policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) + Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) + ExistByName(ctx context.Context, policyTemplateName string) (exist bool, err error) + ExistByKind(ctx context.Context, policyTemplateKind string) (exist bool, err error) + ExistByID(ctx context.Context, policyTemplateId uuid.UUID) (exist bool, err error) + ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) + GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) + DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) + CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) } type PolicyTemplateRepository struct { @@ -43,7 +44,7 @@ func NewPolicyTemplateRepository(db *gorm.DB) IPolicyTemplateRepository { } } -func (r *PolicyTemplateRepository) Create(dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { +func (r *PolicyTemplateRepository) Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { jsonByte, err := json.Marshal(dto.ParametersSchema) if err != nil { @@ -98,7 +99,7 @@ func (r *PolicyTemplateRepository) Create(dto model.PolicyTemplate) (policyTempl return policyTemplate.ID, nil } -func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) (err error) { +func (r *PolicyTemplateRepository) Update(ctx context.Context, dto domain.UpdatePolicyTemplateUpdate) (err error) { updateMap := make(map[string]interface{}) updateMap["updator_id"] = dto.UpdatorId @@ -154,7 +155,7 @@ func (r *PolicyTemplateRepository) Update(dto domain.UpdatePolicyTemplateUpdate) }) } -func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []model.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.PolicyTemplate, err error) { var policyTemplates []model.PolicyTemplate if pg == nil { pg = pagination.NewPagination(nil) @@ -174,24 +175,24 @@ func (r *PolicyTemplateRepository) Fetch(pg *pagination.Pagination) (out []model if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found policyTemplate version") + log.Info(ctx, "Not found policyTemplate version") } else { - log.Error(res.Error) + log.Error(ctx, res.Error) } } - outPolicyTemplate := r.reflectPolicyTemplate(policyTemplate, policyTemplateVersion) + outPolicyTemplate := r.reflectPolicyTemplate(ctx, policyTemplate, policyTemplateVersion) out = append(out, outPolicyTemplate) } return out, nil } -func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.PolicyTemplate, policyTemplateVersion model.PolicyTemplateSupportedVersion) (out model.PolicyTemplate) { +func (r *PolicyTemplateRepository) reflectPolicyTemplate(ctx context.Context, policyTemplate model.PolicyTemplate, policyTemplateVersion model.PolicyTemplateSupportedVersion) (out model.PolicyTemplate) { if err := serializer.Map(policyTemplate.Model, &out); err != nil { - log.Error(err) + log.Error(ctx, err) } if err := serializer.Map(policyTemplate, &out); err != nil { - log.Error(err) + log.Error(ctx, err) } out.TemplateName = policyTemplate.Name out.ID = policyTemplate.ID @@ -200,7 +201,7 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.Po if len(policyTemplateVersion.ParameterSchema) > 0 { if err := json.Unmarshal([]byte(policyTemplateVersion.ParameterSchema), &schemas); err != nil { - log.Error(err) + log.Error(ctx, err) } else { out.ParametersSchema = schemas } @@ -227,7 +228,7 @@ func (r *PolicyTemplateRepository) reflectPolicyTemplate(policyTemplate model.Po return } -func (r *PolicyTemplateRepository) ExistsBy(key string, value interface{}) (exists bool, err error) { +func (r *PolicyTemplateRepository) ExistsBy(ctx context.Context, key string, value interface{}) (exists bool, err error) { query := fmt.Sprintf("%s = ?", key) var policyTemplate model.PolicyTemplate @@ -236,10 +237,10 @@ func (r *PolicyTemplateRepository) ExistsBy(key string, value interface{}) (exis if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Infof("Not found policyTemplate %s='%v'", key, value) + log.Infof(ctx, "Not found policyTemplate %s='%v'", key, value) return false, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return false, res.Error } } @@ -247,19 +248,19 @@ func (r *PolicyTemplateRepository) ExistsBy(key string, value interface{}) (exis return true, nil } -func (r *PolicyTemplateRepository) ExistByName(policyTemplateName string) (exist bool, err error) { - return r.ExistsBy("name", policyTemplateName) +func (r *PolicyTemplateRepository) ExistByName(ctx context.Context, policyTemplateName string) (exist bool, err error) { + return r.ExistsBy(ctx, "name", policyTemplateName) } -func (r *PolicyTemplateRepository) ExistByKind(policyTemplateKind string) (exist bool, err error) { - return r.ExistsBy("kind", policyTemplateKind) +func (r *PolicyTemplateRepository) ExistByKind(ctx context.Context, policyTemplateKind string) (exist bool, err error) { + return r.ExistsBy(ctx, "kind", policyTemplateKind) } -func (r *PolicyTemplateRepository) ExistByID(policyTemplateId uuid.UUID) (exist bool, err error) { - return r.ExistsBy("id", policyTemplateId) +func (r *PolicyTemplateRepository) ExistByID(ctx context.Context, policyTemplateId uuid.UUID) (exist bool, err error) { + return r.ExistsBy(ctx, "id", policyTemplateId) } -func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *model.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetBy(ctx context.Context, key string, value interface{}) (out *model.PolicyTemplate, err error) { query := fmt.Sprintf("%s = ?", key) var policyTemplate model.PolicyTemplate @@ -268,10 +269,10 @@ func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *mo if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Infof("Not found policyTemplate %s='%v'", key, value) + log.Infof(ctx, "Not found policyTemplate %s='%v'", key, value) return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -282,24 +283,24 @@ func (r *PolicyTemplateRepository) GetBy(key string, value interface{}) (out *mo First(&policyTemplateVersion) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found policyTemplate version") + log.Info(ctx, "Not found policyTemplate version") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } fmt.Printf("BBBB %+v\n", policyTemplate.PermittedOrganizations) - result := r.reflectPolicyTemplate(policyTemplate, policyTemplateVersion) + result := r.reflectPolicyTemplate(ctx, policyTemplate, policyTemplateVersion) fmt.Printf("2222BBBB %+v\n", result.PermittedOrganizations) return &result, nil } -func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) { - return r.GetBy("id", policyTemplateId) +func (r *PolicyTemplateRepository) GetByID(ctx context.Context, policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) { + return r.GetBy(ctx, "id", policyTemplateId) // var policyTemplate PolicyTemplate // res := r.db.Preload(clause.Associations).Where("id = ?", policyTemplateId). @@ -320,8 +321,8 @@ func (r *PolicyTemplateRepository) GetByID(policyTemplateId uuid.UUID) (out *mod // return &result, nil } -func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *model.PolicyTemplate, err error) { - return r.GetBy("name", policyTemplateName) +func (r *PolicyTemplateRepository) GetByName(ctx context.Context, policyTemplateName string) (out *model.PolicyTemplate, err error) { + return r.GetBy(ctx, "name", policyTemplateName) // var policyTemplate PolicyTemplate // res := r.db.Limit(1). @@ -342,11 +343,11 @@ func (r *PolicyTemplateRepository) GetByName(policyTemplateName string) (out *mo // return &result, nil } -func (r *PolicyTemplateRepository) GetByKind(policyTemplateKind string) (out *model.PolicyTemplate, err error) { - return r.GetBy("kind", policyTemplateKind) +func (r *PolicyTemplateRepository) GetByKind(ctx context.Context, policyTemplateKind string) (out *model.PolicyTemplate, err error) { + return r.GetBy(ctx, "kind", policyTemplateKind) } -func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error) { +func (r *PolicyTemplateRepository) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) { return r.db.Transaction(func(tx *gorm.DB) error { if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&model.PolicyTemplateSupportedVersion{}).Error; err != nil { return err @@ -364,16 +365,16 @@ func (r *PolicyTemplateRepository) Delete(policyTemplateId uuid.UUID) (err error }) } -func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { +func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { var supportedVersions []model.PolicyTemplateSupportedVersion res := r.db.Where("policy_template_id = ?", policyTemplateId).Find(&supportedVersions) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found policyTemplate kind") + log.Info(ctx, "Not found policyTemplate kind") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -391,17 +392,17 @@ func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(policyTemplateId u return result, nil } -func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { +func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db. Where("policy_template_id = ? and version = ?", policyTemplateId, version). First(&policyTemplateVersion) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found policyTemplate version") + log.Info(ctx, "Not found policyTemplate version") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } @@ -412,29 +413,29 @@ func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(policyTemplateId uui First(&policyTemplate) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found policyTemplate id") + log.Info(ctx, "Not found policyTemplate id") return nil, nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return nil, res.Error } } - result := r.reflectPolicyTemplate(policyTemplate, policyTemplateVersion) + result := r.reflectPolicyTemplate(ctx, policyTemplate, policyTemplateVersion) return &result, nil } -func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId uuid.UUID, version string) (err error) { +func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) { var policyTemplate model.PolicyTemplate res := r.db.Select("version").First(&policyTemplate) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found policyTemplate id") + log.Info(ctx, "Not found policyTemplate id") return nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return res.Error } } @@ -451,10 +452,10 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId Delete(&policyTemplateVersion) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info("Not found policyTemplate version") + log.Info(ctx, "Not found policyTemplate version") return nil } else { - log.Error(res.Error) + log.Error(ctx, res.Error) return res.Error } } @@ -462,7 +463,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(policyTemplateId return nil } -func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { +func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db.Limit(1). Where("policy_template_id = ? and version = ?", policyTemplateId, version). @@ -471,13 +472,13 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId if res.Error == nil { err = errors.Errorf("Version %s already exists for the policyTemplate", newVersion) - log.Error(res.Error) + log.Error(ctx, res.Error) return "", err } if !errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Error(res.Error) + log.Error(ctx, res.Error) return "", res.Error } @@ -491,7 +492,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(policyTemplateId if err != nil { parseErr := errors.Errorf("Unable to parse parameter schema: %v", err) - log.Error(parseErr) + log.Error(ctx, parseErr) return "", parseErr } diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 7c76a846..ed503e7a 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -53,18 +53,18 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp return "", httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } - exists, err := u.repo.ExistByName(dto.TemplateName) + exists, err := u.repo.ExistByName(ctx, dto.TemplateName) if err == nil && exists { return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") } - exists, err = u.repo.ExistByKind(dto.Kind) + exists, err = u.repo.ExistByKind(ctx, dto.Kind) if err == nil && exists { return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_KIND", "policy template kind already exists") } for _, organizationId := range dto.PermittedOrganizationIds { - _, err = u.organizationRepo.Get(organizationId) + _, err = u.organizationRepo.Get(ctx, organizationId) if err != nil { return "", httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } @@ -72,7 +72,7 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp userId := user.GetUserId() dto.CreatorId = &userId - id, err := u.repo.Create(dto) + id, err := u.repo.Create(ctx, dto) if err != nil { return "", err @@ -82,13 +82,13 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp } func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) { - policyTemplates, err = u.repo.Fetch(pg) + policyTemplates, err = u.repo.Fetch(ctx, pg) if err != nil { return nil, err } - organizations, err := u.organizationRepo.Fetch(nil) + organizations, err := u.organizationRepo.Fetch(ctx, nil) if err == nil { for i, policyTemplate := range policyTemplates { permittedOrgIdSet := u.getPermittedOrganiationIdSet(&policyTemplate) @@ -102,7 +102,7 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagina } func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { - policyTemplate, err := u.repo.GetByID(policyTemplateID) + policyTemplate, err := u.repo.GetByID(ctx, policyTemplateID) if err != nil { return nil, err @@ -110,7 +110,7 @@ func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.U permittedOrgIdSet := u.getPermittedOrganiationIdSet(policyTemplate) - organizations, err := u.organizationRepo.Fetch(nil) + organizations, err := u.organizationRepo.Fetch(ctx, nil) if err == nil { u.updatePermittedOrganizations(organizations, permittedOrgIdSet, policyTemplate) } @@ -124,19 +124,19 @@ func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uui return httpErrors.NewBadRequestError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } - _, err = u.repo.GetByID(policyTemplateId) + _, err = u.repo.GetByID(ctx, policyTemplateId) if err != nil { return httpErrors.NewNotFoundError(err, "PT_FAILED_FETCH_POLICY_TEMPLATE", "") } - exists, err := u.repo.ExistByName(*update.TemplateName) + exists, err := u.repo.ExistByName(ctx, *update.TemplateName) if err == nil && exists { return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") } if update.PermittedOrganizationIds != nil { for _, organizationId := range *update.PermittedOrganizationIds { - _, err = u.organizationRepo.Get(organizationId) + _, err = u.organizationRepo.Get(ctx, organizationId) if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } @@ -155,7 +155,7 @@ func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uui PermittedOrganizationIds: update.PermittedOrganizationIds, } - err = u.repo.Update(dto) + err = u.repo.Update(ctx, dto) if err != nil { return err } @@ -164,19 +164,19 @@ func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uui } func (u *PolicyTemplateUsecase) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) { - return u.repo.Delete(policyTemplateId) + return u.repo.Delete(ctx, policyTemplateId) } func (u *PolicyTemplateUsecase) IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) { - return u.repo.ExistByName(policyTemplateName) + return u.repo.ExistByName(ctx, policyTemplateName) } func (u *PolicyTemplateUsecase) IsPolicyTemplateKindExist(ctx context.Context, policyTemplateKind string) (bool, error) { - return u.repo.ExistByKind(policyTemplateKind) + return u.repo.ExistByKind(ctx, policyTemplateKind) } func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { - policyTemplate, err := u.repo.GetPolicyTemplateVersion(policyTemplateId, version) + policyTemplate, err := u.repo.GetPolicyTemplateVersion(ctx, policyTemplateId, version) if err != nil { return nil, err @@ -184,7 +184,7 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, po permittedOrgIdSet := u.getPermittedOrganiationIdSet(policyTemplate) - organizations, err := u.organizationRepo.Fetch(nil) + organizations, err := u.organizationRepo.Fetch(ctx, nil) if err == nil { u.updatePermittedOrganizations(organizations, permittedOrgIdSet, policyTemplate) } @@ -234,15 +234,15 @@ func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *model } func (u *PolicyTemplateUsecase) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { - return u.repo.ListPolicyTemplateVersions(policyTemplateId) + return u.repo.ListPolicyTemplateVersions(ctx, policyTemplateId) } func (u *PolicyTemplateUsecase) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) { - return u.repo.DeletePolicyTemplateVersion(policyTemplateId, version) + return u.repo.DeletePolicyTemplateVersion(ctx, policyTemplateId, version) } func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { - return u.repo.CreatePolicyTemplateVersion(policyTemplateId, newVersion, schema, rego, libs) + return u.repo.CreatePolicyTemplateVersion(ctx, policyTemplateId, newVersion, schema, rego, libs) } func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) { From 22acb2c035796fc13a7d551b58d7f844c65f4cfa Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 13 Mar 2024 11:25:28 +0900 Subject: [PATCH 129/502] remove unnecessary log --- internal/database/database.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/internal/database/database.go b/internal/database/database.go index 043bd031..91cfd606 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/log" "os" "strings" @@ -192,10 +191,7 @@ func EnsureDefaultRows(db *gorm.DB) error { for _, ep := range eps { storedEps[ep.Name] = struct{}{} } - log.Debugf(context.Background(), "storedEps: %+v", storedEps) for _, ep := range api.ApiMap { - log.Debug(context.Background(), "ep.Name", ep.Name) - log.Debug(context.Background(), "storedEps[ep.Name]", storedEps[ep.Name]) if _, ok := storedEps[ep.Name]; !ok { if err := repoFactory.Endpoint.Create(ctx, &model.Endpoint{ Name: ep.Name, From 481e0194504c55f38ae6ce6a614977eadaf43db4 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 15 Mar 2024 14:55:21 +0900 Subject: [PATCH 130/502] fix conflict during rebase --- internal/delivery/http/alert.go | 12 +++---- internal/delivery/http/app-group.go | 12 +++---- internal/delivery/http/app-serve-app.go | 28 ++++++++-------- internal/delivery/http/audit.go | 6 ++-- internal/delivery/http/auth.go | 2 +- internal/delivery/http/cloud-account.go | 14 ++++---- internal/delivery/http/cluster.go | 10 +++--- internal/delivery/http/dashboard.go | 8 ++--- internal/delivery/http/organization.go | 24 +++++++------- internal/delivery/http/permission.go | 6 ++-- internal/delivery/http/policy-template.go | 12 +++---- internal/delivery/http/project.go | 16 ++++----- internal/delivery/http/role.go | 4 +-- internal/delivery/http/stack-template.go | 40 +++++++++++------------ internal/delivery/http/stack.go | 14 ++++---- internal/delivery/http/user.go | 28 ++++++++-------- internal/pagination/pagination.go | 7 ++-- internal/repository/policy-template.go | 4 +-- internal/serializer/serializer.go | 21 ++++++------ internal/usecase/cluster.go | 4 +-- internal/usecase/dashboard.go | 2 +- internal/usecase/organization.go | 2 +- internal/usecase/policy-template.go | 20 ++++++------ internal/usecase/project.go | 2 +- internal/usecase/stack.go | 10 +++--- pkg/domain/mapper.go | 0 26 files changed, 155 insertions(+), 153 deletions(-) delete mode 100644 pkg/domain/mapper.go diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go index 4829e8d3..5ec1fa9b 100644 --- a/internal/delivery/http/alert.go +++ b/internal/delivery/http/alert.go @@ -126,13 +126,13 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { var out domain.GetAlertsResponse out.Alerts = make([]domain.AlertResponse, len(alerts)) for i, alert := range alerts { - if err := serializer.Map(alert, &out.Alerts[i]); err != nil { + if err := serializer.Map(r.Context(), alert, &out.Alerts[i]); err != nil { log.Info(r.Context(), err) } outAlertActions := make([]domain.AlertActionResponse, len(alert.AlertActions)) for j, alertAction := range alert.AlertActions { - if err := serializer.Map(alertAction, &outAlertActions[j]); err != nil { + if err := serializer.Map(r.Context(), alertAction, &outAlertActions[j]); err != nil { log.Info(r.Context(), err) } } @@ -142,7 +142,7 @@ func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -182,12 +182,12 @@ func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { } var out domain.GetAlertResponse - if err := serializer.Map(alert, &out.Alert); err != nil { + if err := serializer.Map(r.Context(), alert, &out.Alert); err != nil { log.Info(r.Context(), err) } outAlertActions := make([]domain.AlertActionResponse, len(alert.AlertActions)) for j, alertAction := range alert.AlertActions { - if err := serializer.Map(alertAction, &outAlertActions[j]); err != nil { + if err := serializer.Map(r.Context(), alertAction, &outAlertActions[j]); err != nil { log.Info(r.Context(), err) continue } @@ -274,7 +274,7 @@ func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) log.Info(r.Context(), "alert : ", helper.ModelToJson(input)) var dto model.AlertAction - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.AlertId = alertId diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index dd7142a3..0a497091 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -45,7 +45,7 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) } var dto model.AppGroup - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } @@ -96,13 +96,13 @@ func (h *AppGroupHandler) GetAppGroups(w http.ResponseWriter, r *http.Request) { var out domain.GetAppGroupsResponse out.AppGroups = make([]domain.AppGroupResponse, len(appGroups)) for i, appGroup := range appGroups { - if err := serializer.Map(appGroup, &out.AppGroups[i]); err != nil { + if err := serializer.Map(r.Context(), appGroup, &out.AppGroups[i]); err != nil { log.Info(r.Context(), err) continue } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -139,7 +139,7 @@ func (h *AppGroupHandler) GetAppGroup(w http.ResponseWriter, r *http.Request) { } var out domain.GetAppGroupResponse - if err := serializer.Map(appGroup, &out.AppGroup); err != nil { + if err := serializer.Map(r.Context(), appGroup, &out.AppGroup); err != nil { log.Info(r.Context(), err) } @@ -225,7 +225,7 @@ func (h *AppGroupHandler) GetApplications(w http.ResponseWriter, r *http.Request var out domain.GetApplicationsResponse out.Applications = make([]domain.ApplicationResponse, len(applications)) for i, application := range applications { - if err := serializer.Map(application, &out.Applications[i]); err != nil { + if err := serializer.Map(r.Context(), application, &out.Applications[i]); err != nil { log.Info(r.Context(), err) continue } @@ -266,7 +266,7 @@ func (h *AppGroupHandler) CreateApplication(w http.ResponseWriter, r *http.Reque } var dto model.Application - if err := serializer.Map(input, &dto); err != nil { + if err := serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.AppGroupId = appGroupId diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index f75ff95c..2430d0e9 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -118,7 +118,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re (appReq).SetDefaultValue() var app model.AppServeApp - if err = serializer.Map(appReq, &app); err != nil { + if err = serializer.Map(r.Context(), appReq, &app); err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } @@ -134,7 +134,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re app.CreatedAt = now var task model.AppServeAppTask - if err = serializer.Map(appReq, &task); err != nil { + if err = serializer.Map(r.Context(), appReq, &task); err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } @@ -209,7 +209,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re } var out domain.CreateAppServeAppResponse - if err = serializer.Map(app, &out); err != nil { + if err = serializer.Map(r.Context(), app, &out); err != nil { ErrorJSON(w, r, err) return } @@ -268,13 +268,13 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ var out domain.GetAppServeAppsResponse out.AppServeApps = make([]domain.AppServeAppResponse, len(apps)) for i, app := range apps { - if err := serializer.Map(app, &out.AppServeApps[i]); err != nil { + if err := serializer.Map(r.Context(), app, &out.AppServeApps[i]); err != nil { log.Info(r.Context(), err) continue } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -338,7 +338,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque app.AppServeAppTasks = newTasks var out domain.GetAppServeAppResponse - if err := serializer.Map(app, &out.AppServeApp); err != nil { + if err := serializer.Map(r.Context(), app, &out.AppServeApp); err != nil { log.Info(r.Context(), err) } @@ -388,7 +388,7 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - if err := serializer.Map(task, &out.AppServeAppTask); err != nil { + if err := serializer.Map(r.Context(), task, &out.AppServeAppTask); err != nil { log.Info(r.Context(), err) } @@ -478,13 +478,13 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r var out domain.GetAppServeAppTasksResponse out.AppServeAppTasks = make([]domain.AppServeAppTaskResponse, len(tasks)) for i, task := range tasks { - if err := serializer.Map(task, &out.AppServeAppTasks[i]); err != nil { + if err := serializer.Map(r.Context(), task, &out.AppServeAppTasks[i]); err != nil { log.Info(r.Context(), err) continue } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -552,10 +552,10 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - if err := serializer.Map(app, &out.AppServeApp); err != nil { + if err := serializer.Map(r.Context(), app, &out.AppServeApp); err != nil { log.Info(r.Context(), err) } - if err := serializer.Map(task, &out.AppServeAppTask); err != nil { + if err := serializer.Map(r.Context(), task, &out.AppServeAppTask); err != nil { log.Info(r.Context(), err) } @@ -809,18 +809,18 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re // break // } //} - //if err = serializer.Map(latestTask, &task); err != nil { + //if err = serializer.Map(r.Context(), latestTask, &task); err != nil { // ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) // return //} var latestTask = app.AppServeAppTasks[0] - if err = serializer.Map(latestTask, &task); err != nil { + if err = serializer.Map(r.Context(), latestTask, &task); err != nil { //ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } - if err = serializer.Map(appReq, &task); err != nil { + if err = serializer.Map(r.Context(), appReq, &task); err != nil { //ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 5b8defff..e95ae959 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -68,12 +68,12 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { var out domain.GetAuditsResponse out.Audits = make([]domain.AuditResponse, len(audits)) for i, audit := range audits { - if err := serializer.Map(audit, &out.Audits[i]); err != nil { + if err := serializer.Map(r.Context(), audit, &out.Audits[i]); err != nil { log.Info(r.Context(), err) } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -113,7 +113,7 @@ func (h *AuditHandler) GetAudit(w http.ResponseWriter, r *http.Request) { log.Info(r.Context(), audit) var out domain.GetAuditResponse - if err := serializer.Map(audit, &out.Audit); err != nil { + if err := serializer.Map(r.Context(), audit, &out.Audit); err != nil { log.Info(r.Context(), err) } diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 5208a42a..bf81e50e 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -97,7 +97,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { } var out domain.LoginResponse - if err = serializer.Map(user, &out.User); err != nil { + if err = serializer.Map(r.Context(), user, &out.User); err != nil { log.Error(r.Context(), err) } diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index c2685eb8..53295041 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -55,7 +55,7 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. } var dto model.CloudAccount - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.OrganizationId = organizationId @@ -107,13 +107,13 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re var out domain.GetCloudAccountsResponse out.CloudAccounts = make([]domain.CloudAccountResponse, len(cloudAccounts)) for i, cloudAccount := range cloudAccounts { - if err := serializer.Map(cloudAccount, &out.CloudAccounts[i]); err != nil { + if err := serializer.Map(r.Context(), cloudAccount, &out.CloudAccounts[i]); err != nil { log.Info(r.Context(), err) continue } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -153,7 +153,7 @@ func (h *CloudAccountHandler) GetCloudAccount(w http.ResponseWriter, r *http.Req } var out domain.GetCloudAccountResponse - if err := serializer.Map(cloudAccount, &out.CloudAccount); err != nil { + if err := serializer.Map(r.Context(), cloudAccount, &out.CloudAccount); err != nil { log.Info(r.Context(), err) } @@ -200,7 +200,7 @@ func (h *CloudAccountHandler) UpdateCloudAccount(w http.ResponseWriter, r *http. } var dto model.CloudAccount - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.ID = cloudAccountId @@ -250,7 +250,7 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. } var dto model.CloudAccount - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.ID = parsedId @@ -416,7 +416,7 @@ func (h *CloudAccountHandler) GetResourceQuota(w http.ResponseWriter, r *http.Re } var out domain.GetCloudAccountResourceQuotaResponse - if err := serializer.Map(resourceQuota, &out.ResourceQuota); err != nil { + if err := serializer.Map(r.Context(), resourceQuota, &out.ResourceQuota); err != nil { log.Info(r.Context(), err) } out.Available = available diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 7dea7c9e..b67042e4 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -54,7 +54,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { var out domain.GetClustersResponse out.Clusters = make([]domain.ClusterResponse, len(clusters)) for i, cluster := range clusters { - if err := serializer.Map(cluster, &out.Clusters[i]); err != nil { + if err := serializer.Map(r.Context(), cluster, &out.Clusters[i]); err != nil { log.Info(r.Context(), err) continue } @@ -67,7 +67,7 @@ func (h *ClusterHandler) GetClusters(w http.ResponseWriter, r *http.Request) { } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -100,7 +100,7 @@ func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { } var out domain.GetClusterResponse - if err := serializer.Map(cluster, &out.Cluster); err != nil { + if err := serializer.Map(r.Context(), cluster, &out.Cluster); err != nil { log.Info(r.Context(), err) } @@ -158,7 +158,7 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { } var dto model.Cluster - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } @@ -212,7 +212,7 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { } var dto model.Cluster - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.SetDefaultConf() diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 55c75cd5..69e49c6f 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -74,7 +74,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { var out domain.GetDashboardChartsResponse out.Charts = make([]domain.DashboardChartResponse, len(charts)) for i, chart := range charts { - if err := serializer.Map(chart, &out.Charts[i]); err != nil { + if err := serializer.Map(r.Context(), chart, &out.Charts[i]); err != nil { log.Info(r.Context(), err) continue } @@ -153,7 +153,7 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { } var out domain.DashboardChartResponse - if err := serializer.Map(charts[0], &out); err != nil { + if err := serializer.Map(r.Context(), charts[0], &out); err != nil { log.Info(r.Context(), err) } @@ -193,7 +193,7 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { var out domain.GetDashboardStacksResponse out.Stacks = make([]domain.DashboardStackResponse, len(stacks)) for i, stack := range stacks { - if err := serializer.Map(stack, &out.Stacks[i]); err != nil { + if err := serializer.Map(r.Context(), stack, &out.Stacks[i]); err != nil { log.Info(r.Context(), err) continue } @@ -231,7 +231,7 @@ func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) return } var out domain.GetDashboardResourcesResponse - if err := serializer.Map(resources, &out.Resources); err != nil { + if err := serializer.Map(r.Context(), resources, &out.Resources); err != nil { log.Info(r.Context(), err) } diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index a224781d..683873d4 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -55,7 +55,7 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. ctx := r.Context() var organization model.Organization - if err = serializer.Map(input, &organization); err != nil { + if err = serializer.Map(r.Context(), input, &organization); err != nil { log.Error(r.Context(), err) } @@ -122,14 +122,14 @@ func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http. err = h.usecase.ChangeAdminId(r.Context(), organizationId, admin.ID) if err != nil { - log.ErrorfWithContext(r.Context(), "error is :%s(%T)", err.Error(), err) + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } organization.AdminId = &admin.ID var out domain.CreateOrganizationResponse - if err = serializer.Map(organization, &out); err != nil { + if err = serializer.Map(r.Context(), organization, &out); err != nil { log.Error(r.Context(), err) } @@ -166,14 +166,14 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re out.Organizations = make([]domain.OrganizationResponse, len(*organizations)) for i, organization := range *organizations { - if err = serializer.Map(organization, &out.Organizations[i]); err != nil { + if err = serializer.Map(r.Context(), organization, &out.Organizations[i]); err != nil { log.Error(r.Context(), err) } log.Info(r.Context(), organization) } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -211,24 +211,24 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req return } var out domain.GetOrganizationResponse - if err = serializer.Map(organization, &out.Organization); err != nil { + if err = serializer.Map(r.Context(), organization, &out.Organization); err != nil { log.Error(r.Context(), err) } out.Organization.StackTemplates = make([]domain.SimpleStackTemplateResponse, len(organization.StackTemplates)) for i, stackTemplate := range organization.StackTemplates { - if err = serializer.Map(stackTemplate, &out.Organization.StackTemplates[i]); err != nil { - log.ErrorWithContext(r.Context(), err) + if err = serializer.Map(r.Context(), stackTemplate, &out.Organization.StackTemplates[i]); err != nil { + log.Error(r.Context(), err) } err := json.Unmarshal(stackTemplate.Services, &out.Organization.StackTemplates[i].Services) if err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } } out.Organization.PolicyTemplates = make([]domain.SimplePolicyTemplateResponse, len(organization.PolicyTemplates)) for i, policyTemplate := range organization.PolicyTemplates { - if err = serializer.Map(policyTemplate, &out.Organization.PolicyTemplates[i]); err != nil { - log.ErrorWithContext(r.Context(), err) + if err = serializer.Map(r.Context(), policyTemplate, &out.Organization.PolicyTemplates[i]); err != nil { + log.Error(r.Context(), err) } } @@ -325,7 +325,7 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. } var out domain.UpdateOrganizationResponse - if err = serializer.Map(organization, &out); err != nil { + if err = serializer.Map(r.Context(), organization, &out); err != nil { log.Error(r.Context(), err) } diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 488c971a..84ea905d 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -42,7 +42,7 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http permissionSet := model.NewDefaultPermissionSet() var premissionSetResponse domain.PermissionSetResponse - if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { + if err := serializer.Map(r.Context(), permissionSet, &premissionSetResponse); err != nil { log.Info(r.Context(), err) } @@ -86,7 +86,7 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http } var premissionSetResponse domain.PermissionSetResponse - if err := serializer.Map(permissionSet, &premissionSetResponse); err != nil { + if err := serializer.Map(r.Context(), permissionSet, &premissionSetResponse); err != nil { log.Info(r.Context(), err) } @@ -135,7 +135,7 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h for _, permissionResponse := range input.Permissions { var permission model.Permission - if err := serializer.Map(permissionResponse, &permission); err != nil { + if err := serializer.Map(r.Context(), permissionResponse, &permission); err != nil { log.Info(r.Context(), err) } diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 20590ece..ccb5ada7 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -69,7 +69,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h } var dto model.PolicyTemplate - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } @@ -229,7 +229,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http } var out domain.GetPolicyTemplateResponse - if err = serializer.Map(*policyTemplate, &out.PolicyTemplate); err != nil { + if err = serializer.Map(r.Context(), *policyTemplate, &out.PolicyTemplate); err != nil { log.Error(r.Context(), err) } @@ -265,13 +265,13 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt var out domain.ListPolicyTemplateResponse out.PolicyTemplates = make([]domain.PolicyTemplateResponse, len(policyTemplates)) for i, policyTemplate := range policyTemplates { - if err := serializer.Map(policyTemplate, &out.PolicyTemplates[i]); err != nil { + if err := serializer.Map(r.Context(), policyTemplate, &out.PolicyTemplates[i]); err != nil { log.Info(r.Context(), err) continue } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -319,7 +319,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter } var out domain.ListPolicyTemplateVersionsResponse - if err = serializer.Map(*policyTemplateVersions, &out); err != nil { + if err = serializer.Map(r.Context(), *policyTemplateVersions, &out); err != nil { log.Error(r.Context(), err) } @@ -426,7 +426,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, } var out domain.GetPolicyTemplateVersionResponse - if err = serializer.Map(*policyTemplate, &out.PolicyTemplate); err != nil { + if err = serializer.Map(r.Context(), *policyTemplate, &out.PolicyTemplate); err != nil { log.Error(r.Context(), err) } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 015c4c48..10c38379 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -189,7 +189,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { var out domain.GetProjectsResponse out.Projects = pr - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -231,7 +231,7 @@ func (p ProjectHandler) Admin_GetProjects(w http.ResponseWriter, r *http.Request var out domain.GetProjectsResponse out.Projects = pr - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -301,7 +301,7 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { } var pdr domain.ProjectDetailResponse - if err = serializer.Map(*project, &pdr); err != nil { + if err = serializer.Map(r.Context(), *project, &pdr); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) return @@ -764,7 +764,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request } out = domain.GetProjectMembersResponse{ProjectMembers: pmrs} - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -1298,7 +1298,7 @@ func (p ProjectHandler) GetProjectNamespaces(w http.ResponseWriter, r *http.Requ pnrs := make([]domain.ProjectNamespaceResponse, 0) for _, pn := range pns { var pnr domain.ProjectNamespaceResponse - if err = serializer.Map(pn, &pnr); err != nil { + if err = serializer.Map(r.Context(), pn, &pnr); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) return @@ -1382,7 +1382,7 @@ func (p ProjectHandler) GetProjectNamespace(w http.ResponseWriter, r *http.Reque } var pnr domain.ProjectNamespaceResponse - if err = serializer.Map(*pn, &pnr); err != nil { + if err = serializer.Map(r.Context(), *pn, &pnr); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) return @@ -1631,7 +1631,7 @@ func (p ProjectHandler) GetProjectNamespaceK8sResources(w http.ResponseWriter, r } var out domain.GetProjectNamespaceK8sResourcesResponse - if err = serializer.Map(k8sResources, &out.K8sResources); err != nil { + if err = serializer.Map(r.Context(), k8sResources, &out.K8sResources); err != nil { log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -1684,7 +1684,7 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, } var out domain.GetProjectNamespaceResourcesUsageResponse - if err = serializer.Map(resourcesUsage, &out.ResourcesUsage); err != nil { + if err = serializer.Map(r.Context(), resourcesUsage, &out.ResourcesUsage); err != nil { log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index c760b9d2..8aebd4ab 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -143,7 +143,7 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if err := serializer.Map(r.Context(), *pg, &out.Pagination); err != nil { log.Info(r.Context(), err) } @@ -320,7 +320,7 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) } } - if err := serializer.Map(*pg, &out.Pagination); err != nil { + if err := serializer.Map(r.Context(), *pg, &out.Pagination); err != nil { log.Info(r.Context(), err) } diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index a03b41fd..3297f29a 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -48,7 +48,7 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt } var dto model.StackTemplate - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } @@ -91,13 +91,13 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. var out domain.GetStackTemplatesResponse out.StackTemplates = make([]domain.StackTemplateResponse, len(stackTemplates)) for i, stackTemplate := range stackTemplates { - if err := serializer.Map(stackTemplate, &out.StackTemplates[i]); err != nil { + if err := serializer.Map(r.Context(), stackTemplate, &out.StackTemplates[i]); err != nil { log.Info(r.Context(), err) } out.StackTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) for j, organization := range stackTemplate.Organizations { - if err := serializer.Map(organization, &out.StackTemplates[i].Organizations[j]); err != nil { + if err := serializer.Map(r.Context(), organization, &out.StackTemplates[i].Organizations[j]); err != nil { log.Info(r.Context(), err) continue } @@ -109,7 +109,7 @@ func (h *StackTemplateHandler) GetStackTemplates(w http.ResponseWriter, r *http. } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -148,13 +148,13 @@ func (h *StackTemplateHandler) GetStackTemplate(w http.ResponseWriter, r *http.R } var out domain.GetStackTemplateResponse - if err := serializer.Map(stackTemplate, &out.StackTemplate); err != nil { + if err := serializer.Map(r.Context(), stackTemplate, &out.StackTemplate); err != nil { log.Info(r.Context(), err) } out.StackTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) for i, organization := range stackTemplate.Organizations { - if err := serializer.Map(organization, &out.StackTemplate.Organizations[i]); err != nil { + if err := serializer.Map(r.Context(), organization, &out.StackTemplate.Organizations[i]); err != nil { log.Info(r.Context(), err) continue } @@ -194,7 +194,7 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt } var dto model.StackTemplate - if err := serializer.Map(r, &dto); err != nil { + if err := serializer.Map(r.Context(), r, &dto); err != nil { log.Info(r.Context(), err) } dto.ID = stackTemplateId @@ -289,7 +289,7 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW } var dto model.StackTemplate - if err := serializer.Map(input, &dto); err != nil { + if err := serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.ID = stackTemplateId @@ -336,25 +336,25 @@ func (h *StackTemplateHandler) GetOrganizationStackTemplates(w http.ResponseWrit var out domain.GetStackTemplatesResponse out.StackTemplates = make([]domain.StackTemplateResponse, len(stackTemplates)) for i, stackTemplate := range stackTemplates { - if err := serializer.Map(stackTemplate, &out.StackTemplates[i]); err != nil { - log.InfoWithContext(r.Context(), err) + if err := serializer.Map(r.Context(), stackTemplate, &out.StackTemplates[i]); err != nil { + log.Info(r.Context(), err) } out.StackTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) for j, organization := range stackTemplate.Organizations { - if err := serializer.Map(organization, &out.StackTemplates[i].Organizations[j]); err != nil { - log.InfoWithContext(r.Context(), err) + if err := serializer.Map(r.Context(), organization, &out.StackTemplates[i].Organizations[j]); err != nil { + log.Info(r.Context(), err) } } err := json.Unmarshal(stackTemplate.Services, &out.StackTemplates[i].Services) if err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } } - if out.Pagination, err = pg.Response(); err != nil { - log.InfoWithContext(r.Context(), err) + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -397,20 +397,20 @@ func (h *StackTemplateHandler) GetOrganizationStackTemplate(w http.ResponseWrite } var out domain.GetStackTemplateResponse - if err := serializer.Map(stackTemplate, &out.StackTemplate); err != nil { - log.InfoWithContext(r.Context(), err) + if err := serializer.Map(r.Context(), stackTemplate, &out.StackTemplate); err != nil { + log.Info(r.Context(), err) } out.StackTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(stackTemplate.Organizations)) for i, organization := range stackTemplate.Organizations { - if err := serializer.Map(organization, &out.StackTemplate.Organizations[i]); err != nil { - log.InfoWithContext(r.Context(), err) + if err := serializer.Map(r.Context(), organization, &out.StackTemplate.Organizations[i]); err != nil { + log.Info(r.Context(), err) } } err = json.Unmarshal(stackTemplate.Services, &out.StackTemplate.Services) if err != nil { - log.ErrorWithContext(r.Context(), err) + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index be985e76..62f3ee7b 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -53,7 +53,7 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { } var dto model.Stack - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.OrganizationId = organizationId @@ -122,11 +122,11 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { var out domain.GetStacksResponse out.Stacks = make([]domain.StackResponse, len(stacks)) for i, stack := range stacks { - if err := serializer.Map(stack, &out.Stacks[i]); err != nil { + if err := serializer.Map(r.Context(), stack, &out.Stacks[i]); err != nil { log.Info(r.Context(), err) } - if err := serializer.Map(stack.CreatedAt, &out.Stacks[i].CreatedAt); err != nil { + if err := serializer.Map(r.Context(), stack.CreatedAt, &out.Stacks[i].CreatedAt); err != nil { log.Info(r.Context(), err) } @@ -136,7 +136,7 @@ func (h *StackHandler) GetStacks(w http.ResponseWriter, r *http.Request) { } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -170,7 +170,7 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { } var out domain.GetStackResponse - if err := serializer.Map(stack, &out.Stack); err != nil { + if err := serializer.Map(r.Context(), stack, &out.Stack); err != nil { log.Info(r.Context(), err) } @@ -212,7 +212,7 @@ func (h *StackHandler) GetStackStatus(w http.ResponseWriter, r *http.Request) { var out domain.GetStackStatusResponse out.StepStatus = make([]domain.StackStepStatus, len(steps)) for i, step := range steps { - if err := serializer.Map(step, &out.StepStatus[i]); err != nil { + if err := serializer.Map(r.Context(), step, &out.StepStatus[i]); err != nil { log.Info(r.Context(), err) } } @@ -261,7 +261,7 @@ func (h *StackHandler) UpdateStack(w http.ResponseWriter, r *http.Request) { } var dto model.Stack - if err = serializer.Map(input, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.ID = stackId diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 203194db..9d6f09ef 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -88,7 +88,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var user model.User - if err = serializer.Map(input, &user); err != nil { + if err = serializer.Map(r.Context(), input, &user); err != nil { log.Error(r.Context(), err) } user.Organization = model.Organization{ @@ -121,7 +121,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { } var out domain.CreateUserResponse - if err = serializer.Map(*resUser, &out.User); err != nil { + if err = serializer.Map(r.Context(), *resUser, &out.User); err != nil { log.Error(r.Context(), err) } @@ -168,7 +168,7 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { } var out domain.GetUserResponse - if err = serializer.Map(*user, &out.User); err != nil { + if err = serializer.Map(r.Context(), *user, &out.User); err != nil { log.Error(r.Context(), err) } @@ -211,12 +211,12 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { var out domain.ListUserResponse out.Users = make([]domain.ListUserBody, len(*users)) for i, user := range *users { - if err = serializer.Map(user, &out.Users[i]); err != nil { + if err = serializer.Map(r.Context(), user, &out.Users[i]); err != nil { log.Error(r.Context(), err) } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -300,7 +300,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var user model.User - if err = serializer.Map(input, &user); err != nil { + if err = serializer.Map(r.Context(), input, &user); err != nil { ErrorJSON(w, r, err) return } @@ -334,7 +334,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } var out domain.UpdateUserResponse - if err = serializer.Map(*resUser, &out.User); err != nil { + if err = serializer.Map(r.Context(), *resUser, &out.User); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) return @@ -401,7 +401,7 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { } var out domain.GetMyProfileResponse - if err = serializer.Map(*user, &out.User); err != nil { + if err = serializer.Map(r.Context(), *user, &out.User); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) return @@ -453,7 +453,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var user model.User - if err = serializer.Map(input, &user); err != nil { + if err = serializer.Map(r.Context(), input, &user); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) return @@ -471,7 +471,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { } var out domain.UpdateMyProfileResponse - if err = serializer.Map(*resUser, &out.User); err != nil { + if err = serializer.Map(r.Context(), *resUser, &out.User); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) return @@ -801,12 +801,12 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { var out admin_domain.ListUserResponse out.Users = make([]domain.ListUserBody, len(*users)) for i, user := range *users { - if err = serializer.Map(user, &out.Users[i]); err != nil { + if err = serializer.Map(r.Context(), user, &out.Users[i]); err != nil { log.Error(r.Context(), err) } } - if out.Pagination, err = pg.Response(); err != nil { + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -851,7 +851,7 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { } var out admin_domain.GetUserResponse - if err = serializer.Map(*user, &out.User); err != nil { + if err = serializer.Map(r.Context(), *user, &out.User); err != nil { log.Error(r.Context(), err) } @@ -1010,7 +1010,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { } var out admin_domain.UpdateUserResponse - if err = serializer.Map(*resUser, &out.User); err != nil { + if err = serializer.Map(r.Context(), *resUser, &out.User); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) return diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 591a498c..5630bbb2 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -1,6 +1,7 @@ package pagination import ( + "context" "net/url" "strconv" "strings" @@ -144,13 +145,13 @@ func (p *Pagination) Fetch(db *gorm.DB, dest interface{}) (*database.Paginator, return paginator, db } -func (p *Pagination) Response() (out domain.PaginationResponse, err error) { - if err := serializer.Map(*p, &out); err != nil { +func (p *Pagination) Response(ctx context.Context) (out domain.PaginationResponse, err error) { + if err := serializer.Map(ctx, *p, &out); err != nil { return out, err } out.Filters = make([]domain.FilterResponse, len(p.Filters)) for i, f := range p.Filters { - if err := serializer.Map(f, &out.Filters[i]); err != nil { + if err := serializer.Map(ctx, f, &out.Filters[i]); err != nil { continue } } diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index dcd45c22..92053bb4 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -188,10 +188,10 @@ func (r *PolicyTemplateRepository) Fetch(ctx context.Context, pg *pagination.Pag } func (r *PolicyTemplateRepository) reflectPolicyTemplate(ctx context.Context, policyTemplate model.PolicyTemplate, policyTemplateVersion model.PolicyTemplateSupportedVersion) (out model.PolicyTemplate) { - if err := serializer.Map(policyTemplate.Model, &out); err != nil { + if err := serializer.Map(ctx, policyTemplate.Model, &out); err != nil { log.Error(ctx, err) } - if err := serializer.Map(policyTemplate, &out); err != nil { + if err := serializer.Map(ctx, policyTemplate, &out); err != nil { log.Error(ctx, err) } out.TemplateName = policyTemplate.Name diff --git a/internal/serializer/serializer.go b/internal/serializer/serializer.go index 01fdec59..ddb434a7 100644 --- a/internal/serializer/serializer.go +++ b/internal/serializer/serializer.go @@ -1,6 +1,7 @@ package serializer import ( + "context" "fmt" "reflect" @@ -16,7 +17,7 @@ type compositeKey struct { dstType reflect.Type } -func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) error { +func recursiveMap(ctx context.Context, src interface{}, dst interface{}, converterMap ConverterMap) error { srcVal := reflect.ValueOf(src) srcType := srcVal.Type() @@ -40,14 +41,14 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e dstField.Set(srcField) continue } else if srcField.Type().Kind() == reflect.Struct && dstField.Type().Kind() == reflect.Struct { - if err := recursiveMap(srcField.Interface(), dstField.Addr().Interface(), converterMap); err != nil { - log.Error(err) + if err := recursiveMap(ctx, srcField.Interface(), dstField.Addr().Interface(), converterMap); err != nil { + log.Error(ctx, err) continue } } else if srcField.Kind() == reflect.Pointer && dstField.Type().Kind() == reflect.Struct { if !reflect.Value.IsNil(srcField) { - if err := recursiveMap(srcField.Elem().Interface(), dstField.Addr().Interface(), converterMap); err != nil { - log.Error(err) + if err := recursiveMap(ctx, srcField.Elem().Interface(), dstField.Addr().Interface(), converterMap); err != nil { + log.Error(ctx, err) continue } } @@ -74,13 +75,13 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e converterKey := compositeKey{srcType: srcField.Type(), dstType: dstField.Type()} if converter, ok := converterMap[converterKey]; ok { if converted, err := converter(srcField.Interface()); err != nil { - log.Error(err) + log.Error(ctx, err) continue } else { dstField.Set(reflect.ValueOf(converted)) } } else { - log.Debugf("no converter found for %s -> %s", srcField.Type(), dstField.Type()) + log.Debugf(ctx, "no converter found for %s -> %s", srcField.Type(), dstField.Type()) continue } } @@ -96,7 +97,7 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e */ } else { if fieldName == "Model" { - if err := recursiveMap(srcField.Interface(), dst, converterMap); err != nil { + if err := recursiveMap(ctx, srcField.Interface(), dst, converterMap); err != nil { return err } } @@ -106,8 +107,8 @@ func recursiveMap(src interface{}, dst interface{}, converterMap ConverterMap) e return nil } -func Map(src interface{}, dst interface{}) error { - return recursiveMap(src, dst, ConverterMap{ +func Map(ctx context.Context, src interface{}, dst interface{}) error { + return recursiveMap(ctx, src, dst, ConverterMap{ {srcType: reflect.TypeOf((*uuid.UUID)(nil)).Elem(), dstType: reflect.TypeOf("")}: func(i interface{}) (interface{}, error) { return i.(uuid.UUID).String(), nil }, diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index 52fb3287..a2b04912 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -457,7 +457,7 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom out.SshKeyName = "tks-seoul" out.ClusterRegion = "ap-northeast-2" - if err := serializer.Map(cluster, &out); err != nil { + if err := serializer.Map(ctx, cluster, &out); err != nil { log.Error(ctx, err) } @@ -466,7 +466,7 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom out.TksUserNodeMax = cluster.TksUserNodeMax / domain.MAX_AZ_NUM } - if err := serializer.Map(cluster, &out); err != nil { + if err := serializer.Map(ctx, cluster, &out); err != nil { log.Error(ctx, err) } diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 12d15d91..40a8b9b4 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -105,7 +105,7 @@ func (u *DashboardUsecase) GetStacks(ctx context.Context, organizationId string) } stack := reflectClusterToStack(ctx, cluster, appGroups) dashboardStack := domain.DashboardStack{} - if err := serializer.Map(stack, &dashboardStack); err != nil { + if err := serializer.Map(ctx, stack, &dashboardStack); err != nil { log.Info(ctx, err) } diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 7fe6ea4f..83970930 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -105,7 +105,7 @@ func (u *OrganizationUsecase) Get(ctx context.Context, organizationId string) (o clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, uuid.Nil, nil) if err != nil { - log.Info(err) + log.Info(ctx, err) out.ClusterCount = 0 } out.ClusterCount = len(clusters) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index ed503e7a..7f38429e 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -91,9 +91,9 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagina organizations, err := u.organizationRepo.Fetch(ctx, nil) if err == nil { for i, policyTemplate := range policyTemplates { - permittedOrgIdSet := u.getPermittedOrganiationIdSet(&policyTemplate) + permittedOrgIdSet := u.getPermittedOrganiationIdSet(ctx, &policyTemplate) - u.updatePermittedOrganizations(organizations, permittedOrgIdSet, &policyTemplates[i]) + u.updatePermittedOrganizations(ctx, organizations, permittedOrgIdSet, &policyTemplates[i]) } } @@ -108,11 +108,11 @@ func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.U return nil, err } - permittedOrgIdSet := u.getPermittedOrganiationIdSet(policyTemplate) + permittedOrgIdSet := u.getPermittedOrganiationIdSet(ctx, policyTemplate) organizations, err := u.organizationRepo.Fetch(ctx, nil) if err == nil { - u.updatePermittedOrganizations(organizations, permittedOrgIdSet, policyTemplate) + u.updatePermittedOrganizations(ctx, organizations, permittedOrgIdSet, policyTemplate) } return policyTemplate, nil @@ -182,21 +182,21 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, po return nil, err } - permittedOrgIdSet := u.getPermittedOrganiationIdSet(policyTemplate) + permittedOrgIdSet := u.getPermittedOrganiationIdSet(ctx, policyTemplate) organizations, err := u.organizationRepo.Fetch(ctx, nil) if err == nil { - u.updatePermittedOrganizations(organizations, permittedOrgIdSet, policyTemplate) + u.updatePermittedOrganizations(ctx, organizations, permittedOrgIdSet, policyTemplate) } return policyTemplate, nil } -func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]model.Organization, permittedOrgIdSet map[string]string, policyTemplate *model.PolicyTemplate) { +func (*PolicyTemplateUsecase) updatePermittedOrganizations(ctx context.Context, organizations *[]model.Organization, permittedOrgIdSet map[string]string, policyTemplate *model.PolicyTemplate) { // 허용리스트가 비어있으면 모든 Org에 대해서 허용 permitted := len(permittedOrgIdSet) == 0 - log.Info("CHECK HERE ", permitted) + log.Info(ctx, "CHECK HERE ", permitted) for _, organization := range *organizations { @@ -219,7 +219,7 @@ func (*PolicyTemplateUsecase) updatePermittedOrganizations(organizations *[]mode } } -func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *model.PolicyTemplate) map[string]string { +func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(ctx context.Context, policyTemplate *model.PolicyTemplate) map[string]string { permittedOrgIdSet := make(map[string]string) for _, permittedOrg := range policyTemplate.PermittedOrganizations { @@ -228,7 +228,7 @@ func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(policyTemplate *model // ktkfree : 이부분 확인 부탁 드립니다. // //permittedOrgIdSet[permittedOrg.OrganizationId] = "1" - log.Info("CHECK HERE ", permittedOrg) + log.Info(ctx, "CHECK HERE ", permittedOrg) } return permittedOrgIdSet } diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 2fa7d364..817eb24e 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -274,7 +274,7 @@ func (u *ProjectUsecase) GetProjectUser(ctx context.Context, projectUserId strin return nil, errors.Wrap(err, "Failed to retrieve user by id") } var pu model.ProjectUser - if err = serializer.Map(user, &pu); err != nil { + if err = serializer.Map(ctx, user, &pu); err != nil { log.Error(ctx, err) return nil, err } diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index f49dc70c..00a2e6c9 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -104,7 +104,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom // Make stack nodes var stackConf domain.StackConfResponse - if err = serializer.Map(dto, &stackConf); err != nil { + if err = serializer.Map(ctx, dto, &stackConf); err != nil { log.Info(ctx, err) } if stackTemplate.CloudService == "AWS" && stackTemplate.KubeType == "AWS" { @@ -197,7 +197,7 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err // Make stack nodes var stackConf domain.StackConfResponse - if err = serializer.Map(cluster, &stackConf); err != nil { + if err = serializer.Map(ctx, cluster, &stackConf); err != nil { log.Info(ctx, err) } @@ -250,7 +250,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod for _, resource := range stackResources { if resource.ID == domain.StackId(cluster.ID) { - if err := serializer.Map(resource, &out.Resource); err != nil { + if err := serializer.Map(ctx, resource, &out.Resource); err != nil { log.Error(ctx, err) } } @@ -337,7 +337,7 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag for _, resource := range stackResources { if resource.ID == domain.StackId(cluster.ID) { - if err := serializer.Map(resource, &outStack.Resource); err != nil { + if err := serializer.Map(ctx, resource, &outStack.Resource); err != nil { log.Error(ctx, err) } } @@ -619,7 +619,7 @@ func (u *StackUsecase) DeleteFavorite(ctx context.Context, stackId domain.StackI } func reflectClusterToStack(ctx context.Context, cluster model.Cluster, appGroups []model.AppGroup) (out model.Stack) { - if err := serializer.Map(cluster, &out); err != nil { + if err := serializer.Map(ctx, cluster, &out); err != nil { log.Error(ctx, err) } diff --git a/pkg/domain/mapper.go b/pkg/domain/mapper.go deleted file mode 100644 index e69de29b..00000000 From 3e91b3e222b7edec76f43275d7ac21135b45eeac Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 18 Mar 2024 10:57:12 +0900 Subject: [PATCH 131/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/{usecase => policy-template}/policy-template-rego.go | 4 ++-- internal/usecase/policy-template.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) rename internal/{usecase => policy-template}/policy-template-rego.go (99%) diff --git a/internal/usecase/policy-template-rego.go b/internal/policy-template/policy-template-rego.go similarity index 99% rename from internal/usecase/policy-template-rego.go rename to internal/policy-template/policy-template-rego.go index 53836580..2c701d49 100644 --- a/internal/usecase/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -1,4 +1,4 @@ -package usecase +package policytemplate import ( "regexp" @@ -241,7 +241,7 @@ func isSubstitutionRequired(expr string) bool { strings.HasPrefix(trimmed, "input.parameters.") } -func extractParameter(modules map[string]*ast.Module) []*domain.ParameterDef { +func ExtractParameter(modules map[string]*ast.Module) []*domain.ParameterDef { defStore := NewParamDefStore() for _, module := range modules { diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 4222e2ae..16e44af9 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -9,6 +9,7 @@ import ( "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + policytemplate "github.com/openinfradev/tks-api/internal/policy-template" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" @@ -272,7 +273,7 @@ func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, } if parseParameter { - response.ParametersSchema = extractParameter(modules) + response.ParametersSchema = policytemplate.ExtractParameter(modules) } return response, nil From 41a3a06efc77c396f595f5b3d79f4a0c4e1404db Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 18 Mar 2024 13:29:57 +0900 Subject: [PATCH 132/502] Lint: fix code according to golangci-lint --- cmd/server/main.go | 3 ++ internal/delivery/api/endpoint.go | 1 - .../delivery/api/generated_endpoints.go.go | 8 ---- internal/delivery/http/auth.go | 1 - internal/delivery/http/permission.go | 11 ------ internal/delivery/http/project.go | 11 ++++-- internal/helper/ssh.go | 22 ++++++----- internal/keycloak/keycloak.go | 10 ----- internal/kubernetes/kubernetes.go | 3 ++ internal/kubernetes/kubernetes_test.go | 17 +++++---- internal/mail/smtp.go | 4 +- internal/middleware/audit/audit.go | 2 +- internal/model/permission.go | 4 -- internal/repository/cluster.go | 2 +- internal/repository/project.go | 9 ----- internal/repository/user.go | 10 ++--- internal/usecase/cloud-account.go | 22 +++++------ internal/usecase/policy-template.go | 38 +++++++++---------- internal/usecase/project.go | 28 +++++++++++--- pkg/domain/auth.go | 5 --- pkg/log/log.go | 5 +-- 21 files changed, 94 insertions(+), 122 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 34d84fab..1d2cc060 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -121,6 +121,9 @@ func main() { // Ensure default rows in database err = database.EnsureDefaultRows(db) + if err != nil { + log.Fatal(ctx, "cannot Initializing Default Rows in Database: ", err) + } // Initialize external client var argoClient argowf.ArgoClient diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index f1482cd0..88f3ecbf 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -12,7 +12,6 @@ type EndpointInfo struct { const ( // Auth Login Endpoint = iota - PingToken Logout RefreshToken FindId diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 26f11263..6eaeda6d 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -7,10 +7,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Login", Group: "Auth", }, - PingToken: { - Name: "PingToken", - Group: "Auth", - }, Logout: { Name: "Logout", Group: "Auth", @@ -744,8 +740,6 @@ func (e Endpoint) String() string { switch e { case Login: return "Login" - case PingToken: - return "PingToken" case Logout: return "Logout" case RefreshToken: @@ -1118,8 +1112,6 @@ func GetEndpoint(name string) Endpoint { switch name { case "Login": return Login - case "PingToken": - return PingToken case "Logout": return Logout case "RefreshToken": diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index bf81e50e..f817f8ba 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -18,7 +18,6 @@ import ( type IAuthHandler interface { Login(w http.ResponseWriter, r *http.Request) Logout(w http.ResponseWriter, r *http.Request) - // Deprecated: PingToken is deprecated. Use VerifyToken instead. RefreshToken(w http.ResponseWriter, r *http.Request) FindId(w http.ResponseWriter, r *http.Request) FindPassword(w http.ResponseWriter, r *http.Request) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 84ea905d..9e660850 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -114,17 +114,6 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http // @Router /organizations/{organizationId}/roles/{roleId}/permissions [put] // @Security JWT func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { - // path parameter - var roleId string - _ = roleId - vars := mux.Vars(r) - if v, ok := vars["roleId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - roleId = v - } - // request input := domain.UpdatePermissionsByRoleIdRequest{} err := UnmarshalRequestInput(r, &input) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 10c38379..a8216219 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -57,8 +57,7 @@ type IProjectHandler interface { } type ProjectHandler struct { - usecase usecase.IProjectUsecase - roleUsecase usecase.IRoleUsecase + usecase usecase.IProjectUsecase } func NewProjectHandler(u usecase.Usecase) IProjectHandler { @@ -179,6 +178,10 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { // get myUserId from login component requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + log.Error(r.Context(), "Failed to retrieve user info from request") + ErrorJSON(w, r, fmt.Errorf("failed to retrieve user info from request")) + } myUserId := requestUserInfo.GetUserId().String() pr, err := p.usecase.GetProjects(r.Context(), organizationId, myUserId, onlyMyProject, pg) if err != nil { @@ -482,7 +485,7 @@ func (p ProjectHandler) GetProjectRoles(w http.ResponseWriter, r *http.Request) urlParams := r.URL.Query() queryParam := urlParams.Get("query") - query := usecase.ProjectAll + var query int if queryParam == "" || strings.EqualFold(queryParam, "all") { query = usecase.ProjectAll } else if strings.EqualFold(queryParam, "leader") { @@ -715,7 +718,7 @@ func (p ProjectHandler) GetProjectMembers(w http.ResponseWriter, r *http.Request urlParams := r.URL.Query() queryParam := urlParams.Get("query") - query := usecase.ProjectAll + var query int if queryParam == "" || strings.EqualFold(queryParam, "all") { query = usecase.ProjectAll } else if strings.EqualFold(queryParam, "leader") { diff --git a/internal/helper/ssh.go b/internal/helper/ssh.go index 08505708..83f45d68 100644 --- a/internal/helper/ssh.go +++ b/internal/helper/ssh.go @@ -2,6 +2,8 @@ package helper import ( "bytes" + "context" + "github.com/openinfradev/tks-api/pkg/log" "io" "sync" "time" @@ -96,11 +98,12 @@ func (sws *LogicSshWsSession) Close() { } } func (sws *LogicSshWsSession) Start(quitChan chan bool) { - go sws.receiveWsMsg(quitChan) - go sws.sendComboOutput(quitChan) + ctx := context.Background() + go sws.receiveWsMsg(ctx, quitChan) + go sws.sendComboOutput(ctx, quitChan) } -func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) { +func (sws *LogicSshWsSession) receiveWsMsg(ctx context.Context, exitCh chan bool) { wsConn := sws.wsConn //tells other go routine quit defer setQuit(exitCh) @@ -131,20 +134,19 @@ func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) { } */ - sws.sendWebsocketInputCommandToSshSessionStdinPipe(wsData) + sws.sendWebsocketInputCommandToSshSessionStdinPipe(ctx, wsData) } } } // sendWebsocketInputCommandToSshSessionStdinPipe -func (sws *LogicSshWsSession) sendWebsocketInputCommandToSshSessionStdinPipe(cmdBytes []byte) { +func (sws *LogicSshWsSession) sendWebsocketInputCommandToSshSessionStdinPipe(ctx context.Context, cmdBytes []byte) { if _, err := sws.stdinPipe.Write(cmdBytes); err != nil { - - //log.Error("ws cmd bytes write to ssh.stdin pipe failed") + log.Error(ctx, "ws cmd bytes write to ssh.stdin pipe failed") } } -func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) { +func (sws *LogicSshWsSession) sendComboOutput(ctx context.Context, exitCh chan bool) { wsConn := sws.wsConn defer setQuit(exitCh) @@ -162,11 +164,11 @@ func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) { if len(bs) > 0 { err := wsConn.WriteMessage(websocket.TextMessage, bs) if err != nil { - //log.Error("ssh sending combo output to webSocket failed") + log.Error(ctx, "ssh sending combo output to webSocket failed") } _, err = sws.logBuff.Write(bs) if err != nil { - //log.Error("combo output to log buffer failed") + log.Error(ctx, "combo output to log buffer failed") } sws.comboOutput.buffer.Reset() } diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 277f1296..3304800a 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -754,16 +754,6 @@ func (k *Keycloak) getClientByClientId(ctx context.Context, accessToken string, return *clients[0].ID, nil } -func (k *Keycloak) createClientRole(ctx context.Context, accessToken string, realm string, clientUuid string, - roleName string) (string, error) { - id, err := k.client.CreateClientRole(context.Background(), accessToken, realm, clientUuid, gocloak.Role{Name: gocloak.StringP(roleName)}) - if err != nil { - log.Error(ctx, "Creating Client Role is failed", err) - return "", err - } - return id, nil -} - func (k *Keycloak) getClientRole(ctx context.Context, accessToken string, realm string, clientUuid string, roleName string) (*gocloak.Role, error) { role, err := k.client.GetClientRole(context.Background(), accessToken, realm, clientUuid, roleName) diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index d709134b..7559ea26 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -609,6 +609,9 @@ func MergeKubeconfigsWithSingleUser(kubeconfigs []string) (string, error) { } err := encoder.Encode(combindConfig) + if err != nil { + return "", err + } //modContents, err := yaml.Marshal(combindConfig) // write the kubeconfig to a file diff --git a/internal/kubernetes/kubernetes_test.go b/internal/kubernetes/kubernetes_test.go index 9505998b..4a7d6bf8 100644 --- a/internal/kubernetes/kubernetes_test.go +++ b/internal/kubernetes/kubernetes_test.go @@ -1,6 +1,7 @@ package kubernetes_test import ( + "context" "github.com/openinfradev/tks-api/internal/kubernetes" "gopkg.in/yaml.v3" "os" @@ -17,7 +18,7 @@ func TestGetResourceApiVersionByClusterId(t *testing.T) { return } - res, err := kubernetes.GetResourceApiVersion(dat, "ClusterRole") + res, err := kubernetes.GetResourceApiVersion(context.Background(), dat, "ClusterRole") if err != nil { t.Errorf("GetResourceApiVersion() error = %v", err) return @@ -34,7 +35,7 @@ func TestEnsureClusterRole(t *testing.T) { return } - err = kubernetes.EnsureClusterRole(dat, "p123") + err = kubernetes.EnsureClusterRole(context.Background(), dat, "p123") if err != nil { t.Errorf("EnsureClusterRole() error = %v", err) return @@ -48,7 +49,7 @@ func TestEnsureCommonClusterRole(t *testing.T) { return } - err = kubernetes.EnsureCommonClusterRole(dat, "p123") + err = kubernetes.EnsureCommonClusterRole(context.Background(), dat, "p123") if err != nil { t.Errorf("EnsureClusterRole() error = %v", err) return @@ -62,7 +63,7 @@ func TestEnsureCommonClusterRoleBinding(t *testing.T) { return } - err = kubernetes.EnsureCommonClusterRoleBinding(dat, "p123") + err = kubernetes.EnsureCommonClusterRoleBinding(context.Background(), dat, "p123") if err != nil { t.Errorf("EnsureClusterRole() error = %v", err) return @@ -76,7 +77,7 @@ func TestEnsureClusterRoleBinding(t *testing.T) { return } - err = kubernetes.EnsureClusterRoleBinding(dat, "p123") + err = kubernetes.EnsureClusterRoleBinding(context.Background(), dat, "p123") if err != nil { t.Errorf("EnsureClusterRole() error = %v", err) return @@ -90,7 +91,7 @@ func TestEnsureRoleBinding(t *testing.T) { return } - err = kubernetes.EnsureRoleBinding(dat, "p123", "test") + err = kubernetes.EnsureRoleBinding(context.Background(), dat, "p123", "test") if err != nil { t.Errorf("EnsureClusterRole() error = %v", err) return @@ -104,7 +105,7 @@ func TestRemoveClusterRoleBinding(t *testing.T) { return } - err = kubernetes.RemoveClusterRoleBinding(dat, "p123") + err = kubernetes.RemoveClusterRoleBinding(context.Background(), dat, "p123") if err != nil { t.Errorf("EnsureClusterRole() error = %v", err) return @@ -118,7 +119,7 @@ func TestRemoveRoleBinding(t *testing.T) { return } - err = kubernetes.RemoveRoleBinding(dat, "p123", "test") + err = kubernetes.RemoveRoleBinding(context.Background(), dat, "p123", "test") if err != nil { t.Errorf("EnsureClusterRole() error = %v", err) return diff --git a/internal/mail/smtp.go b/internal/mail/smtp.go index 23714e50..62dc4578 100644 --- a/internal/mail/smtp.go +++ b/internal/mail/smtp.go @@ -116,11 +116,11 @@ func New(m *MessageInfo) Mailer { switch mailProvider { case "aws": mailer = NewAwsMailer(m) - log.Infof(nil, "aws ses mailer, %v", mailer) + log.Infof(context.TODO(), "aws ses mailer, %v", mailer) case "smtp": mailer = NewSmtpMailer(m) - log.Infof(nil, "smtp mailer, %v", mailer) + log.Infof(context.TODO(), "smtp mailer, %v", mailer) } return mailer diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 33162b5f..93af1e14 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -51,7 +51,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han message, description := "", "" if fn, ok := auditMap[endpoint]; ok { // workarround pingtoken - if endpoint != internalApi.PingToken { + if endpoint != internalApi.VerifyToken { body, err := io.ReadAll(r.Body) if err != nil { log.Error(r.Context(), err) diff --git a/internal/model/permission.go b/internal/model/permission.go index b83824af..9283bea3 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -570,8 +570,6 @@ func (p *PermissionSet) SetAllowedPermissionSet() { for _, permission := range edgePermissions { permission.IsAllowed = helper.BoolP(true) } - - return } func (p *PermissionSet) SetUserPermissionSet() { @@ -589,8 +587,6 @@ func (p *PermissionSet) SetUserPermissionSet() { for _, permission := range edgePermissions { permission.IsAllowed = helper.BoolP(true) } - - return } func (p *PermissionSet) SetRoleId(roleId string) { diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 02acaa2f..9d25be0a 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -49,7 +49,7 @@ func NewClusterRepository(db *gorm.DB) IClusterRepository { // Logics func (r *ClusterRepository) WithTrx(trxHandle *gorm.DB) IClusterRepository { if trxHandle == nil { - log.Info(nil, "Transaction Database not found") + log.Info(context.TODO(), "Transaction Database not found") return r } r.tx = trxHandle diff --git a/internal/repository/project.go b/internal/repository/project.go index ccd54b60..a5df7edf 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -64,9 +64,6 @@ func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) } func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { - if pg == nil { - pg = pagination.NewPagination(nil) - } res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ @@ -158,9 +155,6 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri } func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { - if pg == nil { - pg = pagination.NewPagination(nil) - } res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ @@ -215,9 +209,6 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio } func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { - if pg == nil { - pg = pagination.NewPagination(nil) - } res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " false as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ diff --git a/internal/repository/user.go b/internal/repository/user.go index 59627743..478aaba5 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -69,7 +69,7 @@ func (r *UserRepository) CreateWithUuid(ctx context.Context, uuid uuid.UUID, acc log.Error(ctx, res.Error.Error()) return model.User{}, res.Error } - user, err := r.getUserByAccountId(nil, accountId, organizationId) + user, err := r.getUserByAccountId(ctx, accountId, organizationId) if err != nil { return model.User{}, err } @@ -105,9 +105,7 @@ func (r *UserRepository) List(ctx context.Context, filters ...FilterFunc) (*[]mo } var out []model.User - for _, user := range users { - out = append(out, user) - } + out = append(out, users...) return &out, nil } @@ -126,9 +124,7 @@ func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination. } var out []model.User - for _, user := range users { - out = append(out, user) - } + out = append(out, users...) return &out, nil } diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index 5de5c4f2..33c9ceae 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -389,8 +389,8 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount Quota: quotaValue, Required: 5, }) - if quotaValue < currentUsage.NLB+5 { - available = false + if quotaValue >= currentUsage.NLB+5 { + available = true } case "L-E9E9831D": // Classic log.Infof(ctx, "CLB : usage %d, quota %d", currentUsage.CLB, quotaValue) @@ -400,8 +400,8 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount Quota: quotaValue, Required: 1, }) - if quotaValue < currentUsage.CLB+1 { - available = false + if quotaValue >= currentUsage.CLB+1 { + available = true } case "L-A4707A72": // IGW log.Infof(ctx, "IGW : usage %d, quota %d", currentUsage.IGW, quotaValue) @@ -411,8 +411,8 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount Quota: quotaValue, Required: 1, }) - if quotaValue < currentUsage.IGW+1 { - available = false + if quotaValue >= currentUsage.IGW+1 { + available = true } case "L-1194D53C": // Cluster log.Infof(ctx, "Cluster : usage %d, quota %d", currentUsage.Cluster, quotaValue) @@ -422,8 +422,8 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount Quota: quotaValue, Required: 1, }) - if quotaValue < currentUsage.Cluster+1 { - available = false + if quotaValue >= currentUsage.Cluster+1 { + available = true } case "L-0263D0A3": // Elastic IP log.Infof(ctx, "Elastic IP : usage %d, quota %d", currentUsage.EIP, quotaValue) @@ -433,15 +433,15 @@ func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccount Quota: quotaValue, Required: 3, }) - if quotaValue < currentUsage.EIP+3 { - available = false + if quotaValue >= currentUsage.EIP+3 { + available = true } } } //return fmt.Errorf("Always return err") - return true, out, nil + return available, out, nil } func (u *CloudAccountUsecase) getClusterCnt(ctx context.Context, cloudAccountId uuid.UUID) (cnt int) { diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index b8889eb4..d6e42574 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -197,25 +197,25 @@ func (*PolicyTemplateUsecase) updatePermittedOrganizations(ctx context.Context, log.Info(ctx, "CHECK HERE ", permitted) - for _, organization := range *organizations { - - _, ok := permittedOrgIdSet[organization.ID] - - if !ok { - policyTemplate.PermittedOrganizations = append( - policyTemplate.PermittedOrganizations, - - // ktkfree : 역시 이부분 확인 부탁 드립니다. - /* - domain.PermittedOrganization{ - OrganizationId: organization.ID, - OrganizationName: organization.Name, - Permitted: permitted, - } - */ - ) - } - } + // TODO: 이부분 확인 부탁 드립니다. + //for _, organization := range *organizations { + // _, ok := permittedOrgIdSet[organization.ID] + // + // if !ok { + // policyTemplate.PermittedOrganizations = append( + // policyTemplate.PermittedOrganizations, + // + // // ktkfree : 역시 이부분 확인 부탁 드립니다. + // /* + // domain.PermittedOrganization{ + // OrganizationId: organization.ID, + // OrganizationName: organization.Name, + // Permitted: permitted, + // } + // */ + // ) + // } + //} } func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(ctx context.Context, policyTemplate *model.PolicyTemplate) map[string]string { diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 817eb24e..ff773d0d 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -98,22 +98,25 @@ func (u *ProjectUsecase) CreateProject(ctx context.Context, p *model.Project) (s func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { if userId == "" { - pr, err = u.projectRepo.GetAllProjects(ctx, organizationId, pg) + if pr, err = u.projectRepo.GetAllProjects(ctx, organizationId, pg); err != nil { + log.Error(ctx, err) + return nil, errors.Wrap(err, "Failed to get projects.") + } } else { userUuid, err := uuid.Parse(userId) if err != nil { log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to parse uuid to string") } - if onlyMyProject == false { + if !onlyMyProject { pr, err = u.projectRepo.GetProjects(ctx, organizationId, userUuid, pg) } else { pr, err = u.projectRepo.GetProjectsByUserId(ctx, organizationId, userUuid, pg) } - } - if err != nil { - log.Error(ctx, err) - return nil, errors.Wrap(err, "Failed to get projects.") + if err != nil { + log.Error(ctx, err) + return nil, errors.Wrap(err, "Failed to get projects.") + } } return pr, err @@ -571,6 +574,11 @@ func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organiza log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } + err = u.kc.EnsureClientRoleWithClientName(ctx, organizationId, keycloak.DefaultClientID, role+"@"+projectId) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to create project namespace.") + } } return nil } @@ -620,6 +628,10 @@ func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, o return errors.Wrap(err, "Failed to create project namespace.") } err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to create project namespace.") + } return nil } @@ -639,6 +651,10 @@ func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, return errors.Wrap(err, "Failed to create project namespace.") } err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to create project namespace.") + } return nil } diff --git a/pkg/domain/auth.go b/pkg/domain/auth.go index 4dbaeeef..d88da980 100644 --- a/pkg/domain/auth.go +++ b/pkg/domain/auth.go @@ -6,11 +6,6 @@ type LoginRequest struct { OrganizationId string `json:"organizationId" validate:"required"` } -type PingTokenRequest struct { - Token string `json:"token" validate:"required"` - OrganizationId string `json:"organizationId" validate:"required"` -} - type LoginResponse struct { User struct { AccountId string `json:"accountId"` diff --git a/pkg/log/log.go b/pkg/log/log.go index 1c532e15..d48d133e 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -259,10 +259,7 @@ func getRelativeFilePath(absolutePath string) string { } relativePath := strings.TrimPrefix(absolutePath, wd) - - if strings.HasPrefix(relativePath, "/") { - relativePath = relativePath[1:] - } + relativePath = strings.TrimPrefix(relativePath, "/") return relativePath } From dc29f8fc13b6e50756c194741ae8bc3b9a4e74a8 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 18 Mar 2024 13:30:20 +0900 Subject: [PATCH 133/502] Lint: fix code according to golangci-lint --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4545b2b5..8fdb76d5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -32,4 +32,4 @@ jobs: # - https://github.com/golangci/golangci-lint-action/issues/442 run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0 - name: Run golangci-lint - run: golangci-lint run --version --verbose --out-format=github-actions + run: golangci-lint run --verbose --out-format=github-actions From f1b00c73eb707eba175202e881af486de5e5aaed Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 18 Mar 2024 13:38:56 +0900 Subject: [PATCH 134/502] Lint: upgrade the version of golangci-lint package --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8fdb76d5..79ffeb20 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -30,6 +30,6 @@ jobs: # - https://github.com/golangci/golangci-lint/issues/2922 # - https://github.com/golangci/golangci-lint/issues/2673 # - https://github.com/golangci/golangci-lint-action/issues/442 - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0 + run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.2 - name: Run golangci-lint run: golangci-lint run --verbose --out-format=github-actions From 5965313da214b81deae43e4649fc614261b8c814 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 18 Mar 2024 13:50:54 +0900 Subject: [PATCH 135/502] trivial. fix lint error --- .github/workflows/lint.yml | 2 +- internal/policy-template/policy-template-rego.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 79ffeb20..f889b7a3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: "1.18" + go-version: "1.21" cache: false - name: Install golangci-lint # Install golangci-lint from source instead of using diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index 2c701d49..1a68c874 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -90,7 +90,7 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str updateLocalAssignMap(expr, localAssignMap) if expr.IsCall() { - call := expr.Terms.([]*ast.Term) + call, _ := expr.Terms.([]*ast.Term) if len(call) > 2 { ruleName := call[0].String() @@ -313,7 +313,7 @@ func findKey(defs []*domain.ParameterDef, key string) *domain.ParameterDef { } func createKey(key string, isLast bool) *domain.ParameterDef { - finalType := "any" + var finalType string pKey := key isArray := false From c7dd9dbe4a4306c1a3392083e1f7e0f485389121 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 18 Mar 2024 13:42:23 +0900 Subject: [PATCH 136/502] feature. change resource name alert to event --- api/swagger/docs.go | 794 +++++++++--------- api/swagger/swagger.json | 794 +++++++++--------- api/swagger/swagger.yaml | 496 +++++------ internal/database/database.go | 35 +- internal/delivery/api/endpoint.go | 27 +- .../delivery/api/generated_endpoints.go.go | 116 ++- internal/delivery/http/alert.go | 291 ------- internal/delivery/http/system-notification.go | 291 +++++++ internal/middleware/auth/role/default.go | 18 +- internal/model/alert.go | 60 -- internal/model/system-notification.go | 60 ++ internal/repository/alert.go | 146 ---- internal/repository/repository.go | 30 +- internal/repository/system-notification.go | 146 ++++ internal/route/route.go | 80 +- internal/usecase/alert.go | 281 ------- internal/usecase/dashboard.go | 26 +- internal/usecase/system-notification.go | 281 +++++++ internal/usecase/usecase.go | 32 +- pkg/domain/alert.go | 137 --- pkg/domain/system-notification.go | 137 +++ pkg/httpErrors/errorCode.go | 4 +- 22 files changed, 2101 insertions(+), 2181 deletions(-) delete mode 100644 internal/delivery/http/alert.go create mode 100644 internal/delivery/http/system-notification.go delete mode 100644 internal/model/alert.go create mode 100644 internal/model/system-notification.go delete mode 100644 internal/repository/alert.go create mode 100644 internal/repository/system-notification.go delete mode 100644 internal/usecase/alert.go create mode 100644 internal/usecase/system-notification.go delete mode 100644 pkg/domain/alert.go create mode 100644 pkg/domain/system-notification.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 37878fe7..967c0070 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1697,37 +1697,6 @@ const docTemplate = `{ } } }, - "/auth/ping": { - "post": { - "description": "ping with token", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "ping with token", - "parameters": [ - { - "description": "token info", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/clusters": { "get": { "security": [ @@ -2325,235 +2294,6 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/alerts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Alerts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Get Alerts", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse" - } - } - } - } - }, - "/organizations/{organizationId}/alerts/{alertId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Get Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "alertId", - "name": "alertId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Update Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Delete Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "alertId", - "name": "alertId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/alerts/{alertId}/actions": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create alert action", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Create alert action", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ @@ -6214,14 +5954,253 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack Status", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/system-notifications": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotifications", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Get SystemNotifications", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Get SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Update SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Delete SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { + "post": { "security": [ { "JWT": [] } ], - "description": "Get Stack Status", + "description": "Create systemNotification action", "consumes": [ "application/json" ], @@ -6229,9 +6208,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "SystemNotifications" ], - "summary": "Get Stack Status", + "summary": "Create systemNotification action", "parameters": [ { "type": "string", @@ -6239,21 +6218,11 @@ const docTemplate = `{ "name": "organizationId", "in": "path", "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" - } + "description": "OK" } } } @@ -6707,14 +6676,14 @@ const docTemplate = `{ } } }, - "/system-api/organizations/{organizationId}/alerts": { + "/system-api/organizations/{organizationId}/system-notifications": { "post": { "security": [ { "JWT": [] } ], - "description": "Create alert. ADMIN ONLY", + "description": "Create systemNotification. ADMIN ONLY", "consumes": [ "application/json" ], @@ -6722,9 +6691,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Alerts" + "SystemNotifications" ], - "summary": "Create alert. ADMIN ONLY", + "summary": "Create systemNotification. ADMIN ONLY", "parameters": [ { "type": "string", @@ -6950,103 +6919,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse": { - "type": "object", - "properties": { - "alertId": { - "type": "string" - }, - "content": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "taker": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "updatedAt": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.AlertResponse": { - "type": "object", - "properties": { - "alertActions": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse" - } - }, - "closedAt": { - "type": "string" - }, - "cluster": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" - }, - "code": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "firedAt": { - "type": "string" - }, - "grade": { - "type": "string" - }, - "grafanaUrl": { - "type": "string" - }, - "id": { - "type": "string" - }, - "lastTaker": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "node": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "processingSec": { - "type": "integer" - }, - "rawData": { - "type": "string" - }, - "status": { - "type": "string" - }, - "takedAt": { - "type": "string" - }, - "takedSec": { - "type": "integer" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -8612,28 +8484,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse": { - "type": "object", - "properties": { - "alert": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse": { - "type": "object", - "properties": { - "alerts": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse" - } - }, - "pagination": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse": { "type": "object", "properties": { @@ -9098,6 +8948,28 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse": { + "type": "object", + "properties": { + "systemNotification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "systemNotifications": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse": { "type": "object", "properties": { @@ -9557,21 +9429,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { - "type": "object", - "required": [ - "organizationId", - "token" - ], - "properties": { - "organizationId": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.PodCount": { "type": "object", "properties": { @@ -10423,24 +10280,113 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Unit": { + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationActionResponse": { "type": "object", "properties": { - "data": { + "content": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "systemNotificationId": { + "type": "string" + }, + "taker": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse": { + "type": "object", + "properties": { + "closedAt": { + "type": "string" + }, + "cluster": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" + }, + "code": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "firedAt": { + "type": "string" + }, + "grade": { + "type": "string" + }, + "grafanaUrl": { + "type": "string" + }, + "id": { + "type": "string" + }, + "lastTaker": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "message": { + "type": "string" + }, + "name": { + "type": "string" + }, + "node": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "processingSec": { + "type": "integer" + }, + "rawData": { + "type": "string" + }, + "status": { + "type": "string" + }, + "systemNotificationActions": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationActionResponse" } }, - "name": { + "takedAt": { + "type": "string" + }, + "takedSec": { + "type": "integer" + }, + "updatedAt": { "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest": { + "github_com_openinfradev_tks-api_pkg_domain.Unit": { "type": "object", "properties": { - "description": { + "data": { + "type": "array", + "items": { + "type": "string" + } + }, + "name": { "type": "string" } } @@ -10807,6 +10753,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 95fb048a..f333c1f6 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1691,37 +1691,6 @@ } } }, - "/auth/ping": { - "post": { - "description": "ping with token", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Auth" - ], - "summary": "ping with token", - "parameters": [ - { - "description": "token info", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/clusters": { "get": { "security": [ @@ -2319,235 +2288,6 @@ } } }, - "/organizations/{organizationId}/alerts": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Alerts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Get Alerts", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse" - } - } - } - } - }, - "/organizations/{organizationId}/alerts/{alertId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Get Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "alertId", - "name": "alertId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse" - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Update Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - }, - "delete": { - "security": [ - { - "JWT": [] - } - ], - "description": "Delete Alert", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Delete Alert", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "alertId", - "name": "alertId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/alerts/{alertId}/actions": { - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create alert action", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Alerts" - ], - "summary": "Create alert action", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/organizations/{organizationId}/cloud-accounts": { "get": { "security": [ @@ -6208,14 +5948,253 @@ } } }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack Status", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/system-notifications": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotifications", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Get SystemNotifications", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Get SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Update SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Delete SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { + "post": { "security": [ { "JWT": [] } ], - "description": "Get Stack Status", + "description": "Create systemNotification action", "consumes": [ "application/json" ], @@ -6223,9 +6202,9 @@ "application/json" ], "tags": [ - "Stacks" + "SystemNotifications" ], - "summary": "Get Stack Status", + "summary": "Create systemNotification action", "parameters": [ { "type": "string", @@ -6233,21 +6212,11 @@ "name": "organizationId", "in": "path", "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" - } + "description": "OK" } } } @@ -6701,14 +6670,14 @@ } } }, - "/system-api/organizations/{organizationId}/alerts": { + "/system-api/organizations/{organizationId}/system-notifications": { "post": { "security": [ { "JWT": [] } ], - "description": "Create alert. ADMIN ONLY", + "description": "Create systemNotification. ADMIN ONLY", "consumes": [ "application/json" ], @@ -6716,9 +6685,9 @@ "application/json" ], "tags": [ - "Alerts" + "SystemNotifications" ], - "summary": "Create alert. ADMIN ONLY", + "summary": "Create systemNotification. ADMIN ONLY", "parameters": [ { "type": "string", @@ -6944,103 +6913,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse": { - "type": "object", - "properties": { - "alertId": { - "type": "string" - }, - "content": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "taker": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "updatedAt": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.AlertResponse": { - "type": "object", - "properties": { - "alertActions": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse" - } - }, - "closedAt": { - "type": "string" - }, - "cluster": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" - }, - "code": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "firedAt": { - "type": "string" - }, - "grade": { - "type": "string" - }, - "grafanaUrl": { - "type": "string" - }, - "id": { - "type": "string" - }, - "lastTaker": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "node": { - "type": "string" - }, - "organizationId": { - "type": "string" - }, - "processingSec": { - "type": "integer" - }, - "rawData": { - "type": "string" - }, - "status": { - "type": "string" - }, - "takedAt": { - "type": "string" - }, - "takedSec": { - "type": "integer" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -8606,28 +8478,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse": { - "type": "object", - "properties": { - "alert": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse": { - "type": "object", - "properties": { - "alerts": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse" - } - }, - "pagination": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse": { "type": "object", "properties": { @@ -9092,6 +8942,28 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse": { + "type": "object", + "properties": { + "systemNotification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "systemNotifications": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse": { "type": "object", "properties": { @@ -9551,21 +9423,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest": { - "type": "object", - "required": [ - "organizationId", - "token" - ], - "properties": { - "organizationId": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.PodCount": { "type": "object", "properties": { @@ -10417,24 +10274,113 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Unit": { + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationActionResponse": { "type": "object", "properties": { - "data": { + "content": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "systemNotificationId": { + "type": "string" + }, + "taker": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "updatedAt": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse": { + "type": "object", + "properties": { + "closedAt": { + "type": "string" + }, + "cluster": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" + }, + "code": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "firedAt": { + "type": "string" + }, + "grade": { + "type": "string" + }, + "grafanaUrl": { + "type": "string" + }, + "id": { + "type": "string" + }, + "lastTaker": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "message": { + "type": "string" + }, + "name": { + "type": "string" + }, + "node": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "processingSec": { + "type": "integer" + }, + "rawData": { + "type": "string" + }, + "status": { + "type": "string" + }, + "systemNotificationActions": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationActionResponse" } }, - "name": { + "takedAt": { + "type": "string" + }, + "takedSec": { + "type": "integer" + }, + "updatedAt": { "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest": { + "github_com_openinfradev_tks-api_pkg_domain.Unit": { "type": "object", "properties": { - "description": { + "data": { + "type": "array", + "items": { + "type": "string" + } + }, + "name": { "type": "string" } } @@ -10801,6 +10747,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index e0de0963..d727754a 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -147,70 +147,6 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest' type: array type: object - github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse: - properties: - alertId: - type: string - content: - type: string - createdAt: - type: string - id: - type: string - status: - type: string - taker: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' - updatedAt: - type: string - type: object - github_com_openinfradev_tks-api_pkg_domain.AlertResponse: - properties: - alertActions: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertActionResponse' - type: array - closedAt: - type: string - cluster: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse' - code: - type: string - createdAt: - type: string - description: - type: string - firedAt: - type: string - grade: - type: string - grafanaUrl: - type: string - id: - type: string - lastTaker: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' - message: - type: string - name: - type: string - node: - type: string - organizationId: - type: string - processingSec: - type: integer - rawData: - type: string - status: - type: string - takedAt: - type: string - takedSec: - type: integer - updatedAt: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse: properties: appGroupType: @@ -1286,20 +1222,6 @@ definitions: - organizationId - userName type: object - github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse: - properties: - alert: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse' - type: object - github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse: - properties: - alerts: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AlertResponse' - type: array - pagination: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' - type: object github_com_openinfradev_tks-api_pkg_domain.GetAppGroupResponse: properties: appGroup: @@ -1595,6 +1517,20 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse: + properties: + systemNotification: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse' + type: object + github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + systemNotifications: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse: properties: createdAt: @@ -1896,16 +1832,6 @@ definitions: permitted: type: boolean type: object - github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest: - properties: - organizationId: - type: string - token: - type: string - required: - - organizationId - - token - type: object github_com_openinfradev_tks-api_pkg_domain.PodCount: properties: day: @@ -2476,6 +2402,70 @@ definitions: status: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationActionResponse: + properties: + content: + type: string + createdAt: + type: string + id: + type: string + status: + type: string + systemNotificationId: + type: string + taker: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + updatedAt: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse: + properties: + closedAt: + type: string + cluster: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse' + code: + type: string + createdAt: + type: string + description: + type: string + firedAt: + type: string + grade: + type: string + grafanaUrl: + type: string + id: + type: string + lastTaker: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + message: + type: string + name: + type: string + node: + type: string + organizationId: + type: string + processingSec: + type: integer + rawData: + type: string + status: + type: string + systemNotificationActions: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationActionResponse' + type: array + takedAt: + type: string + takedSec: + type: integer + updatedAt: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.Unit: properties: data: @@ -2485,11 +2475,6 @@ definitions: name: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest: - properties: - description: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest: properties: endpointUrl: @@ -2730,6 +2715,11 @@ definitions: required: - serviceIds type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest: + properties: + description: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest: properties: description: @@ -3992,26 +3982,6 @@ paths: summary: logout tags: - Auth - /auth/ping: - post: - consumes: - - application/json - description: ping with token - parameters: - - description: token info - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PingTokenRequest' - produces: - - application/json - responses: - "200": - description: OK - summary: ping with token - tags: - - Auth /clusters: get: consumes: @@ -4386,152 +4356,6 @@ paths: summary: Update organization detail tags: - Organizations - /organizations/{organizationId}/alerts: - get: - consumes: - - application/json - description: Get Alerts - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: pageSize - in: query - name: limit - type: string - - description: pageNumber - in: query - name: page - type: string - - description: sortColumn - in: query - name: soertColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertsResponse' - security: - - JWT: [] - summary: Get Alerts - tags: - - Alerts - /organizations/{organizationId}/alerts/{alertId}: - delete: - consumes: - - application/json - description: Delete Alert - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: alertId - in: path - name: alertId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Delete Alert - tags: - - Alerts - get: - consumes: - - application/json - description: Get Alert - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: alertId - in: path - name: alertId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAlertResponse' - security: - - JWT: [] - summary: Get Alert - tags: - - Alerts - put: - consumes: - - application/json - description: Update Alert - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: Update cloud setting request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAlertRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Update Alert - tags: - - Alerts - /organizations/{organizationId}/alerts/{alertId}/actions: - post: - consumes: - - application/json - description: Create alert action - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: Create alert action - tags: - - Alerts /organizations/{organizationId}/cloud-accounts: get: consumes: @@ -6914,6 +6738,152 @@ paths: summary: Check name for stack tags: - Stacks + /organizations/{organizationId}/system-notifications: + get: + consumes: + - application/json + description: Get SystemNotifications + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse' + security: + - JWT: [] + summary: Get SystemNotifications + tags: + - SystemNotifications + /organizations/{organizationId}/system-notifications/{systemNotificationId}: + delete: + consumes: + - application/json + description: Delete SystemNotification + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: systemNotificationId + in: path + name: systemNotificationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete SystemNotification + tags: + - SystemNotifications + get: + consumes: + - application/json + description: Get SystemNotification + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: systemNotificationId + in: path + name: systemNotificationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse' + security: + - JWT: [] + summary: Get SystemNotification + tags: + - SystemNotifications + put: + consumes: + - application/json + description: Update SystemNotification + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: Update cloud setting request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update SystemNotification + tags: + - SystemNotifications + /organizations/{organizationId}/system-notifications/{systemNotificationId}/actions: + post: + consumes: + - application/json + description: Create systemNotification action + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Create systemNotification action + tags: + - SystemNotifications /organizations/{organizationId}/users: get: consumes: @@ -7202,11 +7172,11 @@ paths: summary: '[CompileRego] Rego 코드 컴파일 및 파라미터 파싱' tags: - PolicyTemplate - /system-api/organizations/{organizationId}/alerts: + /system-api/organizations/{organizationId}/system-notifications: post: consumes: - application/json - description: Create alert. ADMIN ONLY + description: Create systemNotification. ADMIN ONLY parameters: - description: organizationId in: path @@ -7220,9 +7190,9 @@ paths: description: OK security: - JWT: [] - summary: Create alert. ADMIN ONLY + summary: Create systemNotification. ADMIN ONLY tags: - - Alerts + - SystemNotifications securityDefinitions: JWT: in: header diff --git a/internal/database/database.go b/internal/database/database.go index 91cfd606..147a6bb3 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -3,10 +3,11 @@ package database import ( "context" "fmt" - "github.com/openinfradev/tks-api/internal/pagination" "os" "strings" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/delivery/api" internal_gorm "github.com/openinfradev/tks-api/internal/gorm" @@ -109,11 +110,11 @@ func migrateSchema(db *gorm.DB) error { return err } - // Alert - if err := db.AutoMigrate(&model.Alert{}); err != nil { + // Event + if err := db.AutoMigrate(&model.SystemNotification{}); err != nil { return err } - if err := db.AutoMigrate(&model.AlertAction{}); err != nil { + if err := db.AutoMigrate(&model.SystemNotificationAction{}); err != nil { return err } @@ -162,19 +163,19 @@ func migrateSchema(db *gorm.DB) error { func EnsureDefaultRows(db *gorm.DB) error { // Create default rows repoFactory := repository.Repository{ - Auth: repository.NewAuthRepository(db), - User: repository.NewUserRepository(db), - Cluster: repository.NewClusterRepository(db), - Organization: repository.NewOrganizationRepository(db), - AppGroup: repository.NewAppGroupRepository(db), - AppServeApp: repository.NewAppServeAppRepository(db), - CloudAccount: repository.NewCloudAccountRepository(db), - StackTemplate: repository.NewStackTemplateRepository(db), - Alert: repository.NewAlertRepository(db), - Role: repository.NewRoleRepository(db), - Permission: repository.NewPermissionRepository(db), - Endpoint: repository.NewEndpointRepository(db), - Project: repository.NewProjectRepository(db), + Auth: repository.NewAuthRepository(db), + User: repository.NewUserRepository(db), + Cluster: repository.NewClusterRepository(db), + Organization: repository.NewOrganizationRepository(db), + AppGroup: repository.NewAppGroupRepository(db), + AppServeApp: repository.NewAppServeAppRepository(db), + CloudAccount: repository.NewCloudAccountRepository(db), + StackTemplate: repository.NewStackTemplateRepository(db), + SystemNotification: repository.NewSystemNotificationRepository(db), + Role: repository.NewRoleRepository(db), + Permission: repository.NewPermissionRepository(db), + Endpoint: repository.NewEndpointRepository(db), + Project: repository.NewProjectRepository(db), } // diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index f1482cd0..eee8197c 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -112,13 +112,26 @@ const ( GetStacksDashboard // 대시보드/대시보드/조회 GetResourcesDashboard // 대시보드/대시보드/조회 - // Alert - CreateAlert - GetAlerts - GetAlert - DeleteAlert - UpdateAlert - CreateAlertAction + // AlertTemplate + Admin_CreateAlertTemplate + Admin_UpdateAlertTemplate + Admin_GetAlertTemplates + Admin_GetAlertTemplate + + // SystemAlert + // CreateSystemAlert + // GetSystemAlerts + // GetSystemAlert + // DeleteSystemAlert + // UpdateSystemAlert + + // SystemNotification + CreateSystemNotification + GetSystemNotifications + GetSystemNotification + DeleteSystemNotification + UpdateSystemNotification + CreateSystemNotificationAction // Stack GetStacks // 스택관리/조회 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 26f11263..4f845a1d 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -331,29 +331,45 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetResourcesDashboard", Group: "Dashboard", }, - CreateAlert: { - Name: "CreateAlert", - Group: "Alert", + Admin_CreateAlertTemplate: { + Name: "Admin_CreateAlertTemplate", + Group: "AlertTemplate", }, - GetAlerts: { - Name: "GetAlerts", - Group: "Alert", + Admin_UpdateAlertTemplate: { + Name: "Admin_UpdateAlertTemplate", + Group: "AlertTemplate", }, - GetAlert: { - Name: "GetAlert", - Group: "Alert", + Admin_GetAlertTemplates: { + Name: "Admin_GetAlertTemplates", + Group: "AlertTemplate", }, - DeleteAlert: { - Name: "DeleteAlert", - Group: "Alert", + Admin_GetAlertTemplate: { + Name: "Admin_GetAlertTemplate", + Group: "AlertTemplate", }, - UpdateAlert: { - Name: "UpdateAlert", - Group: "Alert", + CreateSystemNotification: { + Name: "CreateSystemNotification", + Group: "SystemNotification", }, - CreateAlertAction: { - Name: "CreateAlertAction", - Group: "Alert", + GetSystemNotifications: { + Name: "GetSystemNotifications", + Group: "SystemNotification", + }, + GetSystemNotification: { + Name: "GetSystemNotification", + Group: "SystemNotification", + }, + DeleteSystemNotification: { + Name: "DeleteSystemNotification", + Group: "SystemNotification", + }, + UpdateSystemNotification: { + Name: "UpdateSystemNotification", + Group: "SystemNotification", + }, + CreateSystemNotificationAction: { + Name: "CreateSystemNotificationAction", + Group: "SystemNotification", }, GetStacks: { Name: "GetStacks", @@ -906,18 +922,26 @@ func (e Endpoint) String() string { return "GetStacksDashboard" case GetResourcesDashboard: return "GetResourcesDashboard" - case CreateAlert: - return "CreateAlert" - case GetAlerts: - return "GetAlerts" - case GetAlert: - return "GetAlert" - case DeleteAlert: - return "DeleteAlert" - case UpdateAlert: - return "UpdateAlert" - case CreateAlertAction: - return "CreateAlertAction" + case Admin_CreateAlertTemplate: + return "Admin_CreateAlertTemplate" + case Admin_UpdateAlertTemplate: + return "Admin_UpdateAlertTemplate" + case Admin_GetAlertTemplates: + return "Admin_GetAlertTemplates" + case Admin_GetAlertTemplate: + return "Admin_GetAlertTemplate" + case CreateSystemNotification: + return "CreateSystemNotification" + case GetSystemNotifications: + return "GetSystemNotifications" + case GetSystemNotification: + return "GetSystemNotification" + case DeleteSystemNotification: + return "DeleteSystemNotification" + case UpdateSystemNotification: + return "UpdateSystemNotification" + case CreateSystemNotificationAction: + return "CreateSystemNotificationAction" case GetStacks: return "GetStacks" case CreateStack: @@ -1280,18 +1304,26 @@ func GetEndpoint(name string) Endpoint { return GetStacksDashboard case "GetResourcesDashboard": return GetResourcesDashboard - case "CreateAlert": - return CreateAlert - case "GetAlerts": - return GetAlerts - case "GetAlert": - return GetAlert - case "DeleteAlert": - return DeleteAlert - case "UpdateAlert": - return UpdateAlert - case "CreateAlertAction": - return CreateAlertAction + case "Admin_CreateAlertTemplate": + return Admin_CreateAlertTemplate + case "Admin_UpdateAlertTemplate": + return Admin_UpdateAlertTemplate + case "Admin_GetAlertTemplates": + return Admin_GetAlertTemplates + case "Admin_GetAlertTemplate": + return Admin_GetAlertTemplate + case "CreateSystemNotification": + return CreateSystemNotification + case "GetSystemNotifications": + return GetSystemNotifications + case "GetSystemNotification": + return GetSystemNotification + case "DeleteSystemNotification": + return DeleteSystemNotification + case "UpdateSystemNotification": + return UpdateSystemNotification + case "CreateSystemNotificationAction": + return CreateSystemNotificationAction case "GetStacks": return GetStacks case "CreateStack": diff --git a/internal/delivery/http/alert.go b/internal/delivery/http/alert.go deleted file mode 100644 index 5ec1fa9b..00000000 --- a/internal/delivery/http/alert.go +++ /dev/null @@ -1,291 +0,0 @@ -package http - -import ( - "fmt" - "io" - "net/http" - - "github.com/google/uuid" - "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/internal/model" - "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" - "github.com/openinfradev/tks-api/internal/usecase" - "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" - "github.com/pkg/errors" -) - -type AlertHandler struct { - usecase usecase.IAlertUsecase -} - -func NewAlertHandler(h usecase.Usecase) *AlertHandler { - return &AlertHandler{ - usecase: h.Alert, - } -} - -// CreateAlert godoc -// -// @Tags Alerts -// @Summary Create alert. ADMIN ONLY -// @Description Create alert. ADMIN ONLY -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} nil -// @Router /system-api/organizations/{organizationId}/alerts [post] -// @Security JWT -func (h *AlertHandler) CreateAlert(w http.ResponseWriter, r *http.Request) { - - /* - INFO[2023-04-26 18:14:11] body : {"receiver":"webhook-alert","status":"firing","alerts":[{"status":"firing","labels":{"alertname":"TestAlert1"},"annotations":{},"startsAt":"2023-04-26T09:14:01.489894015Z","endsAt":"0001-01-01T00:00:00Z","generatorURL":"","fingerprint":"0dafe30dffce9487"}],"groupLabels":{"alertname":"TestAlert1"},"commonLabels":{"alertname":"TestAlert1"},"commonAnnotations":{},"externalURL":"http://lma-alertmanager.lma:9093","version":"4","groupKey":"{}:{alertname=\"TestAlert1\"}","truncatedAlerts":0} - INFO[2023-04-26 18:14:11] {"receiver":"webhook-alert","status":"firing","alerts":[{"status":"firing","labels":{"alertname":"TestAlert1"},"annotations":{},"startsAt":"2023-04-26T09:14:01.489894015Z","endsAt":"0001-01-01T00:00:00Z","generatorURL":"","fingerprint":"0dafe30dffce9487"}],"groupLabels":{"alertname":"TestAlert1"},"commonLabels":{"alertname":"TestAlert1"},"commonAnnotations":{},"externalURL":"http://lma-alertmanager.lma:9093","version":"4","groupKey":"{}:{alertname=\"TestAlert1\"}","truncatedAlerts":0} - */ - - /* - // webhook 으로 부터 받은 body parse - bodyBytes, err := io.ReadAll(r.Body) - if err != nil { - log.Error(r.Context(),err) - } - bodyString := string(bodyBytes) - log.Info(r.Context(),bodyString) - */ - - // 외부로부터(alert manager) 오는 데이터이므로, dto 변환없이 by-pass 처리한다. - input := domain.CreateAlertRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - ErrorJSON(w, r, err) - return - } - - err = h.usecase.Create(r.Context(), input) - if err != nil { - ErrorJSON(w, r, err) - return - } - - ResponseJSON(w, r, http.StatusOK, nil) -} - -// GetAlert godoc -// -// @Tags Alerts -// @Summary Get Alerts -// @Description Get Alerts -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetAlertsResponse -// @Router /organizations/{organizationId}/alerts [get] -// @Security JWT -func (h *AlertHandler) GetAlerts(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "", "")) - return - } - - urlParams := r.URL.Query() - pg := pagination.NewPagination(&urlParams) - // convert status - for i, filter := range pg.GetFilters() { - if filter.Column == "status" { - for j, value := range filter.Values { - switch value { - case "CREATED": - pg.GetFilters()[i].Values[j] = "0" - case "INPROGRESS": - pg.GetFilters()[i].Values[j] = "1" - case "CLOSED": - pg.GetFilters()[i].Values[j] = "2" - case "ERROR": - pg.GetFilters()[i].Values[j] = "3" - } - } - } - } - - alerts, err := h.usecase.Fetch(r.Context(), organizationId, pg) - if err != nil { - ErrorJSON(w, r, err) - return - } - - var out domain.GetAlertsResponse - out.Alerts = make([]domain.AlertResponse, len(alerts)) - for i, alert := range alerts { - if err := serializer.Map(r.Context(), alert, &out.Alerts[i]); err != nil { - log.Info(r.Context(), err) - } - - outAlertActions := make([]domain.AlertActionResponse, len(alert.AlertActions)) - for j, alertAction := range alert.AlertActions { - if err := serializer.Map(r.Context(), alertAction, &outAlertActions[j]); err != nil { - log.Info(r.Context(), err) - } - } - out.Alerts[i].AlertActions = outAlertActions - if len(outAlertActions) > 0 { - out.Alerts[i].LastTaker = outAlertActions[0].Taker - } - } - - if out.Pagination, err = pg.Response(r.Context()); err != nil { - log.Info(r.Context(), err) - } - - ResponseJSON(w, r, http.StatusOK, out) -} - -// GetAlert godoc -// -// @Tags Alerts -// @Summary Get Alert -// @Description Get Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param alertId path string true "alertId" -// @Success 200 {object} domain.GetAlertResponse -// @Router /organizations/{organizationId}/alerts/{alertId} [get] -// @Security JWT -func (h *AlertHandler) GetAlert(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - strId, ok := vars["alertId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid alertId"), "", "")) - return - } - - alertId, err := uuid.Parse(strId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "", "")) - return - } - - alert, err := h.usecase.Get(r.Context(), alertId) - if err != nil { - ErrorJSON(w, r, err) - return - } - - var out domain.GetAlertResponse - if err := serializer.Map(r.Context(), alert, &out.Alert); err != nil { - log.Info(r.Context(), err) - } - outAlertActions := make([]domain.AlertActionResponse, len(alert.AlertActions)) - for j, alertAction := range alert.AlertActions { - if err := serializer.Map(r.Context(), alertAction, &outAlertActions[j]); err != nil { - log.Info(r.Context(), err) - continue - } - } - out.Alert.AlertActions = outAlertActions - - ResponseJSON(w, r, http.StatusOK, out) -} - -// UpdateAlert godoc -// -// @Tags Alerts -// @Summary Update Alert -// @Description Update Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateAlertRequest true "Update cloud setting request" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId} [put] -// @Security JWT -func (h *AlertHandler) UpdateAlert(w http.ResponseWriter, r *http.Request) { - ErrorJSON(w, r, fmt.Errorf("Need implementation")) -} - -// DeleteAlert godoc -// -// @Tags Alerts -// @Summary Delete Alert -// @Description Delete Alert -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param alertId path string true "alertId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId} [delete] -// @Security JWT -func (h *AlertHandler) DeleteAlert(w http.ResponseWriter, r *http.Request) { - ErrorJSON(w, r, fmt.Errorf("Need implementation")) -} - -func (h *AlertHandler) AlertTest(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - ErrorJSON(w, r, err) - return - } - - log.Info(r.Context(), "TEST ", body) -} - -// CreateAlertAction godoc -// -// @Tags Alerts -// @Summary Create alert action -// @Description Create alert action -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} nil -// @Router /organizations/{organizationId}/alerts/{alertId}/actions [post] -// @Security JWT -func (h *AlertHandler) CreateAlertAction(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - strId, ok := vars["alertId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid alertId"), "", "")) - return - } - - alertId, err := uuid.Parse(strId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "", "")) - return - } - - input := domain.CreateAlertActionRequest{} - err = UnmarshalRequestInput(r, &input) - if err != nil { - ErrorJSON(w, r, err) - return - } - - log.Info(r.Context(), "alert : ", helper.ModelToJson(input)) - - var dto model.AlertAction - if err = serializer.Map(r.Context(), input, &dto); err != nil { - log.Info(r.Context(), err) - } - dto.AlertId = alertId - - alertAction, err := h.usecase.CreateAlertAction(r.Context(), dto) - if err != nil { - ErrorJSON(w, r, err) - return - } - - var out domain.CreateAlertActionResponse - out.ID = alertAction.String() - ResponseJSON(w, r, http.StatusOK, out) -} diff --git a/internal/delivery/http/system-notification.go b/internal/delivery/http/system-notification.go new file mode 100644 index 00000000..9f056bcb --- /dev/null +++ b/internal/delivery/http/system-notification.go @@ -0,0 +1,291 @@ +package http + +import ( + "fmt" + "io" + "net/http" + + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" +) + +type SystemNotificationHandler struct { + usecase usecase.ISystemNotificationUsecase +} + +func NewSystemNotificationHandler(h usecase.Usecase) *SystemNotificationHandler { + return &SystemNotificationHandler{ + usecase: h.SystemNotification, + } +} + +// CreateSystemNotification godoc +// +// @Tags SystemNotifications +// @Summary Create systemNotification. ADMIN ONLY +// @Description Create systemNotification. ADMIN ONLY +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} nil +// @Router /system-api/organizations/{organizationId}/system-notifications [post] +// @Security JWT +func (h *SystemNotificationHandler) CreateSystemNotification(w http.ResponseWriter, r *http.Request) { + + /* + INFO[2023-04-26 18:14:11] body : {"receiver":"webhook-systemNotification","status":"firing","systemNotifications":[{"status":"firing","labels":{"systemNotificationname":"TestSystemNotification1"},"annotations":{},"startsAt":"2023-04-26T09:14:01.489894015Z","endsAt":"0001-01-01T00:00:00Z","generatorURL":"","fingerprint":"0dafe30dffce9487"}],"groupLabels":{"systemNotificationname":"TestSystemNotification1"},"commonLabels":{"systemNotificationname":"TestSystemNotification1"},"commonAnnotations":{},"externalURL":"http://lma-systemNotificationmanager.lma:9093","version":"4","groupKey":"{}:{systemNotificationname=\"TestSystemNotification1\"}","truncatedSystemNotifications":0} + INFO[2023-04-26 18:14:11] {"receiver":"webhook-systemNotification","status":"firing","systemNotifications":[{"status":"firing","labels":{"systemNotificationname":"TestSystemNotification1"},"annotations":{},"startsAt":"2023-04-26T09:14:01.489894015Z","endsAt":"0001-01-01T00:00:00Z","generatorURL":"","fingerprint":"0dafe30dffce9487"}],"groupLabels":{"systemNotificationname":"TestSystemNotification1"},"commonLabels":{"systemNotificationname":"TestSystemNotification1"},"commonAnnotations":{},"externalURL":"http://lma-systemNotificationmanager.lma:9093","version":"4","groupKey":"{}:{systemNotificationname=\"TestSystemNotification1\"}","truncatedSystemNotifications":0} + */ + + /* + // webhook 으로 부터 받은 body parse + bodyBytes, err := io.ReadAll(r.Body) + if err != nil { + log.Error(r.Context(),err) + } + bodyString := string(bodyBytes) + log.Info(r.Context(),bodyString) + */ + + // 외부로부터(systemNotification manager) 오는 데이터이므로, dto 변환없이 by-pass 처리한다. + input := domain.CreateSystemNotificationRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + err = h.usecase.Create(r.Context(), input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +// GetSystemNotification godoc +// +// @Tags SystemNotifications +// @Summary Get SystemNotifications +// @Description Get SystemNotifications +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetSystemNotificationsResponse +// @Router /organizations/{organizationId}/system-notifications [get] +// @Security JWT +func (h *SystemNotificationHandler) GetSystemNotifications(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "", "")) + return + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + // convert status + for i, filter := range pg.GetFilters() { + if filter.Column == "status" { + for j, value := range filter.Values { + switch value { + case "CREATED": + pg.GetFilters()[i].Values[j] = "0" + case "INPROGRESS": + pg.GetFilters()[i].Values[j] = "1" + case "CLOSED": + pg.GetFilters()[i].Values[j] = "2" + case "ERROR": + pg.GetFilters()[i].Values[j] = "3" + } + } + } + } + + systemNotifications, err := h.usecase.Fetch(r.Context(), organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetSystemNotificationsResponse + out.SystemNotifications = make([]domain.SystemNotificationResponse, len(systemNotifications)) + for i, systemNotification := range systemNotifications { + if err := serializer.Map(r.Context(), systemNotification, &out.SystemNotifications[i]); err != nil { + log.Info(r.Context(), err) + } + + outSystemNotificationActions := make([]domain.SystemNotificationActionResponse, len(systemNotification.SystemNotificationActions)) + for j, systemNotificationAction := range systemNotification.SystemNotificationActions { + if err := serializer.Map(r.Context(), systemNotificationAction, &outSystemNotificationActions[j]); err != nil { + log.Info(r.Context(), err) + } + } + out.SystemNotifications[i].SystemNotificationActions = outSystemNotificationActions + if len(outSystemNotificationActions) > 0 { + out.SystemNotifications[i].LastTaker = outSystemNotificationActions[0].Taker + } + } + + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetSystemNotification godoc +// +// @Tags SystemNotifications +// @Summary Get SystemNotification +// @Description Get SystemNotification +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param systemNotificationId path string true "systemNotificationId" +// @Success 200 {object} domain.GetSystemNotificationResponse +// @Router /organizations/{organizationId}/system-notifications/{systemNotificationId} [get] +// @Security JWT +func (h *SystemNotificationHandler) GetSystemNotification(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["systemNotificationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid systemNotificationId"), "", "")) + return + } + + systemNotificationId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "", "")) + return + } + + systemNotification, err := h.usecase.Get(r.Context(), systemNotificationId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetSystemNotificationResponse + if err := serializer.Map(r.Context(), systemNotification, &out.SystemNotification); err != nil { + log.Info(r.Context(), err) + } + outSystemNotificationActions := make([]domain.SystemNotificationActionResponse, len(systemNotification.SystemNotificationActions)) + for j, systemNotificationAction := range systemNotification.SystemNotificationActions { + if err := serializer.Map(r.Context(), systemNotificationAction, &outSystemNotificationActions[j]); err != nil { + log.Info(r.Context(), err) + continue + } + } + out.SystemNotification.SystemNotificationActions = outSystemNotificationActions + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdateSystemNotification godoc +// +// @Tags SystemNotifications +// @Summary Update SystemNotification +// @Description Update SystemNotification +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.UpdateSystemNotificationRequest true "Update cloud setting request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/system-notifications/{systemNotificationId} [put] +// @Security JWT +func (h *SystemNotificationHandler) UpdateSystemNotification(w http.ResponseWriter, r *http.Request) { + ErrorJSON(w, r, fmt.Errorf("Need implementation")) +} + +// DeleteSystemNotification godoc +// +// @Tags SystemNotifications +// @Summary Delete SystemNotification +// @Description Delete SystemNotification +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param systemNotificationId path string true "systemNotificationId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/system-notifications/{systemNotificationId} [delete] +// @Security JWT +func (h *SystemNotificationHandler) DeleteSystemNotification(w http.ResponseWriter, r *http.Request) { + ErrorJSON(w, r, fmt.Errorf("Need implementation")) +} + +func (h *SystemNotificationHandler) SystemNotificationTest(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + ErrorJSON(w, r, err) + return + } + + log.Info(r.Context(), "TEST ", body) +} + +// CreateSystemNotificationAction godoc +// +// @Tags SystemNotifications +// @Summary Create systemNotification action +// @Description Create systemNotification action +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/system-notifications/{systemNotificationId}/actions [post] +// @Security JWT +func (h *SystemNotificationHandler) CreateSystemNotificationAction(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["systemNotificationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid systemNotificationId"), "", "")) + return + } + + systemNotificationId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "", "")) + return + } + + input := domain.CreateSystemNotificationActionRequest{} + err = UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + log.Info(r.Context(), "systemNotification : ", helper.ModelToJson(input)) + + var dto model.SystemNotificationAction + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + dto.SystemNotificationId = systemNotificationId + + systemNotificationAction, err := h.usecase.CreateSystemNotificationAction(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CreateSystemNotificationActionResponse + out.ID = systemNotificationAction.String() + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/middleware/auth/role/default.go b/internal/middleware/auth/role/default.go index 9b69bdaa..b50efd3f 100644 --- a/internal/middleware/auth/role/default.go +++ b/internal/middleware/auth/role/default.go @@ -115,14 +115,6 @@ var defaultPermissionOfAdmin = defaultPermission{ internalApi.GetStacksDashboard, internalApi.GetResourcesDashboard, - // Alert - internalApi.CreateAlert, - internalApi.GetAlerts, - internalApi.GetAlert, - internalApi.DeleteAlert, - internalApi.UpdateAlert, - internalApi.CreateAlertAction, - // Stack internalApi.GetStacks, internalApi.CreateStack, @@ -227,9 +219,13 @@ var defaultPermissionOfUser = defaultPermission{ internalApi.GetStacksDashboard, internalApi.GetResourcesDashboard, - // Alert - internalApi.GetAlerts, - internalApi.GetAlert, + // SystemNotification + internalApi.CreateSystemNotification, + internalApi.GetSystemNotifications, + internalApi.GetSystemNotification, + internalApi.DeleteSystemNotification, + internalApi.UpdateSystemNotification, + internalApi.CreateSystemNotificationAction, // Stack internalApi.GetStacks, diff --git a/internal/model/alert.go b/internal/model/alert.go deleted file mode 100644 index 5d360781..00000000 --- a/internal/model/alert.go +++ /dev/null @@ -1,60 +0,0 @@ -package model - -import ( - "time" - - "github.com/google/uuid" - "github.com/openinfradev/tks-api/pkg/domain" - "gorm.io/datatypes" - "gorm.io/gorm" -) - -// Models -type Alert struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - Name string - Code string - Description string - Grade string - Message string - ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - Node string - CheckPoint string - GrafanaUrl string - FiredAt *time.Time `gorm:"-:all"` - TakedAt *time.Time `gorm:"-:all"` - ClosedAt *time.Time `gorm:"-:all"` - TakedSec int `gorm:"-:all"` - ProcessingSec int `gorm:"-:all"` - LastTaker User `gorm:"-:all"` - AlertActions []AlertAction - Summary string - RawData datatypes.JSON - Status domain.AlertActionStatus `gorm:"index"` -} - -func (c *Alert) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - -type AlertAction struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - AlertId uuid.UUID - Content string - Status domain.AlertActionStatus - TakerId *uuid.UUID `gorm:"type:uuid"` - Taker User `gorm:"foreignKey:TakerId"` -} - -func (c *AlertAction) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go new file mode 100644 index 00000000..aa723983 --- /dev/null +++ b/internal/model/system-notification.go @@ -0,0 +1,60 @@ +package model + +import ( + "time" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +// Models +type SystemNotification struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + Name string + Code string + Description string + Grade string + Message string + ClusterId domain.ClusterId + Cluster Cluster `gorm:"foreignKey:ClusterId"` + Node string + CheckPoint string + GrafanaUrl string + FiredAt *time.Time `gorm:"-:all"` + TakedAt *time.Time `gorm:"-:all"` + ClosedAt *time.Time `gorm:"-:all"` + TakedSec int `gorm:"-:all"` + ProcessingSec int `gorm:"-:all"` + LastTaker User `gorm:"-:all"` + SystemNotificationActions []SystemNotificationAction + Summary string + RawData datatypes.JSON + Status domain.SystemNotificationActionStatus `gorm:"index"` +} + +func (c *SystemNotification) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} + +type SystemNotificationAction struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + SystemNotificationId uuid.UUID + Content string + Status domain.SystemNotificationActionStatus + TakerId *uuid.UUID `gorm:"type:uuid"` + Taker User `gorm:"foreignKey:TakerId"` +} + +func (c *SystemNotificationAction) BeforeCreate(tx *gorm.DB) (err error) { + c.ID = uuid.New() + return nil +} diff --git a/internal/repository/alert.go b/internal/repository/alert.go deleted file mode 100644 index ef25d7bf..00000000 --- a/internal/repository/alert.go +++ /dev/null @@ -1,146 +0,0 @@ -package repository - -import ( - "context" - "time" - - "github.com/google/uuid" - "gorm.io/gorm" - "gorm.io/gorm/clause" - - "github.com/openinfradev/tks-api/internal/model" - "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/pkg/domain" -) - -// Interfaces -type IAlertRepository interface { - Get(ctx context.Context, alertId uuid.UUID) (model.Alert, error) - GetByName(ctx context.Context, organizationId string, name string) (model.Alert, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Alert, error) - FetchPodRestart(ctx context.Context, organizationId string, start time.Time, end time.Time) ([]model.Alert, error) - Create(ctx context.Context, dto model.Alert) (alertId uuid.UUID, err error) - Update(ctx context.Context, dto model.Alert) (err error) - Delete(ctx context.Context, dto model.Alert) (err error) - - CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) -} - -type AlertRepository struct { - db *gorm.DB -} - -func NewAlertRepository(db *gorm.DB) IAlertRepository { - return &AlertRepository{ - db: db, - } -} - -// Logics -func (r *AlertRepository) Get(ctx context.Context, alertId uuid.UUID) (out model.Alert, err error) { - res := r.db.WithContext(ctx).Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "id = ?", alertId) - if res.Error != nil { - return model.Alert{}, res.Error - } - return -} - -func (r *AlertRepository) GetByName(ctx context.Context, organizationId string, name string) (out model.Alert, err error) { - res := r.db.WithContext(ctx).Preload("AlertActions.Taker").Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) - if res.Error != nil { - return model.Alert{}, res.Error - } - return -} - -func (r *AlertRepository) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.Alert, err error) { - if pg == nil { - pg = pagination.NewPagination(nil) - } - - _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.Alert{}). - Preload("AlertActions", func(db *gorm.DB) *gorm.DB { - return db.Order("created_at ASC") - }).Preload("AlertActions.Taker"). - Preload("Cluster", "status = 2"). - Preload("Organization"). - Joins("join clusters on clusters.id = alerts.cluster_id AND clusters.status = 2"). - Where("alerts.organization_id = ?", organizationId), &out) - - if res.Error != nil { - return nil, res.Error - } - return -} - -func (r *AlertRepository) FetchPodRestart(ctx context.Context, organizationId string, start time.Time, end time.Time) (out []model.Alert, err error) { - res := r.db.WithContext(ctx).Preload(clause.Associations).Order("created_at DESC"). - Where("organization_id = ? AND name = 'pod-restart-frequently' AND created_at BETWEEN ? AND ?", organizationId, start, end). - Find(&out) - if res.Error != nil { - return nil, res.Error - } - return -} - -func (r *AlertRepository) Create(ctx context.Context, dto model.Alert) (alertId uuid.UUID, err error) { - alert := model.Alert{ - OrganizationId: dto.OrganizationId, - Name: dto.Name, - Code: dto.Code, - Message: dto.Message, - Description: dto.Description, - Grade: dto.Grade, - ClusterId: dto.ClusterId, - Node: dto.Node, - GrafanaUrl: dto.GrafanaUrl, - CheckPoint: dto.CheckPoint, - Summary: dto.Summary, - RawData: dto.RawData, - Status: domain.AlertActionStatus_CREATED, - } - res := r.db.WithContext(ctx).Create(&alert) - if res.Error != nil { - return uuid.Nil, res.Error - } - return alert.ID, nil -} - -func (r *AlertRepository) Update(ctx context.Context, dto model.Alert) (err error) { - res := r.db.WithContext(ctx).Model(&model.Alert{}). - Where("id = ?", dto.ID). - Updates(map[string]interface{}{"Description": dto.Description}) - if res.Error != nil { - return res.Error - } - return nil -} - -func (r *AlertRepository) Delete(ctx context.Context, dto model.Alert) (err error) { - res := r.db.WithContext(ctx).Delete(&model.Alert{}, "id = ?", dto.ID) - if res.Error != nil { - return res.Error - } - return nil -} - -func (r *AlertRepository) CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) { - alert := model.AlertAction{ - AlertId: dto.AlertId, - Content: dto.Content, - Status: dto.Status, - TakerId: dto.TakerId, - } - res := r.db.WithContext(ctx).Create(&alert) - if res.Error != nil { - return uuid.Nil, res.Error - } - res = r.db.WithContext(ctx).Model(&model.Alert{}). - Where("id = ?", dto.AlertId). - Update("status", dto.Status) - if res.Error != nil { - return uuid.Nil, res.Error - } - - return alert.ID, nil -} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 7190cf18..0e6d197b 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -12,21 +12,21 @@ import ( type FilterFunc func(user *gorm.DB) *gorm.DB type Repository struct { - Auth IAuthRepository - User IUserRepository - Cluster IClusterRepository - Organization IOrganizationRepository - AppGroup IAppGroupRepository - AppServeApp IAppServeAppRepository - CloudAccount ICloudAccountRepository - StackTemplate IStackTemplateRepository - Alert IAlertRepository - Role IRoleRepository - Permission IPermissionRepository - Endpoint IEndpointRepository - Project IProjectRepository - Audit IAuditRepository - PolicyTemplate IPolicyTemplateRepository + Auth IAuthRepository + User IUserRepository + Cluster IClusterRepository + Organization IOrganizationRepository + AppGroup IAppGroupRepository + AppServeApp IAppServeAppRepository + CloudAccount ICloudAccountRepository + StackTemplate IStackTemplateRepository + SystemNotification ISystemNotificationRepository + Role IRoleRepository + Permission IPermissionRepository + Endpoint IEndpointRepository + Project IProjectRepository + Audit IAuditRepository + PolicyTemplate IPolicyTemplateRepository } func CombinedGormFilter(table string, filters []pagination.Filter, combinedFilter pagination.CombinedFilter) FilterFunc { diff --git a/internal/repository/system-notification.go b/internal/repository/system-notification.go new file mode 100644 index 00000000..3c6dff2b --- /dev/null +++ b/internal/repository/system-notification.go @@ -0,0 +1,146 @@ +package repository + +import ( + "context" + "time" + + "github.com/google/uuid" + "gorm.io/gorm" + "gorm.io/gorm/clause" + + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/domain" +) + +// Interfaces +type ISystemNotificationRepository interface { + Get(ctx context.Context, systemNotificationId uuid.UUID) (model.SystemNotification, error) + GetByName(ctx context.Context, organizationId string, name string) (model.SystemNotification, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotification, error) + FetchPodRestart(ctx context.Context, organizationId string, start time.Time, end time.Time) ([]model.SystemNotification, error) + Create(ctx context.Context, dto model.SystemNotification) (systemNotificationId uuid.UUID, err error) + Update(ctx context.Context, dto model.SystemNotification) (err error) + Delete(ctx context.Context, dto model.SystemNotification) (err error) + + CreateSystemNotificationAction(ctx context.Context, dto model.SystemNotificationAction) (systemNotificationActionId uuid.UUID, err error) +} + +type SystemNotificationRepository struct { + db *gorm.DB +} + +func NewSystemNotificationRepository(db *gorm.DB) ISystemNotificationRepository { + return &SystemNotificationRepository{ + db: db, + } +} + +// Logics +func (r *SystemNotificationRepository) Get(ctx context.Context, systemNotificationId uuid.UUID) (out model.SystemNotification, err error) { + res := r.db.WithContext(ctx).Preload("SystemNotificationActions.Taker").Preload(clause.Associations).First(&out, "id = ?", systemNotificationId) + if res.Error != nil { + return model.SystemNotification{}, res.Error + } + return +} + +func (r *SystemNotificationRepository) GetByName(ctx context.Context, organizationId string, name string) (out model.SystemNotification, err error) { + res := r.db.WithContext(ctx).Preload("SystemNotificationActions.Taker").Preload(clause.Associations).First(&out, "organization_id = ? AND name = ?", organizationId, name) + if res.Error != nil { + return model.SystemNotification{}, res.Error + } + return +} + +func (r *SystemNotificationRepository) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotification, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.SystemNotification{}). + Preload("SystemNotificationActions", func(db *gorm.DB) *gorm.DB { + return db.Order("created_at ASC") + }).Preload("SystemNotificationActions.Taker"). + Preload("Cluster", "status = 2"). + Preload("Organization"). + Joins("join clusters on clusters.id = system_notifications.cluster_id AND clusters.status = 2"). + Where("system_notifications.organization_id = ?", organizationId), &out) + + if res.Error != nil { + return nil, res.Error + } + return +} + +func (r *SystemNotificationRepository) FetchPodRestart(ctx context.Context, organizationId string, start time.Time, end time.Time) (out []model.SystemNotification, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).Order("created_at DESC"). + Where("organization_id = ? AND name = 'pod-restart-frequently' AND created_at BETWEEN ? AND ?", organizationId, start, end). + Find(&out) + if res.Error != nil { + return nil, res.Error + } + return +} + +func (r *SystemNotificationRepository) Create(ctx context.Context, dto model.SystemNotification) (systemNotificationId uuid.UUID, err error) { + systemNotification := model.SystemNotification{ + OrganizationId: dto.OrganizationId, + Name: dto.Name, + Code: dto.Code, + Message: dto.Message, + Description: dto.Description, + Grade: dto.Grade, + ClusterId: dto.ClusterId, + Node: dto.Node, + GrafanaUrl: dto.GrafanaUrl, + CheckPoint: dto.CheckPoint, + Summary: dto.Summary, + RawData: dto.RawData, + Status: domain.SystemNotificationActionStatus_CREATED, + } + res := r.db.WithContext(ctx).Create(&systemNotification) + if res.Error != nil { + return uuid.Nil, res.Error + } + return systemNotification.ID, nil +} + +func (r *SystemNotificationRepository) Update(ctx context.Context, dto model.SystemNotification) (err error) { + res := r.db.WithContext(ctx).Model(&model.SystemNotification{}). + Where("id = ?", dto.ID). + Updates(map[string]interface{}{"Description": dto.Description}) + if res.Error != nil { + return res.Error + } + return nil +} + +func (r *SystemNotificationRepository) Delete(ctx context.Context, dto model.SystemNotification) (err error) { + res := r.db.WithContext(ctx).Delete(&model.SystemNotification{}, "id = ?", dto.ID) + if res.Error != nil { + return res.Error + } + return nil +} + +func (r *SystemNotificationRepository) CreateSystemNotificationAction(ctx context.Context, dto model.SystemNotificationAction) (systemNotificationActionId uuid.UUID, err error) { + systemNotification := model.SystemNotificationAction{ + SystemNotificationId: dto.SystemNotificationId, + Content: dto.Content, + Status: dto.Status, + TakerId: dto.TakerId, + } + res := r.db.WithContext(ctx).Create(&systemNotification) + if res.Error != nil { + return uuid.Nil, res.Error + } + res = r.db.WithContext(ctx).Model(&model.SystemNotification{}). + Where("id = ?", dto.SystemNotificationId). + Update("status", dto.Status) + if res.Error != nil { + return uuid.Nil, res.Error + } + + return systemNotification.ID, nil +} diff --git a/internal/route/route.go b/internal/route/route.go index 5989edba..5d789954 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -41,40 +41,40 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa cache := gcache.New(5*time.Minute, 10*time.Minute) repoFactory := repository.Repository{ - Auth: repository.NewAuthRepository(db), - User: repository.NewUserRepository(db), - Cluster: repository.NewClusterRepository(db), - Organization: repository.NewOrganizationRepository(db), - AppGroup: repository.NewAppGroupRepository(db), - AppServeApp: repository.NewAppServeAppRepository(db), - CloudAccount: repository.NewCloudAccountRepository(db), - StackTemplate: repository.NewStackTemplateRepository(db), - Alert: repository.NewAlertRepository(db), - Role: repository.NewRoleRepository(db), - Project: repository.NewProjectRepository(db), - Permission: repository.NewPermissionRepository(db), - Endpoint: repository.NewEndpointRepository(db), - Audit: repository.NewAuditRepository(db), - PolicyTemplate: repository.NewPolicyTemplateRepository(db), + Auth: repository.NewAuthRepository(db), + User: repository.NewUserRepository(db), + Cluster: repository.NewClusterRepository(db), + Organization: repository.NewOrganizationRepository(db), + AppGroup: repository.NewAppGroupRepository(db), + AppServeApp: repository.NewAppServeAppRepository(db), + CloudAccount: repository.NewCloudAccountRepository(db), + StackTemplate: repository.NewStackTemplateRepository(db), + SystemNotification: repository.NewSystemNotificationRepository(db), + Role: repository.NewRoleRepository(db), + Project: repository.NewProjectRepository(db), + Permission: repository.NewPermissionRepository(db), + Endpoint: repository.NewEndpointRepository(db), + Audit: repository.NewAuditRepository(db), + PolicyTemplate: repository.NewPolicyTemplateRepository(db), } usecaseFactory := usecase.Usecase{ - Auth: usecase.NewAuthUsecase(repoFactory, kc), - User: usecase.NewUserUsecase(repoFactory, kc), - Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache), - Organization: usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), - AppGroup: usecase.NewAppGroupUsecase(repoFactory, argoClient), - AppServeApp: usecase.NewAppServeAppUsecase(repoFactory, argoClient), - CloudAccount: usecase.NewCloudAccountUsecase(repoFactory, argoClient), - StackTemplate: usecase.NewStackTemplateUsecase(repoFactory), - Dashboard: usecase.NewDashboardUsecase(repoFactory, cache), - Alert: usecase.NewAlertUsecase(repoFactory), - Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), - Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), - Audit: usecase.NewAuditUsecase(repoFactory), - Role: usecase.NewRoleUsecase(repoFactory), - Permission: usecase.NewPermissionUsecase(repoFactory), - PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), + Auth: usecase.NewAuthUsecase(repoFactory, kc), + User: usecase.NewUserUsecase(repoFactory, kc), + Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache), + Organization: usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), + AppGroup: usecase.NewAppGroupUsecase(repoFactory, argoClient), + AppServeApp: usecase.NewAppServeAppUsecase(repoFactory, argoClient), + CloudAccount: usecase.NewCloudAccountUsecase(repoFactory, argoClient), + StackTemplate: usecase.NewStackTemplateUsecase(repoFactory), + Dashboard: usecase.NewDashboardUsecase(repoFactory, cache), + SystemNotification: usecase.NewSystemNotificationUsecase(repoFactory), + Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), + Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), + Audit: usecase.NewAuditUsecase(repoFactory), + Role: usecase.NewRoleUsecase(repoFactory), + Permission: usecase.NewPermissionUsecase(repoFactory), + PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), } customMiddleware := internalMiddleware.NewMiddleware( @@ -196,14 +196,14 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) - alertHandler := delivery.NewAlertHandler(usecaseFactory) - r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/alerts", alertHandler.CreateAlert).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts", customMiddleware.Handle(internalApi.GetAlerts, http.HandlerFunc(alertHandler.GetAlerts))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", customMiddleware.Handle(internalApi.GetAlert, http.HandlerFunc(alertHandler.GetAlert))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", customMiddleware.Handle(internalApi.DeleteAlert, http.HandlerFunc(alertHandler.DeleteAlert))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}", customMiddleware.Handle(internalApi.UpdateAlert, http.HandlerFunc(alertHandler.UpdateAlert))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}/actions", customMiddleware.Handle(internalApi.CreateAlertAction, http.HandlerFunc(alertHandler.CreateAlertAction))).Methods(http.MethodPost) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/alerts/{alertId}/actions/status", customMiddleware.Handle(http.HandlerFunc(alertHandler.UpdateAlertActionStatus))).Methods(http.MethodPatch) + systemNotificationHandler := delivery.NewSystemNotificationHandler(usecaseFactory) + r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/alerts", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications", customMiddleware.Handle(internalApi.GetSystemNotifications, http.HandlerFunc(systemNotificationHandler.GetSystemNotifications))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.GetSystemNotification, http.HandlerFunc(systemNotificationHandler.GetSystemNotification))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.DeleteSystemNotification, http.HandlerFunc(systemNotificationHandler.DeleteSystemNotification))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.UpdateSystemNotification, http.HandlerFunc(systemNotificationHandler.UpdateSystemNotification))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions", customMiddleware.Handle(internalApi.CreateSystemNotificationAction, http.HandlerFunc(systemNotificationHandler.CreateSystemNotificationAction))).Methods(http.MethodPost) + //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationsId}/actions/status", customMiddleware.Handle(http.HandlerFunc(systemNotificationsHandler.UpdateSystemNotificationActionStatus))).Methods(http.MethodPatch) stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) @@ -267,7 +267,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(permissionHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) - r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", alertHandler.CreateAlert).Methods(http.MethodPost) + r.HandleFunc(API_PREFIX+API_VERSION+"/systemNotificationtest", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) diff --git a/internal/usecase/alert.go b/internal/usecase/alert.go deleted file mode 100644 index 7632170f..00000000 --- a/internal/usecase/alert.go +++ /dev/null @@ -1,281 +0,0 @@ -package usecase - -import ( - "context" - "encoding/json" - "fmt" - "strings" - "time" - - "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/model" - "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" - "github.com/pkg/errors" - "gorm.io/gorm" -) - -type IAlertUsecase interface { - Get(ctx context.Context, alertId uuid.UUID) (model.Alert, error) - GetByName(ctx context.Context, organizationId string, name string) (model.Alert, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Alert, error) - Create(ctx context.Context, dto domain.CreateAlertRequest) (err error) - Update(ctx context.Context, dto model.Alert) error - Delete(ctx context.Context, dto model.Alert) error - - CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) -} - -type AlertUsecase struct { - repo repository.IAlertRepository - clusterRepo repository.IClusterRepository - organizationRepo repository.IOrganizationRepository - appGroupRepo repository.IAppGroupRepository -} - -func NewAlertUsecase(r repository.Repository) IAlertUsecase { - return &AlertUsecase{ - repo: r.Alert, - clusterRepo: r.Cluster, - appGroupRepo: r.AppGroup, - organizationRepo: r.Organization, - } -} - -func (u *AlertUsecase) Create(ctx context.Context, input domain.CreateAlertRequest) (err error) { - if input.Alerts == nil || len(input.Alerts) == 0 { - return fmt.Errorf("No data found") - } - - allClusters, err := u.clusterRepo.Fetch(ctx, nil) - if err != nil { - return fmt.Errorf("No clusters") - } - - for _, alert := range input.Alerts { - clusterId := alert.Labels.TacoCluster - organizationId, err := u.getOrganizationFromCluster(&allClusters, clusterId) - if err != nil { - log.Error(ctx, err) - continue - } - - organization, err := u.organizationRepo.Get(ctx, organizationId) - if err != nil { - log.Error(ctx, err) - continue - } - primaryCluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(organization.PrimaryClusterId)) - if err != nil { - log.Error(ctx, err) - continue - } - - rawData, err := json.Marshal(alert) - if err != nil { - rawData = []byte{} - } - - /* - target := "" - // discriminative 에 target 에 대한 정보가 있다. - // discriminative: $labels.taco_cluster, $labels.instance - discriminative := alert.Annotations.Discriminative - if discriminative != "" { - trimed := strings.TrimLeft(discriminative, " ") - trimed = strings.TrimLeft(trimed, "$") - arr := strings.Split(trimed, ",") - - for _, refer := range arr { - - } - } - */ - - node := "" - if strings.Contains(alert.Labels.AlertName, "node") { - node = alert.Labels.Instance - } - - dto := model.Alert{ - OrganizationId: organizationId, - Name: alert.Labels.AlertName, - Code: alert.Labels.AlertName, - Grade: alert.Labels.Severity, - Node: node, - Message: alert.Annotations.Message, - Description: alert.Annotations.Description, - CheckPoint: alert.Annotations.Checkpoint, - Summary: alert.Annotations.Summary, - ClusterId: domain.ClusterId(clusterId), - GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, alert, domain.ClusterId(clusterId)), - RawData: rawData, - } - - _, err = u.repo.Create(ctx, dto) - if err != nil { - continue - } - } - - return nil -} - -func (u *AlertUsecase) Update(ctx context.Context, dto model.Alert) error { - return nil -} - -func (u *AlertUsecase) Get(ctx context.Context, alertId uuid.UUID) (alert model.Alert, err error) { - alert, err = u.repo.Get(ctx, alertId) - if err != nil { - return alert, err - } - u.makeAdditionalInfo(&alert) - - return -} - -func (u *AlertUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.Alert, err error) { - out, err = u.repo.GetByName(ctx, organizationId, name) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return out, httpErrors.NewNotFoundError(err, "", "") - } - return out, err - } - return -} - -func (u *AlertUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (alerts []model.Alert, err error) { - alerts, err = u.repo.Fetch(ctx, organizationId, pg) - if err != nil { - return nil, err - } - - for i := range alerts { - u.makeAdditionalInfo(&alerts[i]) - } - - return alerts, nil -} - -func (u *AlertUsecase) Delete(ctx context.Context, dto model.Alert) (err error) { - _, ok := request.UserFrom(ctx) - if !ok { - return httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") - } - - _, err = u.Get(ctx, dto.ID) - if err != nil { - return httpErrors.NewNotFoundError(err, "AL_NOT_FOUND_ALERT", "") - } - - err = u.repo.Delete(ctx, dto) - if err != nil { - return err - } - - return nil -} - -func (u *AlertUsecase) CreateAlertAction(ctx context.Context, dto model.AlertAction) (alertActionId uuid.UUID, err error) { - user, ok := request.UserFrom(ctx) - if !ok { - return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") - } - - _, err = u.repo.Get(ctx, dto.AlertId) - if err != nil { - return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Not found alert"), "AL_NOT_FOUND_ALERT", "") - } - - userId := user.GetUserId() - dto.TakerId = &userId - dto.CreatedAt = time.Now() - - alertActionId, err = u.repo.CreateAlertAction(ctx, dto) - if err != nil { - return uuid.Nil, err - } - log.Info(ctx, "newly created alertActionId:", alertActionId) - - return -} - -func (u *AlertUsecase) getOrganizationFromCluster(clusters *[]model.Cluster, strId string) (organizationId string, err error) { - clusterId := domain.ClusterId(strId) - if !clusterId.Validate() { - return "", fmt.Errorf("Invalid clusterId %s", strId) - } - - for _, cluster := range *clusters { - if cluster.ID == clusterId { - return cluster.OrganizationId, nil - } - } - - return "", fmt.Errorf("No martched organization %s", strId) -} - -func (u *AlertUsecase) makeAdditionalInfo(alert *model.Alert) { - alert.FiredAt = &alert.CreatedAt - //alert.Status = model.AlertActionStatus_CREATED - - if len(alert.AlertActions) > 0 { - alert.TakedAt = &alert.AlertActions[0].CreatedAt - for _, action := range alert.AlertActions { - if action.Status == domain.AlertActionStatus_CLOSED { - alert.ClosedAt = &action.CreatedAt - alert.ProcessingSec = int((action.CreatedAt).Sub(alert.CreatedAt).Seconds()) - } - } - - alert.LastTaker = alert.AlertActions[len(alert.AlertActions)-1].Taker - alert.TakedSec = int((alert.AlertActions[0].CreatedAt).Sub(alert.CreatedAt).Seconds()) - //alert.Status = alert.AlertActions[len(alert.AlertActions)-1].Status - } -} - -func (u *AlertUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, alert domain.CreateAlertRequestAlert, clusterId domain.ClusterId) (url string) { - primaryGrafanaEndpoint := "" - appGroups, err := u.appGroupRepo.Fetch(ctx, primaryCluster.ID, nil) - if err == nil { - for _, appGroup := range appGroups { - if appGroup.AppGroupType == domain.AppGroupType_LMA { - applications, err := u.appGroupRepo.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) - if err != nil { - return "" - } - if len(applications) > 0 { - primaryGrafanaEndpoint = applications[0].Endpoint - } - } - } - } - - // check type - url = primaryGrafanaEndpoint - - // tks_node_dashboard/tks-kubernetes-view-nodes?orgId=1&refresh=30s&var-datasource=default&var-taco_cluster=c19rjkn4j&var-job=prometheus-node-exporter&var-hostname=All&var-node=10.0.168.71:9100&var-device=All&var-maxmount=%2F&var-show_hostname=prometheus-node-exporter-xt4vb - - switch alert.Labels.AlertName { - case "node-memory-high-utilization": - url = primaryGrafanaEndpoint + "/d/tks_node_dashboard/tks-kubernetes-view-nodes?var-taco_cluster=" + clusterId.String() + "&kiosk" - case "node-cpu-high-load": - url = primaryGrafanaEndpoint + "/d/tks_node_dashboard/tks-kubernetes-view-nodes?var-taco_cluster=" + clusterId.String() + "&kiosk" - case "node-disk-full": - url = primaryGrafanaEndpoint + "/d/tks_node_dashboard/tks-kubernetes-view-nodes?var-taco_cluster=" + clusterId.String() + "&kiosk" - case "pod-restart-frequently": - url = primaryGrafanaEndpoint + "/d/tks_podv1_dashboard/tks-kubernetes-view-pods-v1?var-taco_cluster=" + clusterId.String() + "&kiosk" - case "pvc-full": - url = primaryGrafanaEndpoint + "/d/tks_cluster_dashboard/tks-kubernetes-view-cluster-global?var-taco_cluster=" + clusterId.String() + "&kiosk" - default: - log.Errorf(ctx, "Invalid alert name %s", alert.Labels.AlertName) - } - - return -} diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 40a8b9b4..760dd2ee 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -33,20 +33,20 @@ type IDashboardUsecase interface { } type DashboardUsecase struct { - organizationRepo repository.IOrganizationRepository - clusterRepo repository.IClusterRepository - appGroupRepo repository.IAppGroupRepository - alertRepo repository.IAlertRepository - cache *gcache.Cache + organizationRepo repository.IOrganizationRepository + clusterRepo repository.IClusterRepository + appGroupRepo repository.IAppGroupRepository + systemNotificationRepo repository.ISystemNotificationRepository + cache *gcache.Cache } func NewDashboardUsecase(r repository.Repository, cache *gcache.Cache) IDashboardUsecase { return &DashboardUsecase{ - organizationRepo: r.Organization, - clusterRepo: r.Cluster, - appGroupRepo: r.AppGroup, - alertRepo: r.Alert, - cache: cache, + organizationRepo: r.Organization, + clusterRepo: r.Cluster, + appGroupRepo: r.AppGroup, + systemNotificationRepo: r.SystemNotification, + cache: cache, } } @@ -286,7 +286,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(ctx context.Context, organizat return res, fmt.Errorf("Invalid month") } - alerts, err := u.alertRepo.FetchPodRestart(ctx, organizationId, startDate, endDate) + events, err := u.systemNotificationRepo.FetchPodRestart(ctx, organizationId, startDate, endDate) if err != nil { return res, err } @@ -309,8 +309,8 @@ func (u *DashboardUsecase) getChartFromPrometheus(ctx context.Context, organizat cntPodRestart := 0 if baseDate <= now.Format("2006-01-02") && baseDate >= organization.CreatedAt.Format("2006-01-02") { - for _, alert := range alerts { - strDate := alert.CreatedAt.Format("2006-01-02") + for _, event := range events { + strDate := event.CreatedAt.Format("2006-01-02") if strDate == baseDate { cntPodRestart += 1 diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go new file mode 100644 index 00000000..94738a27 --- /dev/null +++ b/internal/usecase/system-notification.go @@ -0,0 +1,281 @@ +package usecase + +import ( + "context" + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" + "gorm.io/gorm" +) + +type ISystemNotificationUsecase interface { + Get(ctx context.Context, systemNotificationId uuid.UUID) (model.SystemNotification, error) + GetByName(ctx context.Context, organizationId string, name string) (model.SystemNotification, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotification, error) + Create(ctx context.Context, dto domain.CreateSystemNotificationRequest) (err error) + Update(ctx context.Context, dto model.SystemNotification) error + Delete(ctx context.Context, dto model.SystemNotification) error + + CreateSystemNotificationAction(ctx context.Context, dto model.SystemNotificationAction) (systemNotificationActionId uuid.UUID, err error) +} + +type SystemNotificationUsecase struct { + repo repository.ISystemNotificationRepository + clusterRepo repository.IClusterRepository + organizationRepo repository.IOrganizationRepository + appGroupRepo repository.IAppGroupRepository +} + +func NewSystemNotificationUsecase(r repository.Repository) ISystemNotificationUsecase { + return &SystemNotificationUsecase{ + repo: r.SystemNotification, + clusterRepo: r.Cluster, + appGroupRepo: r.AppGroup, + organizationRepo: r.Organization, + } +} + +func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.CreateSystemNotificationRequest) (err error) { + if input.SystemNotifications == nil || len(input.SystemNotifications) == 0 { + return fmt.Errorf("No data found") + } + + allClusters, err := u.clusterRepo.Fetch(ctx, nil) + if err != nil { + return fmt.Errorf("No clusters") + } + + for _, systemNotification := range input.SystemNotifications { + clusterId := systemNotification.Labels.TacoCluster + organizationId, err := u.getOrganizationFromCluster(&allClusters, clusterId) + if err != nil { + log.Error(ctx, err) + continue + } + + organization, err := u.organizationRepo.Get(ctx, organizationId) + if err != nil { + log.Error(ctx, err) + continue + } + primaryCluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(organization.PrimaryClusterId)) + if err != nil { + log.Error(ctx, err) + continue + } + + rawData, err := json.Marshal(systemNotification) + if err != nil { + rawData = []byte{} + } + + /* + target := "" + // discriminative 에 target 에 대한 정보가 있다. + // discriminative: $labels.taco_cluster, $labels.instance + discriminative := systemNotification.Annotations.Discriminative + if discriminative != "" { + trimed := strings.TrimLeft(discriminative, " ") + trimed = strings.TrimLeft(trimed, "$") + arr := strings.Split(trimed, ",") + + for _, refer := range arr { + + } + } + */ + + node := "" + if strings.Contains(systemNotification.Labels.SystemNotificationName, "node") { + node = systemNotification.Labels.Instance + } + + dto := model.SystemNotification{ + OrganizationId: organizationId, + Name: systemNotification.Labels.SystemNotificationName, + Code: systemNotification.Labels.SystemNotificationName, + Grade: systemNotification.Labels.Severity, + Node: node, + Message: systemNotification.Annotations.Message, + Description: systemNotification.Annotations.Description, + CheckPoint: systemNotification.Annotations.Checkpoint, + Summary: systemNotification.Annotations.Summary, + ClusterId: domain.ClusterId(clusterId), + GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, systemNotification, domain.ClusterId(clusterId)), + RawData: rawData, + } + + _, err = u.repo.Create(ctx, dto) + if err != nil { + continue + } + } + + return nil +} + +func (u *SystemNotificationUsecase) Update(ctx context.Context, dto model.SystemNotification) error { + return nil +} + +func (u *SystemNotificationUsecase) Get(ctx context.Context, systemNotificationId uuid.UUID) (systemNotification model.SystemNotification, err error) { + systemNotification, err = u.repo.Get(ctx, systemNotificationId) + if err != nil { + return systemNotification, err + } + u.makeAdditionalInfo(&systemNotification) + + return +} + +func (u *SystemNotificationUsecase) GetByName(ctx context.Context, organizationId string, name string) (out model.SystemNotification, err error) { + out, err = u.repo.GetByName(ctx, organizationId, name) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return out, httpErrors.NewNotFoundError(err, "", "") + } + return out, err + } + return +} + +func (u *SystemNotificationUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (systemNotifications []model.SystemNotification, err error) { + systemNotifications, err = u.repo.Fetch(ctx, organizationId, pg) + if err != nil { + return nil, err + } + + for i := range systemNotifications { + u.makeAdditionalInfo(&systemNotifications[i]) + } + + return systemNotifications, nil +} + +func (u *SystemNotificationUsecase) Delete(ctx context.Context, dto model.SystemNotification) (err error) { + _, ok := request.UserFrom(ctx) + if !ok { + return httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + + _, err = u.Get(ctx, dto.ID) + if err != nil { + return httpErrors.NewNotFoundError(err, "EV_NOT_FOUND_EVENT", "") + } + + err = u.repo.Delete(ctx, dto) + if err != nil { + return err + } + + return nil +} + +func (u *SystemNotificationUsecase) CreateSystemNotificationAction(ctx context.Context, dto model.SystemNotificationAction) (systemNotificationActionId uuid.UUID, err error) { + user, ok := request.UserFrom(ctx) + if !ok { + return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + + _, err = u.repo.Get(ctx, dto.SystemNotificationId) + if err != nil { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Not found systemNotification"), "EV_NOT_FOUND_EVENT", "") + } + + userId := user.GetUserId() + dto.TakerId = &userId + dto.CreatedAt = time.Now() + + systemNotificationActionId, err = u.repo.CreateSystemNotificationAction(ctx, dto) + if err != nil { + return uuid.Nil, err + } + log.Info(ctx, "newly created systemNotificationActionId:", systemNotificationActionId) + + return +} + +func (u *SystemNotificationUsecase) getOrganizationFromCluster(clusters *[]model.Cluster, strId string) (organizationId string, err error) { + clusterId := domain.ClusterId(strId) + if !clusterId.Validate() { + return "", fmt.Errorf("Invalid clusterId %s", strId) + } + + for _, cluster := range *clusters { + if cluster.ID == clusterId { + return cluster.OrganizationId, nil + } + } + + return "", fmt.Errorf("No martched organization %s", strId) +} + +func (u *SystemNotificationUsecase) makeAdditionalInfo(systemNotification *model.SystemNotification) { + systemNotification.FiredAt = &systemNotification.CreatedAt + //systemNotification.Status = model.SystemNotificationActionStatus_CREATED + + if len(systemNotification.SystemNotificationActions) > 0 { + systemNotification.TakedAt = &systemNotification.SystemNotificationActions[0].CreatedAt + for _, action := range systemNotification.SystemNotificationActions { + if action.Status == domain.SystemNotificationActionStatus_CLOSED { + systemNotification.ClosedAt = &action.CreatedAt + systemNotification.ProcessingSec = int((action.CreatedAt).Sub(systemNotification.CreatedAt).Seconds()) + } + } + + systemNotification.LastTaker = systemNotification.SystemNotificationActions[len(systemNotification.SystemNotificationActions)-1].Taker + systemNotification.TakedSec = int((systemNotification.SystemNotificationActions[0].CreatedAt).Sub(systemNotification.CreatedAt).Seconds()) + //systemNotification.Status = systemNotification.SystemNotificationActions[len(systemNotification.SystemNotificationActions)-1].Status + } +} + +func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, systemNotification domain.SystemNotification, clusterId domain.ClusterId) (url string) { + primaryGrafanaEndpoint := "" + appGroups, err := u.appGroupRepo.Fetch(ctx, primaryCluster.ID, nil) + if err == nil { + for _, appGroup := range appGroups { + if appGroup.AppGroupType == domain.AppGroupType_LMA { + applications, err := u.appGroupRepo.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) + if err != nil { + return "" + } + if len(applications) > 0 { + primaryGrafanaEndpoint = applications[0].Endpoint + } + } + } + } + + // check type + url = primaryGrafanaEndpoint + + // tks_node_dashboard/tks-kubernetes-view-nodes?orgId=1&refresh=30s&var-datasource=default&var-taco_cluster=c19rjkn4j&var-job=prometheus-node-exporter&var-hostname=All&var-node=10.0.168.71:9100&var-device=All&var-maxmount=%2F&var-show_hostname=prometheus-node-exporter-xt4vb + + switch systemNotification.Labels.SystemNotificationName { + case "node-memory-high-utilization": + url = primaryGrafanaEndpoint + "/d/tks_node_dashboard/tks-kubernetes-view-nodes?var-taco_cluster=" + clusterId.String() + "&kiosk" + case "node-cpu-high-load": + url = primaryGrafanaEndpoint + "/d/tks_node_dashboard/tks-kubernetes-view-nodes?var-taco_cluster=" + clusterId.String() + "&kiosk" + case "node-disk-full": + url = primaryGrafanaEndpoint + "/d/tks_node_dashboard/tks-kubernetes-view-nodes?var-taco_cluster=" + clusterId.String() + "&kiosk" + case "pod-restart-frequently": + url = primaryGrafanaEndpoint + "/d/tks_podv1_dashboard/tks-kubernetes-view-pods-v1?var-taco_cluster=" + clusterId.String() + "&kiosk" + case "pvc-full": + url = primaryGrafanaEndpoint + "/d/tks_cluster_dashboard/tks-kubernetes-view-cluster-global?var-taco_cluster=" + clusterId.String() + "&kiosk" + default: + log.Errorf(ctx, "Invalid systemNotification name %s", systemNotification.Labels.SystemNotificationName) + } + + return +} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index f0ad4014..9053100d 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -1,20 +1,20 @@ package usecase type Usecase struct { - Auth IAuthUsecase - User IUserUsecase - Cluster IClusterUsecase - Organization IOrganizationUsecase - AppGroup IAppGroupUsecase - AppServeApp IAppServeAppUsecase - CloudAccount ICloudAccountUsecase - StackTemplate IStackTemplateUsecase - Dashboard IDashboardUsecase - Alert IAlertUsecase - Stack IStackUsecase - Project IProjectUsecase - Role IRoleUsecase - Permission IPermissionUsecase - Audit IAuditUsecase - PolicyTemplate IPolicyTemplateUsecase + Auth IAuthUsecase + User IUserUsecase + Cluster IClusterUsecase + Organization IOrganizationUsecase + AppGroup IAppGroupUsecase + AppServeApp IAppServeAppUsecase + CloudAccount ICloudAccountUsecase + StackTemplate IStackTemplateUsecase + Dashboard IDashboardUsecase + SystemNotification ISystemNotificationUsecase + Stack IStackUsecase + Project IProjectUsecase + Role IRoleUsecase + Permission IPermissionUsecase + Audit IAuditUsecase + PolicyTemplate IPolicyTemplateUsecase } diff --git a/pkg/domain/alert.go b/pkg/domain/alert.go deleted file mode 100644 index a60073bf..00000000 --- a/pkg/domain/alert.go +++ /dev/null @@ -1,137 +0,0 @@ -package domain - -import ( - "time" - - "github.com/google/uuid" -) - -// enum -type AlertActionStatus int32 - -const ( - AlertActionStatus_CREATED AlertActionStatus = iota - AlertActionStatus_INPROGRESS - AlertActionStatus_CLOSED - AlertActionStatus_ERROR -) - -var alertActionStatus = [...]string{ - "CREATED", - "INPROGRESS", - "CLOSED", - "ERROR", -} - -func (m AlertActionStatus) String() string { return alertActionStatus[(m)] } -func (m AlertActionStatus) FromString(s string) AlertActionStatus { - for i, v := range alertActionStatus { - if v == s { - return AlertActionStatus(i) - } - } - return AlertActionStatus_ERROR -} - -type CreateAlertRequestAlert struct { - Status string `json:"status"` - GeneratorURL string `json:"generatorURL"` - FingerPrint string `json:"fingerprint"` - StartsAt time.Time `json:"startsAt"` - EndsAt time.Time `json:"endsAt"` - Labels struct { - AlertName string `json:"alertname"` - Container string `json:"container"` - Endpoint string `json:"endpoint"` - Job string `json:"job"` - Namespace string `json:"namespace"` - Pod string `json:"pod"` - Prometheus string `json:"prometheus"` - Service string `json:"service"` - Severity string `json:"severity"` - Instance string `json:"instance"` - TacoCluster string `json:"taco_cluster"` - } `json:"labels"` - Annotations struct { - Message string `json:"message"` - Summary string `json:"summary"` - Description string `json:"description"` - Checkpoint string `json:"Checkpoint"` - Discriminative string `json:"discriminative"` - } `json:"annotations"` -} - -type CreateAlertRequest struct { - Receiver string `json:"receiver"` - Status string `json:"status"` - ExternalURL string `json:"externalURL"` - Version string `json:"version"` - GroupKey string `json:"groupKey"` - TruncateAlerts int `json:"truncateAlerts"` - Alerts []CreateAlertRequestAlert `json:"alerts"` - GroupLabels struct { - Alertname string `json:"alertname"` - } `json:"groupLabels"` - //CommonLabels string `json:"commonLabels"` - //CommonAnnotations string `json:"commonAnnotations"` -} - -type AlertResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - Message string `json:"message"` - Code string `json:"code"` - Grade string `json:"grade"` - Cluster SimpleClusterResponse `json:"cluster"` - GrafanaUrl string `json:"grafanaUrl"` - Node string `json:"node"` - FiredAt *time.Time `json:"firedAt"` - TakedAt *time.Time `json:"takedAt"` - ClosedAt *time.Time `json:"closedAt"` - Status string `json:"status"` - ProcessingSec int `json:"processingSec"` - TakedSec int `json:"takedSec"` - AlertActions []AlertActionResponse `json:"alertActions"` - LastTaker SimpleUserResponse `json:"lastTaker"` - RawData string `json:"rawData"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - -type AlertActionResponse struct { - ID uuid.UUID `json:"id"` - AlertId uuid.UUID `json:"alertId"` - Content string `json:"content"` - Status string `json:"status"` - Taker SimpleUserResponse `json:"taker"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - -type GetAlertsResponse struct { - Alerts []AlertResponse `json:"alerts"` - Pagination PaginationResponse `json:"pagination"` -} - -type GetAlertResponse struct { - Alert AlertResponse `json:"alert"` -} - -type CreateAlertResponse struct { - ID string `json:"id"` -} - -type UpdateAlertRequest struct { - Description string `json:"description"` -} - -type CreateAlertActionRequest struct { - Content string `json:"content"` - Status string `json:"status" validate:"oneof=INPROGRESS CLOSED"` -} - -type CreateAlertActionResponse struct { - ID string `json:"id"` -} diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go new file mode 100644 index 00000000..6d875aa6 --- /dev/null +++ b/pkg/domain/system-notification.go @@ -0,0 +1,137 @@ +package domain + +import ( + "time" + + "github.com/google/uuid" +) + +// enum +type SystemNotificationActionStatus int32 + +const ( + SystemNotificationActionStatus_CREATED SystemNotificationActionStatus = iota + SystemNotificationActionStatus_INPROGRESS + SystemNotificationActionStatus_CLOSED + SystemNotificationActionStatus_ERROR +) + +var systemNotificationActionStatus = [...]string{ + "CREATED", + "INPROGRESS", + "CLOSED", + "ERROR", +} + +func (m SystemNotificationActionStatus) String() string { return systemNotificationActionStatus[(m)] } +func (m SystemNotificationActionStatus) FromString(s string) SystemNotificationActionStatus { + for i, v := range systemNotificationActionStatus { + if v == s { + return SystemNotificationActionStatus(i) + } + } + return SystemNotificationActionStatus_ERROR +} + +type SystemNotification struct { + Status string `json:"status"` + GeneratorURL string `json:"generatorURL"` + FingerPrint string `json:"fingerprint"` + StartsAt time.Time `json:"startsAt"` + EndsAt time.Time `json:"endsAt"` + Labels struct { + SystemNotificationName string `json:"systemNotificationname"` + Container string `json:"container"` + Endpoint string `json:"endpoint"` + Job string `json:"job"` + Namespace string `json:"namespace"` + Pod string `json:"pod"` + Prometheus string `json:"prometheus"` + Service string `json:"service"` + Severity string `json:"severity"` + Instance string `json:"instance"` + TacoCluster string `json:"taco_cluster"` + } `json:"labels"` + Annotations struct { + Message string `json:"message"` + Summary string `json:"summary"` + Description string `json:"description"` + Checkpoint string `json:"Checkpoint"` + Discriminative string `json:"discriminative"` + } `json:"annotations"` +} + +type CreateSystemNotificationRequest struct { + Receiver string `json:"receiver"` + Status string `json:"status"` + ExternalURL string `json:"externalURL"` + Version string `json:"version"` + GroupKey string `json:"groupKey"` + TruncateSystemNotifications int `json:"truncateSystemNotifications"` + SystemNotifications []SystemNotification `json:"systemNotifications"` + GroupLabels struct { + SystemNotificationname string `json:"systemNotificationname"` + } `json:"groupLabels"` + //CommonLabels string `json:"commonLabels"` + //CommonAnnotations string `json:"commonAnnotations"` +} + +type SystemNotificationResponse struct { + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + Message string `json:"message"` + Code string `json:"code"` + Grade string `json:"grade"` + Cluster SimpleClusterResponse `json:"cluster"` + GrafanaUrl string `json:"grafanaUrl"` + Node string `json:"node"` + FiredAt *time.Time `json:"firedAt"` + TakedAt *time.Time `json:"takedAt"` + ClosedAt *time.Time `json:"closedAt"` + Status string `json:"status"` + ProcessingSec int `json:"processingSec"` + TakedSec int `json:"takedSec"` + SystemNotificationActions []SystemNotificationActionResponse `json:"systemNotificationActions"` + LastTaker SimpleUserResponse `json:"lastTaker"` + RawData string `json:"rawData"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type SystemNotificationActionResponse struct { + ID uuid.UUID `json:"id"` + SystemNotificationId uuid.UUID `json:"systemNotificationId"` + Content string `json:"content"` + Status string `json:"status"` + Taker SimpleUserResponse `json:"taker"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type GetSystemNotificationsResponse struct { + SystemNotifications []SystemNotificationResponse `json:"systemNotifications"` + Pagination PaginationResponse `json:"pagination"` +} + +type GetSystemNotificationResponse struct { + SystemNotification SystemNotificationResponse `json:"systemNotification"` +} + +type CreateSystemNotificationResponse struct { + ID string `json:"id"` +} + +type UpdateSystemNotificationRequest struct { + Description string `json:"description"` +} + +type CreateSystemNotificationActionRequest struct { + Content string `json:"content"` + Status string `json:"status" validate:"oneof=INPROGRESS CLOSED"` +} + +type CreateSystemNotificationActionResponse struct { + ID string `json:"id"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 8c51361d..c2ee6d0d 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -70,8 +70,8 @@ var errorMap = map[ErrorCode]string{ "S_INVALID_CLUSTER_ID": "BYOH 타입의 클러스터 생성은 반드시 clusterId 값이 필요합니다.", "S_INVALID_CLOUD_SERVICE": "클라우드 서비스 타입이 잘못되었습니다.", - // Alert - "AL_NOT_FOUND_ALERT": "지정한 앨럿이 존재하지 않습니다.", + // Event + "EV_NOT_FOUND_EVENT": "지정한 앨럿이 존재하지 않습니다.", // AppGroup "AG_NOT_FOUND_CLUSTER": "지장한 클러스터가 존재하지 않습니다.", From 73ae8753ad9b13e0e5585c24772aaf67b4af07e2 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 19 Mar 2024 16:13:34 +0900 Subject: [PATCH 137/502] feature. add templates mapping for organization --- api/swagger/docs.go | 146 ++++++++++++++++-- api/swagger/swagger.json | 146 ++++++++++++++++-- api/swagger/swagger.yaml | 95 +++++++++++- internal/delivery/api/endpoint.go | 6 +- .../delivery/api/generated_endpoints.go.go | 44 ++++-- internal/delivery/http/organization.go | 111 ++++++++++++- internal/middleware/audit/audit-map.go | 16 +- internal/middleware/auth/role/default.go | 5 +- internal/model/app-group.go | 11 -- internal/model/app-serve-app.go | 13 -- internal/model/audit.go | 5 - internal/model/cloud-account.go | 5 - internal/model/cluster.go | 5 - internal/model/organization.go | 30 ++-- internal/model/permission.go | 7 - internal/model/policy-template.go | 5 - internal/model/project.go | 19 --- internal/model/role.go | 5 - internal/model/stack-template.go | 5 - internal/model/system-notification.go | 10 -- internal/model/user.go | 6 - internal/repository/app-group.go | 4 + internal/repository/app-serve-app.go | 4 +- internal/repository/audit.go | 1 + internal/repository/cloud-account.go | 1 + internal/repository/cluster.go | 1 + internal/repository/organization.go | 29 +++- internal/repository/permission.go | 2 + internal/repository/policy-template.go | 1 + internal/repository/project.go | 2 + internal/repository/role.go | 5 +- internal/repository/stack-template.go | 2 + internal/repository/system-notification.go | 2 + internal/repository/user.go | 17 +- internal/route/route.go | 7 +- internal/usecase/organization.go | 63 ++++++-- pkg/domain/organization.go | 16 +- pkg/domain/stack-template.go | 20 ++- pkg/httpErrors/errorCode.go | 6 + 39 files changed, 672 insertions(+), 206 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 967c0070..457bdecb 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -202,6 +202,52 @@ const docTemplate = `{ } } }, + "/admin/organizations/{organizationId}": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update organization detail ( for admin )", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Update organization detail ( for admin )", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse" + } + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -2178,6 +2224,40 @@ const docTemplate = `{ } } }, + "/organizations/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for organization", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Check name for organization", + "parameters": [ + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}": { "get": { "security": [ @@ -6919,6 +6999,53 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "primaryClusterId": { + "type": "string" + }, + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -9270,9 +9397,6 @@ const docTemplate = `{ "name": { "type": "string" }, - "phone": { - "type": "string" - }, "policyTemplates": { "type": "array", "items": { @@ -10028,7 +10152,7 @@ const docTemplate = `{ "services": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse" } }, "template": { @@ -10036,6 +10160,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse": { "type": "object", "properties": { @@ -10551,9 +10683,6 @@ const docTemplate = `{ "maxLength": 30, "minLength": 1 }, - "phone": { - "type": "string" - }, "primaryClusterId": { "type": "string" } @@ -10570,9 +10699,6 @@ const docTemplate = `{ }, "name": { "type": "string" - }, - "phone": { - "type": "string" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index f333c1f6..1194bfaf 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -196,6 +196,52 @@ } } }, + "/admin/organizations/{organizationId}": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update organization detail ( for admin )", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Update organization detail ( for admin )", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse" + } + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -2172,6 +2218,40 @@ } } }, + "/organizations/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for organization", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Check name for organization", + "parameters": [ + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}": { "get": { "security": [ @@ -6913,6 +6993,53 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "primaryClusterId": { + "type": "string" + }, + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -9264,9 +9391,6 @@ "name": { "type": "string" }, - "phone": { - "type": "string" - }, "policyTemplates": { "type": "array", "items": { @@ -10022,7 +10146,7 @@ "services": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse" } }, "template": { @@ -10030,6 +10154,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse": { "type": "object", "properties": { @@ -10545,9 +10677,6 @@ "maxLength": 30, "minLength": 1 }, - "phone": { - "type": "string" - }, "primaryClusterId": { "type": "string" } @@ -10564,9 +10693,6 @@ }, "name": { "type": "string" - }, - "phone": { - "type": "string" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index d727754a..b4b647d7 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -147,6 +147,38 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest: + properties: + description: + maxLength: 100 + minLength: 0 + type: string + name: + maxLength: 30 + minLength: 1 + type: string + policyTemplateIds: + items: + type: string + type: array + primaryClusterId: + type: string + stackTemplateIds: + items: + type: string + type: array + systemNotificationTemplateIds: + items: + type: string + type: array + required: + - name + type: object + github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse: + properties: + id: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse: properties: appGroupType: @@ -1728,8 +1760,6 @@ definitions: type: string name: type: string - phone: - type: string policyTemplates: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimplePolicyTemplateResponse' @@ -2235,11 +2265,16 @@ definitions: type: string services: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse' type: array template: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse: + properties: + type: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse: properties: accountId: @@ -2581,8 +2616,6 @@ definitions: maxLength: 30 minLength: 1 type: string - phone: - type: string primaryClusterId: type: string required: @@ -2596,8 +2629,6 @@ definitions: type: string name: type: string - phone: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest: properties: @@ -3027,6 +3058,35 @@ paths: summary: Get Audit tags: - Audits + /admin/organizations/{organizationId}: + put: + consumes: + - application/json + description: Update organization detail ( for admin ) + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: update organization request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse' + security: + - JWT: [] + summary: Update organization detail ( for admin ) + tags: + - Organizations /admin/organizations/{organizationId}/projects: get: consumes: @@ -7125,6 +7185,27 @@ paths: summary: Get user email existence tags: - Users + /organizations/name/{name}/existence: + get: + consumes: + - application/json + description: Check name for organization + parameters: + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Check name for organization + tags: + - Organizations /permissions/templates: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 81013594..8ff1bab7 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -39,12 +39,14 @@ const ( DeleteMyProfile // Organization - CreateOrganization + Admin_CreateOrganization + Admin_DeleteOrganization + Admin_UpdateOrganization GetOrganizations GetOrganization - DeleteOrganization UpdateOrganization UpdatePrimaryCluster + CheckOrganizationName // Cluster CreateCluster diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 6a09a23f..1955a7e8 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -91,8 +91,16 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "DeleteMyProfile", Group: "MyProfile", }, - CreateOrganization: { - Name: "CreateOrganization", + Admin_CreateOrganization: { + Name: "Admin_CreateOrganization", + Group: "Organization", + }, + Admin_DeleteOrganization: { + Name: "Admin_DeleteOrganization", + Group: "Organization", + }, + Admin_UpdateOrganization: { + Name: "Admin_UpdateOrganization", Group: "Organization", }, GetOrganizations: { @@ -103,10 +111,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetOrganization", Group: "Organization", }, - DeleteOrganization: { - Name: "DeleteOrganization", - Group: "Organization", - }, UpdateOrganization: { Name: "UpdateOrganization", Group: "Organization", @@ -115,6 +119,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdatePrimaryCluster", Group: "Organization", }, + CheckOrganizationName: { + Name: "CheckOrganizationName", + Group: "Organization", + }, CreateCluster: { Name: "CreateCluster", Group: "Cluster", @@ -798,18 +806,22 @@ func (e Endpoint) String() string { return "RenewPasswordExpiredDate" case DeleteMyProfile: return "DeleteMyProfile" - case CreateOrganization: - return "CreateOrganization" + case Admin_CreateOrganization: + return "Admin_CreateOrganization" + case Admin_DeleteOrganization: + return "Admin_DeleteOrganization" + case Admin_UpdateOrganization: + return "Admin_UpdateOrganization" case GetOrganizations: return "GetOrganizations" case GetOrganization: return "GetOrganization" - case DeleteOrganization: - return "DeleteOrganization" case UpdateOrganization: return "UpdateOrganization" case UpdatePrimaryCluster: return "UpdatePrimaryCluster" + case CheckOrganizationName: + return "CheckOrganizationName" case CreateCluster: return "CreateCluster" case GetClusters: @@ -1178,18 +1190,22 @@ func GetEndpoint(name string) Endpoint { return RenewPasswordExpiredDate case "DeleteMyProfile": return DeleteMyProfile - case "CreateOrganization": - return CreateOrganization + case "Admin_CreateOrganization": + return Admin_CreateOrganization + case "Admin_DeleteOrganization": + return Admin_DeleteOrganization + case "Admin_UpdateOrganization": + return Admin_UpdateOrganization case "GetOrganizations": return GetOrganizations case "GetOrganization": return GetOrganization - case "DeleteOrganization": - return DeleteOrganization case "UpdateOrganization": return UpdateOrganization case "UpdatePrimaryCluster": return UpdatePrimaryCluster + case "CheckOrganizationName": + return CheckOrganizationName case "CreateCluster": return CreateCluster case "GetClusters": diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 683873d4..eafbe9aa 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" + "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" @@ -43,7 +44,7 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { // @Success 200 {object} object // @Router /organizations [post] // @Security JWT -func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http.Request) { +func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r *http.Request) { input := domain.CreateOrganizationRequest{} err := UnmarshalRequestInput(r, &input) @@ -246,7 +247,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Success 200 {object} domain.DeleteOrganizationResponse // @Router /organizations/{organizationId} [delete] // @Security JWT -func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { +func (h *OrganizationHandler) Admin_DeleteOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] if !ok { @@ -313,7 +314,12 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. return } - organization, err := h.usecase.Update(r.Context(), organizationId, input) + var dto model.Organization + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + + organization, err := h.usecase.Update(r.Context(), organizationId, dto) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -332,6 +338,67 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. ResponseJSON(w, r, http.StatusOK, out) } +// Admin_UpdateOrganization godoc +// +// @Tags Organizations +// @Summary Update organization detail ( for admin ) +// @Description Update organization detail ( for admin ) +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.Admin_UpdateOrganizationRequest true "update organization request" +// @Success 200 {object} domain.Admin_UpdateOrganizationResponse +// @Router /admin/organizations/{organizationId} [put] +// @Security JWT +func (h *OrganizationHandler) Admin_UpdateOrganization(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.Admin_UpdateOrganizationRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto model.Organization + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + + for _, strId := range input.StackTemplateIds { + stackTemplateId, err := uuid.Parse(strId) + if err != nil || stackTemplateId == uuid.Nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + dto.StackTemplateIds = append(dto.StackTemplateIds, stackTemplateId) + } + for _, strId := range input.PolicyTemplateIds { + policyTemplateId, err := uuid.Parse(strId) + if err != nil || policyTemplateId == uuid.Nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + dto.PolicyTemplateIds = append(dto.PolicyTemplateIds, policyTemplateId) + } + + err = h.usecase.UpdateWithTemplates(r.Context(), organizationId, dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.Admin_UpdateOrganizationResponse + out.ID = organizationId + + ResponseJSON(w, r, http.StatusOK, out) +} + // UpdatePrimaryCluster godoc // // @Tags Organizations @@ -371,3 +438,41 @@ func (h *OrganizationHandler) UpdatePrimaryCluster(w http.ResponseWriter, r *htt ResponseJSON(w, r, http.StatusOK, nil) } + +// CheckOrganizationName godoc +// +// @Tags Organizations +// @Summary Check name for organization +// @Description Check name for organization +// @Accept json +// @Produce json +// @Param name path string true "name" +// @Success 200 {object} nil +// @Router /organizations/name/{name}/existence [GET] +// @Security JWT +func (h *OrganizationHandler) CheckOrganizationName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name, ok := vars["name"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid name"), "O_INVALID_ORGANIZATION_NAME", "")) + return + } + + exist := false + pg := pagination.NewPaginationWithFilter("name", "", "$eq", []string{name}) + organizations, err := h.usecase.Fetch(r.Context(), pg) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + if organizations != nil && len(*organizations) > 0 { + exist = true + } + + var out domain.CheckStackNameResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index a5fead14..d7c70439 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -45,7 +45,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("클라우드 어카운트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.DeleteCloudAccount: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.DeleteCloudAccount: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { if isSuccess(statusCode) { output := domain.DeleteCloudAccountResponse{} if err := json.Unmarshal(in, &output); err != nil { @@ -55,7 +55,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return "클라우드어카운트 [%s]를 삭제하는데 실패하였습니다. ", errorText(ctx, out) } - }, internalApi.CreateUser: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateUser: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateUserRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -65,7 +65,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("사용자 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreateOrganization: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateOrganization: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateOrganizationRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -75,7 +75,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("조직 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.DeleteOrganization: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_DeleteOrganization: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { if isSuccess(statusCode) { output := domain.DeleteOrganizationResponse{} if err := json.Unmarshal(in, &output); err != nil { @@ -85,7 +85,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return "조직 [%s]를 삭제하는데 실패하였습니다. ", errorText(ctx, out) } - }, internalApi.CreateAppServeApp: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateAppServeApp: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateAppServeAppRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -95,7 +95,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("앱서빙 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateStackTemplate: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateStackTemplate: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateStackTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -106,7 +106,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("스택 템플릿 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateUser: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateUser: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateUserRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -116,7 +116,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreatePolicyTemplate: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreatePolicyTemplate: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreatePolicyTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) diff --git a/internal/middleware/auth/role/default.go b/internal/middleware/auth/role/default.go index b50efd3f..d56e092e 100644 --- a/internal/middleware/auth/role/default.go +++ b/internal/middleware/auth/role/default.go @@ -57,10 +57,11 @@ var defaultPermissionOfAdmin = defaultPermission{ internalApi.DeleteMyProfile, // Organization - internalApi.CreateOrganization, + internalApi.Admin_CreateOrganization, + internalApi.Admin_UpdateOrganization, + internalApi.Admin_DeleteOrganization, internalApi.GetOrganizations, internalApi.GetOrganization, - internalApi.DeleteOrganization, internalApi.UpdateOrganization, // Cluster diff --git a/internal/model/app-group.go b/internal/model/app-group.go index fea48726..72cd1f88 100644 --- a/internal/model/app-group.go +++ b/internal/model/app-group.go @@ -2,7 +2,6 @@ package model import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/datatypes" "gorm.io/gorm" @@ -26,11 +25,6 @@ type AppGroup struct { Updator User `gorm:"foreignKey:UpdatorId"` } -func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = domain.AppGroupId(helper.GenerateApplicaionGroupId()) - return nil -} - type Application struct { gorm.Model @@ -40,8 +34,3 @@ type Application struct { Metadata datatypes.JSON Type domain.ApplicationType } - -func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go index 4b6e779e..4a9b2186 100644 --- a/internal/model/app-serve-app.go +++ b/internal/model/app-serve-app.go @@ -2,9 +2,6 @@ package model import ( "time" - - "github.com/google/uuid" - "gorm.io/gorm" ) type AppServeApp struct { @@ -55,13 +52,3 @@ type AppServeAppTask struct { UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` } - -func (a *AppServeApp) BeforeCreate(tx *gorm.DB) (err error) { - a.ID = uuid.New().String() - return nil -} - -func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} diff --git a/internal/model/audit.go b/internal/model/audit.go index bfa853c1..1f39c252 100644 --- a/internal/model/audit.go +++ b/internal/model/audit.go @@ -19,8 +19,3 @@ type Audit struct { UserId *uuid.UUID `gorm:"type:uuid"` User User `gorm:"foreignKey:UserId"` } - -func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/cloud-account.go b/internal/model/cloud-account.go index 33d3a14b..98bf3f9c 100644 --- a/internal/model/cloud-account.go +++ b/internal/model/cloud-account.go @@ -31,8 +31,3 @@ type CloudAccount struct { UpdatorId *uuid.UUID `gorm:"type:uuid"` Updator User `gorm:"foreignKey:UpdatorId"` } - -func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 8ca4b764..4e7480f6 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -77,8 +77,3 @@ type ClusterFavorite struct { UserId uuid.UUID `gorm:"type:uuid"` User User `gorm:"foreignKey:UserId"` } - -func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/organization.go b/internal/model/organization.go index f95a8a5b..2c6ca725 100644 --- a/internal/model/organization.go +++ b/internal/model/organization.go @@ -10,18 +10,20 @@ import ( type Organization struct { gorm.Model - ID string `gorm:"primarykey;type:varchar(36);not null"` - Name string - Description string - Phone string - PrimaryClusterId string - WorkflowId string - Status domain.OrganizationStatus - StatusDesc string - CreatorId *uuid.UUID `gorm:"type:uuid"` - StackTemplates []StackTemplate `gorm:"many2many:stack_template_organizations"` - PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organiations;"` - ClusterCount int `gorm:"-:all"` - AdminId *uuid.UUID - Admin *User `gorm:"foreignKey:AdminId"` + ID string `gorm:"primarykey;type:varchar(36);not null"` + Name string + Description string + Phone string + PrimaryClusterId string + WorkflowId string + Status domain.OrganizationStatus + StatusDesc string + CreatorId *uuid.UUID `gorm:"type:uuid"` + StackTemplates []StackTemplate `gorm:"many2many:stack_template_organizations;"` + StackTemplateIds []uuid.UUID `gorm:"-:all"` + PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organiations;"` + PolicyTemplateIds []uuid.UUID `gorm:"-:all"` + ClusterCount int `gorm:"-:all"` + AdminId *uuid.UUID + Admin *User `gorm:"foreignKey:AdminId"` } diff --git a/internal/model/permission.go b/internal/model/permission.go index 9283bea3..9be78e6d 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -35,13 +35,6 @@ type Permission struct { Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` } -func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { - if p.ID == uuid.Nil { - p.ID = uuid.New() - } - return nil -} - type PermissionSet struct { Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` Stack *Permission `gorm:"-:all" json:"stack,omitempty"` diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index 430c4b7d..52b947c2 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -41,8 +41,3 @@ type PolicyTemplate struct { UpdatorId *uuid.UUID `gorm:"type:uuid"` Updator User `gorm:"foreignKey:UpdatorId"` } - -func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/project.go b/internal/model/project.go index 011e7704..7b69911f 100644 --- a/internal/model/project.go +++ b/internal/model/project.go @@ -7,30 +7,11 @@ import ( "gorm.io/gorm" ) -func (a *Project) BeforeCreate(*gorm.DB) (err error) { - a.ID = uuid.New().String() - return nil -} - func (t *ProjectRole) BeforeCreate(*gorm.DB) (err error) { t.ID = uuid.New().String() return nil } -func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} - -//func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { -// t.ID = uuid.New().String() -// return nil -//} - -func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { - return nil -} - type Project struct { ID string `gorm:"primarykey" json:"id"` OrganizationId string `json:"organizationId"` diff --git a/internal/model/role.go b/internal/model/role.go index 01f6497a..981d92d2 100644 --- a/internal/model/role.go +++ b/internal/model/role.go @@ -7,11 +7,6 @@ import ( "gorm.io/gorm" ) -func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { - r.ID = uuid.New().String() - return nil -} - type Role struct { gorm.Model diff --git a/internal/model/stack-template.go b/internal/model/stack-template.go index c74cad06..afcef83b 100644 --- a/internal/model/stack-template.go +++ b/internal/model/stack-template.go @@ -29,11 +29,6 @@ type StackTemplate struct { Updator User `gorm:"foreignKey:UpdatorId"` } -func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - type StackTemplateOrganization struct { StackTemplateId uuid.UUID `gorm:"primarykey"` OrganizationId string `gorm:"primarykey"` diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go index aa723983..aea8cbb0 100644 --- a/internal/model/system-notification.go +++ b/internal/model/system-notification.go @@ -38,11 +38,6 @@ type SystemNotification struct { Status domain.SystemNotificationActionStatus `gorm:"index"` } -func (c *SystemNotification) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - type SystemNotificationAction struct { gorm.Model @@ -53,8 +48,3 @@ type SystemNotificationAction struct { TakerId *uuid.UUID `gorm:"type:uuid"` Taker User `gorm:"foreignKey:TakerId"` } - -func (c *SystemNotificationAction) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/user.go b/internal/model/user.go index 96303110..c8a2c7de 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -4,7 +4,6 @@ import ( "time" "github.com/google/uuid" - "gorm.io/gorm" ) type User struct { @@ -27,8 +26,3 @@ type User struct { Department string `json:"department"` Description string `json:"description"` } - -func (g *User) BeforeCreate(tx *gorm.DB) (err error) { - g.PasswordUpdatedAt = time.Now() - return nil -} diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index df2b76af..2885155b 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -7,6 +7,8 @@ import ( "gorm.io/datatypes" "gorm.io/gorm" + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" @@ -61,6 +63,7 @@ func (r *AppGroupRepository) Get(ctx context.Context, id domain.AppGroupId) (out func (r *AppGroupRepository) Create(ctx context.Context, dto model.AppGroup) (appGroupId domain.AppGroupId, err error) { appGroup := model.AppGroup{ + ID: domain.AppGroupId(helper.GenerateApplicaionGroupId()), ClusterId: dto.ClusterId, AppGroupType: dto.AppGroupType, Name: dto.Name, @@ -116,6 +119,7 @@ func (r *AppGroupRepository) UpsertApplication(ctx context.Context, dto model.Ap Type: dto.Type, }). Assign(model.Application{ + ID: uuid.New(), Endpoint: dto.Endpoint, Metadata: datatypes.JSON([]byte(dto.Metadata))}). FirstOrCreate(&model.Application{}) diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 53460c70..a37559ca 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" @@ -42,7 +43,7 @@ func NewAppServeAppRepository(db *gorm.DB) IAppServeAppRepository { } func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) { - + app.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&app) if res.Error != nil { return "", "", res.Error @@ -53,6 +54,7 @@ func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *mode // Update creates new appServeApp task for existing appServeApp. func (r *AppServeAppRepository) CreateTask(ctx context.Context, task *model.AppServeAppTask) (string, error) { + task.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(task) if res.Error != nil { return "", res.Error diff --git a/internal/repository/audit.go b/internal/repository/audit.go index 8d9a594f..c0ac2010 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -54,6 +54,7 @@ func (r *AuditRepository) Fetch(ctx context.Context, pg *pagination.Pagination) func (r *AuditRepository) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { audit := model.Audit{ + ID: uuid.New(), OrganizationId: dto.OrganizationId, Group: dto.Group, Message: dto.Message, diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index 72508451..b3dd6efc 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -75,6 +75,7 @@ func (r *CloudAccountRepository) Fetch(ctx context.Context, organizationId strin func (r *CloudAccountRepository) Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { cloudAccount := model.CloudAccount{ + ID: uuid.New(), OrganizationId: dto.OrganizationId, Name: dto.Name, Description: dto.Description, diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 9d25be0a..88c786ee 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -212,6 +212,7 @@ func (r *ClusterRepository) SetFavorite(ctx context.Context, clusterId domain.Cl } clusterFavorite := model.ClusterFavorite{ + ID: uuid.New(), ClusterId: clusterId, UserId: userId, } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index e98cd899..f7266bba 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -2,6 +2,7 @@ package repository import ( "context" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -16,9 +17,11 @@ type IOrganizationRepository interface { Create(ctx context.Context, dto *model.Organization) (model.Organization, error) Fetch(ctx context.Context, pg *pagination.Pagination) (res *[]model.Organization, err error) Get(ctx context.Context, organizationId string) (res model.Organization, err error) - Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) + Update(ctx context.Context, organizationId string, in model.Organization) (model.Organization, error) UpdatePrimaryClusterId(ctx context.Context, organizationId string, primaryClusterId string) error UpdateAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error + UpdateStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) + UpdatePolicyTemplates(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) Delete(ctx context.Context, organizationId string) (err error) InitWorkflow(ctx context.Context, organizationId string, workflowId string, status domain.OrganizationStatus) error } @@ -94,13 +97,12 @@ func (r *OrganizationRepository) Get(ctx context.Context, id string) (out model. return } -func (r *OrganizationRepository) Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (out model.Organization, err error) { +func (r *OrganizationRepository) Update(ctx context.Context, organizationId string, in model.Organization) (out model.Organization, err error) { res := r.db.WithContext(ctx).Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "name": in.Name, "description": in.Description, - "phone": in.Phone, }) if res.Error != nil { @@ -163,3 +165,24 @@ func (r *OrganizationRepository) InitWorkflow(ctx context.Context, organizationI } return nil } + +func (r *OrganizationRepository) UpdateStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) { + var organization = model.Organization{} + res := r.db.WithContext(ctx).Preload("StackTemplates").First(&organization, "id = ?", organizationId) + if res.Error != nil { + return res.Error + } + + err = r.db.WithContext(ctx).Model(&organization).Association("StackTemplates").Replace(stackTemplates) + if err != nil { + return err + } + + return nil +} + +func (r *OrganizationRepository) UpdatePolicyTemplates(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) { + // [TODO] + + return nil +} diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 335ce2e4..144d0a68 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -2,6 +2,7 @@ package repository import ( "context" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "gorm.io/gorm" @@ -47,6 +48,7 @@ func (r PermissionRepository) Create(ctx context.Context, p *model.Permission) e // } //} + p.ID = uuid.New() return r.db.WithContext(ctx).Create(p).Error } diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 92053bb4..806661d9 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -52,6 +52,7 @@ func (r *PolicyTemplateRepository) Create(ctx context.Context, dto model.PolicyT } policyTemplate := model.PolicyTemplate{ + ID: uuid.New(), Type: "tks", Name: dto.TemplateName, Version: "v1.0.0", diff --git a/internal/repository/project.go b/internal/repository/project.go index a5df7edf..53c4041d 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -55,6 +55,7 @@ func NewProjectRepository(db *gorm.DB) IProjectRepository { } func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) (string, error) { + p.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&p) if res.Error != nil { return "", res.Error @@ -366,6 +367,7 @@ func (r *ProjectRepository) GetProjectRoleByName(ctx context.Context, name strin } func (r *ProjectRepository) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { + pm.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&pm) if res.Error != nil { return "", res.Error diff --git a/internal/repository/role.go b/internal/repository/role.go index b3b1aa12..a4af220d 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -1,10 +1,11 @@ package repository import ( + "context" "fmt" "math" - "context" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "gorm.io/gorm" @@ -36,6 +37,7 @@ func (r RoleRepository) Create(ctx context.Context, roleObj *model.Role) (string if roleObj == nil { return "", fmt.Errorf("roleObj is nil") } + roleObj.ID = uuid.New().String() if err := r.db.WithContext(ctx).Create(roleObj).Error; err != nil { return "", err } @@ -69,7 +71,6 @@ func (r RoleRepository) ListTksRoles(ctx context.Context, organizationId string, return roles, nil } - func (r RoleRepository) GetTksRole(ctx context.Context, id string) (*model.Role, error) { var role model.Role if err := r.db.WithContext(ctx).First(&role, "id = ?", id).Error; err != nil { diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 56dc5bd1..e94b70fc 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -2,6 +2,7 @@ package repository import ( "context" + "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -77,6 +78,7 @@ func (r *StackTemplateRepository) FetchWithOrganization(ctx context.Context, org } func (r *StackTemplateRepository) Create(ctx context.Context, dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { + dto.ID = uuid.New() res := r.db.WithContext(ctx).Create(&dto) if res.Error != nil { return uuid.Nil, res.Error diff --git a/internal/repository/system-notification.go b/internal/repository/system-notification.go index 3c6dff2b..58bb1336 100644 --- a/internal/repository/system-notification.go +++ b/internal/repository/system-notification.go @@ -85,6 +85,7 @@ func (r *SystemNotificationRepository) FetchPodRestart(ctx context.Context, orga func (r *SystemNotificationRepository) Create(ctx context.Context, dto model.SystemNotification) (systemNotificationId uuid.UUID, err error) { systemNotification := model.SystemNotification{ + ID: uuid.New(), OrganizationId: dto.OrganizationId, Name: dto.Name, Code: dto.Code, @@ -126,6 +127,7 @@ func (r *SystemNotificationRepository) Delete(ctx context.Context, dto model.Sys func (r *SystemNotificationRepository) CreateSystemNotificationAction(ctx context.Context, dto model.SystemNotificationAction) (systemNotificationActionId uuid.UUID, err error) { systemNotification := model.SystemNotificationAction{ + ID: uuid.New(), SystemNotificationId: dto.SystemNotificationId, Content: dto.Content, Status: dto.Status, diff --git a/internal/repository/user.go b/internal/repository/user.go index 478aaba5..451271e0 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -55,14 +55,15 @@ func (r *UserRepository) CreateWithUuid(ctx context.Context, uuid uuid.UUID, acc department string, description string, organizationId string, roleId string) (model.User, error) { newUser := model.User{ - ID: uuid, - AccountId: accountId, - Name: name, - Email: email, - Department: department, - Description: description, - OrganizationId: organizationId, - RoleId: roleId, + ID: uuid, + AccountId: accountId, + Name: name, + Email: email, + Department: department, + Description: description, + OrganizationId: organizationId, + RoleId: roleId, + PasswordUpdatedAt: time.Now(), } res := r.db.WithContext(ctx).Create(&newUser) if res.Error != nil { diff --git a/internal/route/route.go b/internal/route/route.go index 5d789954..7e40bd6a 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -116,7 +116,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/next-password-change", customMiddleware.Handle(internalApi.RenewPasswordExpiredDate, http.HandlerFunc(userHandler.RenewPasswordExpiredDate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.DeleteMyProfile, http.HandlerFunc(userHandler.DeleteMyProfile))).Methods(http.MethodDelete) - // Admin r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_CreateUser, http.HandlerFunc(userHandler.Admin_Create))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_ListUser, http.HandlerFunc(userHandler.Admin_List))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_GetUser, http.HandlerFunc(userHandler.Admin_Get))).Methods(http.MethodGet) @@ -124,12 +123,14 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_DeleteUser, http.HandlerFunc(userHandler.Admin_Delete))).Methods(http.MethodDelete) organizationHandler := delivery.NewOrganizationHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.CreateOrganization, http.HandlerFunc(organizationHandler.CreateOrganization))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations", customMiddleware.Handle(internalApi.Admin_CreateOrganization, http.HandlerFunc(organizationHandler.Admin_CreateOrganization))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.Admin_DeleteOrganization, http.HandlerFunc(organizationHandler.Admin_DeleteOrganization))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.Admin_UpdateOrganization, http.HandlerFunc(organizationHandler.Admin_UpdateOrganization))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.GetOrganizations, http.HandlerFunc(organizationHandler.GetOrganizations))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.GetOrganization, http.HandlerFunc(organizationHandler.GetOrganization))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.DeleteOrganization, http.HandlerFunc(organizationHandler.DeleteOrganization))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.UpdateOrganization, http.HandlerFunc(organizationHandler.UpdateOrganization))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/primary-cluster", customMiddleware.Handle(internalApi.UpdatePrimaryCluster, http.HandlerFunc(organizationHandler.UpdatePrimaryCluster))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/name/{name}/existence", customMiddleware.Handle(internalApi.CheckOrganizationName, http.HandlerFunc(organizationHandler.CheckOrganizationName))).Methods(http.MethodGet) clusterHandler := delivery.NewClusterHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/clusters", customMiddleware.Handle(internalApi.CreateCluster, http.HandlerFunc(clusterHandler.CreateCluster))).Methods(http.MethodPost) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 83970930..7409a392 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -24,27 +24,31 @@ type IOrganizationUsecase interface { Create(context.Context, *model.Organization) (organizationId string, err error) Fetch(ctx context.Context, pg *pagination.Pagination) (*[]model.Organization, error) Get(ctx context.Context, organizationId string) (model.Organization, error) - Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) + Update(ctx context.Context, organizationId string, dto model.Organization) (model.Organization, error) UpdatePrimaryClusterId(ctx context.Context, organizationId string, clusterId string) (err error) + UpdateWithTemplates(ctx context.Context, organizationId string, dto model.Organization) (err error) ChangeAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error Delete(ctx context.Context, organizationId string, accessToken string) error } type OrganizationUsecase struct { - repo repository.IOrganizationRepository - roleRepo repository.IRoleRepository - clusterRepo repository.IClusterRepository - argo argowf.ArgoClient - kc keycloak.IKeycloak + repo repository.IOrganizationRepository + roleRepo repository.IRoleRepository + clusterRepo repository.IClusterRepository + stackTemplateRepo repository.IStackTemplateRepository + policyTemplateRepo repository.IPolicyTemplateRepository + argo argowf.ArgoClient + kc keycloak.IKeycloak } func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClient, kc keycloak.IKeycloak) IOrganizationUsecase { return &OrganizationUsecase{ - repo: r.Organization, - roleRepo: r.Role, - clusterRepo: r.Cluster, - argo: argoClient, - kc: kc, + repo: r.Organization, + roleRepo: r.Role, + clusterRepo: r.Cluster, + stackTemplateRepo: r.StackTemplate, + argo: argoClient, + kc: kc, } } @@ -144,7 +148,7 @@ func (u *OrganizationUsecase) Delete(ctx context.Context, organizationId string, return nil } -func (u *OrganizationUsecase) Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) { +func (u *OrganizationUsecase) Update(ctx context.Context, organizationId string, in model.Organization) (model.Organization, error) { _, err := u.Get(ctx, organizationId) if err != nil { return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") @@ -188,3 +192,38 @@ func (u *OrganizationUsecase) ChangeAdminId(ctx context.Context, organizationId return nil } + +func (u *OrganizationUsecase) UpdateWithTemplates(ctx context.Context, organizationId string, dto model.Organization) (err error) { + _, err = u.Update(ctx, organizationId, dto) + if err != nil { + return err + } + + stackTemplates := make([]model.StackTemplate, 0) + for _, stackTemplateId := range dto.StackTemplateIds { + stackTemplate, err := u.stackTemplateRepo.Get(ctx, stackTemplateId) + if err != nil { + return fmt.Errorf("Invalid stackTemplateId") + } + stackTemplates = append(stackTemplates, stackTemplate) + } + err = u.repo.UpdateStackTemplates(ctx, organizationId, stackTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_STACK_TEMPLATES", "") + } + + policyTemplates := make([]model.PolicyTemplate, 0) + for _, policyTemplateId := range dto.PolicyTemplateIds { + policyTemplate, err := u.policyTemplateRepo.GetByID(ctx, policyTemplateId) + if err != nil { + return fmt.Errorf("Invalid policyTemplateId") + } + policyTemplates = append(policyTemplates, *policyTemplate) + } + err = u.repo.UpdatePolicyTemplates(ctx, organizationId, policyTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_POLICY_TEMPLATES", "") + } + + return nil +} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 7153744d..3e330fa6 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -52,7 +52,6 @@ type OrganizationResponse struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` - Phone string `json:"phone"` PrimaryClusterId string `json:"primaryClusterId"` Status string `json:"status"` StatusDesc string `json:"statusDesc"` @@ -94,14 +93,25 @@ type UpdateOrganizationRequest struct { PrimaryClusterId string `json:"primaryClusterId"` Name string `json:"name" validate:"required,min=1,max=30"` Description string `json:"description" validate:"omitempty,min=0,max=100"` - Phone string `json:"phone"` } type UpdateOrganizationResponse struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` - Phone string `json:"phone"` +} + +type Admin_UpdateOrganizationRequest struct { + PrimaryClusterId string `json:"primaryClusterId"` + Name string `json:"name" validate:"required,min=1,max=30"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` + StackTemplateIds []string `json:"stackTemplateIds"` + PolicyTemplateIds []string `json:"policyTemplateIds"` + SystemNotificationTemplateIds []string `json:"systemNotificationTemplateIds"` +} + +type Admin_UpdateOrganizationResponse struct { + ID string `json:"id"` } type UpdatePrimaryClusterRequest struct { diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index d25a570a..ff1f2570 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -37,15 +37,19 @@ type StackTemplateResponse struct { UpdatedAt time.Time `json:"updatedAt"` } +type SimpleStackTemplateServiceResponse struct { + Type string `json:"type"` +} + type SimpleStackTemplateResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Template string `json:"template"` - CloudService string `json:"cloudService"` - KubeVersion string `json:"kubeVersion"` - KubeType string `json:"kubeType"` - Services []StackTemplateServiceResponse `json:"services"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Template string `json:"template"` + CloudService string `json:"cloudService"` + KubeVersion string `json:"kubeVersion"` + KubeType string `json:"kubeType"` + Services []SimpleStackTemplateServiceResponse `json:"services"` } type GetStackTemplatesResponse struct { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index c2ee6d0d..30bcb76e 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -33,6 +33,12 @@ var errorMap = map[ErrorCode]string{ "A_EXPIRED_CODE": "인증번호가 만료되었습니다.", "A_UNUSABLE_TOKEN": "사용할 수 없는 토큰입니다.", + // Organization + "O_INVALID_ORGANIZATION_NAME": "조직에 이미 존재하는 이름입니다.", + "O_FAILED_UPDATE_STACK_TEMPLATES": "조직에 스택템플릿을 설정하는데 실패했습니다", + "O_FAILED_UPDATE_POLICY_TEMPLATES": "조직에 정책템플릿을 설정하는데 실패했습니다", + "O_FAILED_UPDATE_SYSTEM_NOTIFICATION_TEMPLATES": "조직에 알림템플릿을 설정하는데 실패했습니다", + // User "U_NO_USER": "해당 사용자 정보를 찾을 수 없습니다.", From 2bcfa50251b4935cb79b7b7f93d0c56c348eea16 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 19 Mar 2024 17:23:07 +0900 Subject: [PATCH 138/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 5 +- go.sum | 2 + internal/delivery/http/policy-template.go | 29 +- internal/model/policy-template.go | 68 ++++- internal/repository/policy-template.go | 340 +++++----------------- internal/usecase/policy-template.go | 205 +++++++------ pkg/domain/policy-template.go | 19 +- 7 files changed, 282 insertions(+), 386 deletions(-) diff --git a/go.mod b/go.mod index 4f2e46d4..a1014793 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/servicequotas v1.20.1 github.com/aws/aws-sdk-go-v2/service/ses v1.21.0 github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 + github.com/deckarep/golang-set/v2 v2.6.0 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 @@ -37,8 +38,10 @@ require ( github.com/thoas/go-funk v0.9.3 github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0 golang.org/x/crypto v0.21.0 + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/net v0.22.0 golang.org/x/oauth2 v0.17.0 + golang.org/x/text v0.14.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 gorm.io/datatypes v1.2.0 @@ -124,10 +127,8 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.15.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect diff --git a/go.sum b/go.sum index 99f38a76..d3bf874f 100644 --- a/go.sum +++ b/go.sum @@ -69,6 +69,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index dc6e7173..3e9cb819 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -63,7 +63,6 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h err := UnmarshalRequestInput(r, &input) if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) return } @@ -80,7 +79,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h } var out domain.CreatePolicyTemplateReponse - out.ID = domain.PolicyTemplateId(policyTemplateId) + out.ID = policyTemplateId.String() ResponseJSON(w, r, http.StatusOK, out) } @@ -122,7 +121,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h return } - err = h.usecase.Update(r.Context(), id, input) + err = h.usecase.Update(r.Context(), id, input.TemplateName, input.Description, input.Severity, input.Deprecated, input.PermittedOrganizationIds) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -135,7 +134,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h return } - ResponseJSON(w, r, http.StatusOK, "") + ResponseJSON(w, r, http.StatusOK, nil) } // DeletePolicyTemplate godoc @@ -228,11 +227,20 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http return } + if policyTemplate == nil { + ResponseJSON(w, r, http.StatusNotFound, nil) + return + } + var out domain.GetPolicyTemplateResponse if err = serializer.Map(r.Context(), *policyTemplate, &out.PolicyTemplate); err != nil { log.Error(r.Context(), err) } + if err = h.usecase.UpdatePermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { + log.Error(r.Context(), err) + } + ResponseJSON(w, r, http.StatusOK, out) } @@ -271,6 +279,10 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt } } + if err = h.usecase.UpdatePermittedOrganizationsForList(r.Context(), &policyTemplates, &out.PolicyTemplates); err != nil { + log.Error(r.Context(), err) + } + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -415,13 +427,14 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, policyTemplate, err := h.usecase.GetPolicyTemplateVersion(r.Context(), id, version) if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) return } + } - ErrorJSON(w, r, err) + if policyTemplate == nil { + ResponseJSON(w, r, http.StatusNotFound, nil) return } @@ -430,6 +443,10 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, log.Error(r.Context(), err) } + if err = h.usecase.UpdatePermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { + log.Error(r.Context(), err) + } + ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index 52b947c2..01aa3383 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -1,11 +1,18 @@ package model import ( + "encoding/json" + "strings" + "github.com/google/uuid" "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/gorm" ) +const ( + FILE_DELIMETER = "---\n" +) + type PolicyTemplateSupportedVersion struct { gorm.Model @@ -21,18 +28,17 @@ type PolicyTemplate struct { gorm.Model ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` - Type string // Org or Tks - Name string - Version string + TemplateName string + Type string // Org or Tks + Version string `gorm:"-:all"` // 삭제 예정 SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` Description string Kind string Deprecated bool Mandatory bool // Tks 인 경우에는 무시 Severity string - PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organiations;"` - TemplateName string `gorm:"-:all" json:"templateName"` - ParametersSchema []domain.ParameterDef `gorm:"-:all" json:"parametersSchema,omitempty"` + PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organiations"` + ParametersSchema []domain.ParameterDef `gorm:"-:all"` Rego string `gorm:"-:all"` Libs []string `gorm:"-:all"` PermittedOrganizationIds []string `gorm:"-:all"` @@ -41,3 +47,53 @@ type PolicyTemplate struct { UpdatorId *uuid.UUID `gorm:"type:uuid"` Updator User `gorm:"foreignKey:UpdatorId"` } + +func (pt *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { + pt.ID = uuid.New() + + jsonByte, err := json.Marshal(pt.ParametersSchema) + + if err != nil { + return err + } + + libs := strings.Join(pt.Libs, FILE_DELIMETER) + + pt.Version = "v1.0.0" + + pt.SupportedVersions = []PolicyTemplateSupportedVersion{ + { + Version: "v1.0.0", + ParameterSchema: string(jsonByte), + Rego: pt.Rego, + Libs: libs, + }, + } + + return nil +} + +func (pt *PolicyTemplate) AfterFind(tx *gorm.DB) (err error) { + // 목록 조회 시 에러가 발생해서 전체 조회가 실패하는 것을 방지하기 위해서 에러는 무시 + if len(pt.SupportedVersions) > 0 { + supportedVersion := pt.SupportedVersions[0] + pt.Version = supportedVersion.Version + pt.Rego = supportedVersion.Rego + pt.Libs = strings.Split(supportedVersion.ParameterSchema, FILE_DELIMETER) + + // 마찬가지로 에러 무시 + json.Unmarshal([]byte(supportedVersion.ParameterSchema), &pt.ParametersSchema) + } + + pt.PermittedOrganizationIds = make([]string, len(pt.PermittedOrganizations)) + for i, org := range pt.PermittedOrganizations { + pt.PermittedOrganizationIds[i] = org.ID + } + + return +} + +type PolicyTemplatePermittedOrganization struct { + PolicyTemplateId uuid.UUID `gorm:"primarykey"` + OrganizationId string `gorm:"primarykey"` +} diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 806661d9..18cf0841 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -9,17 +9,15 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gorm.io/gorm" - "gorm.io/gorm/clause" ) type IPolicyTemplateRepository interface { - Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) - Update(ctx context.Context, dto domain.UpdatePolicyTemplateUpdate) (err error) + Create(ctx context.Context, policyTemplate model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) + Update(ctx context.Context, policyTemplateId uuid.UUID, updateMap map[string]interface{}, permittedOrganizations *[]model.Organization) (err error) Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.PolicyTemplate, err error) GetByName(ctx context.Context, policyTemplateName string) (out *model.PolicyTemplate, err error) GetByKind(ctx context.Context, policyTemplateKind string) (out *model.PolicyTemplate, err error) @@ -45,95 +43,24 @@ func NewPolicyTemplateRepository(db *gorm.DB) IPolicyTemplateRepository { } func (r *PolicyTemplateRepository) Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { - jsonByte, err := json.Marshal(dto.ParametersSchema) + err = r.db.WithContext(ctx).Create(&dto).Error if err != nil { return uuid.Nil, err } - policyTemplate := model.PolicyTemplate{ - ID: uuid.New(), - Type: "tks", - Name: dto.TemplateName, - Version: "v1.0.0", - SupportedVersions: []model.PolicyTemplateSupportedVersion{ - { - Version: "v1.0.0", - ParameterSchema: string(jsonByte), - Rego: dto.Rego, - }, - }, - Description: dto.Description, - Kind: dto.Kind, - Deprecated: false, - Mandatory: false, // Tks 인 경우에는 무시 - Severity: dto.Severity, - } - - err = r.db.Transaction(func(tx *gorm.DB) error { - err := tx.Create(&policyTemplate).Error - - if err != nil { - return err - } - - if dto.PermittedOrganizationIds != nil { - permittedOrganizations := make([]model.Organization, len(dto.PermittedOrganizationIds)) - for i, permittedOrganizationId := range dto.PermittedOrganizationIds { - permittedOrganizations[i] = model.Organization{ID: permittedOrganizationId} - } - - err = tx.Model(&policyTemplate).Association("PermittedOrganizations").Replace(permittedOrganizations) - - if err != nil { - return err - } - } - - return nil - }) - - if err != nil { - return uuid.Nil, err - } - - return policyTemplate.ID, nil + return dto.ID, nil } -func (r *PolicyTemplateRepository) Update(ctx context.Context, dto domain.UpdatePolicyTemplateUpdate) (err error) { - updateMap := make(map[string]interface{}) - - updateMap["updator_id"] = dto.UpdatorId - - if dto.Description != nil { - updateMap["description"] = dto.Description - } - - if dto.Deprecated != nil { - updateMap["deprecated"] = dto.Deprecated - } - - if dto.Severity != nil { - updateMap["severity"] = dto.Severity - } - - if dto.TemplateName != nil { - updateMap["name"] = dto.TemplateName - } - - fmt.Printf("--updateMap=%+v\n--", updateMap) +func (r *PolicyTemplateRepository) Update(ctx context.Context, policyTemplateId uuid.UUID, + updateMap map[string]interface{}, permittedOrganizations *[]model.Organization) (err error) { var policyTemplate model.PolicyTemplate - policyTemplate.ID = dto.ID - - return r.db.Transaction(func(tx *gorm.DB) error { - if dto.PermittedOrganizationIds != nil { - permittedOrganizations := make([]model.Organization, len(*dto.PermittedOrganizationIds)) - for i, permittedOrganizationId := range *dto.PermittedOrganizationIds { - permittedOrganizations[i] = model.Organization{ID: permittedOrganizationId} - } + policyTemplate.ID = policyTemplateId - err = r.db.Model(&policyTemplate).Limit(1). + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if permittedOrganizations != nil { + err = r.db.WithContext(ctx).Model(&policyTemplate).Limit(1). Association("PermittedOrganizations").Replace(permittedOrganizations) if err != nil { @@ -142,8 +69,8 @@ func (r *PolicyTemplateRepository) Update(ctx context.Context, dto domain.Update } if len(updateMap) > 0 { - err = r.db.Model(&policyTemplate).Limit(1). - Where("id = ? and type = 'tks'", dto.ID). + err = r.db.WithContext(ctx).Model(&policyTemplate).Limit(1). + Where("id = ? and type = 'tks'", policyTemplateId). Updates(updateMap).Error if err != nil { @@ -162,78 +89,26 @@ func (r *PolicyTemplateRepository) Fetch(ctx context.Context, pg *pagination.Pag pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.Preload(clause.Associations).Model(&model.PolicyTemplate{}). + _, res := pg.Fetch(r.db.WithContext(ctx). + Preload("SupportedVersions", func(db *gorm.DB) *gorm.DB { + // 최신 버전만 + return db.Order("policy_template_supported_versions.version DESC") + }). + Preload("PermittedOrganizations").Preload("Creator").Preload("Updator"). + Model(&model.PolicyTemplate{}). Where("type = 'tks'"), &policyTemplates) if res.Error != nil { return nil, res.Error } - for _, policyTemplate := range policyTemplates { - var policyTemplateVersion model.PolicyTemplateSupportedVersion - res = r.db. - Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). - First(&policyTemplateVersion) - - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info(ctx, "Not found policyTemplate version") - } else { - log.Error(ctx, res.Error) - } - } - - outPolicyTemplate := r.reflectPolicyTemplate(ctx, policyTemplate, policyTemplateVersion) - out = append(out, outPolicyTemplate) - } - return out, nil -} - -func (r *PolicyTemplateRepository) reflectPolicyTemplate(ctx context.Context, policyTemplate model.PolicyTemplate, policyTemplateVersion model.PolicyTemplateSupportedVersion) (out model.PolicyTemplate) { - if err := serializer.Map(ctx, policyTemplate.Model, &out); err != nil { - log.Error(ctx, err) - } - if err := serializer.Map(ctx, policyTemplate, &out); err != nil { - log.Error(ctx, err) - } - out.TemplateName = policyTemplate.Name - out.ID = policyTemplate.ID - - var schemas []domain.ParameterDef - - if len(policyTemplateVersion.ParameterSchema) > 0 { - if err := json.Unmarshal([]byte(policyTemplateVersion.ParameterSchema), &schemas); err != nil { - log.Error(ctx, err) - } else { - out.ParametersSchema = schemas - } - } - - // ktkfree : 이 부분은 재 구현 부탁 드립니다. - // PermittedOrganizations 필드가 model 과 response 를 위한 객체의 형이 다르네요. - // 아울러 reflect 는 repository 가 아닌 usecase 에 표현되는게 더 좋겠습니다. - - /* - out.PermittedOrganizations = make([]domain.PermittedOrganization, len(policyTemplate.PermittedOrganizations)) - for i, org := range policyTemplate.PermittedOrganizations { - out.PermittedOrganizations[i] = domain.PermittedOrganization{ - OrganizationId: org.ID, - OrganizationName: org.Name, - Permitted: true, - } - } - */ - - out.Rego = policyTemplateVersion.Rego - out.Libs = strings.Split(policyTemplateVersion.Libs, "---\n") - - return + return policyTemplates, nil } func (r *PolicyTemplateRepository) ExistsBy(ctx context.Context, key string, value interface{}) (exists bool, err error) { query := fmt.Sprintf("%s = ?", key) var policyTemplate model.PolicyTemplate - res := r.db.Where(query, value). + res := r.db.WithContext(ctx).Where(query, value). First(&policyTemplate) if res.Error != nil { @@ -250,7 +125,7 @@ func (r *PolicyTemplateRepository) ExistsBy(ctx context.Context, key string, val } func (r *PolicyTemplateRepository) ExistByName(ctx context.Context, policyTemplateName string) (exist bool, err error) { - return r.ExistsBy(ctx, "name", policyTemplateName) + return r.ExistsBy(ctx, "template_name", policyTemplateName) } func (r *PolicyTemplateRepository) ExistByKind(ctx context.Context, policyTemplateKind string) (exist bool, err error) { @@ -265,12 +140,19 @@ func (r *PolicyTemplateRepository) GetBy(ctx context.Context, key string, value query := fmt.Sprintf("%s = ?", key) var policyTemplate model.PolicyTemplate - res := r.db.Preload(clause.Associations).Where(query, value). + // res := r.db.WithContext(ctx).Preload(clause.Associations).Where(query, value). + // First(&policyTemplate) + res := r.db.WithContext(ctx). + Preload("SupportedVersions", func(db *gorm.DB) *gorm.DB { + // 최신 버전만 + return db.Order("policy_template_supported_versions.version DESC").Limit(1) + }). + Preload("PermittedOrganizations").Preload("Creator").Preload("Updator"). + Where(query, value). First(&policyTemplate) - if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Infof(ctx, "Not found policyTemplate %s='%v'", key, value) + log.Info(ctx, "Not found policyTemplate id") return nil, nil } else { log.Error(ctx, res.Error) @@ -278,70 +160,20 @@ func (r *PolicyTemplateRepository) GetBy(ctx context.Context, key string, value } } - var policyTemplateVersion model.PolicyTemplateSupportedVersion - res = r.db.Limit(1). - Where("policy_template_id = ? and version = ?", policyTemplate.ID, policyTemplate.Version). - First(&policyTemplateVersion) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info(ctx, "Not found policyTemplate version") - return nil, nil - } else { - log.Error(ctx, res.Error) - return nil, res.Error - } + if len(policyTemplate.SupportedVersions) == 0 { + log.Info(ctx, "Not found policyTemplate version") + return nil, nil } - fmt.Printf("BBBB %+v\n", policyTemplate.PermittedOrganizations) - - result := r.reflectPolicyTemplate(ctx, policyTemplate, policyTemplateVersion) - fmt.Printf("2222BBBB %+v\n", result.PermittedOrganizations) - - return &result, nil + return &policyTemplate, nil } func (r *PolicyTemplateRepository) GetByID(ctx context.Context, policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) { return r.GetBy(ctx, "id", policyTemplateId) - - // var policyTemplate PolicyTemplate - // res := r.db.Preload(clause.Associations).Where("id = ?", policyTemplateId). - // First(&policyTemplate) - - // if res.Error != nil { - // if errors.Is(res.Error, gorm.ErrRecordNotFound) { - // log.Info("Not found policyTemplate id") - // return nil, nil - // } else { - // log.Error(res.Error) - // return nil, res.Error - // } - // } - - // result := r.reflect(policyTemplate) - - // return &result, nil } func (r *PolicyTemplateRepository) GetByName(ctx context.Context, policyTemplateName string) (out *model.PolicyTemplate, err error) { return r.GetBy(ctx, "name", policyTemplateName) - - // var policyTemplate PolicyTemplate - // res := r.db.Limit(1). - // Where("name = ?", policyTemplateName). - // First(&policyTemplate) - // if res.Error != nil { - // if errors.Is(res.Error, gorm.ErrRecordNotFound) { - // log.Info("Not found policyTemplate name") - // return nil, nil - // } else { - // log.Error(res.Error) - // return nil, res.Error - // } - // } - - // result := r.reflect(policyTemplate) - - // return &result, nil } func (r *PolicyTemplateRepository) GetByKind(ctx context.Context, policyTemplateKind string) (out *model.PolicyTemplate, err error) { @@ -349,7 +181,7 @@ func (r *PolicyTemplateRepository) GetByKind(ctx context.Context, policyTemplate } func (r *PolicyTemplateRepository) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) { - return r.db.Transaction(func(tx *gorm.DB) error { + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { if err := tx.Where("policy_template_id = ?", policyTemplateId).Delete(&model.PolicyTemplateSupportedVersion{}).Error; err != nil { return err } @@ -368,11 +200,11 @@ func (r *PolicyTemplateRepository) Delete(ctx context.Context, policyTemplateId func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { var supportedVersions []model.PolicyTemplateSupportedVersion - res := r.db.Where("policy_template_id = ?", policyTemplateId).Find(&supportedVersions) + res := r.db.WithContext(ctx).Where("policy_template_id = ?", policyTemplateId).Find(&supportedVersions) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info(ctx, "Not found policyTemplate kind") + log.Info(ctx, "Not found policyTemplate Id") return nil, nil } else { log.Error(ctx, res.Error) @@ -394,22 +226,10 @@ func (r *PolicyTemplateRepository) ListPolicyTemplateVersions(ctx context.Contex } func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { - var policyTemplateVersion model.PolicyTemplateSupportedVersion - res := r.db. - Where("policy_template_id = ? and version = ?", policyTemplateId, version). - First(&policyTemplateVersion) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info(ctx, "Not found policyTemplate version") - return nil, nil - } else { - log.Error(ctx, res.Error) - return nil, res.Error - } - } - var policyTemplate model.PolicyTemplate - res = r.db. + + res := r.db.WithContext(ctx).Preload("SupportedVersions", "version=?", version). + Preload("PermittedOrganizations").Preload("Creator").Preload("Updator"). Where("id = ?", policyTemplateId). First(&policyTemplate) if res.Error != nil { @@ -422,51 +242,51 @@ func (r *PolicyTemplateRepository) GetPolicyTemplateVersion(ctx context.Context, } } - result := r.reflectPolicyTemplate(ctx, policyTemplate, policyTemplateVersion) + if len(policyTemplate.SupportedVersions) == 0 { + log.Info(ctx, "Not found policyTemplate version") + return nil, nil + } - return &result, nil + return &policyTemplate, nil } func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) { - var policyTemplate model.PolicyTemplate - res := r.db.Select("version").First(&policyTemplate) + // TODO: Operator에 현재 버전 사용중인 정책이 있는지 체크 필요 - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info(ctx, "Not found policyTemplate id") - return nil - } else { - log.Error(ctx, res.Error) + var policyTemplateVersion model.PolicyTemplateSupportedVersion + + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + var count int64 + res := r.db.WithContext(ctx).Model(&policyTemplateVersion).Where("policy_template_id = ?", policyTemplateId).Count(&count) + if res.Error != nil { return res.Error } - } - // 현재 버전이 템플릿에서 최신 버전으로 사용 중이면 삭제 금지 - if policyTemplate.Version == version { - return fmt.Errorf("version '%s' is currently in use", version) - } - - // TODO: Operator에 현재 버전 사용중인 정책이 있는지 체크 필요 + // 마지막으로 존재하는 버전은 삭제할 수 없으므로 해당 id의 버전 카운트가 2 이상이어야 함 + if count < 2 { + return errors.New("Unable to delete last single version") + } - var policyTemplateVersion model.PolicyTemplateSupportedVersion - res = r.db.Where("policy_template_id = ? and version = ?", policyTemplateId, version). - Delete(&policyTemplateVersion) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Info(ctx, "Not found policyTemplate version") - return nil - } else { - log.Error(ctx, res.Error) - return res.Error + // relaton을 unscoped로 삭제하지 않으면 동일한 키로 다시 생성할 때 키가 같은 레코드가 deleted 상태로 존재하므로 unscoped delete + res = r.db.WithContext(ctx).Unscoped().Where("policy_template_id = ? and version = ?", policyTemplateId, version). + Delete(&policyTemplateVersion) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info(ctx, "Not found policyTemplate version") + return nil + } else { + log.Error(ctx, res.Error) + return res.Error + } } - } - return nil + return nil + }) } func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { var policyTemplateVersion model.PolicyTemplateSupportedVersion - res := r.db.Limit(1). + res := r.db.WithContext(ctx).Limit(1). Where("policy_template_id = ? and version = ?", policyTemplateId, version). First(&policyTemplateVersion) @@ -485,7 +305,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Conte libsString := "" if len(libs) > 0 { - libsString = strings.Join(libs, "---\n") + libsString = strings.Join(libs, model.FILE_DELIMETER) } jsonBytes, err := json.Marshal(schema) @@ -506,19 +326,7 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Conte ParameterSchema: string(jsonBytes), } - err = r.db.Transaction(func(tx *gorm.DB) error { - if err := tx.Create(newPolicyTemplateVersion).Error; err != nil { - return err - } - - if err := tx.Model(&model.PolicyTemplate{}).Where("id = ?", policyTemplateId).Update("version", newVersion).Error; err != nil { - return err - } - - return nil - }) - - if err != nil { + if err := r.db.WithContext(ctx).Create(newPolicyTemplateVersion).Error; err != nil { return "", err } diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index d6e42574..5bd18577 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + mapset "github.com/deckarep/golang-set/v2" "github.com/google/uuid" "github.com/open-policy-agent/opa/ast" "github.com/openinfradev/tks-api/internal/middleware/auth/request" @@ -13,13 +14,13 @@ import ( "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" ) type IPolicyTemplateUsecase interface { - Create(ctx context.Context, policyTemplate model.PolicyTemplate) (policyTemplateId string, err error) + Create(ctx context.Context, policyTemplate model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) - Update(ctx context.Context, policyTemplateId uuid.UUID, update domain.UpdatePolicyTemplateRequest) (err error) + Update(ctx context.Context, policyTemplateId uuid.UUID, templateName *string, description *string, + severity *string, deorecated *bool, permittedOrganizationIds *[]string) (err error) Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) @@ -30,6 +31,11 @@ type IPolicyTemplateUsecase interface { CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) + + UpdatePermittedOrganizations(ctx context.Context, + policyTemplate *model.PolicyTemplate, out *domain.PolicyTemplateResponse) error + UpdatePermittedOrganizationsForList(ctx context.Context, + policyTemplates *[]model.PolicyTemplate, outs *[]domain.PolicyTemplateResponse) error } type PolicyTemplateUsecase struct { @@ -46,38 +52,46 @@ func NewPolicyTemplateUsecase(r repository.Repository) IPolicyTemplateUsecase { } } -func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId string, err error) { +func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { user, ok := request.UserFrom(ctx) if !ok { - return "", httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") + return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } exists, err := u.repo.ExistByName(ctx, dto.TemplateName) if err == nil && exists { - return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") } exists, err = u.repo.ExistByKind(ctx, dto.Kind) if err == nil && exists { - return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_KIND", "policy template kind already exists") + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_KIND", "policy template kind already exists") } - for _, organizationId := range dto.PermittedOrganizationIds { - _, err = u.organizationRepo.Get(ctx, organizationId) + dto.PermittedOrganizations = make([]model.Organization, len(dto.PermittedOrganizationIds)) + for i, organizationId := range dto.PermittedOrganizationIds { + + organization, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { - return "", httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } + dto.PermittedOrganizations[i] = organization } userId := user.GetUserId() dto.CreatorId = &userId + + // 시스템 템플릿 속성 설정 + dto.Type = "tks" + dto.Mandatory = false + id, err := u.repo.Create(ctx, dto) if err != nil { - return "", err + return uuid.Nil, err } - return id.String(), nil + return id, nil } func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) { @@ -87,37 +101,76 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagina return nil, err } + return policyTemplates, nil +} + +func (u *PolicyTemplateUsecase) UpdatePermittedOrganizations(ctx context.Context, + policyTemplate *model.PolicyTemplate, out *domain.PolicyTemplateResponse) error { organizations, err := u.organizationRepo.Fetch(ctx, nil) - if err == nil { - for i, policyTemplate := range policyTemplates { - permittedOrgIdSet := u.getPermittedOrganiationIdSet(ctx, &policyTemplate) - u.updatePermittedOrganizations(ctx, organizations, permittedOrgIdSet, &policyTemplates[i]) - } + if err != nil { + return err } - return policyTemplates, nil + u.updatePermittedOrganizations(ctx, organizations, policyTemplate, out) + return nil } -func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { - policyTemplate, err := u.repo.GetByID(ctx, policyTemplateID) +func (u *PolicyTemplateUsecase) UpdatePermittedOrganizationsForList(ctx context.Context, + policyTemplates *[]model.PolicyTemplate, outs *[]domain.PolicyTemplateResponse) error { + + organizations, err := u.organizationRepo.Fetch(ctx, nil) if err != nil { - return nil, err + return err } - permittedOrgIdSet := u.getPermittedOrganiationIdSet(ctx, policyTemplate) + results := *outs - organizations, err := u.organizationRepo.Fetch(ctx, nil) - if err == nil { - u.updatePermittedOrganizations(ctx, organizations, permittedOrgIdSet, policyTemplate) + for i, policyTemplate := range *policyTemplates { + u.updatePermittedOrganizations(ctx, organizations, &policyTemplate, &results[i]) + } + + return nil +} + +// 모든 조직 목록에 대해 허용 여부 업데이트 +func (u *PolicyTemplateUsecase) updatePermittedOrganizations(ctx context.Context, organizations *[]model.Organization, policyTemplate *model.PolicyTemplate, out *domain.PolicyTemplateResponse) { + if policyTemplate == nil || organizations == nil || out == nil { + return + } + + // 정책 템플릿에서 허용된 조직 목록이 없다는 것은 모든 조직이 사용할 수 있음을 의미함 + allPermitted := len(policyTemplate.PermittedOrganizationIds) == 0 + + // 허용된 조직 포함 여부를 효율적으로 처리하기 위해 ID 리스트를 셋으로 변환 + permittedOrganizationIdSet := mapset.NewSet(policyTemplate.PermittedOrganizationIds...) + + out.PermittedOrganizations = make([]domain.PermittedOrganization, len(*organizations)) + + for i, organization := range *organizations { + permitted := allPermitted || permittedOrganizationIdSet.ContainsOne(organization.ID) + + out.PermittedOrganizations[i] = domain.PermittedOrganization{ + OrganizationId: organization.ID, + OrganizationName: organization.Name, + Permitted: permitted, + } + } +} + +func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { + policyTemplate, err := u.repo.GetByID(ctx, policyTemplateID) + + if err != nil { + return nil, err } return policyTemplate, nil } -func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uuid.UUID, update domain.UpdatePolicyTemplateRequest) (err error) { +func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uuid.UUID, templateName *string, description *string, severity *string, deprecated *bool, permittedOrganizationIds *[]string) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") @@ -128,33 +181,51 @@ func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uui return httpErrors.NewNotFoundError(err, "PT_FAILED_FETCH_POLICY_TEMPLATE", "") } - exists, err := u.repo.ExistByName(ctx, *update.TemplateName) - if err == nil && exists { - return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") + updateMap := make(map[string]interface{}) + + if templateName != nil { + exists, err := u.repo.ExistByName(ctx, *templateName) + if err == nil && exists { + return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") + } + updateMap["name"] = templateName + } + + if description != nil { + updateMap["description"] = description + } + + if deprecated != nil { + updateMap["deprecated"] = deprecated + } + + if severity != nil { + updateMap["severity"] = severity } - if update.PermittedOrganizationIds != nil { - for _, organizationId := range *update.PermittedOrganizationIds { - _, err = u.organizationRepo.Get(ctx, organizationId) + var newPermittedOrganizations *[]model.Organization = nil + + if permittedOrganizationIds != nil { + permittedOrganizations := make([]model.Organization, len(*permittedOrganizationIds)) + + for i, organizationId := range *permittedOrganizationIds { + organization, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } + + permittedOrganizations[i] = organization } + newPermittedOrganizations = &permittedOrganizations + } else if len(updateMap) == 0 { + // 허용된 조직도 필드 속성도 업데이트되지 않았으므로 아무것도 업데이트할 것이 없음 + return nil } updatorId := user.GetUserId() - dto := domain.UpdatePolicyTemplateUpdate{ - ID: policyTemplateId, - Type: "tks", - UpdatorId: updatorId, - TemplateName: update.TemplateName, - Description: update.Description, - Severity: update.Severity, - Deprecated: update.Deprecated, - PermittedOrganizationIds: update.PermittedOrganizationIds, - } + updateMap["updator_id"] = updatorId - err = u.repo.Update(ctx, dto) + err = u.repo.Update(ctx, policyTemplateId, updateMap, newPermittedOrganizations) if err != nil { return err } @@ -181,57 +252,9 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, po return nil, err } - permittedOrgIdSet := u.getPermittedOrganiationIdSet(ctx, policyTemplate) - - organizations, err := u.organizationRepo.Fetch(ctx, nil) - if err == nil { - u.updatePermittedOrganizations(ctx, organizations, permittedOrgIdSet, policyTemplate) - } - return policyTemplate, nil } -func (*PolicyTemplateUsecase) updatePermittedOrganizations(ctx context.Context, organizations *[]model.Organization, permittedOrgIdSet map[string]string, policyTemplate *model.PolicyTemplate) { - // 허용리스트가 비어있으면 모든 Org에 대해서 허용 - permitted := len(permittedOrgIdSet) == 0 - - log.Info(ctx, "CHECK HERE ", permitted) - - // TODO: 이부분 확인 부탁 드립니다. - //for _, organization := range *organizations { - // _, ok := permittedOrgIdSet[organization.ID] - // - // if !ok { - // policyTemplate.PermittedOrganizations = append( - // policyTemplate.PermittedOrganizations, - // - // // ktkfree : 역시 이부분 확인 부탁 드립니다. - // /* - // domain.PermittedOrganization{ - // OrganizationId: organization.ID, - // OrganizationName: organization.Name, - // Permitted: permitted, - // } - // */ - // ) - // } - //} -} - -func (*PolicyTemplateUsecase) getPermittedOrganiationIdSet(ctx context.Context, policyTemplate *model.PolicyTemplate) map[string]string { - permittedOrgIdSet := make(map[string]string) - - for _, permittedOrg := range policyTemplate.PermittedOrganizations { - // Set 처리를 위해서 키만 사용, 값은 아무거나 - - // ktkfree : 이부분 확인 부탁 드립니다. - // - //permittedOrgIdSet[permittedOrg.OrganizationId] = "1" - log.Info(ctx, "CHECK HERE ", permittedOrg) - } - return permittedOrgIdSet -} - func (u *PolicyTemplateUsecase) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { return u.repo.ListPolicyTemplateVersions(ctx, policyTemplateId) } diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 5faa8640..ea9998ba 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -6,19 +6,8 @@ import ( "github.com/google/uuid" ) -type PolicyTemplateId string - -func (pp PolicyTemplateId) String() string { - return string(pp) -} - -func (pp PolicyTemplateId) Validate() bool { - // return helper.ValidatePolicyTemplateId(pp.String()) - return true -} - type CommonPolicyTemplate struct { - ID PolicyTemplateId `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` Type string `json:"type" enums:"tks,organization" example:"tks"` Creator SimpleUserResponse `json:"creator,omitempty"` Updator SimpleUserResponse `json:"updator,omitempty"` @@ -53,7 +42,7 @@ type PermittedOrganization struct { } type PolicyTemplateResponse struct { - ID PolicyTemplateId `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` Type string `json:"type" enums:"tks,organization" example:"tks"` Creator SimpleUserResponse `json:"creator"` Updator SimpleUserResponse `json:"updator"` @@ -144,11 +133,11 @@ type CreateOrganizationPolicyTemplateRequest struct { } type CreatePolicyTemplateReponse struct { - ID PolicyTemplateId `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` } type CreateOrganizationPolicyTemplateReponse struct { - ID PolicyTemplateId `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` } type UpdateCommmonPolicyTemplateRequest struct { From 572b4bb178568b0ec11bad66b442e14dc967b37b Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 19 Mar 2024 17:30:33 +0900 Subject: [PATCH 139/502] =?UTF-8?q?Lint=20=EC=97=90=EB=9F=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/model/policy-template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index 01aa3383..c5e2f433 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -82,7 +82,7 @@ func (pt *PolicyTemplate) AfterFind(tx *gorm.DB) (err error) { pt.Libs = strings.Split(supportedVersion.ParameterSchema, FILE_DELIMETER) // 마찬가지로 에러 무시 - json.Unmarshal([]byte(supportedVersion.ParameterSchema), &pt.ParametersSchema) + _ = json.Unmarshal([]byte(supportedVersion.ParameterSchema), &pt.ParametersSchema) } pt.PermittedOrganizationIds = make([]string, len(pt.PermittedOrganizations)) From 1b037f0cb497fe65ff068303b936cba90b436772 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 19 Mar 2024 18:24:52 +0900 Subject: [PATCH 140/502] bug fix. --- internal/model/permission.go | 82 ++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/internal/model/permission.go b/internal/model/permission.go index 9be78e6d..5025d766 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -70,10 +70,6 @@ func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func( return edgePermissions } -func SetRoleIDToPermission(roleID string, permission *Permission) { - permission.RoleID = helper.StringP(roleID) -} - func endpointObjects(eps ...api.Endpoint) []*Endpoint { var result []*Endpoint for _, ep := range eps { @@ -87,12 +83,15 @@ func endpointObjects(eps ...api.Endpoint) []*Endpoint { func newDashboard() *Permission { dashboard := &Permission{ + ID: uuid.New(), Name: string(DashBoardPermission), Children: []*Permission{ { + ID: uuid.New(), Name: "대시보드", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -105,21 +104,26 @@ func newDashboard() *Permission { }, }, { + ID: uuid.New(), Name: "대시보드 설정", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), }, @@ -133,9 +137,11 @@ func newDashboard() *Permission { func newStack() *Permission { stack := &Permission{ + ID: uuid.New(), Name: string(StackPermission), Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -150,6 +156,7 @@ func newStack() *Permission { ), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -158,6 +165,7 @@ func newStack() *Permission { ), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -165,6 +173,7 @@ func newStack() *Permission { ), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -179,24 +188,30 @@ func newStack() *Permission { func newSecurityPolicy() *Permission { security_policy := &Permission{ + ID: uuid.New(), Name: string(SecurityPolicyPermission), Children: []*Permission{ { + ID: uuid.New(), Name: "보안/정책", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), }, @@ -210,12 +225,15 @@ func newSecurityPolicy() *Permission { func newProjectManagement() *Permission { projectManagement := &Permission{ + ID: uuid.New(), Name: string(ProjectManagementPermission), Children: []*Permission{ { + ID: uuid.New(), Name: "프로젝트", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -224,6 +242,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -233,9 +252,11 @@ func newProjectManagement() *Permission { }, }, { + ID: uuid.New(), Name: "앱 서빙", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -248,6 +269,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "빌드", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -261,6 +283,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "배포", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -274,6 +297,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -283,9 +307,11 @@ func newProjectManagement() *Permission { }, }, { + ID: uuid.New(), Name: "설정-일반", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -297,6 +323,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -304,6 +331,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -313,9 +341,11 @@ func newProjectManagement() *Permission { }, }, { + ID: uuid.New(), Name: "설정-멤버", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -326,6 +356,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -333,6 +364,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -340,6 +372,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -349,9 +382,11 @@ func newProjectManagement() *Permission { }, }, { + ID: uuid.New(), Name: "설정-네임스페이스", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -360,6 +395,7 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -367,11 +403,13 @@ func newProjectManagement() *Permission { ), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects(), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( @@ -388,21 +426,26 @@ func newProjectManagement() *Permission { func newNotification() *Permission { notification := &Permission{ + ID: uuid.New(), Name: string(NotificationPermission), Children: []*Permission{ { + ID: uuid.New(), Name: "시스템 경고", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, }, }, { + ID: uuid.New(), Name: "보안/정책 감사로그", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, @@ -416,130 +459,161 @@ func newNotification() *Permission { func newConfiguration() *Permission { configuration := &Permission{ + ID: uuid.New(), Name: string(ConfigurationPermission), Children: []*Permission{ { + ID: uuid.New(), Name: "일반", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), }, }, }, { + ID: uuid.New(), Name: "클라우드 계정", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), }, }, }, { + ID: uuid.New(), Name: "스택 템플릿", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, }, }, { + ID: uuid.New(), Name: "프로젝트 관리", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), }, }, }, { + ID: uuid.New(), Name: "사용자", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), }, }, }, { + ID: uuid.New(), Name: "사용자 권한 관리", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), }, }, }, { + ID: uuid.New(), Name: "알림 설정", Children: []*Permission{ { + ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), }, { + ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), }, From 4632519d4444cb92acfc032861d8b1c5d099207b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 19 Mar 2024 18:52:48 +0900 Subject: [PATCH 141/502] feature. implemntation organization templates --- api/swagger/docs.go | 806 ++++++++++++++++-- api/swagger/swagger.json | 806 ++++++++++++++++-- api/swagger/swagger.yaml | 410 ++++++++- internal/database/database.go | 49 +- internal/delivery/api/endpoint.go | 23 +- .../delivery/api/generated_endpoints.go.go | 96 ++- internal/delivery/http/organization.go | 14 + internal/delivery/http/stack.go | 1 - .../delivery/http/system-notification-rule.go | 245 ++++++ .../http/system-notification-template.go | 221 +++++ internal/model/organization.go | 34 +- internal/model/stack-template.go | 2 +- internal/model/system-notification-rule.go | 41 + .../model/system-notification-template.go | 30 + internal/pagination/pagination.go | 19 +- internal/repository/endpoint.go | 10 +- internal/repository/organization.go | 15 + internal/repository/repository.go | 32 +- .../repository/system-notification-rule.go | 122 +++ .../system-notification-template.go | 118 +++ internal/route/route.go | 84 +- internal/usecase/dashboard.go | 6 +- internal/usecase/organization.go | 41 +- internal/usecase/stack-template.go | 4 +- internal/usecase/system-notification-rule.go | 107 +++ .../usecase/system-notification-template.go | 141 +++ internal/usecase/usecase.go | 34 +- pkg/domain/alert.go | 137 +++ pkg/domain/organization.go | 25 +- pkg/domain/system-notification-rule.go | 47 + pkg/domain/system-notification-template.go | 61 ++ pkg/httpErrors/errorCode.go | 51 +- 32 files changed, 3443 insertions(+), 389 deletions(-) create mode 100644 internal/delivery/http/system-notification-rule.go create mode 100644 internal/delivery/http/system-notification-template.go create mode 100644 internal/model/system-notification-rule.go create mode 100644 internal/model/system-notification-template.go create mode 100644 internal/repository/system-notification-rule.go create mode 100644 internal/repository/system-notification-template.go create mode 100644 internal/usecase/system-notification-rule.go create mode 100644 internal/usecase/system-notification-template.go create mode 100644 pkg/domain/alert.go create mode 100644 pkg/domain/system-notification-rule.go create mode 100644 pkg/domain/system-notification-template.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 457bdecb..56497339 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1268,6 +1268,167 @@ const docTemplate = `{ } } }, + "/admin/system-notification-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotificationTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Get SystemNotificationTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create alert template. ADMIN ONLY", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Create alert template. ADMIN ONLY", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse" + } + } + } + } + }, + "/admin/system-notification-templates/{systemNotificationTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Get SystemNotificationTemplate", + "parameters": [ + { + "type": "string", + "description": "systemNotificationTemplateId", + "name": "systemNotificationTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update SystemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Update SystemNotificationTemplate", + "parameters": [ + { + "description": "Update alert template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/app-groups": { "get": { "security": [ @@ -5669,12 +5830,6 @@ const docTemplate = `{ "description": "sortOrder", "name": "sortOrder", "in": "query" - }, - { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", - "in": "query" } ], "responses": { @@ -6078,14 +6233,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/system-notifications": { + "/organizations/{organizationId}/system-notification-rules": { "get": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotifications", + "description": "Get SystemNotificationRules", "consumes": [ "application/json" ], @@ -6093,17 +6248,10 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Get SystemNotifications", + "summary": "Get SystemNotificationRules", "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, { "type": "string", "description": "pageSize", @@ -6143,20 +6291,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse" } } } - } - }, - "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotification", + "description": "Create SystemNotificationRule", "consumes": [ "application/json" ], @@ -6164,41 +6310,38 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Get SystemNotification", + "summary": "Create SystemNotificationRule", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", - "in": "path", - "required": true + "description": "create stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse" } } } - }, - "put": { + } + }, + "/organizations/{organizationId}/system-notification-rules/name/{name}/existence": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update SystemNotification", + "description": "Check name for systemNotificationRule", "consumes": [ "application/json" ], @@ -6206,40 +6349,36 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Update SystemNotification", + "summary": "Check name for systemNotificationRule", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", + "description": "name", + "name": "name", "in": "path", "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" - } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse" + } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete SystemNotification", + "description": "Get SystemNotificationRule", "consumes": [ "application/json" ], @@ -6247,40 +6386,34 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Delete SystemNotification", + "summary": "Get SystemNotificationRule", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse" + } } } - } - }, - "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { - "post": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Create systemNotification action", + "description": "Update SystemNotificationRule", "consumes": [ "application/json" ], @@ -6288,16 +6421,18 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Create systemNotification action", + "summary": "Update SystemNotificationRule", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "description": "Update systemNotificationRule request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest" + } } ], "responses": { @@ -6305,16 +6440,277 @@ const docTemplate = `{ "description": "OK" } } - } - }, - "/organizations/{organizationId}/users": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get user list", + "description": "Delete SystemNotificationRule", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationRules" + ], + "summary": "Delete SystemNotificationRule", + "parameters": [ + { + "type": "string", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/system-notifications": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotifications", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Get SystemNotifications", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Get SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Update SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Delete SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create systemNotification action", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Create systemNotification action", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/users": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user list", "consumes": [ "application/json" ], @@ -7456,6 +7852,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { @@ -8297,6 +8701,36 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest": { "type": "object", "required": [ @@ -9083,6 +9517,50 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse": { + "type": "object", + "properties": { + "systemNotificationRule": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "systemNotificationRules": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse": { + "type": "object", + "properties": { + "systemNotificationTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "systemNotificationTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse": { "type": "object", "properties": { @@ -9379,6 +9857,25 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { + "type": "object", + "required": [ + "key", + "order", + "value" + ], + "properties": { + "key": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { @@ -9421,6 +9918,12 @@ const docTemplate = `{ "statusDesc": { "type": "string" }, + "systemNotificationTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" + } + }, "updatedAt": { "type": "string" } @@ -10168,6 +10671,26 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse": { "type": "object", "properties": { @@ -10509,6 +11032,76 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse": { + "type": "object", + "required": [ + "metricQuery" + ], + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "metricParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + } + }, + "metricQuery": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" + } + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.Unit": { "type": "object", "properties": { @@ -10887,6 +11480,45 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest": { + "type": "object", + "required": [ + "metricQuery", + "name", + "organizationIds" + ], + "properties": { + "description": { + "type": "string" + }, + "metricParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + } + }, + "metricQuery": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 1194bfaf..77d56851 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1262,6 +1262,167 @@ } } }, + "/admin/system-notification-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotificationTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Get SystemNotificationTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create alert template. ADMIN ONLY", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Create alert template. ADMIN ONLY", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse" + } + } + } + } + }, + "/admin/system-notification-templates/{systemNotificationTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Get SystemNotificationTemplate", + "parameters": [ + { + "type": "string", + "description": "systemNotificationTemplateId", + "name": "systemNotificationTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update SystemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Update SystemNotificationTemplate", + "parameters": [ + { + "description": "Update alert template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/app-groups": { "get": { "security": [ @@ -5663,12 +5824,6 @@ "description": "sortOrder", "name": "sortOrder", "in": "query" - }, - { - "type": "string", - "description": "combinedFilter", - "name": "combinedFilter", - "in": "query" } ], "responses": { @@ -6072,14 +6227,14 @@ } } }, - "/organizations/{organizationId}/system-notifications": { + "/organizations/{organizationId}/system-notification-rules": { "get": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotifications", + "description": "Get SystemNotificationRules", "consumes": [ "application/json" ], @@ -6087,17 +6242,10 @@ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Get SystemNotifications", + "summary": "Get SystemNotificationRules", "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, { "type": "string", "description": "pageSize", @@ -6137,20 +6285,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse" } } } - } - }, - "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotification", + "description": "Create SystemNotificationRule", "consumes": [ "application/json" ], @@ -6158,41 +6304,38 @@ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Get SystemNotification", + "summary": "Create SystemNotificationRule", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", - "in": "path", - "required": true + "description": "create stack template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse" } } } - }, - "put": { + } + }, + "/organizations/{organizationId}/system-notification-rules/name/{name}/existence": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update SystemNotification", + "description": "Check name for systemNotificationRule", "consumes": [ "application/json" ], @@ -6200,40 +6343,36 @@ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Update SystemNotification", + "summary": "Check name for systemNotificationRule", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", + "description": "name", + "name": "name", "in": "path", "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" - } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse" + } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete SystemNotification", + "description": "Get SystemNotificationRule", "consumes": [ "application/json" ], @@ -6241,40 +6380,34 @@ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Delete SystemNotification", + "summary": "Get SystemNotificationRule", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse" + } } } - } - }, - "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { - "post": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Create systemNotification action", + "description": "Update SystemNotificationRule", "consumes": [ "application/json" ], @@ -6282,16 +6415,18 @@ "application/json" ], "tags": [ - "SystemNotifications" + "SystemNotificationRules" ], - "summary": "Create systemNotification action", + "summary": "Update SystemNotificationRule", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "description": "Update systemNotificationRule request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest" + } } ], "responses": { @@ -6299,16 +6434,277 @@ "description": "OK" } } - } - }, - "/organizations/{organizationId}/users": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get user list", + "description": "Delete SystemNotificationRule", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationRules" + ], + "summary": "Delete SystemNotificationRule", + "parameters": [ + { + "type": "string", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/system-notifications": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotifications", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Get SystemNotifications", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Get SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Update SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Delete SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create systemNotification action", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Create systemNotification action", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/users": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user list", "consumes": [ "application/json" ], @@ -7450,6 +7846,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse": { "type": "object", "properties": { @@ -8291,6 +8695,36 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest": { "type": "object", "required": [ @@ -9077,6 +9511,50 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse": { + "type": "object", + "properties": { + "systemNotificationRule": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "systemNotificationRules": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse": { + "type": "object", + "properties": { + "systemNotificationTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "systemNotificationTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse": { "type": "object", "properties": { @@ -9373,6 +9851,25 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { + "type": "object", + "required": [ + "key", + "order", + "value" + ], + "properties": { + "key": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { @@ -9415,6 +9912,12 @@ "statusDesc": { "type": "string" }, + "systemNotificationTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" + } + }, "updatedAt": { "type": "string" } @@ -10162,6 +10665,26 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse": { "type": "object", "properties": { @@ -10503,6 +11026,76 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse": { + "type": "object", + "required": [ + "metricQuery" + ], + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "metricParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + } + }, + "metricQuery": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" + } + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.Unit": { "type": "object", "properties": { @@ -10881,6 +11474,45 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest": { + "type": "object", + "required": [ + "metricQuery", + "name", + "organizationIds" + ], + "properties": { + "description": { + "type": "string" + }, + "metricParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + } + }, + "metricQuery": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index b4b647d7..d89bcc96 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -470,6 +470,11 @@ definitions: existed: type: boolean type: object + github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse: + properties: + existed: + type: boolean + type: object github_com_openinfradev_tks-api_pkg_domain.CloudAccountResponse: properties: awsAccountId: @@ -1042,6 +1047,25 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest: + properties: + description: + type: string + name: + type: string + required: + - name + type: object + github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse: + properties: + id: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse: + properties: + id: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest: properties: description: @@ -1554,6 +1578,34 @@ definitions: systemNotification: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse: + properties: + systemNotificationRule: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse' + type: object + github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + systemNotificationRules: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse: + properties: + systemNotificationTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse' + type: object + github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + systemNotificationTemplates: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse: properties: pagination: @@ -1748,6 +1800,19 @@ definitions: type: array type: object type: object + github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse: + properties: + key: + type: string + order: + type: integer + value: + type: string + required: + - key + - order + - value + type: object github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse: properties: admin: @@ -1776,6 +1841,10 @@ definitions: type: string statusDesc: type: string + systemNotificationTemplates: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse' + type: array updatedAt: type: string type: object @@ -2275,6 +2344,19 @@ definitions: type: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse: + properties: + createdAt: + type: string + description: + type: string + id: + type: string + name: + type: string + updatedAt: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse: properties: accountId: @@ -2501,6 +2583,52 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationRuleResponse: + properties: + createdAt: + type: string + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + description: + type: string + id: + type: string + name: + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationTemplateResponse: + properties: + createdAt: + type: string + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + description: + type: string + id: + type: string + metricParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse' + type: array + metricQuery: + type: string + name: + type: string + organizations: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse' + type: array + updatedAt: + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + required: + - metricQuery + type: object github_com_openinfradev_tks-api_pkg_domain.Unit: properties: data: @@ -2751,6 +2879,32 @@ definitions: description: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest: + properties: + description: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest: + properties: + description: + type: string + metricParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse' + type: array + metricQuery: + type: string + name: + type: string + organizationIds: + items: + type: string + type: array + required: + - metricQuery + - name + - organizationIds + type: object github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest: properties: description: @@ -3732,6 +3886,107 @@ paths: summary: Get GetStackTemplateServices tags: - StackTemplates + /admin/system-notification-templates: + get: + consumes: + - application/json + description: Get SystemNotificationTemplates + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse' + security: + - JWT: [] + summary: Get SystemNotificationTemplates + tags: + - SystemNotificationTemplates + post: + consumes: + - application/json + description: Create alert template. ADMIN ONLY + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse' + security: + - JWT: [] + summary: Create alert template. ADMIN ONLY + tags: + - SystemNotificationTemplates + /admin/system-notification-templates/{systemNotificationTemplateId}: + get: + consumes: + - application/json + description: Get SystemNotificationTemplate + parameters: + - description: systemNotificationTemplateId + in: path + name: systemNotificationTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse' + security: + - JWT: [] + summary: Get SystemNotificationTemplate + tags: + - SystemNotificationTemplates + put: + consumes: + - application/json + description: Update SystemNotificationTemplate + parameters: + - description: Update alert template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update SystemNotificationTemplate + tags: + - SystemNotificationTemplates /app-groups: delete: consumes: @@ -6532,10 +6787,6 @@ paths: in: query name: sortOrder type: string - - description: combinedFilter - in: query - name: combinedFilter - type: string produces: - application/json responses: @@ -6798,6 +7049,157 @@ paths: summary: Check name for stack tags: - Stacks + /organizations/{organizationId}/system-notification-rules: + get: + consumes: + - application/json + description: Get SystemNotificationRules + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse' + security: + - JWT: [] + summary: Get SystemNotificationRules + tags: + - SystemNotificationRules + post: + consumes: + - application/json + description: Create SystemNotificationRule + parameters: + - description: create stack template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse' + security: + - JWT: [] + summary: Create SystemNotificationRule + tags: + - SystemNotificationRules + /organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}: + delete: + consumes: + - application/json + description: Delete SystemNotificationRule + parameters: + - description: systemNotificationRuleId + in: path + name: systemNotificationRuleId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete SystemNotificationRule + tags: + - SystemNotificationRules + get: + consumes: + - application/json + description: Get SystemNotificationRule + parameters: + - description: systemNotificationRuleId + in: path + name: systemNotificationRuleId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse' + security: + - JWT: [] + summary: Get SystemNotificationRule + tags: + - SystemNotificationRules + put: + consumes: + - application/json + description: Update SystemNotificationRule + parameters: + - description: Update systemNotificationRule request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update SystemNotificationRule + tags: + - SystemNotificationRules + /organizations/{organizationId}/system-notification-rules/name/{name}/existence: + get: + consumes: + - application/json + description: Check name for systemNotificationRule + parameters: + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse' + security: + - JWT: [] + summary: Check name for systemNotificationRule + tags: + - SystemNotificationRules /organizations/{organizationId}/system-notifications: get: consumes: diff --git a/internal/database/database.go b/internal/database/database.go index 147a6bb3..67ac9599 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -110,7 +110,7 @@ func migrateSchema(db *gorm.DB) error { return err } - // Event + // SystemNotification if err := db.AutoMigrate(&model.SystemNotification{}); err != nil { return err } @@ -118,6 +118,25 @@ func migrateSchema(db *gorm.DB) error { return err } + // SystemNotificationTemplate + if err := db.AutoMigrate(&model.MetricParameter{}); err != nil { + return err + } + if err := db.AutoMigrate(&model.SystemNotificationTemplate{}); err != nil { + return err + } + + // SystemNotificationRule + if err := db.AutoMigrate(&model.SystemNotificationRule{}); err != nil { + return err + } + if err := db.AutoMigrate(&model.SystemNotificationCondition{}); err != nil { + return err + } + if err := db.AutoMigrate(&model.SystemNotificationMessage{}); err != nil { + return err + } + // Role if err := db.AutoMigrate(&model.Role{}); err != nil { return err @@ -163,19 +182,21 @@ func migrateSchema(db *gorm.DB) error { func EnsureDefaultRows(db *gorm.DB) error { // Create default rows repoFactory := repository.Repository{ - Auth: repository.NewAuthRepository(db), - User: repository.NewUserRepository(db), - Cluster: repository.NewClusterRepository(db), - Organization: repository.NewOrganizationRepository(db), - AppGroup: repository.NewAppGroupRepository(db), - AppServeApp: repository.NewAppServeAppRepository(db), - CloudAccount: repository.NewCloudAccountRepository(db), - StackTemplate: repository.NewStackTemplateRepository(db), - SystemNotification: repository.NewSystemNotificationRepository(db), - Role: repository.NewRoleRepository(db), - Permission: repository.NewPermissionRepository(db), - Endpoint: repository.NewEndpointRepository(db), - Project: repository.NewProjectRepository(db), + Auth: repository.NewAuthRepository(db), + User: repository.NewUserRepository(db), + Cluster: repository.NewClusterRepository(db), + Organization: repository.NewOrganizationRepository(db), + AppGroup: repository.NewAppGroupRepository(db), + AppServeApp: repository.NewAppServeAppRepository(db), + CloudAccount: repository.NewCloudAccountRepository(db), + StackTemplate: repository.NewStackTemplateRepository(db), + SystemNotification: repository.NewSystemNotificationRepository(db), + SystemNotificationRule: repository.NewSystemNotificationRuleRepository(db), + SystemNotificationTemplate: repository.NewSystemNotificationTemplateRepository(db), + Role: repository.NewRoleRepository(db), + Permission: repository.NewPermissionRepository(db), + Endpoint: repository.NewEndpointRepository(db), + Project: repository.NewProjectRepository(db), } // diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 8ff1bab7..31cabce6 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -113,18 +113,18 @@ const ( GetStacksDashboard // 대시보드/대시보드/조회 GetResourcesDashboard // 대시보드/대시보드/조회 - // AlertTemplate - Admin_CreateAlertTemplate - Admin_UpdateAlertTemplate - Admin_GetAlertTemplates - Admin_GetAlertTemplate + // SystemNotificationTemplate + Admin_CreateSystemNotificationTemplate + Admin_UpdateSystemNotificationTemplate + Admin_GetSystemNotificationTemplates + Admin_GetSystemNotificationTemplate - // SystemAlert - // CreateSystemAlert - // GetSystemAlerts - // GetSystemAlert - // DeleteSystemAlert - // UpdateSystemAlert + // SystemNotificationRule + CreateSystemNotificationRule + GetSystemNotificationRules + GetSystemNotificationRule + DeleteSystemNotificationRule + UpdateSystemNotificationRule // SystemNotification CreateSystemNotification @@ -202,6 +202,7 @@ const ( // Admin Project Admin_GetProjects + // PolicyTemplate ListPolicyTemplate CreatePolicyTemplate diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 1955a7e8..a02951c3 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -335,21 +335,41 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetResourcesDashboard", Group: "Dashboard", }, - Admin_CreateAlertTemplate: { - Name: "Admin_CreateAlertTemplate", - Group: "AlertTemplate", + Admin_CreateSystemNotificationTemplate: { + Name: "Admin_CreateSystemNotificationTemplate", + Group: "SystemNotificationTemplate", }, - Admin_UpdateAlertTemplate: { - Name: "Admin_UpdateAlertTemplate", - Group: "AlertTemplate", + Admin_UpdateSystemNotificationTemplate: { + Name: "Admin_UpdateSystemNotificationTemplate", + Group: "SystemNotificationTemplate", }, - Admin_GetAlertTemplates: { - Name: "Admin_GetAlertTemplates", - Group: "AlertTemplate", + Admin_GetSystemNotificationTemplates: { + Name: "Admin_GetSystemNotificationTemplates", + Group: "SystemNotificationTemplate", }, - Admin_GetAlertTemplate: { - Name: "Admin_GetAlertTemplate", - Group: "AlertTemplate", + Admin_GetSystemNotificationTemplate: { + Name: "Admin_GetSystemNotificationTemplate", + Group: "SystemNotificationTemplate", + }, + CreateSystemNotificationRule: { + Name: "CreateSystemNotificationRule", + Group: "SystemNotificationRule", + }, + GetSystemNotificationRules: { + Name: "GetSystemNotificationRules", + Group: "SystemNotificationRule", + }, + GetSystemNotificationRule: { + Name: "GetSystemNotificationRule", + Group: "SystemNotificationRule", + }, + DeleteSystemNotificationRule: { + Name: "DeleteSystemNotificationRule", + Group: "SystemNotificationRule", + }, + UpdateSystemNotificationRule: { + Name: "UpdateSystemNotificationRule", + Group: "SystemNotificationRule", }, CreateSystemNotification: { Name: "CreateSystemNotification", @@ -928,14 +948,24 @@ func (e Endpoint) String() string { return "GetStacksDashboard" case GetResourcesDashboard: return "GetResourcesDashboard" - case Admin_CreateAlertTemplate: - return "Admin_CreateAlertTemplate" - case Admin_UpdateAlertTemplate: - return "Admin_UpdateAlertTemplate" - case Admin_GetAlertTemplates: - return "Admin_GetAlertTemplates" - case Admin_GetAlertTemplate: - return "Admin_GetAlertTemplate" + case Admin_CreateSystemNotificationTemplate: + return "Admin_CreateSystemNotificationTemplate" + case Admin_UpdateSystemNotificationTemplate: + return "Admin_UpdateSystemNotificationTemplate" + case Admin_GetSystemNotificationTemplates: + return "Admin_GetSystemNotificationTemplates" + case Admin_GetSystemNotificationTemplate: + return "Admin_GetSystemNotificationTemplate" + case CreateSystemNotificationRule: + return "CreateSystemNotificationRule" + case GetSystemNotificationRules: + return "GetSystemNotificationRules" + case GetSystemNotificationRule: + return "GetSystemNotificationRule" + case DeleteSystemNotificationRule: + return "DeleteSystemNotificationRule" + case UpdateSystemNotificationRule: + return "UpdateSystemNotificationRule" case CreateSystemNotification: return "CreateSystemNotification" case GetSystemNotifications: @@ -1312,14 +1342,24 @@ func GetEndpoint(name string) Endpoint { return GetStacksDashboard case "GetResourcesDashboard": return GetResourcesDashboard - case "Admin_CreateAlertTemplate": - return Admin_CreateAlertTemplate - case "Admin_UpdateAlertTemplate": - return Admin_UpdateAlertTemplate - case "Admin_GetAlertTemplates": - return Admin_GetAlertTemplates - case "Admin_GetAlertTemplate": - return Admin_GetAlertTemplate + case "Admin_CreateSystemNotificationTemplate": + return Admin_CreateSystemNotificationTemplate + case "Admin_UpdateSystemNotificationTemplate": + return Admin_UpdateSystemNotificationTemplate + case "Admin_GetSystemNotificationTemplates": + return Admin_GetSystemNotificationTemplates + case "Admin_GetSystemNotificationTemplate": + return Admin_GetSystemNotificationTemplate + case "CreateSystemNotificationRule": + return CreateSystemNotificationRule + case "GetSystemNotificationRules": + return GetSystemNotificationRules + case "GetSystemNotificationRule": + return GetSystemNotificationRule + case "DeleteSystemNotificationRule": + return DeleteSystemNotificationRule + case "UpdateSystemNotificationRule": + return UpdateSystemNotificationRule case "CreateSystemNotification": return CreateSystemNotification case "GetSystemNotifications": diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index eafbe9aa..1932db7c 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -232,6 +232,12 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req log.Error(r.Context(), err) } } + out.Organization.SystemNotificationTemplates = make([]domain.SimpleSystemNotificationTemplateResponse, len(organization.SystemNotificationTemplates)) + for i, notificationTemplate := range organization.SystemNotificationTemplates { + if err = serializer.Map(r.Context(), notificationTemplate, &out.Organization.SystemNotificationTemplates[i]); err != nil { + log.Error(r.Context(), err) + } + } ResponseJSON(w, r, http.StatusOK, out) } @@ -386,6 +392,14 @@ func (h *OrganizationHandler) Admin_UpdateOrganization(w http.ResponseWriter, r } dto.PolicyTemplateIds = append(dto.PolicyTemplateIds, policyTemplateId) } + for _, strId := range input.SystemNotificationTemplateIds { + systemNotificationTemplateId, err := uuid.Parse(strId) + if err != nil || systemNotificationTemplateId == uuid.Nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationTemplateId"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + dto.SystemNotificationTemplateIds = append(dto.SystemNotificationTemplateIds, systemNotificationTemplateId) + } err = h.usecase.UpdateWithTemplates(r.Context(), organizationId, dto) if err != nil { diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 62f3ee7b..9f74ace6 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -99,7 +99,6 @@ func (h *StackHandler) InstallStack(w http.ResponseWriter, r *http.Request) { // @Param page query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" -// @Param combinedFilter query string false "combinedFilter" // @Success 200 {object} domain.GetStacksResponse // @Router /organizations/{organizationId}/stacks [get] // @Security JWT diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go new file mode 100644 index 00000000..068966bc --- /dev/null +++ b/internal/delivery/http/system-notification-rule.go @@ -0,0 +1,245 @@ +package http + +import ( + "fmt" + "net/http" + + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" +) + +type SystemNotificationRuleHandler struct { + usecase usecase.ISystemNotificationRuleUsecase +} + +func NewSystemNotificationRuleHandler(h usecase.Usecase) *SystemNotificationRuleHandler { + return &SystemNotificationRuleHandler{ + usecase: h.SystemNotificationRule, + } +} + +// CreateSystemNotificationRule godoc +// +// @Tags SystemNotificationRules +// @Summary Create SystemNotificationRule +// @Description Create SystemNotificationRule +// @Accept json +// @Produce json +// @Param body body domain.CreateSystemNotificationRuleRequest true "create stack template request" +// @Success 200 {object} domain.CreateSystemNotificationRuleResponse +// @Router /organizations/{organizationId}/system-notification-rules [post] +// @Security JWT +func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.ResponseWriter, r *http.Request) { + input := domain.CreateSystemNotificationRuleRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto model.SystemNotificationRule + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + + id, err := h.usecase.Create(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + out := domain.CreateSystemNotificationRuleResponse{ + ID: id.String(), + } + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetSystemNotificationRule godoc +// +// @Tags SystemNotificationRules +// @Summary Get SystemNotificationRules +// @Description Get SystemNotificationRules +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetSystemNotificationRulesResponse +// @Router /organizations/{organizationId}/system-notification-rules [get] +// @Security JWT +func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + systemNotificationRules, err := h.usecase.Fetch(r.Context(), organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetSystemNotificationRulesResponse + out.SystemNotificationRules = make([]domain.SystemNotificationRuleResponse, len(systemNotificationRules)) + for i, systemNotificationRule := range systemNotificationRules { + if err := serializer.Map(r.Context(), systemNotificationRule, &out.SystemNotificationRules[i]); err != nil { + log.Info(r.Context(), err) + } + } + + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetSystemNotificationRule godoc +// +// @Tags SystemNotificationRules +// @Summary Get SystemNotificationRule +// @Description Get SystemNotificationRule +// @Accept json +// @Produce json +// @Param systemNotificationRuleId path string true "systemNotificationRuleId" +// @Success 200 {object} domain.GetSystemNotificationRuleResponse +// @Router /organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId} [get] +// @Security JWT +func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["systemNotificationRuleId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + systemNotificationRuleId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + systemNotificationRule, err := h.usecase.Get(r.Context(), systemNotificationRuleId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetSystemNotificationRuleResponse + if err := serializer.Map(r.Context(), systemNotificationRule, &out.SystemNotificationRule); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdateSystemNotificationRule godoc +// +// @Tags SystemNotificationRules +// @Summary Update SystemNotificationRule +// @Description Update SystemNotificationRule +// @Accept json +// @Produce json +// @Param body body domain.UpdateSystemNotificationRuleRequest true "Update systemNotificationRule request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId} [put] +// @Security JWT +func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["systemNotificationRuleId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + systemNotificationRuleId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + var dto model.SystemNotificationRule + if err := serializer.Map(r.Context(), r, &dto); err != nil { + log.Info(r.Context(), err) + } + dto.ID = systemNotificationRuleId + + err = h.usecase.Update(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) +} + +// DeleteSystemNotificationRule godoc +// +// @Tags SystemNotificationRules +// @Summary Delete SystemNotificationRule +// @Description Delete SystemNotificationRule +// @Accept json +// @Produce json +// @Param systemNotificationRuleId path string true "systemNotificationRuleId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId} [delete] +// @Security JWT +func (h *SystemNotificationRuleHandler) DeleteSystemNotificationRule(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + _, ok := vars["systemNotificationRuleId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + ErrorJSON(w, r, fmt.Errorf("need implementation")) +} + +// CheckSystemNotificationRuleName godoc +// +// @Tags SystemNotificationRules +// @Summary Check name for systemNotificationRule +// @Description Check name for systemNotificationRule +// @Accept json +// @Produce json +// @Param name path string true "name" +// @Success 200 {object} domain.CheckSystemNotificationRuleNameResponse +// @Router /organizations/{organizationId}/system-notification-rules/name/{name}/existence [GET] +// @Security JWT +func (h *SystemNotificationRuleHandler) CheckSystemNotificationRuleName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name, ok := vars["name"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid name"), "SNR_INVALID_STACK_TEMAPLTE_NAME", "")) + return + } + + exist := true + _, err := h.usecase.GetByName(r.Context(), name) + if err != nil { + if _, code := httpErrors.ErrorResponse(err); code == http.StatusNotFound { + exist = false + } else { + ErrorJSON(w, r, err) + return + } + } + + var out domain.CheckSystemNotificationRuleNameResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go new file mode 100644 index 00000000..f1d6dc44 --- /dev/null +++ b/internal/delivery/http/system-notification-template.go @@ -0,0 +1,221 @@ +package http + +import ( + "fmt" + "net/http" + + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" +) + +type SystemNotificationTemplateHandler struct { + usecase usecase.ISystemNotificationTemplateUsecase +} + +func NewSystemNotificationTemplateHandler(h usecase.Usecase) *SystemNotificationTemplateHandler { + return &SystemNotificationTemplateHandler{ + usecase: h.SystemNotificationTemplate, + } +} + +// CreateSystemNotificationTemplate godoc +// +// @Tags SystemNotificationTemplates +// @Summary Create alert template. ADMIN ONLY +// @Description Create alert template. ADMIN ONLY +// @Accept json +// @Produce json +// @Success 200 {object} domain.CreateSystemNotificationTemplateResponse +// @Router /admin/system-notification-templates [post] +// @Security JWT +func (h *SystemNotificationTemplateHandler) CreateSystemNotificationTemplate(w http.ResponseWriter, r *http.Request) { + input := domain.CreateSystemNotificationTemplateRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto model.SystemNotificationTemplate + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + dto.MetricParameters = make([]model.MetricParameter, len(input.MetricParameters)) + for i, metricParameter := range input.MetricParameters { + if err := serializer.Map(r.Context(), metricParameter, &dto.MetricParameters[i]); err != nil { + log.Info(r.Context(), err) + } + } + + id, err := h.usecase.Create(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + out := domain.CreateSystemNotificationTemplateResponse{ + ID: id.String(), + } + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetSystemNotificationTemplate godoc +// +// @Tags SystemNotificationTemplates +// @Summary Get SystemNotificationTemplates +// @Description Get SystemNotificationTemplates +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetSystemNotificationTemplatesResponse +// @Router /admin/system-notification-templates [get] +// @Security JWT +func (h *SystemNotificationTemplateHandler) GetSystemNotificationTemplates(w http.ResponseWriter, r *http.Request) { + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + systemNotificationTemplates, err := h.usecase.Fetch(r.Context(), pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetSystemNotificationTemplatesResponse + out.SystemNotificationTemplates = make([]domain.SystemNotificationTemplateResponse, len(systemNotificationTemplates)) + for i, systemNotificationTemplate := range systemNotificationTemplates { + if err := serializer.Map(r.Context(), systemNotificationTemplate, &out.SystemNotificationTemplates[i]); err != nil { + log.Info(r.Context(), err) + } + + out.SystemNotificationTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(systemNotificationTemplate.Organizations)) + for j, organization := range systemNotificationTemplate.Organizations { + if err := serializer.Map(r.Context(), organization, &out.SystemNotificationTemplates[i].Organizations[j]); err != nil { + log.Info(r.Context(), err) + } + } + } + + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetSystemNotificationTemplate godoc +// +// @Tags SystemNotificationTemplates +// @Summary Get SystemNotificationTemplate +// @Description Get SystemNotificationTemplate +// @Accept json +// @Produce json +// @Param systemNotificationTemplateId path string true "systemNotificationTemplateId" +// @Success 200 {object} domain.GetSystemNotificationTemplateResponse +// @Router /admin/system-notification-templates/{systemNotificationTemplateId} [get] +// @Security JWT +func (h *SystemNotificationTemplateHandler) GetSystemNotificationTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["systemNotificationTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationTemplateId"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + + systemNotificationTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + + systemNotificationTemplate, err := h.usecase.Get(r.Context(), systemNotificationTemplateId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetSystemNotificationTemplateResponse + if err := serializer.Map(r.Context(), systemNotificationTemplate, &out.SystemNotificationTemplate); err != nil { + log.Info(r.Context(), err) + } + + out.SystemNotificationTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(systemNotificationTemplate.Organizations)) + for i, organization := range systemNotificationTemplate.Organizations { + if err := serializer.Map(r.Context(), organization, &out.SystemNotificationTemplate.Organizations[i]); err != nil { + log.Info(r.Context(), err) + continue + } + } + + out.SystemNotificationTemplate.MetricParameters = make([]domain.MetricParameterResponse, len(systemNotificationTemplate.MetricParameters)) + for i, metricParameters := range systemNotificationTemplate.MetricParameters { + if err := serializer.Map(r.Context(), metricParameters, &out.SystemNotificationTemplate.MetricParameters[i]); err != nil { + log.Info(r.Context(), err) + continue + } + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdateSystemNotificationTemplate godoc +// +// @Tags SystemNotificationTemplates +// @Summary Update SystemNotificationTemplate +// @Description Update SystemNotificationTemplate +// @Accept json +// @Produce json +// @Param body body domain.UpdateSystemNotificationTemplateRequest true "Update alert template request" +// @Success 200 {object} nil +// @Router /admin/system-notification-templates/{systemNotificationTemplateId} [put] +// @Security JWT +func (h *SystemNotificationTemplateHandler) UpdateSystemNotificationTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["systemNotificationTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationTemplateId"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + systemNotificationTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + + input := domain.UpdateSystemNotificationTemplateRequest{} + err = UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + var dto model.SystemNotificationTemplate + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + dto.ID = systemNotificationTemplateId + dto.MetricParameters = make([]model.MetricParameter, len(input.MetricParameters)) + for i, metricParameter := range input.MetricParameters { + if err := serializer.Map(r.Context(), metricParameter, &dto.MetricParameters[i]); err != nil { + log.Info(r.Context(), err) + } + dto.MetricParameters[i].SystemNotificationTemplateId = systemNotificationTemplateId + } + + err = h.usecase.Update(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/model/organization.go b/internal/model/organization.go index 2c6ca725..5f466a31 100644 --- a/internal/model/organization.go +++ b/internal/model/organization.go @@ -10,20 +10,22 @@ import ( type Organization struct { gorm.Model - ID string `gorm:"primarykey;type:varchar(36);not null"` - Name string - Description string - Phone string - PrimaryClusterId string - WorkflowId string - Status domain.OrganizationStatus - StatusDesc string - CreatorId *uuid.UUID `gorm:"type:uuid"` - StackTemplates []StackTemplate `gorm:"many2many:stack_template_organizations;"` - StackTemplateIds []uuid.UUID `gorm:"-:all"` - PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organiations;"` - PolicyTemplateIds []uuid.UUID `gorm:"-:all"` - ClusterCount int `gorm:"-:all"` - AdminId *uuid.UUID - Admin *User `gorm:"foreignKey:AdminId"` + ID string `gorm:"primarykey;type:varchar(36);not null"` + Name string + Description string + Phone string + PrimaryClusterId string + WorkflowId string + Status domain.OrganizationStatus + StatusDesc string + CreatorId *uuid.UUID `gorm:"type:uuid"` + StackTemplates []StackTemplate `gorm:"many2many:stack_template_organizations;"` + StackTemplateIds []uuid.UUID `gorm:"-:all"` + PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organiations;"` + PolicyTemplateIds []uuid.UUID `gorm:"-:all"` + SystemNotificationTemplates []SystemNotificationTemplate `gorm:"many2many:system_notification_template_organizations"` + SystemNotificationTemplateIds []uuid.UUID `gorm:"-:all"` + ClusterCount int `gorm:"-:all"` + AdminId *uuid.UUID + Admin *User `gorm:"foreignKey:AdminId"` } diff --git a/internal/model/stack-template.go b/internal/model/stack-template.go index afcef83b..b67e8ed8 100644 --- a/internal/model/stack-template.go +++ b/internal/model/stack-template.go @@ -10,7 +10,7 @@ type StackTemplate struct { gorm.Model ID uuid.UUID `gorm:"primarykey"` - Name string `gorm:"index"` + Name string `gorm:"index,unique"` Description string `gorm:"index"` Template string TemplateType string diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go new file mode 100644 index 00000000..b1ddee30 --- /dev/null +++ b/internal/model/system-notification-rule.go @@ -0,0 +1,41 @@ +package model + +import ( + "github.com/google/uuid" + "gorm.io/datatypes" + "gorm.io/gorm" +) + +type SystemNotificationCondition struct { + SystemNotificationRuleId uuid.UUID `gorm:"primarykey"` + Order int `gorm:"primarykey"` + Severity string + Duration int + Condition datatypes.JSON + EnableEmail bool `gorm:"default:false"` + EnablePortal bool `gorm:"default:true"` +} + +type SystemNotificationMessage struct { + SystemNotificationRuleId uuid.UUID `gorm:"primarykey"` + Title string + Content int + Condition datatypes.JSON + ActionProposal string + TargetUsers []User `gorm:"many2many:system_notification_message_users"` +} + +type SystemNotificationRule struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index,unique"` + Description string + Templates []SystemNotificationTemplate `gorm:"many2many:system_notification_rule_system_notification_templates"` + Messages []SystemNotificationMessage `gorm:"many2many:system_notification_rule_system_notification_messages"` + + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator *User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator *User `gorm:"foreignKey:UpdatorId"` +} diff --git a/internal/model/system-notification-template.go b/internal/model/system-notification-template.go new file mode 100644 index 00000000..3c07964e --- /dev/null +++ b/internal/model/system-notification-template.go @@ -0,0 +1,30 @@ +package model + +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) + +// Models +type MetricParameter struct { + SystemNotificationTemplateId uuid.UUID `gorm:"primarykey"` + Order int `gorm:"primarykey"` + Key string + Value string +} + +type SystemNotificationTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index:idx_name,unique"` + Organizations []Organization `gorm:"many2many:system_notification_template_organizations"` + OrganizationIds []string `gorm:"-:all"` + Description string + MetricQuery string + MetricParameters []MetricParameter `gorm:"foreignKey:SystemNotificationTemplateId;references:ID"` + CreatorId *uuid.UUID + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID + Updator User `gorm:"foreignKey:UpdatorId"` +} diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 5630bbb2..f9ab9e86 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -10,6 +10,7 @@ import ( "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" "golang.org/x/text/cases" "golang.org/x/text/language" "gorm.io/gorm" @@ -26,7 +27,7 @@ const FILTER = "filter" const FILTER_ARRAY = "filter[]" const OR = "or" const OR_ARRAY = "or[]" -const COMBINED_FILTER = "combinedFilter" +const COMBINED_FILTER = "combinedFilter" // deprecated var DEFAULT_LIMIT = 10 @@ -198,20 +199,8 @@ func NewPagination(urlParams *url.Values) *Pagination { pg.Limit = limitNum } } - case COMBINED_FILTER: - if len(value[0]) > 0 { - //"combinedFilter=key1,key2:value" - filterArray := strings.Split(value[0], ":") - if len(filterArray) == 2 { - keys := strings.Split(helper.ToSnakeCase(strings.Replace(filterArray[0], "[]", "", -1)), ",") - value := filterArray[1] - - pg.CombinedFilter = CombinedFilter{ - Columns: keys, - Value: value, - } - } - } + case COMBINED_FILTER: // deprecated + log.Error(context.TODO(), "DEPRECATED filter scheme. COMBINEND_FILTER") case FILTER, FILTER_ARRAY, OR, OR_ARRAY: for _, filterValue := range value { arr := strings.Split(filterValue, "|") diff --git a/internal/repository/endpoint.go b/internal/repository/endpoint.go index e1230aeb..f51bd2bd 100644 --- a/internal/repository/endpoint.go +++ b/internal/repository/endpoint.go @@ -2,8 +2,6 @@ package repository import ( "context" - "fmt" - "math" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -45,14 +43,8 @@ func (e *EndpointRepository) List(ctx context.Context, pg *pagination.Pagination if pg == nil { pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("endpoints", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(e.db.Model(&model.Endpoint{})) - db.Count(&pg.TotalRows) - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.WithContext(ctx).Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&endpoints) + _, res := pg.Fetch(e.db.WithContext(ctx).Model(&model.Endpoint{}), &endpoints) if res.Error != nil { return nil, res.Error } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index f7266bba..306d9cc6 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -22,6 +22,7 @@ type IOrganizationRepository interface { UpdateAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error UpdateStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) UpdatePolicyTemplates(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) + UpdateSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplates []model.SystemNotificationTemplate) (err error) Delete(ctx context.Context, organizationId string) (err error) InitWorkflow(ctx context.Context, organizationId string, workflowId string, status domain.OrganizationStatus) error } @@ -186,3 +187,17 @@ func (r *OrganizationRepository) UpdatePolicyTemplates(ctx context.Context, orga return nil } + +func (r *OrganizationRepository) UpdateSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplates []model.SystemNotificationTemplate) (err error) { + var organization = model.Organization{} + res := r.db.WithContext(ctx).Preload("SystemNotificationTemplates").First(&organization, "id = ?", organizationId) + if res.Error != nil { + return res.Error + } + + err = r.db.WithContext(ctx).Model(&organization).Association("SystemNotificationTemplates").Replace(systemNotificationTemplates) + if err != nil { + return err + } + return nil +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 0e6d197b..d1eb8276 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -12,21 +12,23 @@ import ( type FilterFunc func(user *gorm.DB) *gorm.DB type Repository struct { - Auth IAuthRepository - User IUserRepository - Cluster IClusterRepository - Organization IOrganizationRepository - AppGroup IAppGroupRepository - AppServeApp IAppServeAppRepository - CloudAccount ICloudAccountRepository - StackTemplate IStackTemplateRepository - SystemNotification ISystemNotificationRepository - Role IRoleRepository - Permission IPermissionRepository - Endpoint IEndpointRepository - Project IProjectRepository - Audit IAuditRepository - PolicyTemplate IPolicyTemplateRepository + Auth IAuthRepository + User IUserRepository + Cluster IClusterRepository + Organization IOrganizationRepository + AppGroup IAppGroupRepository + AppServeApp IAppServeAppRepository + CloudAccount ICloudAccountRepository + StackTemplate IStackTemplateRepository + Role IRoleRepository + Permission IPermissionRepository + Endpoint IEndpointRepository + Project IProjectRepository + Audit IAuditRepository + PolicyTemplate IPolicyTemplateRepository + SystemNotification ISystemNotificationRepository + SystemNotificationTemplate ISystemNotificationTemplateRepository + SystemNotificationRule ISystemNotificationRuleRepository } func CombinedGormFilter(table string, filters []pagination.Filter, combinedFilter pagination.CombinedFilter) FilterFunc { diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go new file mode 100644 index 00000000..91123fdb --- /dev/null +++ b/internal/repository/system-notification-rule.go @@ -0,0 +1,122 @@ +package repository + +import ( + "context" + + "github.com/google/uuid" + "gorm.io/gorm" + "gorm.io/gorm/clause" + + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" +) + +// Interfaces +type ISystemNotificationRuleRepository interface { + Get(ctx context.Context, systemNotificationRuleId uuid.UUID) (model.SystemNotificationRule, error) + GetByName(ctx context.Context, name string) (model.SystemNotificationRule, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.SystemNotificationRule, error) + FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotificationRule, err error) + Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRuleId uuid.UUID, err error) + Update(ctx context.Context, dto model.SystemNotificationRule) (err error) + Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) + UpdateOrganizations(ctx context.Context, systemNotificationRuleId uuid.UUID, organizationIds []model.Organization) (err error) +} + +type SystemNotificationRuleRepository struct { + db *gorm.DB +} + +func NewSystemNotificationRuleRepository(db *gorm.DB) ISystemNotificationRuleRepository { + return &SystemNotificationRuleRepository{ + db: db, + } +} + +// Logics +func (r *SystemNotificationRuleRepository) Get(ctx context.Context, systemNotificationRuleId uuid.UUID) (out model.SystemNotificationRule, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "id = ?", systemNotificationRuleId) + if res.Error != nil { + return model.SystemNotificationRule{}, res.Error + } + return +} + +func (r *SystemNotificationRuleRepository) GetByName(ctx context.Context, name string) (out model.SystemNotificationRule, err error) { + res := r.db.WithContext(ctx).First(&out, "name = ?", name) + if res.Error != nil { + return out, res.Error + } + return +} + +func (r *SystemNotificationRuleRepository) Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.SystemNotificationRule, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations), &out) + if res.Error != nil { + return nil, res.Error + } + return +} + +func (r *SystemNotificationRuleRepository) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotificationRule, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch( + r.db.WithContext(ctx).Preload(clause.Associations). + Where("organization_id = ?", organizationId), + &out) + if res.Error != nil { + return nil, res.Error + } + return +} + +func (r *SystemNotificationRuleRepository) Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRuleId uuid.UUID, err error) { + dto.ID = uuid.New() + res := r.db.WithContext(ctx).Create(&dto) + if res.Error != nil { + return uuid.Nil, res.Error + } + return dto.ID, nil +} + +func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) { + res := r.db.WithContext(ctx).Model(&model.SystemNotificationRule{}). + Where("id = ?", dto.ID). + Updates(map[string]interface{}{ + "Name": dto.Name, + "Description": dto.Description, + "UpdatorId": dto.UpdatorId}) + if res.Error != nil { + return res.Error + } + return nil +} + +func (r *SystemNotificationRuleRepository) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { + res := r.db.WithContext(ctx).Delete(&model.SystemNotificationRule{}, "id = ?", dto.ID) + if res.Error != nil { + return res.Error + } + return nil +} + +func (r *SystemNotificationRuleRepository) UpdateOrganizations(ctx context.Context, systemNotificationRuleId uuid.UUID, organizations []model.Organization) (err error) { + var systemNotificationRule = model.SystemNotificationRule{} + res := r.db.WithContext(ctx).Preload("Organizations").First(&systemNotificationRule, "id = ?", systemNotificationRuleId) + if res.Error != nil { + return res.Error + } + err = r.db.WithContext(ctx).Model(&systemNotificationRule).Association("Organizations").Unscoped().Replace(organizations) + if err != nil { + return err + } + + return nil +} diff --git a/internal/repository/system-notification-template.go b/internal/repository/system-notification-template.go new file mode 100644 index 00000000..bd520fb3 --- /dev/null +++ b/internal/repository/system-notification-template.go @@ -0,0 +1,118 @@ +package repository + +import ( + "context" + + "github.com/google/uuid" + "gorm.io/gorm" + "gorm.io/gorm/clause" + + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/log" +) + +// Interfaces +type ISystemNotificationTemplateRepository interface { + Get(ctx context.Context, systemNotificationTemplateId uuid.UUID) (model.SystemNotificationTemplate, error) + GetByName(ctx context.Context, name string) (model.SystemNotificationTemplate, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.SystemNotificationTemplate, error) + Create(ctx context.Context, dto model.SystemNotificationTemplate) (systemNotificationTemplateId uuid.UUID, err error) + Update(ctx context.Context, dto model.SystemNotificationTemplate) (err error) + Delete(ctx context.Context, dto model.SystemNotificationTemplate) (err error) + UpdateOrganizations(ctx context.Context, systemNotificationTemplateId uuid.UUID, organizations []model.Organization) (err error) +} + +type SystemNotificationTemplateRepository struct { + db *gorm.DB +} + +func NewSystemNotificationTemplateRepository(db *gorm.DB) ISystemNotificationTemplateRepository { + return &SystemNotificationTemplateRepository{ + db: db, + } +} + +// Logics +func (r *SystemNotificationTemplateRepository) Get(ctx context.Context, systemNotificationTemplateId uuid.UUID) (out model.SystemNotificationTemplate, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "id = ?", systemNotificationTemplateId) + if res.Error != nil { + return out, res.Error + } + return +} + +func (r *SystemNotificationTemplateRepository) GetByName(ctx context.Context, name string) (out model.SystemNotificationTemplate, err error) { + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "name = ?", name) + if res.Error != nil { + return out, res.Error + } + return +} + +func (r *SystemNotificationTemplateRepository) Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.SystemNotificationTemplate, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations), &out) + if res.Error != nil { + return nil, res.Error + } + return +} + +func (r *SystemNotificationTemplateRepository) Create(ctx context.Context, dto model.SystemNotificationTemplate) (systemNotificationTemplateId uuid.UUID, err error) { + dto.ID = uuid.New() + res := r.db.WithContext(ctx).Create(&dto) + if res.Error != nil { + return uuid.Nil, res.Error + } + + err = r.db.WithContext(ctx).Model(&dto).Association("MetricParameters").Replace(dto.MetricParameters) + if err != nil { + log.Error(ctx, err) + } + + return dto.ID, nil +} + +func (r *SystemNotificationTemplateRepository) Update(ctx context.Context, dto model.SystemNotificationTemplate) (err error) { + res := r.db.WithContext(ctx).Model(&model.SystemNotificationTemplate{}). + Where("id = ?", dto.ID). + Updates(map[string]interface{}{ + "Name": dto.Name, + "Description": dto.Description, + "MetricQuery": dto.MetricQuery, + }) + if res.Error != nil { + return res.Error + } + + if err = r.db.WithContext(ctx).Model(&dto).Association("MetricParameters").Unscoped().Replace(dto.MetricParameters); err != nil { + return err + } + return nil +} + +func (r *SystemNotificationTemplateRepository) Delete(ctx context.Context, dto model.SystemNotificationTemplate) (err error) { + res := r.db.WithContext(ctx).Delete(&model.SystemNotificationTemplate{}, "id = ?", dto.ID) + if res.Error != nil { + return res.Error + } + return nil +} + +func (r *SystemNotificationTemplateRepository) UpdateOrganizations(ctx context.Context, systemNotificationTemplateId uuid.UUID, organizations []model.Organization) (err error) { + var systemNotificationTemplate = model.SystemNotificationTemplate{} + res := r.db.WithContext(ctx).Preload("Organizations").First(&systemNotificationTemplate, "id = ?", systemNotificationTemplateId) + if res.Error != nil { + return res.Error + } + err = r.db.WithContext(ctx).Model(&systemNotificationTemplate).Association("Organizations").Replace(organizations) + if err != nil { + return err + } + + return nil +} diff --git a/internal/route/route.go b/internal/route/route.go index 7e40bd6a..265cd513 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -41,40 +41,44 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa cache := gcache.New(5*time.Minute, 10*time.Minute) repoFactory := repository.Repository{ - Auth: repository.NewAuthRepository(db), - User: repository.NewUserRepository(db), - Cluster: repository.NewClusterRepository(db), - Organization: repository.NewOrganizationRepository(db), - AppGroup: repository.NewAppGroupRepository(db), - AppServeApp: repository.NewAppServeAppRepository(db), - CloudAccount: repository.NewCloudAccountRepository(db), - StackTemplate: repository.NewStackTemplateRepository(db), - SystemNotification: repository.NewSystemNotificationRepository(db), - Role: repository.NewRoleRepository(db), - Project: repository.NewProjectRepository(db), - Permission: repository.NewPermissionRepository(db), - Endpoint: repository.NewEndpointRepository(db), - Audit: repository.NewAuditRepository(db), - PolicyTemplate: repository.NewPolicyTemplateRepository(db), + Auth: repository.NewAuthRepository(db), + User: repository.NewUserRepository(db), + Cluster: repository.NewClusterRepository(db), + Organization: repository.NewOrganizationRepository(db), + AppGroup: repository.NewAppGroupRepository(db), + AppServeApp: repository.NewAppServeAppRepository(db), + CloudAccount: repository.NewCloudAccountRepository(db), + StackTemplate: repository.NewStackTemplateRepository(db), + SystemNotification: repository.NewSystemNotificationRepository(db), + SystemNotificationTemplate: repository.NewSystemNotificationTemplateRepository(db), + SystemNotificationRule: repository.NewSystemNotificationRuleRepository(db), + Role: repository.NewRoleRepository(db), + Project: repository.NewProjectRepository(db), + Permission: repository.NewPermissionRepository(db), + Endpoint: repository.NewEndpointRepository(db), + Audit: repository.NewAuditRepository(db), + PolicyTemplate: repository.NewPolicyTemplateRepository(db), } usecaseFactory := usecase.Usecase{ - Auth: usecase.NewAuthUsecase(repoFactory, kc), - User: usecase.NewUserUsecase(repoFactory, kc), - Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache), - Organization: usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), - AppGroup: usecase.NewAppGroupUsecase(repoFactory, argoClient), - AppServeApp: usecase.NewAppServeAppUsecase(repoFactory, argoClient), - CloudAccount: usecase.NewCloudAccountUsecase(repoFactory, argoClient), - StackTemplate: usecase.NewStackTemplateUsecase(repoFactory), - Dashboard: usecase.NewDashboardUsecase(repoFactory, cache), - SystemNotification: usecase.NewSystemNotificationUsecase(repoFactory), - Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), - Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), - Audit: usecase.NewAuditUsecase(repoFactory), - Role: usecase.NewRoleUsecase(repoFactory), - Permission: usecase.NewPermissionUsecase(repoFactory), - PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), + Auth: usecase.NewAuthUsecase(repoFactory, kc), + User: usecase.NewUserUsecase(repoFactory, kc), + Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache), + Organization: usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), + AppGroup: usecase.NewAppGroupUsecase(repoFactory, argoClient), + AppServeApp: usecase.NewAppServeAppUsecase(repoFactory, argoClient), + CloudAccount: usecase.NewCloudAccountUsecase(repoFactory, argoClient), + StackTemplate: usecase.NewStackTemplateUsecase(repoFactory), + Dashboard: usecase.NewDashboardUsecase(repoFactory, cache), + SystemNotification: usecase.NewSystemNotificationUsecase(repoFactory), + SystemNotificationTemplate: usecase.NewSystemNotificationTemplateUsecase(repoFactory), + SystemNotificationRule: usecase.NewSystemNotificationRuleUsecase(repoFactory), + Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), + Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), + Audit: usecase.NewAuditUsecase(repoFactory), + Role: usecase.NewRoleUsecase(repoFactory), + Permission: usecase.NewPermissionUsecase(repoFactory), + PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), } customMiddleware := internalMiddleware.NewMiddleware( @@ -198,13 +202,25 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) systemNotificationHandler := delivery.NewSystemNotificationHandler(usecaseFactory) - r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/alerts", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) + r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/system-notifications", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications", customMiddleware.Handle(internalApi.GetSystemNotifications, http.HandlerFunc(systemNotificationHandler.GetSystemNotifications))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.GetSystemNotification, http.HandlerFunc(systemNotificationHandler.GetSystemNotification))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.DeleteSystemNotification, http.HandlerFunc(systemNotificationHandler.DeleteSystemNotification))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.UpdateSystemNotification, http.HandlerFunc(systemNotificationHandler.UpdateSystemNotification))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions", customMiddleware.Handle(internalApi.CreateSystemNotificationAction, http.HandlerFunc(systemNotificationHandler.CreateSystemNotificationAction))).Methods(http.MethodPost) - //r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationsId}/actions/status", customMiddleware.Handle(http.HandlerFunc(systemNotificationsHandler.UpdateSystemNotificationActionStatus))).Methods(http.MethodPatch) + r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) + + systemNotificationTemplateHandler := delivery.NewSystemNotificationTemplateHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates", customMiddleware.Handle(internalApi.Admin_CreateSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.CreateSystemNotificationTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates", customMiddleware.Handle(internalApi.Admin_GetSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetSystemNotificationTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_GetSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.GetSystemNotificationTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.UpdateSystemNotificationTemplate))).Methods(http.MethodPut) + + systemNotificationRuleHandler := delivery.NewSystemNotificationRuleHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) @@ -268,8 +284,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(permissionHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) - r.HandleFunc(API_PREFIX+API_VERSION+"/systemNotificationtest", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) - policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates", customMiddleware.Handle(internalApi.CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplate))).Methods(http.MethodPost) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 760dd2ee..567441e0 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -286,7 +286,7 @@ func (u *DashboardUsecase) getChartFromPrometheus(ctx context.Context, organizat return res, fmt.Errorf("Invalid month") } - events, err := u.systemNotificationRepo.FetchPodRestart(ctx, organizationId, startDate, endDate) + systemNotifications, err := u.systemNotificationRepo.FetchPodRestart(ctx, organizationId, startDate, endDate) if err != nil { return res, err } @@ -309,8 +309,8 @@ func (u *DashboardUsecase) getChartFromPrometheus(ctx context.Context, organizat cntPodRestart := 0 if baseDate <= now.Format("2006-01-02") && baseDate >= organization.CreatedAt.Format("2006-01-02") { - for _, event := range events { - strDate := event.CreatedAt.Format("2006-01-02") + for _, systemNotification := range systemNotifications { + strDate := systemNotification.CreatedAt.Format("2006-01-02") if strDate == baseDate { cntPodRestart += 1 diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 7409a392..e8b105f4 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -32,23 +32,25 @@ type IOrganizationUsecase interface { } type OrganizationUsecase struct { - repo repository.IOrganizationRepository - roleRepo repository.IRoleRepository - clusterRepo repository.IClusterRepository - stackTemplateRepo repository.IStackTemplateRepository - policyTemplateRepo repository.IPolicyTemplateRepository - argo argowf.ArgoClient - kc keycloak.IKeycloak + repo repository.IOrganizationRepository + roleRepo repository.IRoleRepository + clusterRepo repository.IClusterRepository + stackTemplateRepo repository.IStackTemplateRepository + policyTemplateRepo repository.IPolicyTemplateRepository + systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository + argo argowf.ArgoClient + kc keycloak.IKeycloak } func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClient, kc keycloak.IKeycloak) IOrganizationUsecase { return &OrganizationUsecase{ - repo: r.Organization, - roleRepo: r.Role, - clusterRepo: r.Cluster, - stackTemplateRepo: r.StackTemplate, - argo: argoClient, - kc: kc, + repo: r.Organization, + roleRepo: r.Role, + clusterRepo: r.Cluster, + stackTemplateRepo: r.StackTemplate, + systemNotificationTemplateRepo: r.SystemNotificationTemplate, + argo: argoClient, + kc: kc, } } @@ -225,5 +227,18 @@ func (u *OrganizationUsecase) UpdateWithTemplates(ctx context.Context, organizat return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_POLICY_TEMPLATES", "") } + systemNotificationTemplates := make([]model.SystemNotificationTemplate, 0) + for _, systemNotificationTemplateId := range dto.SystemNotificationTemplateIds { + systemNotificationTemplate, err := u.systemNotificationTemplateRepo.Get(ctx, systemNotificationTemplateId) + if err != nil { + return fmt.Errorf("Invalid systemNotificationTemplateId") + } + systemNotificationTemplates = append(systemNotificationTemplates, systemNotificationTemplate) + } + err = u.repo.UpdateSystemNotificationTemplates(ctx, organizationId, systemNotificationTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_SYSTEM_NOTIFICATION_TEMPLATES", "") + } + return nil } diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 33dae263..7004d79b 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -48,9 +48,7 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTempla dto.CreatorId = &userId dto.UpdatorId = &userId - pg := pagination.NewPaginationWithFilter("name", "", "$eq", []string{dto.Name}) - stackTemplates, _ := u.Fetch(ctx, pg) - if len(stackTemplates) > 0 { + if _, err = u.GetByName(ctx, dto.Name); err == nil { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate stackTemplate name"), "ST_CREATE_ALREADY_EXISTED_NAME", "") } diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go new file mode 100644 index 00000000..8aa4c384 --- /dev/null +++ b/internal/usecase/system-notification-rule.go @@ -0,0 +1,107 @@ +package usecase + +import ( + "context" + "fmt" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/pkg/errors" + "gorm.io/gorm" +) + +type ISystemNotificationRuleUsecase interface { + Get(ctx context.Context, systemNotificationRuleId uuid.UUID) (model.SystemNotificationRule, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotificationRule, error) + Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRule uuid.UUID, err error) + Update(ctx context.Context, dto model.SystemNotificationRule) error + Delete(ctx context.Context, dto model.SystemNotificationRule) error + UpdateOrganizations(ctx context.Context, dto model.SystemNotificationRule) error + GetByName(ctx context.Context, name string) (model.SystemNotificationRule, error) +} + +type SystemNotificationRuleUsecase struct { + repo repository.ISystemNotificationRuleRepository + organizationRepo repository.IOrganizationRepository +} + +func NewSystemNotificationRuleUsecase(r repository.Repository) ISystemNotificationRuleUsecase { + return &SystemNotificationRuleUsecase{ + repo: r.SystemNotificationRule, + organizationRepo: r.Organization, + } +} + +func (u *SystemNotificationRuleUsecase) Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRuleId uuid.UUID, err error) { + user, ok := request.UserFrom(ctx) + if !ok { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + } + userId := user.GetUserId() + dto.CreatorId = &userId + dto.UpdatorId = &userId + + if _, err = u.GetByName(ctx, dto.Name); err == nil { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate systemNotificationRule name"), "ST_CREATE_ALREADY_EXISTED_NAME", "") + } + + return systemNotificationRuleId, nil +} + +func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.SystemNotificationRule) error { + _, err := u.repo.Get(ctx, dto.ID) + if err != nil { + return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") + } + + err = u.repo.Update(ctx, dto) + if err != nil { + return err + } + return nil +} + +func (u *SystemNotificationRuleUsecase) Get(ctx context.Context, systemNotificationRuleId uuid.UUID) (res model.SystemNotificationRule, err error) { + res, err = u.repo.Get(ctx, systemNotificationRuleId) + if err != nil { + return res, err + } + return +} + +func (u *SystemNotificationRuleUsecase) GetByName(ctx context.Context, name string) (out model.SystemNotificationRule, err error) { + out, err = u.repo.GetByName(ctx, name) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return out, httpErrors.NewNotFoundError(err, "SNR_FAILED_FETCH_STACK_TEMPLATE", "") + } + return out, err + } + + return +} + +func (u *SystemNotificationRuleUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (res []model.SystemNotificationRule, err error) { + res, err = u.repo.FetchWithOrganization(ctx, organizationId, pg) + if err != nil { + return nil, err + } + return res, nil +} + +func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { + return nil +} + +func (u *SystemNotificationRuleUsecase) UpdateOrganizations(ctx context.Context, dto model.SystemNotificationRule) error { + _, err := u.repo.Get(ctx, dto.ID) + if err != nil { + return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") + } + + return nil +} diff --git a/internal/usecase/system-notification-template.go b/internal/usecase/system-notification-template.go new file mode 100644 index 00000000..f4f4acf1 --- /dev/null +++ b/internal/usecase/system-notification-template.go @@ -0,0 +1,141 @@ +package usecase + +import ( + "context" + "fmt" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" + "gorm.io/gorm" +) + +type ISystemNotificationTemplateUsecase interface { + Get(ctx context.Context, alertId uuid.UUID) (model.SystemNotificationTemplate, error) + GetByName(ctx context.Context, name string) (model.SystemNotificationTemplate, error) + Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.SystemNotificationTemplate, error) + Create(ctx context.Context, dto model.SystemNotificationTemplate) (systemNotificationTemplate uuid.UUID, err error) + Update(ctx context.Context, dto model.SystemNotificationTemplate) error + Delete(ctx context.Context, dto model.SystemNotificationTemplate) error +} + +type SystemNotificationTemplateUsecase struct { + repo repository.ISystemNotificationTemplateRepository + clusterRepo repository.IClusterRepository + organizationRepo repository.IOrganizationRepository + appGroupRepo repository.IAppGroupRepository +} + +func NewSystemNotificationTemplateUsecase(r repository.Repository) ISystemNotificationTemplateUsecase { + return &SystemNotificationTemplateUsecase{ + repo: r.SystemNotificationTemplate, + clusterRepo: r.Cluster, + appGroupRepo: r.AppGroup, + organizationRepo: r.Organization, + } +} + +func (u *SystemNotificationTemplateUsecase) Create(ctx context.Context, dto model.SystemNotificationTemplate) (systemNotificationTemplate uuid.UUID, err error) { + user, ok := request.UserFrom(ctx) + if !ok { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + } + userId := user.GetUserId() + dto.CreatorId = &userId + dto.UpdatorId = &userId + + if _, err = u.GetByName(ctx, dto.Name); err == nil { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate systemNotificationTemplate name"), "SNT_CREATE_ALREADY_EXISTED_NAME", "") + } + + systemNotificationTemplate, err = u.repo.Create(ctx, dto) + if err != nil { + return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") + } + log.Info(ctx, "newly created SystemNotificationTemplate ID:", systemNotificationTemplate) + + dto.ID = systemNotificationTemplate + err = u.UpdateOrganizations(ctx, dto) + if err != nil { + return uuid.Nil, err + } + + return systemNotificationTemplate, nil +} + +func (u *SystemNotificationTemplateUsecase) Update(ctx context.Context, dto model.SystemNotificationTemplate) error { + _, err := u.repo.Get(ctx, dto.ID) + if err != nil { + return httpErrors.NewBadRequestError(err, "SNT_NOT_EXISTED_ALERT_TEMPLATE", "") + } + + err = u.repo.Update(ctx, dto) + if err != nil { + return err + } + + err = u.UpdateOrganizations(ctx, dto) + if err != nil { + return err + } + return nil +} + +func (u *SystemNotificationTemplateUsecase) Get(ctx context.Context, systemNotificationTemplate uuid.UUID) (alert model.SystemNotificationTemplate, err error) { + alert, err = u.repo.Get(ctx, systemNotificationTemplate) + if err != nil { + return alert, err + } + return +} + +func (u *SystemNotificationTemplateUsecase) GetByName(ctx context.Context, name string) (out model.SystemNotificationTemplate, err error) { + out, err = u.repo.GetByName(ctx, name) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return out, httpErrors.NewNotFoundError(err, "SNT_FAILED_FETCH_ALERT_TEMPLATE", "") + } + return out, err + } + + return +} + +func (u *SystemNotificationTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (alerts []model.SystemNotificationTemplate, err error) { + alerts, err = u.repo.Fetch(ctx, pg) + if err != nil { + return nil, err + } + return +} + +func (u *SystemNotificationTemplateUsecase) Delete(ctx context.Context, dto model.SystemNotificationTemplate) (err error) { + return nil +} + +func (u *SystemNotificationTemplateUsecase) UpdateOrganizations(ctx context.Context, dto model.SystemNotificationTemplate) error { + _, err := u.repo.Get(ctx, dto.ID) + if err != nil { + return httpErrors.NewBadRequestError(err, "SNT_NOT_EXISTED_ALERT_TEMPLATE", "") + } + + organizations := make([]model.Organization, 0) + for _, organizationId := range dto.OrganizationIds { + organization, err := u.organizationRepo.Get(ctx, organizationId) + if err == nil { + organizations = append(organizations, organization) + } + } + + err = u.repo.UpdateOrganizations(ctx, dto.ID, organizations) + if err != nil { + return httpErrors.NewBadRequestError(err, "SNT_FAILED_UPDATE_ORGANIZATION", "") + } + + return nil +} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index 9053100d..181d1f31 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -1,20 +1,22 @@ package usecase type Usecase struct { - Auth IAuthUsecase - User IUserUsecase - Cluster IClusterUsecase - Organization IOrganizationUsecase - AppGroup IAppGroupUsecase - AppServeApp IAppServeAppUsecase - CloudAccount ICloudAccountUsecase - StackTemplate IStackTemplateUsecase - Dashboard IDashboardUsecase - SystemNotification ISystemNotificationUsecase - Stack IStackUsecase - Project IProjectUsecase - Role IRoleUsecase - Permission IPermissionUsecase - Audit IAuditUsecase - PolicyTemplate IPolicyTemplateUsecase + Auth IAuthUsecase + User IUserUsecase + Cluster IClusterUsecase + Organization IOrganizationUsecase + AppGroup IAppGroupUsecase + AppServeApp IAppServeAppUsecase + CloudAccount ICloudAccountUsecase + StackTemplate IStackTemplateUsecase + Dashboard IDashboardUsecase + SystemNotification ISystemNotificationUsecase + SystemNotificationTemplate ISystemNotificationTemplateUsecase + SystemNotificationRule ISystemNotificationRuleUsecase + Stack IStackUsecase + Project IProjectUsecase + Role IRoleUsecase + Permission IPermissionUsecase + Audit IAuditUsecase + PolicyTemplate IPolicyTemplateUsecase } diff --git a/pkg/domain/alert.go b/pkg/domain/alert.go new file mode 100644 index 00000000..a60073bf --- /dev/null +++ b/pkg/domain/alert.go @@ -0,0 +1,137 @@ +package domain + +import ( + "time" + + "github.com/google/uuid" +) + +// enum +type AlertActionStatus int32 + +const ( + AlertActionStatus_CREATED AlertActionStatus = iota + AlertActionStatus_INPROGRESS + AlertActionStatus_CLOSED + AlertActionStatus_ERROR +) + +var alertActionStatus = [...]string{ + "CREATED", + "INPROGRESS", + "CLOSED", + "ERROR", +} + +func (m AlertActionStatus) String() string { return alertActionStatus[(m)] } +func (m AlertActionStatus) FromString(s string) AlertActionStatus { + for i, v := range alertActionStatus { + if v == s { + return AlertActionStatus(i) + } + } + return AlertActionStatus_ERROR +} + +type CreateAlertRequestAlert struct { + Status string `json:"status"` + GeneratorURL string `json:"generatorURL"` + FingerPrint string `json:"fingerprint"` + StartsAt time.Time `json:"startsAt"` + EndsAt time.Time `json:"endsAt"` + Labels struct { + AlertName string `json:"alertname"` + Container string `json:"container"` + Endpoint string `json:"endpoint"` + Job string `json:"job"` + Namespace string `json:"namespace"` + Pod string `json:"pod"` + Prometheus string `json:"prometheus"` + Service string `json:"service"` + Severity string `json:"severity"` + Instance string `json:"instance"` + TacoCluster string `json:"taco_cluster"` + } `json:"labels"` + Annotations struct { + Message string `json:"message"` + Summary string `json:"summary"` + Description string `json:"description"` + Checkpoint string `json:"Checkpoint"` + Discriminative string `json:"discriminative"` + } `json:"annotations"` +} + +type CreateAlertRequest struct { + Receiver string `json:"receiver"` + Status string `json:"status"` + ExternalURL string `json:"externalURL"` + Version string `json:"version"` + GroupKey string `json:"groupKey"` + TruncateAlerts int `json:"truncateAlerts"` + Alerts []CreateAlertRequestAlert `json:"alerts"` + GroupLabels struct { + Alertname string `json:"alertname"` + } `json:"groupLabels"` + //CommonLabels string `json:"commonLabels"` + //CommonAnnotations string `json:"commonAnnotations"` +} + +type AlertResponse struct { + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + Message string `json:"message"` + Code string `json:"code"` + Grade string `json:"grade"` + Cluster SimpleClusterResponse `json:"cluster"` + GrafanaUrl string `json:"grafanaUrl"` + Node string `json:"node"` + FiredAt *time.Time `json:"firedAt"` + TakedAt *time.Time `json:"takedAt"` + ClosedAt *time.Time `json:"closedAt"` + Status string `json:"status"` + ProcessingSec int `json:"processingSec"` + TakedSec int `json:"takedSec"` + AlertActions []AlertActionResponse `json:"alertActions"` + LastTaker SimpleUserResponse `json:"lastTaker"` + RawData string `json:"rawData"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type AlertActionResponse struct { + ID uuid.UUID `json:"id"` + AlertId uuid.UUID `json:"alertId"` + Content string `json:"content"` + Status string `json:"status"` + Taker SimpleUserResponse `json:"taker"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type GetAlertsResponse struct { + Alerts []AlertResponse `json:"alerts"` + Pagination PaginationResponse `json:"pagination"` +} + +type GetAlertResponse struct { + Alert AlertResponse `json:"alert"` +} + +type CreateAlertResponse struct { + ID string `json:"id"` +} + +type UpdateAlertRequest struct { + Description string `json:"description"` +} + +type CreateAlertActionRequest struct { + Content string `json:"content"` + Status string `json:"status" validate:"oneof=INPROGRESS CLOSED"` +} + +type CreateAlertActionResponse struct { + ID string `json:"id"` +} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 3e330fa6..8f97f42d 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -49,18 +49,19 @@ func (m OrganizationStatus) FromString(s string) OrganizationStatus { } type OrganizationResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - PrimaryClusterId string `json:"primaryClusterId"` - Status string `json:"status"` - StatusDesc string `json:"statusDesc"` - StackTemplates []SimpleStackTemplateResponse `json:"stackTemplates"` - PolicyTemplates []SimplePolicyTemplateResponse `json:"policyTemplates"` - Admin SimpleUserResponse `json:"admin"` - ClusterCount int `json:"stackCount"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + PrimaryClusterId string `json:"primaryClusterId"` + Status string `json:"status"` + StatusDesc string `json:"statusDesc"` + StackTemplates []SimpleStackTemplateResponse `json:"stackTemplates"` + PolicyTemplates []SimplePolicyTemplateResponse `json:"policyTemplates"` + SystemNotificationTemplates []SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplates"` + Admin SimpleUserResponse `json:"admin"` + ClusterCount int `json:"stackCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type SimpleOrganizationResponse = struct { diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go new file mode 100644 index 00000000..e21e3477 --- /dev/null +++ b/pkg/domain/system-notification-rule.go @@ -0,0 +1,47 @@ +package domain + +import ( + "time" +) + +type SystemNotificationRuleResponse struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type SimpleSystemNotificationRuleResponse struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` +} + +type GetSystemNotificationRulesResponse struct { + SystemNotificationRules []SystemNotificationRuleResponse `json:"systemNotificationRules"` + Pagination PaginationResponse `json:"pagination"` +} + +type GetSystemNotificationRuleResponse struct { + SystemNotificationRule SystemNotificationRuleResponse `json:"systemNotificationRule"` +} + +type CreateSystemNotificationRuleRequest struct { + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` +} + +type CreateSystemNotificationRuleResponse struct { + ID string `json:"id"` +} + +type UpdateSystemNotificationRuleRequest struct { + Description string `json:"description"` +} + +type CheckSystemNotificationRuleNameResponse struct { + Existed bool `json:"existed"` +} diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go new file mode 100644 index 00000000..d4ef68c5 --- /dev/null +++ b/pkg/domain/system-notification-template.go @@ -0,0 +1,61 @@ +package domain + +import ( + "time" +) + +type SystemNotificationTemplateResponse struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + MetricQuery string `json:"metricQuery" validate:"required"` + MetricParameters []MetricParameterResponse `json:"metricParameters,omitempty"` + Organizations []SimpleOrganizationResponse `json:"organizations,omitempty"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type SimpleSystemNotificationTemplateResponse struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type MetricParameterResponse struct { + Order int `json:"order" validate:"required"` + Key string `json:"key" validate:"required,name"` + Value string `json:"value" validate:"required"` +} + +type CreateSystemNotificationTemplateRequest struct { + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + OrganizationIds []string `json:"organizationIds" validate:"required"` + MetricQuery string `json:"metricQuery" validate:"required"` + MetricParameters []MetricParameterResponse `json:"metricParameters"` +} + +type CreateSystemNotificationTemplateResponse struct { + ID string `json:"id"` +} + +type UpdateSystemNotificationTemplateRequest struct { + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + OrganizationIds []string `json:"organizationIds" validate:"required"` + MetricQuery string `json:"metricQuery" validate:"required"` + MetricParameters []MetricParameterResponse `json:"metricParameters"` +} + +type GetSystemNotificationTemplatesResponse struct { + SystemNotificationTemplates []SystemNotificationTemplateResponse `json:"systemNotificationTemplates"` + Pagination PaginationResponse `json:"pagination"` +} + +type GetSystemNotificationTemplateResponse struct { + SystemNotificationTemplate SystemNotificationTemplateResponse `json:"systemNotificationTemplate"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 30bcb76e..a6acff9c 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -4,21 +4,22 @@ type ErrorCode string var errorMap = map[ErrorCode]string{ // Common - "C_INTERNAL_ERROR": "예상하지 못한 오류가 발생했습니다. 문제가 계속되면 관리자에게 문의해주세요.", - "C_INVALID_ACCOUNT_ID": "유효하지 않은 어카운트 아이디입니다. 어카운트 아이디를 확인하세요.", - "C_INVALID_STACK_ID": "유효하지 않은 스택 아이디입니다. 스택 아이디를 확인하세요.", - "C_INVALID_CLUSTER_ID": "유효하지 않은 클러스터 아이디입니다. 클러스터 아이디를 확인하세요.", - "C_INVALID_APPGROUP_ID": "유효하지 않은 앱그룹 아이디입니다. 앱그룹 아이디를 확인하세요.", - "C_INVALID_ORGANIZATION_ID": "유효하지 않은 조직 아이디입니다. 조직 아이디를 확인하세요.", - "C_INVALID_PROJECT_ID": "유효하지 않은 프로젝트 아이디입니다. 아이디를 확인하세요.", - "C_INVALID_CLOUD_ACCOUNT_ID": "유효하지 않은 클라우드어카운트 아이디입니다. 클라우드어카운트 아이디를 확인하세요.", - "C_INVALID_STACK_TEMPLATE_ID": "유효하지 않은 스택템플릿 아이디입니다. 스택템플릿 아이디를 확인하세요.", - "C_INVALID_ASA_ID": "유효하지 않은 앱서빙앱 아이디입니다. 앱서빙앱 아이디를 확인하세요.", - "C_INVALID_ASA_TASK_ID": "유효하지 않은 테스크 아이디입니다. 테스크 아이디를 확인하세요.", - "C_INVALID_CLOUD_SERVICE": "유효하지 않은 클라우드서비스입니다.", - "C_INVALID_AUDIT_ID": "유효하지 않은 로그 아이디입니다. 로그 아이디를 확인하세요.", - "C_INVALID_POLICY_TEMPLATE_ID": "유효하지 않은 정책 템플릿 아이디입니다. 정책 템플릿 아이디를 확인하세요.", - "C_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패했습니다.", + "C_INTERNAL_ERROR": "예상하지 못한 오류가 발생했습니다. 문제가 계속되면 관리자에게 문의해주세요.", + "C_INVALID_ACCOUNT_ID": "유효하지 않은 어카운트 아이디입니다. 어카운트 아이디를 확인하세요.", + "C_INVALID_STACK_ID": "유효하지 않은 스택 아이디입니다. 스택 아이디를 확인하세요.", + "C_INVALID_CLUSTER_ID": "유효하지 않은 클러스터 아이디입니다. 클러스터 아이디를 확인하세요.", + "C_INVALID_APPGROUP_ID": "유효하지 않은 앱그룹 아이디입니다. 앱그룹 아이디를 확인하세요.", + "C_INVALID_ORGANIZATION_ID": "유효하지 않은 조직 아이디입니다. 조직 아이디를 확인하세요.", + "C_INVALID_PROJECT_ID": "유효하지 않은 프로젝트 아이디입니다. 아이디를 확인하세요.", + "C_INVALID_CLOUD_ACCOUNT_ID": "유효하지 않은 클라우드어카운트 아이디입니다. 클라우드어카운트 아이디를 확인하세요.", + "C_INVALID_STACK_TEMPLATE_ID": "유효하지 않은 스택템플릿 아이디입니다. 스택템플릿 아이디를 확인하세요.", + "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID": "유효하지 않은 알림템플릿 아이디입니다. 알림템플릿 아이디를 확인하세요.", + "C_INVALID_ASA_ID": "유효하지 않은 앱서빙앱 아이디입니다. 앱서빙앱 아이디를 확인하세요.", + "C_INVALID_ASA_TASK_ID": "유효하지 않은 테스크 아이디입니다. 테스크 아이디를 확인하세요.", + "C_INVALID_CLOUD_SERVICE": "유효하지 않은 클라우드서비스입니다.", + "C_INVALID_AUDIT_ID": "유효하지 않은 로그 아이디입니다. 로그 아이디를 확인하세요.", + "C_INVALID_POLICY_TEMPLATE_ID": "유효하지 않은 정책 템플릿 아이디입니다. 정책 템플릿 아이디를 확인하세요.", + "C_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패했습니다.", // Auth "A_INVALID_ID": "아이디가 존재하지 않습니다.", @@ -76,8 +77,20 @@ var errorMap = map[ErrorCode]string{ "S_INVALID_CLUSTER_ID": "BYOH 타입의 클러스터 생성은 반드시 clusterId 값이 필요합니다.", "S_INVALID_CLOUD_SERVICE": "클라우드 서비스 타입이 잘못되었습니다.", - // Event - "EV_NOT_FOUND_EVENT": "지정한 앨럿이 존재하지 않습니다.", + // Alert + "AL_NOT_FOUND_ALERT": "지정한 앨럿이 존재하지 않습니다.", + + // SystemNotificationTemplate + "SNT_CREATE_ALREADY_EXISTED_NAME": "알림템플릿에 이미 존재하는 이름입니다.", + "SNT_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿을 가져오는데 실패했습니다.", + "SNT_FAILED_UPDATE_ORGANIZATION": "알림템플릿에 조직을 설정하는데 실패했습니다.", + "SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.", + + // SystemNotificationRule + "SNR_CREATE_ALREADY_EXISTED_NAME": "알림템플릿 설정에 이미 존재하는 이름입니다.", + "SNR_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿 설정을 가져오는데 실패했습니다.", + "SNR_FAILED_UPDATE_ORGANIZATION": "알림템플릿 설정에 조직을 설정하는데 실패했습니다.", + "SNR_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿 설정이 존재하지 않습니다.", // AppGroup "AG_NOT_FOUND_CLUSTER": "지장한 클러스터가 존재하지 않습니다.", @@ -86,8 +99,8 @@ var errorMap = map[ErrorCode]string{ "AG_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패하였습니다.", // StackTemplate - "ST_CREATE_ALREADY_EXISTED_NAME": "스택 템플릿에 이미 존재하는 이름입니다.", - "ST_FAILED_UPDATE_ORGANIZATION": "스택 템플릿에 조직을 설정하는데 실패했습니다.", + "ST_CREATE_ALREADY_EXISTED_NAME": "스택템플릿에 이미 존재하는 이름입니다.", + "ST_FAILED_UPDATE_ORGANIZATION": "스택템플릿에 조직을 설정하는데 실패했습니다.", "ST_NOT_EXISTED_STACK_TEMPLATE": "업데이트할 스택템플릿이 존재하지 않습니다.", "ST_INVALID_STACK_TEMAPLTE_NAME": "유효하지 않은 스택템플릿 이름입니다. 스택템플릿 이름을 확인하세요.", "ST_FAILED_FETCH_STACK_TEMPLATE": "스택템플릿을 가져오는데 실패했습니다.", From b0d8cedbf0c0cfed8c23a98fa64de3239ac43731 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 19 Mar 2024 19:16:32 +0900 Subject: [PATCH 142/502] minor fix: add project role in access token --- internal/delivery/http/project.go | 17 ++++--- internal/keycloak/keycloak.go | 35 +++++++++++++- internal/repository/project.go | 2 + internal/usecase/project.go | 80 +++++++++++++++++++++++-------- 4 files changed, 105 insertions(+), 29 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index a8216219..4b12576a 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -108,6 +108,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } + log.Debugf(r.Context(), "projectId = [%s]\n", projectId) project.ID = projectId ProjectLeaderId, err := uuid.Parse(projectReq.ProjectLeaderId) if err != nil { @@ -134,7 +135,9 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { CreatedAt: now, } - projectMemberId, err := p.usecase.AddProjectMember(r.Context(), pm) + log.Debugf(r.Context(), "pm = [%+v]\n", pm) + + projectMemberId, err := p.usecase.AddProjectMember(r.Context(), organizationId, pm) if err != nil { log.Errorf(r.Context(), "projectMemberId: %v", projectMemberId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -594,7 +597,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) ProjectRole: nil, CreatedAt: now, } - pmId, err := p.usecase.AddProjectMember(r.Context(), pm) + pmId, err := p.usecase.AddProjectMember(r.Context(), organizationId, pm) if err != nil { log.Errorf(r.Context(), "projectMemberId: %s", pmId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -603,7 +606,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pmId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, pmId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -875,7 +878,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } } - if err := p.usecase.RemoveProjectMember(r.Context(), projectMemberId); err != nil { + if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, projectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -943,7 +946,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ } } - if err := p.usecase.RemoveProjectMember(r.Context(), pm.ProjectMemberId); err != nil { + if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, pm.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1039,7 +1042,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } // tasks for keycloak & k8s. Assign new role for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1130,7 +1133,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 3304800a..dcb8be03 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -44,6 +44,7 @@ type IKeycloak interface { VerifyAccessToken(ctx context.Context, token string, organizationId string) (bool, error) GetSessions(ctx context.Context, userId string, organizationId string) (*[]string, error) + SetClientScopeRolesToOptionalToTksClient(ctx context.Context, organizationId string) error } type Keycloak struct { config *Config @@ -75,6 +76,34 @@ func New(config *Config) IKeycloak { config: config, } } + +func (k *Keycloak) SetClientScopeRolesToOptionalToTksClient(ctx context.Context, organizationId string) error { + token := k.adminCliToken + c, err := k.client.GetClients(context.TODO(), token.AccessToken, organizationId, gocloak.GetClientsParams{ + ClientID: gocloak.StringP(DefaultClientID), + }) + if err != nil { + return err + } + + defaultClientScopes, err := k.client.GetClientsDefaultScopes(context.TODO(), token.AccessToken, organizationId, *c[0].ID) + if err != nil { + return err + } + for _, defaultClientScope := range defaultClientScopes { + if *defaultClientScope.Name == "roles" { + if err := k.client.RemoveDefaultScopeFromClient(context.TODO(), token.AccessToken, organizationId, *c[0].ID, *defaultClientScope.ID); err != nil { + return err + } + if err := k.client.AddOptionalScopeToClient(context.TODO(), token.AccessToken, organizationId, *c[0].ID, *defaultClientScope.ID); err != nil { + return err + } + } + } + + return nil +} + func (k *Keycloak) InitializeKeycloak(ctx context.Context) error { k.client = gocloak.NewClient(k.config.Address) restyClient := k.client.RestyClient() @@ -132,6 +161,8 @@ func (k *Keycloak) InitializeKeycloak(ctx context.Context) error { return err } + err = k.SetClientScopeRolesToOptionalToTksClient(ctx, DefaultMasterRealm) + for _, defaultMapper := range defaultProtocolTksMapper { if err := k.ensureClientProtocolMappers(ctx, token, DefaultMasterRealm, *adminCliClient.ClientID, "openid", defaultMapper); err != nil { log.Fatal(ctx, err) @@ -177,6 +208,8 @@ func (k *Keycloak) CreateRealm(ctx context.Context, organizationId string) (stri return "", err } + err = k.SetClientScopeRolesToOptionalToTksClient(ctx, organizationId) + for _, defaultMapper := range defaultProtocolTksMapper { if *defaultMapper.Name == "org" { defaultMapper.Config = &map[string]string{ @@ -527,7 +560,7 @@ func (k *Keycloak) AssignClientRoleToUser(ctx context.Context, organizationId st return nil } - err = k.client.AddClientRolesToUser(context.Background(), token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) + err = k.client.AddClientRolesToUser(context.Background(), token.AccessToken, organizationId, *targetClient.ID, userId, []gocloak.Role{*roles[0]}) if err != nil { log.Error(ctx, "Assigning Client Role to User is failed", err) diff --git a/internal/repository/project.go b/internal/repository/project.go index 53c4041d..3a744d65 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -61,6 +61,7 @@ func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) return "", res.Error } + log.Debugf(ctx, "CreateProject: %+v", p) return p.ID, nil } @@ -367,6 +368,7 @@ func (r *ProjectRepository) GetProjectRoleByName(ctx context.Context, name strin } func (r *ProjectRepository) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { + log.Debugf(ctx, "AddProjectMember: %+v", pm) pm.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&pm) if res.Error != nil { diff --git a/internal/usecase/project.go b/internal/usecase/project.go index ff773d0d..4f7b5cef 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -37,12 +37,12 @@ type IProjectUsecase interface { UpdateProject(ctx context.Context, p *model.Project, newLeaderId string) error GetProjectRole(ctx context.Context, id string) (*model.ProjectRole, error) GetProjectRoles(ctx context.Context, query int) ([]model.ProjectRole, error) - AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) + AddProjectMember(ctx context.Context, organizationId string, pm *model.ProjectMember) (string, error) GetProjectUser(ctx context.Context, projectUserId string) (*model.ProjectUser, error) GetProjectMember(ctx context.Context, projectMemberId string) (*model.ProjectMember, error) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) ([]model.ProjectMember, error) GetProjectMemberCount(ctx context.Context, projectMemberId string) (*domain.GetProjectMemberCountResponse, error) - RemoveProjectMember(ctx context.Context, projectMemberId string) error + RemoveProjectMember(ctx context.Context, organizationId string, projectMemberId string) error UpdateProjectMemberRole(ctx context.Context, pm *model.ProjectMember) error CreateProjectNamespace(ctx context.Context, organizationId string, pn *model.ProjectNamespace) error IsProjectNamespaceExist(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) @@ -58,7 +58,7 @@ type IProjectUsecase interface { GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) - AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error + AssignKeycloakClientRoleToMemberForK8s(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error } @@ -93,6 +93,21 @@ func (u *ProjectUsecase) CreateProject(ctx context.Context, p *model.Project) (s return "", errors.Wrap(err, "Failed to create project.") } + prs, err := u.GetProjectRoles(ctx, ProjectAll) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to retrieve project roles.") + } + log.Debugf(ctx, "Project roles: %v", prs) + for _, pr := range prs { + log.Debugf(ctx, "Start to create Project role: %s. orgId: %s, projectId: %s", pr.Name, p.OrganizationId, projectId) + err = u.kc.EnsureClientRoleWithClientName(ctx, p.OrganizationId, keycloak.DefaultClientID, pr.Name+"@"+projectId) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to create project setting on keycloak.") + } + } + return projectId, nil } @@ -171,7 +186,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne } if newLeaderId != "" && currentLeaderId != newLeaderId { - if err := u.RemoveProjectMember(ctx, currentMemberId); err != nil { + if err := u.RemoveProjectMember(ctx, p.OrganizationId, currentMemberId); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to remove project member.") } @@ -198,7 +213,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne IsProjectLeader: true, CreatedAt: *p.UpdatedAt, } - res, err := u.AddProjectMember(ctx, newPm) + res, err := u.AddProjectMember(ctx, p.OrganizationId, newPm) if err != nil { return err } @@ -254,12 +269,26 @@ func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs [] return prs, nil } -func (u *ProjectUsecase) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { +func (u *ProjectUsecase) AddProjectMember(ctx context.Context, organizationId string, pm *model.ProjectMember) (string, error) { projectMemberId, err := u.projectRepo.AddProjectMember(ctx, pm) if err != nil { log.Error(ctx, err) return "", errors.Wrap(err, "Failed to add project member to project.") } + + pr, err := u.GetProjectRole(ctx, pm.ProjectRoleId) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to get project roles.") + } + + // assign keycloak client role to member + err = u.kc.AssignClientRoleToUser(ctx, organizationId, pm.ProjectUserId.String(), keycloak.DefaultClientID, pr.Name+"@"+pm.ProjectId) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to assign keycloak client role to member.") + } + return projectMemberId, nil } @@ -322,11 +351,24 @@ func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMembe return pmcr, nil } -func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, projectMemberId string) error { +func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, organizationId string, projectMemberId string) error { + pm, err := u.GetProjectMember(ctx, projectMemberId) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to get project member to project.") + } + // unassign keycloak client role to member + err = u.kc.UnassignClientRoleToUser(ctx, organizationId, pm.ProjectUserId.String(), keycloak.DefaultClientID, pm.ProjectRole.Name+"@"+pm.ProjectId) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to remove project member to project.") + } + if err := u.projectRepo.RemoveProjectMember(ctx, projectMemberId); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to remove project member to project.") } + return nil } @@ -448,7 +490,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga return errors.Wrap(err, "Failed to create project namespace.") } for _, pm := range projectMembers { - err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -486,7 +528,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o return errors.Wrap(err, "Failed to create project namespace.") } for _, pm := range projectMembers { - err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -574,11 +616,7 @@ func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organiza log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.kc.EnsureClientRoleWithClientName(ctx, organizationId, keycloak.DefaultClientID, role+"@"+projectId) - if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") - } + } return nil } @@ -621,13 +659,13 @@ func (u *ProjectUsecase) DeleteK8SNSRoleBinding(ctx context.Context, organizatio panic("implement me") } -func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { +func (u *ProjectUsecase) AssignKeycloakClientRoleToMemberForK8s(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -635,8 +673,8 @@ func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, o return nil } -func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { - err := u.kc.AssignClientRoleToUser(ctx, organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) +func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, userId string, roleName string) error { + err := u.kc.AssignClientRoleToUser(ctx, organizationId, userId, clientId, roleName+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -650,7 +688,7 @@ func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -658,8 +696,8 @@ func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, return nil } -func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { - err := u.kc.UnassignClientRoleToUser(ctx, organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) +func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, userId string, roleName string) error { + err := u.kc.UnassignClientRoleToUser(ctx, organizationId, userId, clientId, roleName+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") From eb4db7d94cd079de2207bae95d9544fd86d9418d Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 19 Mar 2024 19:19:57 +0900 Subject: [PATCH 143/502] minor fix. --- internal/delivery/http/project.go | 3 --- internal/keycloak/keycloak.go | 8 ++++++++ internal/repository/project.go | 2 -- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 4b12576a..defcf78a 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -108,7 +108,6 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } - log.Debugf(r.Context(), "projectId = [%s]\n", projectId) project.ID = projectId ProjectLeaderId, err := uuid.Parse(projectReq.ProjectLeaderId) if err != nil { @@ -135,8 +134,6 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { CreatedAt: now, } - log.Debugf(r.Context(), "pm = [%+v]\n", pm) - projectMemberId, err := p.usecase.AddProjectMember(r.Context(), organizationId, pm) if err != nil { log.Errorf(r.Context(), "projectMemberId: %v", projectMemberId) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index dcb8be03..18cb0cf3 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -162,6 +162,10 @@ func (k *Keycloak) InitializeKeycloak(ctx context.Context) error { } err = k.SetClientScopeRolesToOptionalToTksClient(ctx, DefaultMasterRealm) + if err != nil { + log.Fatal(ctx, err) + return err + } for _, defaultMapper := range defaultProtocolTksMapper { if err := k.ensureClientProtocolMappers(ctx, token, DefaultMasterRealm, *adminCliClient.ClientID, "openid", defaultMapper); err != nil { @@ -209,6 +213,10 @@ func (k *Keycloak) CreateRealm(ctx context.Context, organizationId string) (stri } err = k.SetClientScopeRolesToOptionalToTksClient(ctx, organizationId) + if err != nil { + log.Error(ctx, err, "SetClientScopeRolesToOptionalToTksClient") + return "", err + } for _, defaultMapper := range defaultProtocolTksMapper { if *defaultMapper.Name == "org" { diff --git a/internal/repository/project.go b/internal/repository/project.go index 3a744d65..53c4041d 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -61,7 +61,6 @@ func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) return "", res.Error } - log.Debugf(ctx, "CreateProject: %+v", p) return p.ID, nil } @@ -368,7 +367,6 @@ func (r *ProjectRepository) GetProjectRoleByName(ctx context.Context, name strin } func (r *ProjectRepository) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { - log.Debugf(ctx, "AddProjectMember: %+v", pm) pm.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&pm) if res.Error != nil { From d568d52c09088c22fa1f67273d908be43e342429 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 19 Mar 2024 20:25:13 +0900 Subject: [PATCH 144/502] minor fix. --- internal/delivery/http/project.go | 68 +++++++++++++++++++++++++++---- internal/keycloak/keycloak.go | 2 +- internal/usecase/project.go | 38 ++++++----------- 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index defcf78a..ba66719a 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -2,6 +2,7 @@ package http import ( "fmt" + "github.com/openinfradev/tks-api/internal/keycloak" "net/http" "strings" "time" @@ -141,6 +142,13 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } + err = p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, projectMemberId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + out := domain.CreateProjectResponse{ProjectId: projectId} ResponseJSON(w, r, http.StatusOK, out) @@ -601,9 +609,16 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } + err = p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pmId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, pmId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pmId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -867,8 +882,16 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque for _, pn := range pns { stackIds[pn.StackId] = struct{}{} } + + err = p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, projectMemberId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", projectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -934,9 +957,15 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // TODO: change multi row delete for _, pm := range projectMemberReq.ProjectMember { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pm.ProjectMemberId); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ProjectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pm.ProjectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1009,6 +1038,12 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R return } + if err = p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, projectMemberId); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { log.Error(r.Context(), err) @@ -1021,7 +1056,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } // tasks for keycloak & k8s. Unassign old role for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", projectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1037,9 +1072,16 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R ErrorJSON(w, r, err) return } + + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, projectMemberId); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + // tasks for keycloak & k8s. Assign new role for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", projectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1111,8 +1153,14 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } + if err = p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pm.ID); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pm.ID); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1129,8 +1177,14 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pm.ID); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pm.ID); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 18cb0cf3..ff69db1c 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -608,7 +608,7 @@ func (k *Keycloak) UnassignClientRoleToUser(ctx context.Context, organizationId return nil } - err = k.client.DeleteClientRolesFromUser(context.Background(), token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) + err = k.client.DeleteClientRolesFromUser(context.Background(), token.AccessToken, organizationId, *targetClient.ID, userId, []gocloak.Role{*roles[0]}) if err != nil { log.Error(ctx, "Unassigning Client Role to User is failed", err) return err diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 4f7b5cef..4fbc4382 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -58,8 +58,8 @@ type IProjectUsecase interface { GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) - AssignKeycloakClientRoleToMemberForK8s(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error - UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error + AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error + UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error } type ProjectUsecase struct { @@ -170,6 +170,7 @@ func (u *ProjectUsecase) IsProjectNameExist(ctx context.Context, organizationId } func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, newLeaderId string) error { + //TODO: [donggyu] have to implementation about un/assigning client roles var currentMemberId, currentLeaderId, projectRoleId string for _, pm := range p.ProjectMembers { @@ -276,19 +277,6 @@ func (u *ProjectUsecase) AddProjectMember(ctx context.Context, organizationId st return "", errors.Wrap(err, "Failed to add project member to project.") } - pr, err := u.GetProjectRole(ctx, pm.ProjectRoleId) - if err != nil { - log.Error(ctx, err) - return "", errors.Wrap(err, "Failed to get project roles.") - } - - // assign keycloak client role to member - err = u.kc.AssignClientRoleToUser(ctx, organizationId, pm.ProjectUserId.String(), keycloak.DefaultClientID, pr.Name+"@"+pm.ProjectId) - if err != nil { - log.Error(ctx, err) - return "", errors.Wrap(err, "Failed to assign keycloak client role to member.") - } - return projectMemberId, nil } @@ -479,7 +467,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga return errors.Wrap(err, "Failed to create project namespace.") } - if err := u.createKeycloakClientRoles(ctx, organizationId, projectId, stackId); err != nil { + if err := u.createKeycloakClientRoles(ctx, organizationId, projectId, stackId+"-k8s-api"); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -535,7 +523,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o } } - if err := u.deleteKeycloakClientRoles(ctx, organizationId, projectId, stackId); err != nil { + if err := u.deleteKeycloakClientRoles(ctx, organizationId, projectId, stackId+"-k8s-api"); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -608,10 +596,10 @@ func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizat return nil } -func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, clientId string) error { // create Roles in keycloak for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { - err := u.kc.EnsureClientRoleWithClientName(ctx, organizationId, stackId+"-k8s-api", role+"@"+projectId) + err := u.kc.EnsureClientRoleWithClientName(ctx, organizationId, clientId, role+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -620,12 +608,12 @@ func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organiza } return nil } -func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, clientId string) error { // first check whether the stac // delete Roles in keycloak for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { - err := u.kc.DeleteClientRoleWithClientName(ctx, organizationId, stackId+"-k8s-api", role+"@"+projectId) + err := u.kc.DeleteClientRoleWithClientName(ctx, organizationId, clientId, role+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -659,13 +647,13 @@ func (u *ProjectUsecase) DeleteK8SNSRoleBinding(ctx context.Context, organizatio panic("implement me") } -func (u *ProjectUsecase) AssignKeycloakClientRoleToMemberForK8s(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { +func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, clientId, pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -682,13 +670,13 @@ func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Contex return nil } -func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { +func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, clientId, pm.ProjectUser.ID.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") From fb058344aa2b712a8233a23274e129df6b0e6b14 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 19 Mar 2024 19:16:32 +0900 Subject: [PATCH 145/502] minor fix: add project role in access token --- internal/delivery/http/project.go | 17 ++++--- internal/keycloak/keycloak.go | 35 +++++++++++++- internal/repository/project.go | 2 + internal/usecase/project.go | 80 +++++++++++++++++++++++-------- 4 files changed, 105 insertions(+), 29 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index a8216219..4b12576a 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -108,6 +108,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } + log.Debugf(r.Context(), "projectId = [%s]\n", projectId) project.ID = projectId ProjectLeaderId, err := uuid.Parse(projectReq.ProjectLeaderId) if err != nil { @@ -134,7 +135,9 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { CreatedAt: now, } - projectMemberId, err := p.usecase.AddProjectMember(r.Context(), pm) + log.Debugf(r.Context(), "pm = [%+v]\n", pm) + + projectMemberId, err := p.usecase.AddProjectMember(r.Context(), organizationId, pm) if err != nil { log.Errorf(r.Context(), "projectMemberId: %v", projectMemberId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -594,7 +597,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) ProjectRole: nil, CreatedAt: now, } - pmId, err := p.usecase.AddProjectMember(r.Context(), pm) + pmId, err := p.usecase.AddProjectMember(r.Context(), organizationId, pm) if err != nil { log.Errorf(r.Context(), "projectMemberId: %s", pmId) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -603,7 +606,7 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pmId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, pmId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -875,7 +878,7 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } } - if err := p.usecase.RemoveProjectMember(r.Context(), projectMemberId); err != nil { + if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, projectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -943,7 +946,7 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ } } - if err := p.usecase.RemoveProjectMember(r.Context(), pm.ProjectMemberId); err != nil { + if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, pm.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1039,7 +1042,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } // tasks for keycloak & k8s. Assign new role for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1130,7 +1133,7 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. } for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 3304800a..dcb8be03 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -44,6 +44,7 @@ type IKeycloak interface { VerifyAccessToken(ctx context.Context, token string, organizationId string) (bool, error) GetSessions(ctx context.Context, userId string, organizationId string) (*[]string, error) + SetClientScopeRolesToOptionalToTksClient(ctx context.Context, organizationId string) error } type Keycloak struct { config *Config @@ -75,6 +76,34 @@ func New(config *Config) IKeycloak { config: config, } } + +func (k *Keycloak) SetClientScopeRolesToOptionalToTksClient(ctx context.Context, organizationId string) error { + token := k.adminCliToken + c, err := k.client.GetClients(context.TODO(), token.AccessToken, organizationId, gocloak.GetClientsParams{ + ClientID: gocloak.StringP(DefaultClientID), + }) + if err != nil { + return err + } + + defaultClientScopes, err := k.client.GetClientsDefaultScopes(context.TODO(), token.AccessToken, organizationId, *c[0].ID) + if err != nil { + return err + } + for _, defaultClientScope := range defaultClientScopes { + if *defaultClientScope.Name == "roles" { + if err := k.client.RemoveDefaultScopeFromClient(context.TODO(), token.AccessToken, organizationId, *c[0].ID, *defaultClientScope.ID); err != nil { + return err + } + if err := k.client.AddOptionalScopeToClient(context.TODO(), token.AccessToken, organizationId, *c[0].ID, *defaultClientScope.ID); err != nil { + return err + } + } + } + + return nil +} + func (k *Keycloak) InitializeKeycloak(ctx context.Context) error { k.client = gocloak.NewClient(k.config.Address) restyClient := k.client.RestyClient() @@ -132,6 +161,8 @@ func (k *Keycloak) InitializeKeycloak(ctx context.Context) error { return err } + err = k.SetClientScopeRolesToOptionalToTksClient(ctx, DefaultMasterRealm) + for _, defaultMapper := range defaultProtocolTksMapper { if err := k.ensureClientProtocolMappers(ctx, token, DefaultMasterRealm, *adminCliClient.ClientID, "openid", defaultMapper); err != nil { log.Fatal(ctx, err) @@ -177,6 +208,8 @@ func (k *Keycloak) CreateRealm(ctx context.Context, organizationId string) (stri return "", err } + err = k.SetClientScopeRolesToOptionalToTksClient(ctx, organizationId) + for _, defaultMapper := range defaultProtocolTksMapper { if *defaultMapper.Name == "org" { defaultMapper.Config = &map[string]string{ @@ -527,7 +560,7 @@ func (k *Keycloak) AssignClientRoleToUser(ctx context.Context, organizationId st return nil } - err = k.client.AddClientRolesToUser(context.Background(), token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) + err = k.client.AddClientRolesToUser(context.Background(), token.AccessToken, organizationId, *targetClient.ID, userId, []gocloak.Role{*roles[0]}) if err != nil { log.Error(ctx, "Assigning Client Role to User is failed", err) diff --git a/internal/repository/project.go b/internal/repository/project.go index 53c4041d..3a744d65 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -61,6 +61,7 @@ func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) return "", res.Error } + log.Debugf(ctx, "CreateProject: %+v", p) return p.ID, nil } @@ -367,6 +368,7 @@ func (r *ProjectRepository) GetProjectRoleByName(ctx context.Context, name strin } func (r *ProjectRepository) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { + log.Debugf(ctx, "AddProjectMember: %+v", pm) pm.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&pm) if res.Error != nil { diff --git a/internal/usecase/project.go b/internal/usecase/project.go index ff773d0d..4f7b5cef 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -37,12 +37,12 @@ type IProjectUsecase interface { UpdateProject(ctx context.Context, p *model.Project, newLeaderId string) error GetProjectRole(ctx context.Context, id string) (*model.ProjectRole, error) GetProjectRoles(ctx context.Context, query int) ([]model.ProjectRole, error) - AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) + AddProjectMember(ctx context.Context, organizationId string, pm *model.ProjectMember) (string, error) GetProjectUser(ctx context.Context, projectUserId string) (*model.ProjectUser, error) GetProjectMember(ctx context.Context, projectMemberId string) (*model.ProjectMember, error) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) ([]model.ProjectMember, error) GetProjectMemberCount(ctx context.Context, projectMemberId string) (*domain.GetProjectMemberCountResponse, error) - RemoveProjectMember(ctx context.Context, projectMemberId string) error + RemoveProjectMember(ctx context.Context, organizationId string, projectMemberId string) error UpdateProjectMemberRole(ctx context.Context, pm *model.ProjectMember) error CreateProjectNamespace(ctx context.Context, organizationId string, pn *model.ProjectNamespace) error IsProjectNamespaceExist(ctx context.Context, organizationId string, projectId string, stackId string, projectNamespace string) (bool, error) @@ -58,7 +58,7 @@ type IProjectUsecase interface { GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) - AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error + AssignKeycloakClientRoleToMemberForK8s(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error } @@ -93,6 +93,21 @@ func (u *ProjectUsecase) CreateProject(ctx context.Context, p *model.Project) (s return "", errors.Wrap(err, "Failed to create project.") } + prs, err := u.GetProjectRoles(ctx, ProjectAll) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to retrieve project roles.") + } + log.Debugf(ctx, "Project roles: %v", prs) + for _, pr := range prs { + log.Debugf(ctx, "Start to create Project role: %s. orgId: %s, projectId: %s", pr.Name, p.OrganizationId, projectId) + err = u.kc.EnsureClientRoleWithClientName(ctx, p.OrganizationId, keycloak.DefaultClientID, pr.Name+"@"+projectId) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to create project setting on keycloak.") + } + } + return projectId, nil } @@ -171,7 +186,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne } if newLeaderId != "" && currentLeaderId != newLeaderId { - if err := u.RemoveProjectMember(ctx, currentMemberId); err != nil { + if err := u.RemoveProjectMember(ctx, p.OrganizationId, currentMemberId); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to remove project member.") } @@ -198,7 +213,7 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne IsProjectLeader: true, CreatedAt: *p.UpdatedAt, } - res, err := u.AddProjectMember(ctx, newPm) + res, err := u.AddProjectMember(ctx, p.OrganizationId, newPm) if err != nil { return err } @@ -254,12 +269,26 @@ func (u *ProjectUsecase) GetProjectRoles(ctx context.Context, query int) (prs [] return prs, nil } -func (u *ProjectUsecase) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { +func (u *ProjectUsecase) AddProjectMember(ctx context.Context, organizationId string, pm *model.ProjectMember) (string, error) { projectMemberId, err := u.projectRepo.AddProjectMember(ctx, pm) if err != nil { log.Error(ctx, err) return "", errors.Wrap(err, "Failed to add project member to project.") } + + pr, err := u.GetProjectRole(ctx, pm.ProjectRoleId) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to get project roles.") + } + + // assign keycloak client role to member + err = u.kc.AssignClientRoleToUser(ctx, organizationId, pm.ProjectUserId.String(), keycloak.DefaultClientID, pr.Name+"@"+pm.ProjectId) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to assign keycloak client role to member.") + } + return projectMemberId, nil } @@ -322,11 +351,24 @@ func (u *ProjectUsecase) GetProjectMemberCount(ctx context.Context, projectMembe return pmcr, nil } -func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, projectMemberId string) error { +func (u *ProjectUsecase) RemoveProjectMember(ctx context.Context, organizationId string, projectMemberId string) error { + pm, err := u.GetProjectMember(ctx, projectMemberId) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to get project member to project.") + } + // unassign keycloak client role to member + err = u.kc.UnassignClientRoleToUser(ctx, organizationId, pm.ProjectUserId.String(), keycloak.DefaultClientID, pm.ProjectRole.Name+"@"+pm.ProjectId) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to remove project member to project.") + } + if err := u.projectRepo.RemoveProjectMember(ctx, projectMemberId); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to remove project member to project.") } + return nil } @@ -448,7 +490,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga return errors.Wrap(err, "Failed to create project namespace.") } for _, pm := range projectMembers { - err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -486,7 +528,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o return errors.Wrap(err, "Failed to create project namespace.") } for _, pm := range projectMembers { - err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -574,11 +616,7 @@ func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organiza log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.kc.EnsureClientRoleWithClientName(ctx, organizationId, keycloak.DefaultClientID, role+"@"+projectId) - if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") - } + } return nil } @@ -621,13 +659,13 @@ func (u *ProjectUsecase) DeleteK8SNSRoleBinding(ctx context.Context, organizatio panic("implement me") } -func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { +func (u *ProjectUsecase) AssignKeycloakClientRoleToMemberForK8s(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -635,8 +673,8 @@ func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, o return nil } -func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { - err := u.kc.AssignClientRoleToUser(ctx, organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) +func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, userId string, roleName string) error { + err := u.kc.AssignClientRoleToUser(ctx, organizationId, userId, clientId, roleName+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -650,7 +688,7 @@ func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId, pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -658,8 +696,8 @@ func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, return nil } -func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, userId string, roleName string) error { - err := u.kc.UnassignClientRoleToUser(ctx, organizationId, userId, stackId+"-k8s-api", roleName+"@"+projectId) +func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, userId string, roleName string) error { + err := u.kc.UnassignClientRoleToUser(ctx, organizationId, userId, clientId, roleName+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") From 7732b8b28998bff1529fb727decef065e685ed37 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 19 Mar 2024 19:19:57 +0900 Subject: [PATCH 146/502] minor fix. --- internal/delivery/http/project.go | 3 --- internal/keycloak/keycloak.go | 8 ++++++++ internal/repository/project.go | 2 -- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 4b12576a..defcf78a 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -108,7 +108,6 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } - log.Debugf(r.Context(), "projectId = [%s]\n", projectId) project.ID = projectId ProjectLeaderId, err := uuid.Parse(projectReq.ProjectLeaderId) if err != nil { @@ -135,8 +134,6 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { CreatedAt: now, } - log.Debugf(r.Context(), "pm = [%+v]\n", pm) - projectMemberId, err := p.usecase.AddProjectMember(r.Context(), organizationId, pm) if err != nil { log.Errorf(r.Context(), "projectMemberId: %v", projectMemberId) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index dcb8be03..18cb0cf3 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -162,6 +162,10 @@ func (k *Keycloak) InitializeKeycloak(ctx context.Context) error { } err = k.SetClientScopeRolesToOptionalToTksClient(ctx, DefaultMasterRealm) + if err != nil { + log.Fatal(ctx, err) + return err + } for _, defaultMapper := range defaultProtocolTksMapper { if err := k.ensureClientProtocolMappers(ctx, token, DefaultMasterRealm, *adminCliClient.ClientID, "openid", defaultMapper); err != nil { @@ -209,6 +213,10 @@ func (k *Keycloak) CreateRealm(ctx context.Context, organizationId string) (stri } err = k.SetClientScopeRolesToOptionalToTksClient(ctx, organizationId) + if err != nil { + log.Error(ctx, err, "SetClientScopeRolesToOptionalToTksClient") + return "", err + } for _, defaultMapper := range defaultProtocolTksMapper { if *defaultMapper.Name == "org" { diff --git a/internal/repository/project.go b/internal/repository/project.go index 3a744d65..53c4041d 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -61,7 +61,6 @@ func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) return "", res.Error } - log.Debugf(ctx, "CreateProject: %+v", p) return p.ID, nil } @@ -368,7 +367,6 @@ func (r *ProjectRepository) GetProjectRoleByName(ctx context.Context, name strin } func (r *ProjectRepository) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { - log.Debugf(ctx, "AddProjectMember: %+v", pm) pm.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&pm) if res.Error != nil { From 3afb31c723d1f4774708ff0ea722561c240bfda9 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 19 Mar 2024 20:25:13 +0900 Subject: [PATCH 147/502] minor fix. --- internal/delivery/http/project.go | 68 +++++++++++++++++++++++++++---- internal/keycloak/keycloak.go | 2 +- internal/usecase/project.go | 38 ++++++----------- 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index defcf78a..ba66719a 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -2,6 +2,7 @@ package http import ( "fmt" + "github.com/openinfradev/tks-api/internal/keycloak" "net/http" "strings" "time" @@ -141,6 +142,13 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { return } + err = p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, projectMemberId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + out := domain.CreateProjectResponse{ProjectId: projectId} ResponseJSON(w, r, http.StatusOK, out) @@ -601,9 +609,16 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } + err = p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pmId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, pmId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pmId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -867,8 +882,16 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque for _, pn := range pns { stackIds[pn.StackId] = struct{}{} } + + err = p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, projectMemberId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", projectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -934,9 +957,15 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // TODO: change multi row delete for _, pm := range projectMemberReq.ProjectMember { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pm.ProjectMemberId); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ProjectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pm.ProjectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1009,6 +1038,12 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R return } + if err = p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, projectMemberId); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + pns, err := p.usecase.GetProjectNamespaces(r.Context(), organizationId, projectId, nil) if err != nil { log.Error(r.Context(), err) @@ -1021,7 +1056,7 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } // tasks for keycloak & k8s. Unassign old role for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", projectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1037,9 +1072,16 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R ErrorJSON(w, r, err) return } + + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, projectMemberId); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + // tasks for keycloak & k8s. Assign new role for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, projectMemberId); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", projectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1111,8 +1153,14 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } + if err = p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pm.ID); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pm.ID); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -1129,8 +1177,14 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pm.ID); err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for stackId := range stackIds { - if err := p.usecase.AssignKeycloakClientRoleToMemberForK8s(r.Context(), organizationId, projectId, stackId, pm.ID); err != nil { + if err := p.usecase.AssignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pm.ID); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 18cb0cf3..ff69db1c 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -608,7 +608,7 @@ func (k *Keycloak) UnassignClientRoleToUser(ctx context.Context, organizationId return nil } - err = k.client.DeleteClientRolesFromUser(context.Background(), token.AccessToken, organizationId, userId, *targetClient.ID, []gocloak.Role{*roles[0]}) + err = k.client.DeleteClientRolesFromUser(context.Background(), token.AccessToken, organizationId, *targetClient.ID, userId, []gocloak.Role{*roles[0]}) if err != nil { log.Error(ctx, "Unassigning Client Role to User is failed", err) return err diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 4f7b5cef..4fbc4382 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -58,8 +58,8 @@ type IProjectUsecase interface { GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) - AssignKeycloakClientRoleToMemberForK8s(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error - UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error + AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error + UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error } type ProjectUsecase struct { @@ -170,6 +170,7 @@ func (u *ProjectUsecase) IsProjectNameExist(ctx context.Context, organizationId } func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, newLeaderId string) error { + //TODO: [donggyu] have to implementation about un/assigning client roles var currentMemberId, currentLeaderId, projectRoleId string for _, pm := range p.ProjectMembers { @@ -276,19 +277,6 @@ func (u *ProjectUsecase) AddProjectMember(ctx context.Context, organizationId st return "", errors.Wrap(err, "Failed to add project member to project.") } - pr, err := u.GetProjectRole(ctx, pm.ProjectRoleId) - if err != nil { - log.Error(ctx, err) - return "", errors.Wrap(err, "Failed to get project roles.") - } - - // assign keycloak client role to member - err = u.kc.AssignClientRoleToUser(ctx, organizationId, pm.ProjectUserId.String(), keycloak.DefaultClientID, pr.Name+"@"+pm.ProjectId) - if err != nil { - log.Error(ctx, err) - return "", errors.Wrap(err, "Failed to assign keycloak client role to member.") - } - return projectMemberId, nil } @@ -479,7 +467,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga return errors.Wrap(err, "Failed to create project namespace.") } - if err := u.createKeycloakClientRoles(ctx, organizationId, projectId, stackId); err != nil { + if err := u.createKeycloakClientRoles(ctx, organizationId, projectId, stackId+"-k8s-api"); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -535,7 +523,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o } } - if err := u.deleteKeycloakClientRoles(ctx, organizationId, projectId, stackId); err != nil { + if err := u.deleteKeycloakClientRoles(ctx, organizationId, projectId, stackId+"-k8s-api"); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } @@ -608,10 +596,10 @@ func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizat return nil } -func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, clientId string) error { // create Roles in keycloak for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { - err := u.kc.EnsureClientRoleWithClientName(ctx, organizationId, stackId+"-k8s-api", role+"@"+projectId) + err := u.kc.EnsureClientRoleWithClientName(ctx, organizationId, clientId, role+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -620,12 +608,12 @@ func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organiza } return nil } -func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, stackId string) error { +func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, clientId string) error { // first check whether the stac // delete Roles in keycloak for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { - err := u.kc.DeleteClientRoleWithClientName(ctx, organizationId, stackId+"-k8s-api", role+"@"+projectId) + err := u.kc.DeleteClientRoleWithClientName(ctx, organizationId, clientId, role+"@"+projectId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -659,13 +647,13 @@ func (u *ProjectUsecase) DeleteK8SNSRoleBinding(ctx context.Context, organizatio panic("implement me") } -func (u *ProjectUsecase) AssignKeycloakClientRoleToMemberForK8s(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { +func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, clientId, pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -682,13 +670,13 @@ func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Contex return nil } -func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, stackId string, projectMemberId string) error { +func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") } - err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) + err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, clientId, pm.ProjectUser.ID.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") From d1e1ca39bceb47bb596b85e4f31fcfb78634b460 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 20 Mar 2024 10:01:43 +0900 Subject: [PATCH 148/502] trivial. change default pagination limit size 10 to 10000 --- internal/pagination/pagination.go | 2 +- internal/repository/system-notification-rule.go | 2 +- internal/repository/system-notification-template.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index f9ab9e86..390e20fa 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -29,7 +29,7 @@ const OR = "or" const OR_ARRAY = "or[]" const COMBINED_FILTER = "combinedFilter" // deprecated -var DEFAULT_LIMIT = 10 +var DEFAULT_LIMIT = 10000 type Pagination struct { Limit int diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 91123fdb..3e07db21 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -113,7 +113,7 @@ func (r *SystemNotificationRuleRepository) UpdateOrganizations(ctx context.Conte if res.Error != nil { return res.Error } - err = r.db.WithContext(ctx).Model(&systemNotificationRule).Association("Organizations").Unscoped().Replace(organizations) + err = r.db.WithContext(ctx).Model(&systemNotificationRule).Association("Organizations").Replace(organizations) if err != nil { return err } diff --git a/internal/repository/system-notification-template.go b/internal/repository/system-notification-template.go index bd520fb3..1bf41ded 100644 --- a/internal/repository/system-notification-template.go +++ b/internal/repository/system-notification-template.go @@ -89,7 +89,7 @@ func (r *SystemNotificationTemplateRepository) Update(ctx context.Context, dto m return res.Error } - if err = r.db.WithContext(ctx).Model(&dto).Association("MetricParameters").Unscoped().Replace(dto.MetricParameters); err != nil { + if err = r.db.WithContext(ctx).Model(&dto).Association("MetricParameters").Replace(dto.MetricParameters); err != nil { return err } return nil From 9f54dbe154e911d4e8f7a21dbddad74b445dac54 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 20 Mar 2024 10:08:05 +0900 Subject: [PATCH 149/502] trivial. remove deprecated code --- internal/repository/repository.go | 48 ------------------------------- internal/repository/role.go | 18 ++---------- 2 files changed, 3 insertions(+), 63 deletions(-) diff --git a/internal/repository/repository.go b/internal/repository/repository.go index d1eb8276..c3bbdc47 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -1,12 +1,7 @@ package repository import ( - "fmt" - "strings" - "gorm.io/gorm" - - "github.com/openinfradev/tks-api/internal/pagination" ) type FilterFunc func(user *gorm.DB) *gorm.DB @@ -30,46 +25,3 @@ type Repository struct { SystemNotificationTemplate ISystemNotificationTemplateRepository SystemNotificationRule ISystemNotificationRuleRepository } - -func CombinedGormFilter(table string, filters []pagination.Filter, combinedFilter pagination.CombinedFilter) FilterFunc { - return func(db *gorm.DB) *gorm.DB { - // and query - for _, filter := range filters { - if len(filter.Values) > 1 { - inQuery := fmt.Sprintf("LOWER(%s.%s::text) in (", table, filter.Column) - for _, val := range filter.Values { - inQuery = inQuery + fmt.Sprintf("LOWER($$%s$$),", val) - } - inQuery = inQuery[:len(inQuery)-1] + ")" - db = db.Where(inQuery) - } else { - if len(filter.Values[0]) > 0 { - if strings.Contains(filter.Values[0], "%") { - filterVal := strings.Replace(filter.Values[0], "%", "`%", -1) - db = db.Where(fmt.Sprintf("LOWER(%s.%s::text) like LOWER($$%%%s%%$$) escape '`'", table, filter.Column, filterVal)) - } else { - db = db.Where(fmt.Sprintf("LOWER(%s.%s::text) like LOWER($$%%%s%%$$)", table, filter.Column, filter.Values[0])) - } - } - } - } - - // or query - // id = '123' or description = '345' - if len(combinedFilter.Columns) > 0 { - orQuery := "" - for _, column := range combinedFilter.Columns { - if strings.Contains(combinedFilter.Value, "%") { - filterVal := strings.Replace(combinedFilter.Value, "%", "`%", -1) - orQuery = orQuery + fmt.Sprintf("LOWER(%s.%s::text) like LOWER($$%%%s%%$$) escape '`' OR ", table, column, filterVal) - } else { - orQuery = orQuery + fmt.Sprintf("LOWER(%s.%s::text) like LOWER($$%%%s%%$$) OR ", table, column, combinedFilter.Value) - } - } - orQuery = orQuery[:len(orQuery)-3] - db = db.Where(orQuery) - } - - return db - } -} diff --git a/internal/repository/role.go b/internal/repository/role.go index a4af220d..f3b677e6 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -3,12 +3,12 @@ package repository import ( "context" "fmt" - "math" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "gorm.io/gorm" + "gorm.io/gorm/clause" ) type IRoleRepository interface { @@ -51,23 +51,11 @@ func (r RoleRepository) ListTksRoles(ctx context.Context, organizationId string, if pg == nil { pg = pagination.NewPagination(nil) } - filterFunc := CombinedGormFilter("roles", pg.GetFilters(), pg.CombinedFilter) - db := filterFunc(r.db.Model(&model.Role{})) - - db.Count(&pg.TotalRows) - pg.TotalPages = int(math.Ceil(float64(pg.TotalRows) / float64(pg.Limit))) - - orderQuery := fmt.Sprintf("%s %s", pg.SortColumn, pg.SortOrder) - res := db.WithContext(ctx). - Offset(pg.GetOffset()). - Limit(pg.GetLimit()). - Order(orderQuery). - Find(&roles, "organization_id = ?", organizationId) - //res := db.Preload("Role").Offset(pg.GetOffset()).Limit(pg.GetLimit()).Order(orderQuery).Find(&objs) + + _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations).Model(&model.Role{}).Where("organization_id = ?", organizationId), &roles) if res.Error != nil { return nil, res.Error } - return roles, nil } From d6d683c2a928edeef4e3e90af8382f59755e27b0 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 20 Mar 2024 11:47:19 +0900 Subject: [PATCH 150/502] add dashboard management --- internal/database/database.go | 5 + internal/delivery/api/endpoint.go | 3 + internal/delivery/http/dashboard.go | 187 +++++++++++++++++++++++++++- internal/delivery/http/handler.go | 20 +++ internal/model/dashboard.go | 20 ++- internal/repository/dashboard.go | 78 ++++++++++++ internal/repository/repository.go | 1 + internal/route/route.go | 4 + internal/usecase/dashboard.go | 29 +++++ pkg/domain/dashboard.go | 34 +++++ 10 files changed, 374 insertions(+), 7 deletions(-) create mode 100644 internal/repository/dashboard.go diff --git a/internal/database/database.go b/internal/database/database.go index 67ac9599..a6d9cb85 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -176,6 +176,10 @@ func migrateSchema(db *gorm.DB) error { return err } + if err := db.AutoMigrate(&model.Dashboard{}); err != nil { + return err + } + return nil } @@ -197,6 +201,7 @@ func EnsureDefaultRows(db *gorm.DB) error { Permission: repository.NewPermissionRepository(db), Endpoint: repository.NewEndpointRepository(db), Project: repository.NewProjectRepository(db), + Dashboard: repository.NewDashboardRepository(db), } // diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 31cabce6..e9943b44 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -108,6 +108,9 @@ const ( GetOrganizationStackTemplate // Dashboard + CreateDashboard + GetDashboard + UpdateDashboard GetChartsDashboard // 대시보드/대시보드/조회 GetChartDashboard // 대시보드/대시보드/조회 GetStacksDashboard // 대시보드/대시보드/조회 diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 69e49c6f..701e1811 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -2,27 +2,204 @@ package http import ( "fmt" - "net/http" - "strings" - "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" + "net/http" + "strings" ) +type IDashboardHandler interface { + CreateDashboard(w http.ResponseWriter, r *http.Request) + GetDashboard(w http.ResponseWriter, r *http.Request) + UpdateDashboard(w http.ResponseWriter, r *http.Request) + GetCharts(w http.ResponseWriter, r *http.Request) + GetChart(w http.ResponseWriter, r *http.Request) + GetStacks(w http.ResponseWriter, r *http.Request) + GetResources(w http.ResponseWriter, r *http.Request) +} + type DashboardHandler struct { usecase usecase.IDashboardUsecase } -func NewDashboardHandler(h usecase.Usecase) *DashboardHandler { +func NewDashboardHandler(h usecase.Usecase) IDashboardHandler { return &DashboardHandler{ usecase: h.Dashboard, } } +// CreateDashboard godoc +// +// @Tags Dashboards +// @Summary Create new dashboard +// @Description Create new dashboard +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param request body domain.CreateDashboardRequest true "Request body to create dashboard" +// @Success 200 {object} domain.CreateDashboardResponse +// @Router /organizations/{organizationId}/dashboards [post] +// @Security JWT +func (h *DashboardHandler) CreateDashboard(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + var dashboardReq []domain.CreateDashboardRequest + if err := UnmarshalRequestInput(r, &dashboardReq); err != nil { + ErrorJSON(w, r, err) + return + } + content, err := MarshalToString(r.Context(), dashboardReq) + if err != nil { + ErrorJSON(w, r, err) + return + } + + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + log.Error(r.Context(), "Failed to retrieve user info from request") + ErrorJSON(w, r, fmt.Errorf("failed to retrieve user info from request")) + } + userId := requestUserInfo.GetUserId() + + dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId.String()) + if err == nil && dashboard != nil { + log.Error(r.Context(), "Dashboard already exists") + ResponseJSON(w, r, http.StatusInternalServerError, "Dashboard already exists") + return + } + + dashboard = &model.Dashboard{ + OrganizationId: organizationId, + UserId: userId, + Content: content, + IsAdmin: false, + } + log.Info(r.Context(), "Processing CREATE request for dashboard") + + dashboardId, err := h.usecase.CreateDashboard(r.Context(), dashboard) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + out := domain.CreateDashboardResponse{DashboardId: dashboardId} + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetDashboard godoc +// +// @Tags Dashboards +// @Summary Get dashboard +// @Description Get dashboard +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetDashboardResponse +// @Router /organizations/{organizationId}/dashboards [get] +// @Security JWT +func (h *DashboardHandler) GetDashboard(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + log.Error(r.Context(), "Failed to retrieve user info from request") + ErrorJSON(w, r, fmt.Errorf("failed to retrieve user info from request")) + } + userId := requestUserInfo.GetUserId().String() + + dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId) + if err != nil { + log.Error(r.Context(), "Failed to retrieve dashboard", err) + ErrorJSON(w, r, err) + return + } + if dashboard == nil { + ResponseJSON(w, r, http.StatusOK, nil) + return + } + if len(dashboard.Content) == 0 { + ResponseJSON(w, r, http.StatusOK, []domain.GetDashboardResponse{}) + return + } + + var dashboardRes []domain.GetDashboardResponse + if err := UnmarshalFromString(r.Context(), dashboard.Content, &dashboardRes); err != nil { + ErrorJSON(w, r, err) + } + ResponseJSON(w, r, http.StatusOK, dashboardRes) +} + +// UpdateDashboard godoc +// +// @Tags Dashboards +// @Summary Update dashboard +// @Description Update dashboard +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param request body domain.UpdateDashboardRequest true "Request body to update dashboard" +// @Success 200 {object} domain.CommonDashboardResponse +// @Router /organizations/{organizationId}/dashboards [put] +// @Security JWT +func (h *DashboardHandler) UpdateDashboard(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + var dashboardReq []domain.CreateDashboardRequest + if err := UnmarshalRequestInput(r, &dashboardReq); err != nil { + ErrorJSON(w, r, err) + return + } + content, err := MarshalToString(r.Context(), dashboardReq) + if err != nil { + ErrorJSON(w, r, err) + return + } + + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + log.Error(r.Context(), "Failed to retrieve user info from request") + ErrorJSON(w, r, fmt.Errorf("failed to retrieve user info from request")) + } + userId := requestUserInfo.GetUserId().String() + + dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId) + if err != nil || dashboard == nil { + log.Error(r.Context(), "Failed to retrieve dashboard", err) + ErrorJSON(w, r, err) + return + } + + dashboard.Content = content + if err := h.usecase.UpdateDashboard(r.Context(), dashboard); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + ResponseJSON(w, r, http.StatusOK, domain.CommonDashboardResponse{Result: "OK"}) +} + // GetCharts godoc // // @Tags Dashboards @@ -83,7 +260,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } -// GetCharts godoc +// GetChart godoc // // @Tags Dashboards // @Summary Get chart data diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index a45435c9..69553b5f 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -2,8 +2,10 @@ package http import ( "bytes" + "context" "encoding/json" "errors" + "fmt" "io" "net/http" @@ -117,3 +119,21 @@ func (h *APIHandler) AddHistory(r *http.Request, projectId string, historyType s return nil } */ + +func UnmarshalFromString(ctx context.Context, content string, in any) error { + err := json.Unmarshal([]byte(content), &in) + if err != nil { + log.Fatalf(ctx, "Unable to unmarshal JSON due to %s", err) + return err + } + return nil +} + +func MarshalToString(ctx context.Context, in any) (string, error) { + b, err := json.Marshal(in) + if err != nil { + log.Fatalf(ctx, "Unable to marshal JSON due to %s", err) + return "", nil + } + return fmt.Sprintf("%s", string(b)), nil +} diff --git a/internal/model/dashboard.go b/internal/model/dashboard.go index 3cb73ce4..f4781338 100644 --- a/internal/model/dashboard.go +++ b/internal/model/dashboard.go @@ -1,4 +1,20 @@ package model -// Dashboard 는 DB repository 접근이 없이 외부 데이터만을 참조하므로, 일단 pkg/domain 의 model 을 사용하도록 해둡니다. -// 즉, usecase 에서 직접 pkg/domain 을 참조하도록 해 두었습니다. +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) + +type Dashboard struct { + gorm.Model + ID uuid.UUID `gorm:"primarykey;type:uuid"` + OrganizationId string `gorm:"type:varchar(36)"` + UserId uuid.UUID + Content string + IsAdmin bool `gorm:"default:false"` +} + +func (d *Dashboard) BeforeCreate(tx *gorm.DB) (err error) { + d.ID = uuid.New() + return nil +} diff --git a/internal/repository/dashboard.go b/internal/repository/dashboard.go new file mode 100644 index 00000000..e5a078e1 --- /dev/null +++ b/internal/repository/dashboard.go @@ -0,0 +1,78 @@ +package repository + +import ( + "context" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" + "gorm.io/gorm" +) + +type IDashboardRepository interface { + CreateDashboard(ctx context.Context, d *model.Dashboard) (string, error) + GetDashboardById(ctx context.Context, organizationId string, dashboardId string) (*model.Dashboard, error) + GetDashboardByUserId(ctx context.Context, organizationId string, userId string) (*model.Dashboard, error) + UpdateDashboard(ctx context.Context, d *model.Dashboard) error +} + +type DashboardRepository struct { + db *gorm.DB +} + +func NewDashboardRepository(db *gorm.DB) IDashboardRepository { + return &DashboardRepository{ + db: db, + } +} + +func (dr DashboardRepository) CreateDashboard(ctx context.Context, d *model.Dashboard) (string, error) { + res := dr.db.WithContext(ctx).Create(&d) + if res.Error != nil { + log.Error(ctx, res.Error) + return "", res.Error + } + + return d.ID.String(), nil +} + +func (dr DashboardRepository) GetDashboardById(ctx context.Context, organizationId string, dashboardId string) (d *model.Dashboard, err error) { + res := dr.db.WithContext(ctx).Limit(1). + Where("organization_id = ? and id = ?", organizationId, dashboardId). + First(&d) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info(ctx, "Cannot find dashboard") + return nil, nil + } else { + log.Error(ctx, res.Error) + return nil, res.Error + } + } + return d, nil +} + +func (dr DashboardRepository) GetDashboardByUserId(ctx context.Context, organizationId string, userId string) (d *model.Dashboard, err error) { + res := dr.db.WithContext(ctx).Limit(1). + Where("organization_id = ? and user_id = ?", organizationId, userId). + First(&d) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info(ctx, "Cannot find dashboard") + return nil, nil + } else { + log.Error(ctx, res.Error) + return nil, res.Error + } + } + return d, nil +} + +func (dr DashboardRepository) UpdateDashboard(ctx context.Context, d *model.Dashboard) error { + res := dr.db.WithContext(ctx).Model(&d). + Updates(model.Dashboard{Content: d.Content}) + if res.Error != nil { + log.Error(ctx, res.Error) + return res.Error + } + return nil +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index c3bbdc47..0114cf59 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -24,4 +24,5 @@ type Repository struct { SystemNotification ISystemNotificationRepository SystemNotificationTemplate ISystemNotificationTemplateRepository SystemNotificationRule ISystemNotificationRuleRepository + Dashboard IDashboardRepository } diff --git a/internal/route/route.go b/internal/route/route.go index 265cd513..d7cea2ff 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -58,6 +58,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Endpoint: repository.NewEndpointRepository(db), Audit: repository.NewAuditRepository(db), PolicyTemplate: repository.NewPolicyTemplateRepository(db), + Dashboard: repository.NewDashboardRepository(db), } usecaseFactory := usecase.Usecase{ @@ -200,6 +201,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts/{chartType}", customMiddleware.Handle(internalApi.GetChartDashboard, http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) systemNotificationHandler := delivery.NewSystemNotificationHandler(usecaseFactory) r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/system-notifications", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 567441e0..82cf8c93 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -27,12 +27,16 @@ import ( ) type IDashboardUsecase interface { + CreateDashboard(ctx context.Context, dashboard *model.Dashboard) (string, error) + GetDashboard(ctx context.Context, organizationId string, userId string) (*model.Dashboard, error) + UpdateDashboard(ctx context.Context, dashboard *model.Dashboard) error GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (res []domain.DashboardChart, err error) GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) GetResources(ctx context.Context, organizationId string) (out domain.DashboardResource, err error) } type DashboardUsecase struct { + dashboardRepo repository.IDashboardRepository organizationRepo repository.IOrganizationRepository clusterRepo repository.IClusterRepository appGroupRepo repository.IAppGroupRepository @@ -42,6 +46,7 @@ type DashboardUsecase struct { func NewDashboardUsecase(r repository.Repository, cache *gcache.Cache) IDashboardUsecase { return &DashboardUsecase{ + dashboardRepo: r.Dashboard, organizationRepo: r.Organization, clusterRepo: r.Cluster, appGroupRepo: r.AppGroup, @@ -50,6 +55,30 @@ func NewDashboardUsecase(r repository.Repository, cache *gcache.Cache) IDashboar } } +func (u *DashboardUsecase) CreateDashboard(ctx context.Context, dashboard *model.Dashboard) (string, error) { + dashboardId, err := u.dashboardRepo.CreateDashboard(ctx, dashboard) + if err != nil { + return "", errors.Wrap(err, "Failed to create dashboard.") + } + + return dashboardId, nil +} + +func (u *DashboardUsecase) GetDashboard(ctx context.Context, organizationId string, userId string) (*model.Dashboard, error) { + dashboard, err := u.dashboardRepo.GetDashboardByUserId(ctx, organizationId, userId) + if err != nil { + return nil, errors.Wrap(err, "Failed to get dashboard.") + } + return dashboard, err +} + +func (u *DashboardUsecase) UpdateDashboard(ctx context.Context, dashboard *model.Dashboard) error { + if err := u.dashboardRepo.UpdateDashboard(ctx, dashboard); err != nil { + return errors.Wrap(err, "Failed to update dashboard") + } + return nil +} + func (u *DashboardUsecase) GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (out []domain.DashboardChart, err error) { _, err = u.organizationRepo.Get(ctx, organizationId) if err != nil { diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 6f3e18e2..672b1d0c 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -141,3 +141,37 @@ type DashboardStackResponse struct { type GetDashboardStacksResponse struct { Stacks []DashboardStackResponse `json:"stacks"` } + +type WidgetResponse struct { + Key string `json:"key"` + StartX int `json:"startX"` + StartY int `json:"startY"` + SizeX int `json:"sizeX"` + SizeY int `json:"sizeY"` +} + +type CreateDashboardRequest struct { + GroupName string `json:"groupName"` + SizeX int `json:"sizeX"` + SizeY int `json:"sizeY"` + Widgets []WidgetResponse `json:"widgets"` +} + +type CreateDashboardResponse struct { + DashboardId string `json:"dashboardId"` +} + +type GetDashboardResponse struct { + GroupName string `json:"groupName"` + SizeX int `json:"sizeX"` + SizeY int `json:"sizeY"` + Widgets []WidgetResponse `json:"widgets"` +} + +type UpdateDashboardRequest struct { + CreateDashboardRequest +} + +type CommonDashboardResponse struct { + Result string `json:"result"` +} From 081bcef6f9d516bd5c498ef3eb47ec3a1e7c56f0 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 20 Mar 2024 13:31:39 +0900 Subject: [PATCH 151/502] dashboard generated_endpoints --- .../delivery/api/generated_endpoints.go.go | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index a02951c3..e2c14e92 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -319,6 +319,18 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetOrganizationStackTemplate", Group: "StackTemplate", }, + CreateDashboard: { + Name: "CreateDashboard", + Group: "Dashboard", + }, + GetDashboard: { + Name: "GetDashboard", + Group: "Dashboard", + }, + UpdateDashboard: { + Name: "UpdateDashboard", + Group: "Dashboard", + }, GetChartsDashboard: { Name: "GetChartsDashboard", Group: "Dashboard", @@ -940,6 +952,12 @@ func (e Endpoint) String() string { return "GetOrganizationStackTemplates" case GetOrganizationStackTemplate: return "GetOrganizationStackTemplate" + case CreateDashboard: + return "CreateDashboard" + case GetDashboard: + return "GetDashboard" + case UpdateDashboard: + return "UpdateDashboard" case GetChartsDashboard: return "GetChartsDashboard" case GetChartDashboard: @@ -1334,6 +1352,12 @@ func GetEndpoint(name string) Endpoint { return GetOrganizationStackTemplates case "GetOrganizationStackTemplate": return GetOrganizationStackTemplate + case "CreateDashboard": + return CreateDashboard + case "GetDashboard": + return GetDashboard + case "UpdateDashboard": + return UpdateDashboard case "GetChartsDashboard": return GetChartsDashboard case "GetChartDashboard": From 16898786ff74af25acfce31d99c781606c8e8306 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 20 Mar 2024 13:34:02 +0900 Subject: [PATCH 152/502] dashboard generating swagger --- api/swagger/docs.go | 221 ++++++++++++++++++++++++++++ api/swagger/swagger.json | 221 ++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 141 ++++++++++++++++++ internal/delivery/http/dashboard.go | 2 +- 4 files changed, 584 insertions(+), 1 deletion(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 56497339..419cc8af 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3145,6 +3145,131 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/dashboards": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Update dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to update dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create new dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Create new dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to create dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse" + } + } + } + } + }, "/organizations/{organizationId}/my-profile": { "get": { "security": [ @@ -8091,6 +8216,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse": { + "type": "object", + "properties": { + "result": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { @@ -8370,6 +8503,34 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest": { + "type": "object", + "properties": { + "groupName": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "widgets": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse": { + "type": "object", + "properties": { + "dashboardId": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { "type": "object", "required": [ @@ -9232,6 +9393,26 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse": { + "type": "object", + "properties": { + "groupName": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "widgets": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse": { "type": "object", "properties": { @@ -11205,6 +11386,26 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest": { + "type": "object", + "properties": { + "groupName": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "widgets": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest": { "type": "object", "required": [ @@ -11657,6 +11858,26 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.WidgetResponse": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "startX": { + "type": "integer" + }, + "startY": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 77d56851..ae184eac 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3139,6 +3139,131 @@ } } }, + "/organizations/{organizationId}/dashboards": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Update dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to update dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create new dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Create new dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to create dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse" + } + } + } + } + }, "/organizations/{organizationId}/my-profile": { "get": { "security": [ @@ -8085,6 +8210,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse": { + "type": "object", + "properties": { + "result": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse": { "type": "object", "properties": { @@ -8364,6 +8497,34 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest": { + "type": "object", + "properties": { + "groupName": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "widgets": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse": { + "type": "object", + "properties": { + "dashboardId": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest": { "type": "object", "required": [ @@ -9226,6 +9387,26 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse": { + "type": "object", + "properties": { + "groupName": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "widgets": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse": { "type": "object", "properties": { @@ -11199,6 +11380,26 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest": { + "type": "object", + "properties": { + "groupName": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "widgets": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest": { "type": "object", "required": [ @@ -11651,6 +11852,26 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.WidgetResponse": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "startX": { + "type": "integer" + }, + "startY": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index d89bcc96..f7be890f 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -627,6 +627,11 @@ definitions: tksUserNodeType: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse: + properties: + result: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse: properties: result: @@ -818,6 +823,24 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest: + properties: + groupName: + type: string + sizeX: + type: integer + sizeY: + type: integer + widgets: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse: + properties: + dashboardId: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest: properties: adminAccountId: @@ -1397,6 +1420,19 @@ definitions: resources: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardResource' type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse: + properties: + groupName: + type: string + sizeX: + type: integer + sizeY: + type: integer + widgets: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse: properties: stacks: @@ -2697,6 +2733,19 @@ definitions: description: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest: + properties: + groupName: + type: string + sizeX: + type: integer + sizeY: + type: integer + widgets: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest: properties: department: @@ -2999,6 +3048,19 @@ definitions: validityPeriod: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.WidgetResponse: + properties: + key: + type: string + sizeX: + type: integer + sizeY: + type: integer + startX: + type: integer + startY: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse: properties: user: @@ -5061,6 +5123,85 @@ paths: summary: Get stacks tags: - Dashboards + /organizations/{organizationId}/dashboards: + get: + consumes: + - application/json + description: Get dashboard + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse' + security: + - JWT: [] + summary: Get dashboard + tags: + - Dashboards + post: + consumes: + - application/json + description: Create new dashboard + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Request body to create dashboard + in: body + name: request + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse' + security: + - JWT: [] + summary: Create new dashboard + tags: + - Dashboards + put: + consumes: + - application/json + description: Update dashboard + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Request body to update dashboard + in: body + name: request + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse' + security: + - JWT: [] + summary: Update dashboard + tags: + - Dashboards /organizations/{organizationId}/my-profile: delete: consumes: diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 701e1811..f299eeb4 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -105,7 +105,7 @@ func (h *DashboardHandler) CreateDashboard(w http.ResponseWriter, r *http.Reques // @Description Get dashboard // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" +// @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.GetDashboardResponse // @Router /organizations/{organizationId}/dashboards [get] // @Security JWT From 786291cfbe7f2b557aed08b84e304ccdcb7ee1d3 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 20 Mar 2024 13:54:12 +0900 Subject: [PATCH 153/502] trivial. change api role for organizations --- api/swagger/docs.go | 118 +++--------------- api/swagger/swagger.json | 118 +++--------------- api/swagger/swagger.yaml | 79 ++---------- internal/delivery/api/endpoint.go | 3 +- .../delivery/api/generated_endpoints.go.go | 20 +-- internal/delivery/http/organization.go | 53 +------- internal/route/route.go | 1 - pkg/domain/organization.go | 15 +-- 8 files changed, 55 insertions(+), 352 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 56497339..899b040f 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -202,52 +202,6 @@ const docTemplate = `{ } } }, - "/admin/organizations/{organizationId}": { - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update organization detail ( for admin )", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Update organization detail ( for admin )", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "update organization request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse" - } - } - } - } - }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -7395,53 +7349,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "policyTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "primaryClusterId": { - "type": "string" - }, - "stackTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "systemNotificationTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -11276,22 +11183,31 @@ const docTemplate = `{ "maxLength": 30, "minLength": 1 }, - "primaryClusterId": { - "type": "string" + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } } } }, "github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse": { "type": "object", "properties": { - "description": { - "type": "string" - }, "id": { "type": "string" - }, - "name": { - "type": "string" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 77d56851..3187f9a6 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -196,52 +196,6 @@ } } }, - "/admin/organizations/{organizationId}": { - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update organization detail ( for admin )", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Update organization detail ( for admin )", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "update organization request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse" - } - } - } - } - }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -7389,53 +7343,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "policyTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "primaryClusterId": { - "type": "string" - }, - "stackTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "systemNotificationTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -11270,22 +11177,31 @@ "maxLength": 30, "minLength": 1 }, - "primaryClusterId": { - "type": "string" + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } } } }, "github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse": { "type": "object", "properties": { - "description": { - "type": "string" - }, "id": { "type": "string" - }, - "name": { - "type": "string" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index d89bcc96..9aff6be7 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -147,38 +147,6 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest' type: array type: object - github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest: - properties: - description: - maxLength: 100 - minLength: 0 - type: string - name: - maxLength: 30 - minLength: 1 - type: string - policyTemplateIds: - items: - type: string - type: array - primaryClusterId: - type: string - stackTemplateIds: - items: - type: string - type: array - systemNotificationTemplateIds: - items: - type: string - type: array - required: - - name - type: object - github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse: - properties: - id: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse: properties: appGroupType: @@ -2744,19 +2712,25 @@ definitions: maxLength: 30 minLength: 1 type: string - primaryClusterId: - type: string + policyTemplateIds: + items: + type: string + type: array + stackTemplateIds: + items: + type: string + type: array + systemNotificationTemplateIds: + items: + type: string + type: array required: - name type: object github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationResponse: properties: - description: - type: string id: type: string - name: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest: properties: @@ -3212,35 +3186,6 @@ paths: summary: Get Audit tags: - Audits - /admin/organizations/{organizationId}: - put: - consumes: - - application/json - description: Update organization detail ( for admin ) - parameters: - - description: organizationId - in: path - name: organizationId - required: true - type: string - - description: update organization request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse' - security: - - JWT: [] - summary: Update organization detail ( for admin ) - tags: - - Organizations /admin/organizations/{organizationId}/projects: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 31cabce6..ef22dee0 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -41,10 +41,9 @@ const ( // Organization Admin_CreateOrganization Admin_DeleteOrganization - Admin_UpdateOrganization + UpdateOrganization GetOrganizations GetOrganization - UpdateOrganization UpdatePrimaryCluster CheckOrganizationName diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index a02951c3..a7d7a599 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -99,8 +99,8 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_DeleteOrganization", Group: "Organization", }, - Admin_UpdateOrganization: { - Name: "Admin_UpdateOrganization", + UpdateOrganization: { + Name: "UpdateOrganization", Group: "Organization", }, GetOrganizations: { @@ -111,10 +111,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetOrganization", Group: "Organization", }, - UpdateOrganization: { - Name: "UpdateOrganization", - Group: "Organization", - }, UpdatePrimaryCluster: { Name: "UpdatePrimaryCluster", Group: "Organization", @@ -830,14 +826,12 @@ func (e Endpoint) String() string { return "Admin_CreateOrganization" case Admin_DeleteOrganization: return "Admin_DeleteOrganization" - case Admin_UpdateOrganization: - return "Admin_UpdateOrganization" + case UpdateOrganization: + return "UpdateOrganization" case GetOrganizations: return "GetOrganizations" case GetOrganization: return "GetOrganization" - case UpdateOrganization: - return "UpdateOrganization" case UpdatePrimaryCluster: return "UpdatePrimaryCluster" case CheckOrganizationName: @@ -1224,14 +1218,12 @@ func GetEndpoint(name string) Endpoint { return Admin_CreateOrganization case "Admin_DeleteOrganization": return Admin_DeleteOrganization - case "Admin_UpdateOrganization": - return Admin_UpdateOrganization + case "UpdateOrganization": + return UpdateOrganization case "GetOrganizations": return GetOrganizations case "GetOrganization": return GetOrganization - case "UpdateOrganization": - return UpdateOrganization case "UpdatePrimaryCluster": return UpdatePrimaryCluster case "CheckOrganizationName": diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 1932db7c..ea446b40 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -325,57 +325,6 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. log.Info(r.Context(), err) } - organization, err := h.usecase.Update(r.Context(), organizationId, dto) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - ErrorJSON(w, r, err) - return - } - - var out domain.UpdateOrganizationResponse - if err = serializer.Map(r.Context(), organization, &out); err != nil { - log.Error(r.Context(), err) - } - - ResponseJSON(w, r, http.StatusOK, out) -} - -// Admin_UpdateOrganization godoc -// -// @Tags Organizations -// @Summary Update organization detail ( for admin ) -// @Description Update organization detail ( for admin ) -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.Admin_UpdateOrganizationRequest true "update organization request" -// @Success 200 {object} domain.Admin_UpdateOrganizationResponse -// @Router /admin/organizations/{organizationId} [put] -// @Security JWT -func (h *OrganizationHandler) Admin_UpdateOrganization(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) - return - } - - input := domain.Admin_UpdateOrganizationRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - ErrorJSON(w, r, err) - return - } - - var dto model.Organization - if err = serializer.Map(r.Context(), input, &dto); err != nil { - log.Info(r.Context(), err) - } - for _, strId := range input.StackTemplateIds { stackTemplateId, err := uuid.Parse(strId) if err != nil || stackTemplateId == uuid.Nil { @@ -407,7 +356,7 @@ func (h *OrganizationHandler) Admin_UpdateOrganization(w http.ResponseWriter, r return } - var out domain.Admin_UpdateOrganizationResponse + var out domain.UpdateOrganizationResponse out.ID = organizationId ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/route/route.go b/internal/route/route.go index 265cd513..bf7b1627 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -129,7 +129,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa organizationHandler := delivery.NewOrganizationHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations", customMiddleware.Handle(internalApi.Admin_CreateOrganization, http.HandlerFunc(organizationHandler.Admin_CreateOrganization))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.Admin_DeleteOrganization, http.HandlerFunc(organizationHandler.Admin_DeleteOrganization))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.Admin_UpdateOrganization, http.HandlerFunc(organizationHandler.Admin_UpdateOrganization))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.GetOrganizations, http.HandlerFunc(organizationHandler.GetOrganizations))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.GetOrganization, http.HandlerFunc(organizationHandler.GetOrganization))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.UpdateOrganization, http.HandlerFunc(organizationHandler.UpdateOrganization))).Methods(http.MethodPut) diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 8f97f42d..478dc45b 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -91,19 +91,6 @@ type ListOrganizationResponse struct { } type UpdateOrganizationRequest struct { - PrimaryClusterId string `json:"primaryClusterId"` - Name string `json:"name" validate:"required,min=1,max=30"` - Description string `json:"description" validate:"omitempty,min=0,max=100"` -} - -type UpdateOrganizationResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` -} - -type Admin_UpdateOrganizationRequest struct { - PrimaryClusterId string `json:"primaryClusterId"` Name string `json:"name" validate:"required,min=1,max=30"` Description string `json:"description" validate:"omitempty,min=0,max=100"` StackTemplateIds []string `json:"stackTemplateIds"` @@ -111,7 +98,7 @@ type Admin_UpdateOrganizationRequest struct { SystemNotificationTemplateIds []string `json:"systemNotificationTemplateIds"` } -type Admin_UpdateOrganizationResponse struct { +type UpdateOrganizationResponse struct { ID string `json:"id"` } From ac48c448c8f20c500743c7ad79e6b7c9a03cb6bb Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 20 Mar 2024 14:05:22 +0900 Subject: [PATCH 154/502] fix lint error --- internal/delivery/http/handler.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index 69553b5f..2e053ae5 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -5,7 +5,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "io" "net/http" @@ -135,5 +134,5 @@ func MarshalToString(ctx context.Context, in any) (string, error) { log.Fatalf(ctx, "Unable to marshal JSON due to %s", err) return "", nil } - return fmt.Sprintf("%s", string(b)), nil + return string(b), nil } From f485abb7b6ec057edb7d11a6381642c6e7a5b80d Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 22 Mar 2024 10:10:16 +0900 Subject: [PATCH 155/502] feature. seperate api for templates --- api/swagger/docs.go | 274 ++++++++++++++++-- api/swagger/swagger.json | 274 ++++++++++++++++-- api/swagger/swagger.yaml | 173 ++++++++++- internal/delivery/api/endpoint.go | 9 +- .../delivery/api/generated_endpoints.go.go | 72 ++++- internal/delivery/http/organization.go | 30 +- internal/delivery/http/stack-template.go | 68 +++++ .../http/system-notification-template.go | 121 ++++++++ internal/middleware/auth/role/default.go | 1 - internal/repository/organization.go | 44 ++- .../system-notification-template.go | 16 + internal/route/route.go | 5 + internal/usecase/organization.go | 49 ---- internal/usecase/stack-template.go | 48 +++ .../usecase/system-notification-template.go | 57 ++++ pkg/domain/organization.go | 13 +- pkg/domain/stack-template.go | 8 + pkg/domain/system-notification-template.go | 8 + pkg/httpErrors/errorCode.go | 15 +- 19 files changed, 1122 insertions(+), 163 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 51083b71..0b44751f 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -5830,6 +5830,74 @@ const docTemplate = `{ } } } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove organization stackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Remove organization stackTemplates", + "parameters": [ + { + "description": "Remove organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add organization stackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Add organization stackTemplates", + "parameters": [ + { + "description": "Add organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } } }, "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { @@ -6553,6 +6621,138 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/system-notification-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization SystemNotificationTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Get Organization SystemNotificationTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove organization systemNotificationTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Remove organization systemNotificationTemplates", + "parameters": [ + { + "description": "Remove organization systemNotification templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add organization systemNotificationTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Add organization systemNotificationTemplates", + "parameters": [ + { + "description": "Add organization systemNotification templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/system-notifications": { "get": { "security": [ @@ -7463,6 +7663,34 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest": { + "type": "object", + "required": [ + "stackTemplateIds" + ], + "properties": { + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest": { + "type": "object", + "required": [ + "systemNotificationTemplateIds" + ], + "properties": { + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest": { "type": "object", "properties": { @@ -10549,6 +10777,34 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest": { + "type": "object", + "required": [ + "stackTemplateIds" + ], + "properties": { + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest": { + "type": "object", + "required": [ + "systemNotificationTemplateIds" + ], + "properties": { + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest": { "type": "object", "properties": { @@ -11383,24 +11639,6 @@ const docTemplate = `{ "type": "string", "maxLength": 30, "minLength": 1 - }, - "policyTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "stackTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "systemNotificationTemplateIds": { - "type": "array", - "items": { - "type": "string" - } } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 3c11ca30..58f58a56 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -5824,6 +5824,74 @@ } } } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove organization stackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Remove organization stackTemplates", + "parameters": [ + { + "description": "Remove organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add organization stackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Add organization stackTemplates", + "parameters": [ + { + "description": "Add organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } } }, "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { @@ -6547,6 +6615,138 @@ } } }, + "/organizations/{organizationId}/system-notification-templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization SystemNotificationTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Get Organization SystemNotificationTemplates", + "parameters": [ + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove organization systemNotificationTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Remove organization systemNotificationTemplates", + "parameters": [ + { + "description": "Remove organization systemNotification templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add organization systemNotificationTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Add organization systemNotificationTemplates", + "parameters": [ + { + "description": "Add organization systemNotification templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/system-notifications": { "get": { "security": [ @@ -7457,6 +7657,34 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest": { + "type": "object", + "required": [ + "stackTemplateIds" + ], + "properties": { + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest": { + "type": "object", + "required": [ + "systemNotificationTemplateIds" + ], + "properties": { + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest": { "type": "object", "properties": { @@ -10543,6 +10771,34 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest": { + "type": "object", + "required": [ + "stackTemplateIds" + ], + "properties": { + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest": { + "type": "object", + "required": [ + "systemNotificationTemplateIds" + ], + "properties": { + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest": { "type": "object", "properties": { @@ -11377,24 +11633,6 @@ "type": "string", "maxLength": 30, "minLength": 1 - }, - "policyTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "stackTemplateIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "systemNotificationTemplateIds": { - "type": "array", - "items": { - "type": "string" - } } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index cc8b53ac..71ac2318 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -140,6 +140,24 @@ definitions: uri: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest: + properties: + stackTemplateIds: + items: + type: string + type: array + required: + - stackTemplateIds + type: object + github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest: + properties: + systemNotificationTemplateIds: + items: + type: string + type: array + required: + - systemNotificationTemplateIds + type: object github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest: properties: projectMembers: @@ -2210,6 +2228,24 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest: + properties: + stackTemplateIds: + items: + type: string + type: array + required: + - stackTemplateIds + type: object + github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest: + properties: + systemNotificationTemplateIds: + items: + type: string + type: array + required: + - systemNotificationTemplateIds + type: object github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest: properties: projectMembers: @@ -2761,18 +2797,6 @@ definitions: maxLength: 30 minLength: 1 type: string - policyTemplateIds: - items: - type: string - type: array - stackTemplateIds: - items: - type: string - type: array - systemNotificationTemplateIds: - items: - type: string - type: array required: - name type: object @@ -6829,6 +6853,48 @@ paths: summary: Get Organization StackTemplates tags: - StackTemplates + post: + consumes: + - application/json + description: Add organization stackTemplates + parameters: + - description: Add organization stack templates request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Add organization stackTemplates + tags: + - StackTemplates + put: + consumes: + - application/json + description: Remove organization stackTemplates + parameters: + - description: Remove organization stack templates request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Remove organization stackTemplates + tags: + - StackTemplates /organizations/{organizationId}/stack-templates/{stackTemplateId}: get: consumes: @@ -7286,6 +7352,89 @@ paths: summary: Check name for systemNotificationRule tags: - SystemNotificationRules + /organizations/{organizationId}/system-notification-templates: + get: + consumes: + - application/json + description: Get Organization SystemNotificationTemplates + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse' + security: + - JWT: [] + summary: Get Organization SystemNotificationTemplates + tags: + - SystemNotificationTemplates + post: + consumes: + - application/json + description: Add organization systemNotificationTemplates + parameters: + - description: Add organization systemNotification templates request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Add organization systemNotificationTemplates + tags: + - SystemNotificationTemplates + put: + consumes: + - application/json + description: Remove organization systemNotificationTemplates + parameters: + - description: Remove organization systemNotification templates request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Remove organization systemNotificationTemplates + tags: + - SystemNotificationTemplates /organizations/{organizationId}/system-notifications: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2acd7f8d..2364a2ea 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -41,11 +41,11 @@ const ( // Organization Admin_CreateOrganization Admin_DeleteOrganization - UpdateOrganization GetOrganizations GetOrganization - UpdatePrimaryCluster CheckOrganizationName + UpdateOrganization + UpdatePrimaryCluster // Cluster CreateCluster @@ -105,6 +105,8 @@ const ( Admin_CheckStackTemplateName GetOrganizationStackTemplates GetOrganizationStackTemplate + AddOrganizationStackTemplates + RemoveOrganizationStackTemplates // Dashboard CreateDashboard @@ -120,6 +122,9 @@ const ( Admin_UpdateSystemNotificationTemplate Admin_GetSystemNotificationTemplates Admin_GetSystemNotificationTemplate + GetOrganizationSystemNotificationTemplates + AddOrganizationSystemNotificationTemplates + RemoveOrganizationSystemNotificationTemplates // SystemNotificationRule CreateSystemNotificationRule diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 87efb1cc..891ac188 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -99,10 +99,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_DeleteOrganization", Group: "Organization", }, - UpdateOrganization: { - Name: "UpdateOrganization", - Group: "Organization", - }, GetOrganizations: { Name: "GetOrganizations", Group: "Organization", @@ -111,14 +107,18 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetOrganization", Group: "Organization", }, - UpdatePrimaryCluster: { - Name: "UpdatePrimaryCluster", - Group: "Organization", - }, CheckOrganizationName: { Name: "CheckOrganizationName", Group: "Organization", }, + UpdateOrganization: { + Name: "UpdateOrganization", + Group: "Organization", + }, + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", + Group: "Organization", + }, CreateCluster: { Name: "CreateCluster", Group: "Cluster", @@ -315,6 +315,14 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetOrganizationStackTemplate", Group: "StackTemplate", }, + AddOrganizationStackTemplates: { + Name: "AddOrganizationStackTemplates", + Group: "StackTemplate", + }, + RemoveOrganizationStackTemplates: { + Name: "RemoveOrganizationStackTemplates", + Group: "StackTemplate", + }, CreateDashboard: { Name: "CreateDashboard", Group: "Dashboard", @@ -359,6 +367,18 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_GetSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, + GetOrganizationSystemNotificationTemplates: { + Name: "GetOrganizationSystemNotificationTemplates", + Group: "SystemNotificationTemplate", + }, + AddOrganizationSystemNotificationTemplates: { + Name: "AddOrganizationSystemNotificationTemplates", + Group: "SystemNotificationTemplate", + }, + RemoveOrganizationSystemNotificationTemplates: { + Name: "RemoveOrganizationSystemNotificationTemplates", + Group: "SystemNotificationTemplate", + }, CreateSystemNotificationRule: { Name: "CreateSystemNotificationRule", Group: "SystemNotificationRule", @@ -838,16 +858,16 @@ func (e Endpoint) String() string { return "Admin_CreateOrganization" case Admin_DeleteOrganization: return "Admin_DeleteOrganization" - case UpdateOrganization: - return "UpdateOrganization" case GetOrganizations: return "GetOrganizations" case GetOrganization: return "GetOrganization" - case UpdatePrimaryCluster: - return "UpdatePrimaryCluster" case CheckOrganizationName: return "CheckOrganizationName" + case UpdateOrganization: + return "UpdateOrganization" + case UpdatePrimaryCluster: + return "UpdatePrimaryCluster" case CreateCluster: return "CreateCluster" case GetClusters: @@ -946,6 +966,10 @@ func (e Endpoint) String() string { return "GetOrganizationStackTemplates" case GetOrganizationStackTemplate: return "GetOrganizationStackTemplate" + case AddOrganizationStackTemplates: + return "AddOrganizationStackTemplates" + case RemoveOrganizationStackTemplates: + return "RemoveOrganizationStackTemplates" case CreateDashboard: return "CreateDashboard" case GetDashboard: @@ -968,6 +992,12 @@ func (e Endpoint) String() string { return "Admin_GetSystemNotificationTemplates" case Admin_GetSystemNotificationTemplate: return "Admin_GetSystemNotificationTemplate" + case GetOrganizationSystemNotificationTemplates: + return "GetOrganizationSystemNotificationTemplates" + case AddOrganizationSystemNotificationTemplates: + return "AddOrganizationSystemNotificationTemplates" + case RemoveOrganizationSystemNotificationTemplates: + return "RemoveOrganizationSystemNotificationTemplates" case CreateSystemNotificationRule: return "CreateSystemNotificationRule" case GetSystemNotificationRules: @@ -1236,16 +1266,16 @@ func GetEndpoint(name string) Endpoint { return Admin_CreateOrganization case "Admin_DeleteOrganization": return Admin_DeleteOrganization - case "UpdateOrganization": - return UpdateOrganization case "GetOrganizations": return GetOrganizations case "GetOrganization": return GetOrganization - case "UpdatePrimaryCluster": - return UpdatePrimaryCluster case "CheckOrganizationName": return CheckOrganizationName + case "UpdateOrganization": + return UpdateOrganization + case "UpdatePrimaryCluster": + return UpdatePrimaryCluster case "CreateCluster": return CreateCluster case "GetClusters": @@ -1344,6 +1374,10 @@ func GetEndpoint(name string) Endpoint { return GetOrganizationStackTemplates case "GetOrganizationStackTemplate": return GetOrganizationStackTemplate + case "AddOrganizationStackTemplates": + return AddOrganizationStackTemplates + case "RemoveOrganizationStackTemplates": + return RemoveOrganizationStackTemplates case "CreateDashboard": return CreateDashboard case "GetDashboard": @@ -1366,6 +1400,12 @@ func GetEndpoint(name string) Endpoint { return Admin_GetSystemNotificationTemplates case "Admin_GetSystemNotificationTemplate": return Admin_GetSystemNotificationTemplate + case "GetOrganizationSystemNotificationTemplates": + return GetOrganizationSystemNotificationTemplates + case "AddOrganizationSystemNotificationTemplates": + return AddOrganizationSystemNotificationTemplates + case "RemoveOrganizationSystemNotificationTemplates": + return RemoveOrganizationSystemNotificationTemplates case "CreateSystemNotificationRule": return CreateSystemNotificationRule case "GetSystemNotificationRules": diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index ea446b40..6fc3e896 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" - "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" @@ -325,39 +324,14 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. log.Info(r.Context(), err) } - for _, strId := range input.StackTemplateIds { - stackTemplateId, err := uuid.Parse(strId) - if err != nil || stackTemplateId == uuid.Nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) - return - } - dto.StackTemplateIds = append(dto.StackTemplateIds, stackTemplateId) - } - for _, strId := range input.PolicyTemplateIds { - policyTemplateId, err := uuid.Parse(strId) - if err != nil || policyTemplateId == uuid.Nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) - return - } - dto.PolicyTemplateIds = append(dto.PolicyTemplateIds, policyTemplateId) - } - for _, strId := range input.SystemNotificationTemplateIds { - systemNotificationTemplateId, err := uuid.Parse(strId) - if err != nil || systemNotificationTemplateId == uuid.Nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationTemplateId"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) - return - } - dto.SystemNotificationTemplateIds = append(dto.SystemNotificationTemplateIds, systemNotificationTemplateId) - } - - err = h.usecase.UpdateWithTemplates(r.Context(), organizationId, dto) + res, err := h.usecase.Update(r.Context(), organizationId, dto) if err != nil { ErrorJSON(w, r, err) return } var out domain.UpdateOrganizationResponse - out.ID = organizationId + out.ID = res.ID ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 3297f29a..ba1d7935 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -451,3 +451,71 @@ func (h *StackTemplateHandler) CheckStackTemplateName(w http.ResponseWriter, r * ResponseJSON(w, r, http.StatusOK, out) } + +// AddOrganizationStackTemplates godoc +// +// @Tags StackTemplates +// @Summary Add organization stackTemplates +// @Description Add organization stackTemplates +// @Accept json +// @Produce json +// @Param body body domain.AddOrganizationStackTemplatesRequest true "Add organization stack templates request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stack-templates [post] +// @Security JWT +func (h *StackTemplateHandler) AddOrganizationStackTemplates(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.AddOrganizationStackTemplatesRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + err = h.usecase.AddOrganizationStackTemplates(r.Context(), organizationId, input.StackTemplateIds) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) +} + +// RemoveOrganizationStackTemplates godoc +// +// @Tags StackTemplates +// @Summary Remove organization stackTemplates +// @Description Remove organization stackTemplates +// @Accept json +// @Produce json +// @Param body body domain.RemoveOrganizationStackTemplatesRequest true "Remove organization stack templates request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stack-templates [put] +// @Security JWT +func (h *StackTemplateHandler) RemoveOrganizationStackTemplates(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.RemoveOrganizationStackTemplatesRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + err = h.usecase.RemoveOrganizationStackTemplates(r.Context(), organizationId, input.StackTemplateIds) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index f1d6dc44..73053e17 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -219,3 +219,124 @@ func (h *SystemNotificationTemplateHandler) UpdateSystemNotificationTemplate(w h ResponseJSON(w, r, http.StatusOK, nil) } + +// GetOrganizationSystemNotificationTemplates godoc +// +// @Tags SystemNotificationTemplates +// @Summary Get Organization SystemNotificationTemplates +// @Description Get Organization SystemNotificationTemplates +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetSystemNotificationTemplatesResponse +// @Router /organizations/{organizationId}/system-notification-templates [get] +// @Security JWT +func (h *SystemNotificationTemplateHandler) GetOrganizationSystemNotificationTemplates(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + systemNotificationTemplates, err := h.usecase.FetchWithOrganization(r.Context(), organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetSystemNotificationTemplatesResponse + out.SystemNotificationTemplates = make([]domain.SystemNotificationTemplateResponse, len(systemNotificationTemplates)) + for i, systemNotificationTemplate := range systemNotificationTemplates { + if err := serializer.Map(r.Context(), systemNotificationTemplate, &out.SystemNotificationTemplates[i]); err != nil { + log.Info(r.Context(), err) + } + + out.SystemNotificationTemplates[i].Organizations = make([]domain.SimpleOrganizationResponse, len(systemNotificationTemplate.Organizations)) + for j, organization := range systemNotificationTemplate.Organizations { + if err := serializer.Map(r.Context(), organization, &out.SystemNotificationTemplates[i].Organizations[j]); err != nil { + log.Info(r.Context(), err) + } + } + } + + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// AddOrganizationSystemNotificationTemplates godoc +// +// @Tags SystemNotificationTemplates +// @Summary Add organization systemNotificationTemplates +// @Description Add organization systemNotificationTemplates +// @Accept json +// @Produce json +// @Param body body domain.AddOrganizationSystemNotificationTemplatesRequest true "Add organization systemNotification templates request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/system-notification-templates [post] +// @Security JWT +func (h *SystemNotificationTemplateHandler) AddOrganizationSystemNotificationTemplates(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.AddOrganizationSystemNotificationTemplatesRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + err = h.usecase.AddOrganizationSystemNotificationTemplates(r.Context(), organizationId, input.SystemNotificationTemplateIds) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) +} + +// RemoveOrganizationSystemNotificationTemplates godoc +// +// @Tags SystemNotificationTemplates +// @Summary Remove organization systemNotificationTemplates +// @Description Remove organization systemNotificationTemplates +// @Accept json +// @Produce json +// @Param body body domain.RemoveOrganizationSystemNotificationTemplatesRequest true "Remove organization systemNotification templates request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/system-notification-templates [put] +// @Security JWT +func (h *SystemNotificationTemplateHandler) RemoveOrganizationSystemNotificationTemplates(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.RemoveOrganizationSystemNotificationTemplatesRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + err = h.usecase.RemoveOrganizationSystemNotificationTemplates(r.Context(), organizationId, input.SystemNotificationTemplateIds) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/middleware/auth/role/default.go b/internal/middleware/auth/role/default.go index d56e092e..70f1f256 100644 --- a/internal/middleware/auth/role/default.go +++ b/internal/middleware/auth/role/default.go @@ -58,7 +58,6 @@ var defaultPermissionOfAdmin = defaultPermission{ // Organization internalApi.Admin_CreateOrganization, - internalApi.Admin_UpdateOrganization, internalApi.Admin_DeleteOrganization, internalApi.GetOrganizations, internalApi.GetOrganization, diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 306d9cc6..2ca270b6 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -20,9 +20,10 @@ type IOrganizationRepository interface { Update(ctx context.Context, organizationId string, in model.Organization) (model.Organization, error) UpdatePrimaryClusterId(ctx context.Context, organizationId string, primaryClusterId string) error UpdateAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error - UpdateStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) - UpdatePolicyTemplates(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) - UpdateSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplates []model.SystemNotificationTemplate) (err error) + AddStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) + RemoveStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) + AddSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplates []model.SystemNotificationTemplate) (err error) + RemoveSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplates []model.SystemNotificationTemplate) (err error) Delete(ctx context.Context, organizationId string) (err error) InitWorkflow(ctx context.Context, organizationId string, workflowId string, status domain.OrganizationStatus) error } @@ -167,14 +168,14 @@ func (r *OrganizationRepository) InitWorkflow(ctx context.Context, organizationI return nil } -func (r *OrganizationRepository) UpdateStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) { +func (r *OrganizationRepository) AddStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) { var organization = model.Organization{} res := r.db.WithContext(ctx).Preload("StackTemplates").First(&organization, "id = ?", organizationId) if res.Error != nil { return res.Error } - err = r.db.WithContext(ctx).Model(&organization).Association("StackTemplates").Replace(stackTemplates) + err = r.db.WithContext(ctx).Model(&organization).Association("StackTemplates").Append(stackTemplates) if err != nil { return err } @@ -182,22 +183,47 @@ func (r *OrganizationRepository) UpdateStackTemplates(ctx context.Context, organ return nil } -func (r *OrganizationRepository) UpdatePolicyTemplates(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) { - // [TODO] +func (r *OrganizationRepository) RemoveStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) { + var organization = model.Organization{} + res := r.db.WithContext(ctx).Preload("StackTemplates").First(&organization, "id = ?", organizationId) + if res.Error != nil { + return res.Error + } + + err = r.db.WithContext(ctx).Model(&organization).Association("StackTemplates").Delete(stackTemplates) + if err != nil { + return err + } return nil } -func (r *OrganizationRepository) UpdateSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplates []model.SystemNotificationTemplate) (err error) { +func (r *OrganizationRepository) AddSystemNotificationTemplates(ctx context.Context, organizationId string, templates []model.SystemNotificationTemplate) (err error) { var organization = model.Organization{} res := r.db.WithContext(ctx).Preload("SystemNotificationTemplates").First(&organization, "id = ?", organizationId) if res.Error != nil { return res.Error } - err = r.db.WithContext(ctx).Model(&organization).Association("SystemNotificationTemplates").Replace(systemNotificationTemplates) + err = r.db.WithContext(ctx).Model(&organization).Association("SystemNotificationTemplates").Append(templates) if err != nil { return err } + + return nil +} + +func (r *OrganizationRepository) RemoveSystemNotificationTemplates(ctx context.Context, organizationId string, templates []model.SystemNotificationTemplate) (err error) { + var organization = model.Organization{} + res := r.db.WithContext(ctx).Preload("SystemNotificationTemplates").First(&organization, "id = ?", organizationId) + if res.Error != nil { + return res.Error + } + + err = r.db.WithContext(ctx).Model(&organization).Association("SystemNotificationTemplates").Delete(templates) + if err != nil { + return err + } + return nil } diff --git a/internal/repository/system-notification-template.go b/internal/repository/system-notification-template.go index 1bf41ded..4c70884f 100644 --- a/internal/repository/system-notification-template.go +++ b/internal/repository/system-notification-template.go @@ -17,6 +17,7 @@ type ISystemNotificationTemplateRepository interface { Get(ctx context.Context, systemNotificationTemplateId uuid.UUID) (model.SystemNotificationTemplate, error) GetByName(ctx context.Context, name string) (model.SystemNotificationTemplate, error) Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.SystemNotificationTemplate, error) + FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotificationTemplate, err error) Create(ctx context.Context, dto model.SystemNotificationTemplate) (systemNotificationTemplateId uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationTemplate) (err error) Delete(ctx context.Context, dto model.SystemNotificationTemplate) (err error) @@ -62,6 +63,21 @@ func (r *SystemNotificationTemplateRepository) Fetch(ctx context.Context, pg *pa return } +func (r *SystemNotificationTemplateRepository) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotificationTemplate, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch( + r.db.WithContext(ctx).Preload(clause.Associations). + Joins("JOIN system_notification_template_organizations ON system_notification_template_organizations.system_notification_template_id = system_notification_templates.id AND system_notification_template_organizations.organization_id = ?", organizationId), + &out) + if res.Error != nil { + return nil, res.Error + } + return +} + func (r *SystemNotificationTemplateRepository) Create(ctx context.Context, dto model.SystemNotificationTemplate) (systemNotificationTemplateId uuid.UUID, err error) { dto.ID = uuid.New() res := r.db.WithContext(ctx).Create(&dto) diff --git a/internal/route/route.go b/internal/route/route.go index da1e31ce..6573b4e9 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -194,6 +194,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.GetOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetOrganizationStackTemplate, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.AddOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.AddOrganizationStackTemplates))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.RemoveOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.RemoveOrganizationStackTemplates))).Methods(http.MethodPut) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) @@ -218,6 +220,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates", customMiddleware.Handle(internalApi.Admin_GetSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetSystemNotificationTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_GetSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.GetSystemNotificationTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.UpdateSystemNotificationTemplate))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.GetOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetOrganizationSystemNotificationTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.AddOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.AddOrganizationSystemNotificationTemplates))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.RemoveOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.RemoveOrganizationSystemNotificationTemplates))).Methods(http.MethodPut) systemNotificationRuleHandler := delivery.NewSystemNotificationRuleHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index e8b105f4..ff7c59d0 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -26,7 +26,6 @@ type IOrganizationUsecase interface { Get(ctx context.Context, organizationId string) (model.Organization, error) Update(ctx context.Context, organizationId string, dto model.Organization) (model.Organization, error) UpdatePrimaryClusterId(ctx context.Context, organizationId string, clusterId string) (err error) - UpdateWithTemplates(ctx context.Context, organizationId string, dto model.Organization) (err error) ChangeAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error Delete(ctx context.Context, organizationId string, accessToken string) error } @@ -194,51 +193,3 @@ func (u *OrganizationUsecase) ChangeAdminId(ctx context.Context, organizationId return nil } - -func (u *OrganizationUsecase) UpdateWithTemplates(ctx context.Context, organizationId string, dto model.Organization) (err error) { - _, err = u.Update(ctx, organizationId, dto) - if err != nil { - return err - } - - stackTemplates := make([]model.StackTemplate, 0) - for _, stackTemplateId := range dto.StackTemplateIds { - stackTemplate, err := u.stackTemplateRepo.Get(ctx, stackTemplateId) - if err != nil { - return fmt.Errorf("Invalid stackTemplateId") - } - stackTemplates = append(stackTemplates, stackTemplate) - } - err = u.repo.UpdateStackTemplates(ctx, organizationId, stackTemplates) - if err != nil { - return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_STACK_TEMPLATES", "") - } - - policyTemplates := make([]model.PolicyTemplate, 0) - for _, policyTemplateId := range dto.PolicyTemplateIds { - policyTemplate, err := u.policyTemplateRepo.GetByID(ctx, policyTemplateId) - if err != nil { - return fmt.Errorf("Invalid policyTemplateId") - } - policyTemplates = append(policyTemplates, *policyTemplate) - } - err = u.repo.UpdatePolicyTemplates(ctx, organizationId, policyTemplates) - if err != nil { - return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_POLICY_TEMPLATES", "") - } - - systemNotificationTemplates := make([]model.SystemNotificationTemplate, 0) - for _, systemNotificationTemplateId := range dto.SystemNotificationTemplateIds { - systemNotificationTemplate, err := u.systemNotificationTemplateRepo.Get(ctx, systemNotificationTemplateId) - if err != nil { - return fmt.Errorf("Invalid systemNotificationTemplateId") - } - systemNotificationTemplates = append(systemNotificationTemplates, systemNotificationTemplate) - } - err = u.repo.UpdateSystemNotificationTemplates(ctx, organizationId, systemNotificationTemplates) - if err != nil { - return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_SYSTEM_NOTIFICATION_TEMPLATES", "") - } - - return nil -} diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 7004d79b..2b56f9e1 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -25,6 +25,8 @@ type IStackTemplateUsecase interface { Delete(ctx context.Context, dto model.StackTemplate) error UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error GetByName(ctx context.Context, name string) (model.StackTemplate, error) + AddOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error + RemoveOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error } type StackTemplateUsecase struct { @@ -153,3 +155,49 @@ func (u *StackTemplateUsecase) UpdateOrganizations(ctx context.Context, dto mode return nil } + +func (u *StackTemplateUsecase) AddOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error { + _, err := u.organizationRepo.Get(ctx, organizationId) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_NOT_EXISTED_NAME", "") + } + + stackTemplates := make([]model.StackTemplate, 0) + for _, strId := range stackTemplateIds { + stackTemplateId, _ := uuid.Parse(strId) + stackTemplate, err := u.repo.Get(ctx, stackTemplateId) + if err == nil { + stackTemplates = append(stackTemplates, stackTemplate) + } + } + + err = u.organizationRepo.AddStackTemplates(ctx, organizationId, stackTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "ST_FAILED_ADD_ORGANIZATION_STACK_TEMPLATE", "") + } + + return nil +} + +func (u *StackTemplateUsecase) RemoveOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error { + _, err := u.organizationRepo.Get(ctx, organizationId) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_NOT_EXISTED_NAME", "") + } + + stackTemplates := make([]model.StackTemplate, 0) + for _, strId := range stackTemplateIds { + stackTemplateId, _ := uuid.Parse(strId) + stackTemplate, err := u.repo.Get(ctx, stackTemplateId) + if err == nil { + stackTemplates = append(stackTemplates, stackTemplate) + } + } + + err = u.organizationRepo.RemoveStackTemplates(ctx, organizationId, stackTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "ST_FAILED_REMOVE_ORGANIZATION_STACK_TEMPLATE", "") + } + + return nil +} diff --git a/internal/usecase/system-notification-template.go b/internal/usecase/system-notification-template.go index f4f4acf1..6516eb77 100644 --- a/internal/usecase/system-notification-template.go +++ b/internal/usecase/system-notification-template.go @@ -19,9 +19,12 @@ type ISystemNotificationTemplateUsecase interface { Get(ctx context.Context, alertId uuid.UUID) (model.SystemNotificationTemplate, error) GetByName(ctx context.Context, name string) (model.SystemNotificationTemplate, error) Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.SystemNotificationTemplate, error) + FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotificationTemplate, error) Create(ctx context.Context, dto model.SystemNotificationTemplate) (systemNotificationTemplate uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationTemplate) error Delete(ctx context.Context, dto model.SystemNotificationTemplate) error + AddOrganizationSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplateIds []string) error + RemoveOrganizationSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplateIds []string) error } type SystemNotificationTemplateUsecase struct { @@ -114,6 +117,14 @@ func (u *SystemNotificationTemplateUsecase) Fetch(ctx context.Context, pg *pagin return } +func (u *SystemNotificationTemplateUsecase) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (res []model.SystemNotificationTemplate, err error) { + res, err = u.repo.FetchWithOrganization(ctx, organizationId, pg) + if err != nil { + return nil, err + } + return res, nil +} + func (u *SystemNotificationTemplateUsecase) Delete(ctx context.Context, dto model.SystemNotificationTemplate) (err error) { return nil } @@ -139,3 +150,49 @@ func (u *SystemNotificationTemplateUsecase) UpdateOrganizations(ctx context.Cont return nil } + +func (u *SystemNotificationTemplateUsecase) AddOrganizationSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplateIds []string) error { + _, err := u.organizationRepo.Get(ctx, organizationId) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_NOT_EXISTED_NAME", "") + } + + systemNotificationTemplates := make([]model.SystemNotificationTemplate, 0) + for _, strId := range systemNotificationTemplateIds { + systemNotificationTemplateId, _ := uuid.Parse(strId) + systemNotificationTemplate, err := u.repo.Get(ctx, systemNotificationTemplateId) + if err == nil { + systemNotificationTemplates = append(systemNotificationTemplates, systemNotificationTemplate) + } + } + + err = u.organizationRepo.AddSystemNotificationTemplates(ctx, organizationId, systemNotificationTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "ST_FAILED_ADD_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE", "") + } + + return nil +} + +func (u *SystemNotificationTemplateUsecase) RemoveOrganizationSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplateIds []string) error { + _, err := u.organizationRepo.Get(ctx, organizationId) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_NOT_EXISTED_NAME", "") + } + + systemNotificationTemplates := make([]model.SystemNotificationTemplate, 0) + for _, strId := range systemNotificationTemplateIds { + systemNotificationTemplateId, _ := uuid.Parse(strId) + systemNotificationTemplate, err := u.repo.Get(ctx, systemNotificationTemplateId) + if err == nil { + systemNotificationTemplates = append(systemNotificationTemplates, systemNotificationTemplate) + } + } + + err = u.organizationRepo.RemoveSystemNotificationTemplates(ctx, organizationId, systemNotificationTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "ST_FAILED_REMOVE_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE", "") + } + + return nil +} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 478dc45b..ef19f12c 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -91,11 +91,8 @@ type ListOrganizationResponse struct { } type UpdateOrganizationRequest struct { - Name string `json:"name" validate:"required,min=1,max=30"` - Description string `json:"description" validate:"omitempty,min=0,max=100"` - StackTemplateIds []string `json:"stackTemplateIds"` - PolicyTemplateIds []string `json:"policyTemplateIds"` - SystemNotificationTemplateIds []string `json:"systemNotificationTemplateIds"` + Name string `json:"name" validate:"required,min=1,max=30"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` } type UpdateOrganizationResponse struct { @@ -106,6 +103,12 @@ type UpdatePrimaryClusterRequest struct { PrimaryClusterId string `json:"primaryClusterId"` } +type UpdateOrganizationTemplatesRequest struct { + StackTemplateIds *[]string `json:"stackTemplateIds,omitempty"` + PolicyTemplateIds *[]string `json:"policyTemplateIds,omitempty"` + SystemNotificationTemplateIds *[]string `json:"systemNotificationTemplateIds,omitempty"` +} + type DeleteOrganizationResponse struct { ID string `json:"id"` } diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index ff1f2570..e5bce152 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -104,3 +104,11 @@ type UpdateStackTemplateOrganizationsRequest struct { type CheckStackTemplateNameResponse struct { Existed bool `json:"existed"` } + +type AddOrganizationStackTemplatesRequest struct { + StackTemplateIds []string `json:"stackTemplateIds" validate:"required"` +} + +type RemoveOrganizationStackTemplatesRequest struct { + StackTemplateIds []string `json:"stackTemplateIds" validate:"required"` +} diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index d4ef68c5..8b242289 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -59,3 +59,11 @@ type GetSystemNotificationTemplatesResponse struct { type GetSystemNotificationTemplateResponse struct { SystemNotificationTemplate SystemNotificationTemplateResponse `json:"systemNotificationTemplate"` } + +type AddOrganizationSystemNotificationTemplatesRequest struct { + SystemNotificationTemplateIds []string `json:"systemNotificationTemplateIds" validate:"required"` +} + +type RemoveOrganizationSystemNotificationTemplatesRequest struct { + SystemNotificationTemplateIds []string `json:"systemNotificationTemplateIds" validate:"required"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index a6acff9c..5dff7467 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -36,6 +36,7 @@ var errorMap = map[ErrorCode]string{ // Organization "O_INVALID_ORGANIZATION_NAME": "조직에 이미 존재하는 이름입니다.", + "O_NOT_EXISTED_NAME": "조직이 존재하지 않습니다.", "O_FAILED_UPDATE_STACK_TEMPLATES": "조직에 스택템플릿을 설정하는데 실패했습니다", "O_FAILED_UPDATE_POLICY_TEMPLATES": "조직에 정책템플릿을 설정하는데 실패했습니다", "O_FAILED_UPDATE_SYSTEM_NOTIFICATION_TEMPLATES": "조직에 알림템플릿을 설정하는데 실패했습니다", @@ -99,11 +100,15 @@ var errorMap = map[ErrorCode]string{ "AG_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패하였습니다.", // StackTemplate - "ST_CREATE_ALREADY_EXISTED_NAME": "스택템플릿에 이미 존재하는 이름입니다.", - "ST_FAILED_UPDATE_ORGANIZATION": "스택템플릿에 조직을 설정하는데 실패했습니다.", - "ST_NOT_EXISTED_STACK_TEMPLATE": "업데이트할 스택템플릿이 존재하지 않습니다.", - "ST_INVALID_STACK_TEMAPLTE_NAME": "유효하지 않은 스택템플릿 이름입니다. 스택템플릿 이름을 확인하세요.", - "ST_FAILED_FETCH_STACK_TEMPLATE": "스택템플릿을 가져오는데 실패했습니다.", + "ST_CREATE_ALREADY_EXISTED_NAME": "스택템플릿에 이미 존재하는 이름입니다.", + "ST_FAILED_UPDATE_ORGANIZATION": "스택템플릿에 조직을 설정하는데 실패했습니다.", + "ST_NOT_EXISTED_STACK_TEMPLATE": "업데이트할 스택템플릿이 존재하지 않습니다.", + "ST_INVALID_STACK_TEMAPLTE_NAME": "유효하지 않은 스택템플릿 이름입니다. 스택템플릿 이름을 확인하세요.", + "ST_FAILED_FETCH_STACK_TEMPLATE": "스택템플릿을 가져오는데 실패했습니다.", + "ST_FAILED_ADD_ORGANIZATION_STACK_TEMPLATE": "조직에 스택템플릿을 추가하는데 실패하였습니다.", + "ST_FAILED_REMOVE_ORGANIZATION_STACK_TEMPLATE": "조직에서 스택템플릿을 삭제하는데 실패하였습니다.", + "ST_FAILED_ADD_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE": "조직에 시스템알람템플릿을 추가하는데 실패하였습니다.", + "ST_FAILED_REMOVE_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE": "조직에서 시스템알람템플릿을 삭제하는데 실패하였습니다.", // PolicyTemplate "PT_CREATE_ALREADY_EXISTED_NAME": "정첵 템플릿에 이미 존재하는 이름입니다.", From d60fcd196a578e77031baf1b40271f72155ce469 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 22 Mar 2024 10:53:52 +0900 Subject: [PATCH 156/502] =?UTF-8?q?/policytemplates=20->=20/policy-templat?= =?UTF-8?q?es,=20=EC=9D=BC=EB=B6=80=20=ED=95=A8=EC=88=98=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy-template.go | 34 +++++++++++------------ internal/route/route.go | 28 +++++++++---------- internal/usecase/policy-template.go | 8 +++--- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 3e9cb819..5b0dfa3e 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -55,7 +55,7 @@ func NewPolicyTemplateHandler(u usecase.Usecase) IPolicyTemplateHandler { // @Produce json // @Param body body domain.CreatePolicyTemplateRequest true "create policy template request" // @Success 200 {object} domain.CreatePolicyTemplateReponse -// @Router /admin/policytemplates [post] +// @Router /admin/policy-templates [post] // @Security JWT func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) { input := domain.CreatePolicyTemplateRequest{} @@ -94,7 +94,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param body body domain.UpdatePolicyTemplateRequest true "update policy template request" // @Success 200 {object} nil -// @Router /admin/policytemplates/{policyTemplateId} [patch] +// @Router /admin/policy-templates/{policyTemplateId} [patch] // @Security JWT func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -146,7 +146,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} nil -// @Router /admin/policytemplates/{policyTemplateId} [delete] +// @Router /admin/policy-templates/{policyTemplateId} [delete] // @Security JWT func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -193,7 +193,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *h // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.GetPolicyTemplateResponse -// @Router /admin/policytemplates/{policyTemplateId} [get] +// @Router /admin/policy-templates/{policyTemplateId} [get] // @Security JWT func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -237,7 +237,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http log.Error(r.Context(), err) } - if err = h.usecase.UpdatePermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { + if err = h.usecase.FillPermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { log.Error(r.Context(), err) } @@ -257,7 +257,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.ListPolicyTemplateResponse -// @Router /admin/policytemplates [get] +// @Router /admin/policy-templates [get] // @Security JWT func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() @@ -279,7 +279,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt } } - if err = h.usecase.UpdatePermittedOrganizationsForList(r.Context(), &policyTemplates, &out.PolicyTemplates); err != nil { + if err = h.usecase.FillPermittedOrganizationsForList(r.Context(), &policyTemplates, &out.PolicyTemplates); err != nil { log.Error(r.Context(), err) } @@ -299,7 +299,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.ListPolicyTemplateVersionsResponse -// @Router /admin/policytemplates/{policyTemplateId}/versions [get] +// @Router /admin/policy-templates/{policyTemplateId}/versions [get] // @Security JWT func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -347,7 +347,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.ListPolicyTemplateStatisticsResponse -// @Router /admin/policytemplates/{policyTemplateId}/statistics [get] +// @Router /admin/policy-templates/{policyTemplateId}/statistics [get] // @Security JWT func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { // result := domain.ListPolicyTemplateStatisticsResponse{ @@ -376,7 +376,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWrit // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.GetPolicyTemplateDeployResponse -// @Router /admin/policytemplates/{policyTemplateId}/deploy [get] +// @Router /admin/policy-templates/{policyTemplateId}/deploy [get] // @Security JWT func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { // c1 := util.UUIDGen() @@ -403,7 +403,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param version path string true "조회할 버전(v0.0.0 형식)" // @Success 200 {object} domain.GetPolicyTemplateVersionResponse -// @Router /admin/policytemplates/{policyTemplateId}/versions/{version} [get] +// @Router /admin/policy-templates/{policyTemplateId}/versions/{version} [get] // @Security JWT func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -443,7 +443,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, log.Error(r.Context(), err) } - if err = h.usecase.UpdatePermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { + if err = h.usecase.FillPermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { log.Error(r.Context(), err) } @@ -460,7 +460,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param body body domain.CreatePolicyTemplateVersionRequest true "create policy template version request" // @Success 200 {object} domain.CreatePolicyTemplateVersionResponse -// @Router /admin/policytemplates/{policyTemplateId}/versions [post] +// @Router /admin/policy-templates/{policyTemplateId}/versions [post] // @Security JWT func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -536,7 +536,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param version path string true "삭제할 버전(v0.0.0 형식)" // @Success 200 {object} nil -// @Router /admin/policytemplates/{policyTemplateId}/versions/{version} [delete] +// @Router /admin/policy-templates/{policyTemplateId}/versions/{version} [delete] // @Security JWT func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -584,7 +584,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite // @Produce json // @Param policyTemplateName path string true "정책 템플릿 이름" // @Success 200 {object} domain.CheckExistedResponse -// @Router /admin/policytemplates/name/{policyTemplateName}/existence [get] +// @Router /admin/policy-templates/name/{policyTemplateName}/existence [get] // @Security JWT func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -616,7 +616,7 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, // @Produce json // @Param policyTemplateKind path string true "정책 템플릿 이름" // @Success 200 {object} domain.ExistsPolicyTemplateKindResponse -// @Router /admin/policytemplates/kind/{policyTemplateKind}/existence [get] +// @Router /admin/policy-templates/kind/{policyTemplateKind}/existence [get] // @Security JWT func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -649,7 +649,7 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, // @Param parseParameter query bool true "파라미터 파싱 여부" // @Param body body domain.RegoCompileRequest true "Rego 코드" // @Success 200 {object} domain.RegoCompileResponse -// @Router /policytemplates/rego-compile [post] +// @Router /policy-templates/rego-compile [post] // @Security JWT func (h *PolicyTemplateHandler) RegoCompile(w http.ResponseWriter, r *http.Request) { parseParameter := false diff --git a/internal/route/route.go b/internal/route/route.go index da1e31ce..c32f93f4 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -288,20 +288,20 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates", customMiddleware.Handle(internalApi.CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplate))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}", customMiddleware.Handle(internalApi.DeletePolicyTemplate, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplate))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetPolicyTemplate, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplate))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.UpdatePolicyTemplate))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/deploy ", customMiddleware.Handle(internalApi.GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateDeploy))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/statistics", customMiddleware.Handle(internalApi.ListPolicyTemplateStatistics, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateStatistics))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.ListPolicyTemplateVersions, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateVersions))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplateVersion))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.DeletePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplateVersion))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateVersion))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateKind))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policytemplates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateName))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/policytemplates/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(policyTemplateHandler.RegoCompile))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.DeletePolicyTemplate, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplate))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetPolicyTemplate, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.UpdatePolicyTemplate))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/deploy ", customMiddleware.Handle(internalApi.GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateDeploy))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/statistics", customMiddleware.Handle(internalApi.ListPolicyTemplateStatistics, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateStatistics))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.ListPolicyTemplateVersions, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateVersions))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplateVersion))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.DeletePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplateVersion))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateVersion))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateKind))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/policy-templates/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(policyTemplateHandler.RegoCompile))).Methods(http.MethodPost) // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 5bd18577..1294f157 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -32,9 +32,9 @@ type IPolicyTemplateUsecase interface { RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) - UpdatePermittedOrganizations(ctx context.Context, + FillPermittedOrganizations(ctx context.Context, policyTemplate *model.PolicyTemplate, out *domain.PolicyTemplateResponse) error - UpdatePermittedOrganizationsForList(ctx context.Context, + FillPermittedOrganizationsForList(ctx context.Context, policyTemplates *[]model.PolicyTemplate, outs *[]domain.PolicyTemplateResponse) error } @@ -104,7 +104,7 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagina return policyTemplates, nil } -func (u *PolicyTemplateUsecase) UpdatePermittedOrganizations(ctx context.Context, +func (u *PolicyTemplateUsecase) FillPermittedOrganizations(ctx context.Context, policyTemplate *model.PolicyTemplate, out *domain.PolicyTemplateResponse) error { organizations, err := u.organizationRepo.Fetch(ctx, nil) @@ -117,7 +117,7 @@ func (u *PolicyTemplateUsecase) UpdatePermittedOrganizations(ctx context.Context return nil } -func (u *PolicyTemplateUsecase) UpdatePermittedOrganizationsForList(ctx context.Context, +func (u *PolicyTemplateUsecase) FillPermittedOrganizationsForList(ctx context.Context, policyTemplates *[]model.PolicyTemplate, outs *[]domain.PolicyTemplateResponse) error { organizations, err := u.organizationRepo.Fetch(ctx, nil) From 2a68d6458a67422d82cf2b61205c49e7784d1b70 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 20 Mar 2024 17:33:47 +0900 Subject: [PATCH 157/502] re mapping permissions --- .../delivery/api/endpoints_permission_test.go | 70 +++ .../delivery/api/generated_endpoints.go.go | 8 - internal/model/permission.go | 585 +++++++++++++----- pkg/domain/endpoint.go | 8 +- pkg/domain/permission.go | 4 - 5 files changed, 513 insertions(+), 162 deletions(-) create mode 100644 internal/delivery/api/endpoints_permission_test.go diff --git a/internal/delivery/api/endpoints_permission_test.go b/internal/delivery/api/endpoints_permission_test.go new file mode 100644 index 00000000..e6033894 --- /dev/null +++ b/internal/delivery/api/endpoints_permission_test.go @@ -0,0 +1,70 @@ +package api_test + +import ( + "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/model" + "testing" +) + +func TestEndpointsUsage(t *testing.T) { + var allEndpoints []string + for _, v := range api.ApiMap { + allEndpoints = append(allEndpoints, v.Name) + } + //allEndpoints := []Endpoint{ + // Login, Logout, RefreshToken, FindId, // 계속해서 모든 Endpoint 추가 + // // 나머지 Endpoint 상수들을 여기에 추가 + //} + usageCount := make(map[string]int) + ps := model.NewAdminPermissionSet() + + permissions := []*model.Permission{ + ps.Dashboard, + ps.Notification, + ps.Configuration, + ps.ProjectManagement, + ps.Stack, + ps.SecurityPolicy, + ps.Common, + ps.Admin, + } + + leafPermissions := make([]*model.Permission, 0) + + for _, perm := range permissions { + leafPermissions = model.GetEdgePermission(perm, leafPermissions, nil) + } + + // Permission 설정에서 Endpoint 사용 횟수 카운트 + for _, perm := range leafPermissions { + countEndpoints(perm, usageCount) + } + + var unusedEndpoints, duplicatedEndpoints []string + + // 미사용 또는 중복 사용된 Endpoint 확인 및 출력 + for _, endpoint := range allEndpoints { + count, exists := usageCount[endpoint] + if !exists { + unusedEndpoints = append(unusedEndpoints, endpoint) + } else if count > 1 { + duplicatedEndpoints = append(duplicatedEndpoints, endpoint) + } + } + + for _, endpoint := range unusedEndpoints { + t.Logf("Unused Endpoint: %s", endpoint) + } + + t.Logf("\n") + for _, endpoint := range duplicatedEndpoints { + t.Logf("Duplicated Endpoint: %s", endpoint) + } + +} + +func countEndpoints(perm *model.Permission, usageCount map[string]int) { + for _, endpoint := range perm.Endpoints { + usageCount[endpoint.Name]++ + } +} diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 891ac188..ede19eb8 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -35,10 +35,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "VerifyToken", Group: "Auth", }, - DeleteToken: { - Name: "DeleteToken", - Group: "Auth", - }, CreateUser: { Name: "CreateUser", Group: "User", @@ -826,8 +822,6 @@ func (e Endpoint) String() string { return "VerifyIdentityForLostPassword" case VerifyToken: return "VerifyToken" - case DeleteToken: - return "DeleteToken" case CreateUser: return "CreateUser" case ListUser: @@ -1234,8 +1228,6 @@ func GetEndpoint(name string) Endpoint { return VerifyIdentityForLostPassword case "VerifyToken": return VerifyToken - case "DeleteToken": - return DeleteToken case "CreateUser": return CreateUser case "ListUser": diff --git a/internal/model/permission.go b/internal/model/permission.go index 5025d766..746b1257 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -11,9 +11,9 @@ type PermissionKind string const ( DashBoardPermission PermissionKind = "대시보드" - StackPermission PermissionKind = "스택 관리" - SecurityPolicyPermission PermissionKind = "보안/정책 관리" - ProjectManagementPermission PermissionKind = "프로젝트 관리" + StackPermission PermissionKind = "스택" + SecurityPolicyPermission PermissionKind = "정책" + ProjectManagementPermission PermissionKind = "프로젝트" NotificationPermission PermissionKind = "알림" ConfigurationPermission PermissionKind = "설정" ) @@ -42,6 +42,8 @@ type PermissionSet struct { ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` Notification *Permission `gorm:"-:all" json:"notification,omitempty"` Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` + Common *Permission `gorm:"-:all" json:"common,omitempty"` + Admin *Permission `gorm:"-:all" json:"admin,omitempty"` } func NewDefaultPermissionSet() *PermissionSet { @@ -52,6 +54,20 @@ func NewDefaultPermissionSet() *PermissionSet { ProjectManagement: newProjectManagement(), Notification: newNotification(), Configuration: newConfiguration(), + Common: newCommon(), + } +} + +func NewAdminPermissionSet() *PermissionSet { + return &PermissionSet{ + Admin: newAdmin(), + Dashboard: newDashboard(), + Stack: newStack(), + SecurityPolicy: newSecurityPolicy(), + ProjectManagement: newProjectManagement(), + Notification: newNotification(), + Configuration: newConfiguration(), + Common: newCommon(), } } @@ -101,84 +117,98 @@ func newDashboard() *Permission { api.GetResourcesDashboard, ), }, + { + ID: uuid.New(), + Name: "수정", + IsAllowed: helper.BoolP(false), + }, }, }, + }, + } + + return dashboard +} + +func newStack() *Permission { + stack := &Permission{ + ID: uuid.New(), + Name: string(StackPermission), + Children: []*Permission{ { ID: uuid.New(), - Name: "대시보드 설정", + Name: "스택", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetStacks, + api.GetStack, + api.CheckStackName, + api.GetStackStatus, + api.GetStackKubeConfig, + + api.SetFavoriteStack, + api.DeleteFavoriteStack, + + // Cluster + api.GetCluster, + api.GetClusters, + api.GetClusterSiteValues, + api.GetBootstrapKubeconfig, + api.GetNodes, + + // AppGroup + api.GetAppgroups, + api.GetAppgroup, + api.GetApplications, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateStack, + api.InstallStack, + api.CreateAppgroup, + + // Cluster + api.CreateCluster, + api.ImportCluster, + api.InstallCluster, + api.CreateBootstrapKubeconfig, + + // AppGroup + api.CreateAppgroup, + api.CreateApplication, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateStack, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } + Endpoints: endpointObjects( + api.DeleteStack, - return dashboard -} + // Cluster + api.DeleteCluster, -func newStack() *Permission { - stack := &Permission{ - ID: uuid.New(), - Name: string(StackPermission), - Children: []*Permission{ - { - ID: uuid.New(), - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetStacks, - api.GetStack, - api.CheckStackName, - api.GetStackStatus, - api.GetStackKubeConfig, - - api.SetFavoriteStack, - api.DeleteFavoriteStack, - ), - }, - { - ID: uuid.New(), - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateStack, - api.InstallStack, - ), - }, - { - ID: uuid.New(), - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateStack, - ), - }, - { - ID: uuid.New(), - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteStack, - ), + // AppGroup + api.DeleteAppgroup, + ), + }, + }, }, }, } @@ -193,27 +223,107 @@ func newSecurityPolicy() *Permission { Children: []*Permission{ { ID: uuid.New(), - Name: "보안/정책", + Name: "정책", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.ListPolicyTemplate, + api.GetPolicyTemplate, + api.GetPolicyTemplateDeploy, + api.ListPolicyTemplateStatistics, + api.ListPolicyTemplateVersions, + api.GetPolicyTemplateVersion, + api.ExistsPolicyTemplateName, + api.ExistsPolicyTemplateKind, + + // ClusterPolicyStatus + api.ListClusterPolicyStatus, + api.GetClusterPolicyTemplateStatus, + + // Policy + api.GetMandatoryPolicies, + api.ListPolicy, + api.GetPolicy, + api.ExistsPolicyName, + + // OrganizationPolicyTemplate + api.ListOrganizationPolicyTemplate, + api.GetOrganizationPolicyTemplate, + api.GetOrganizationPolicyTemplateDeploy, + api.ListOrganizationPolicyTemplateStatistics, + api.ListOrganizationPolicyTemplateVersions, + api.GetOrganizationPolicyTemplateVersion, + api.ExistsOrganizationPolicyTemplateKind, + api.ExistsOrganizationPolicyTemplateName, + + // PolicyTemplateExample + api.ListPolicyTemplateExample, + api.GetPolicyTemplateExample, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.CreatePolicyTemplate, + api.CreatePolicyTemplateVersion, + + // Policy + api.SetMandatoryPolicies, + api.CreatePolicy, + + // OrganizationPolicyTemplate + api.CreateOrganizationPolicyTemplate, + api.CreateOrganizationPolicyTemplateVersion, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.UpdatePolicyTemplate, + + // ClusterPolicyStatus + api.UpdateClusterPolicyTemplateStatus, + + // Policy + api.UpdatePolicy, + api.UpdatePolicyTargetClusters, + + // OrganizationPolicyTemplate + api.UpdateOrganizationPolicyTemplate, + + // PolicyTemplateExample + api.UpdatePolicyTemplateExample, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.DeletePolicyTemplate, + api.DeletePolicyTemplateVersion, + + // Policy + api.DeletePolicy, + + // OrganizationPolicyTemplate + api.DeleteOrganizationPolicyTemplate, + api.DeleteOrganizationPolicyTemplateVersion, + + // PolicyTemplateExample + api.DeletePolicyTemplateExample, + ), }, }, }, @@ -223,77 +333,98 @@ func newSecurityPolicy() *Permission { return security_policy } -func newProjectManagement() *Permission { - projectManagement := &Permission{ +func newNotification() *Permission { + notification := &Permission{ ID: uuid.New(), - Name: string(ProjectManagementPermission), + Name: string(NotificationPermission), Children: []*Permission{ { ID: uuid.New(), - Name: "프로젝트", + Name: "시스템 알림", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, + api.GetSystemNotification, + api.GetSystemNotifications, ), }, { ID: uuid.New(), - Name: "생성", + Name: "수정", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.CreateProject, + api.UpdateSystemNotification, + api.CreateSystemNotificationAction, ), }, + { + ID: uuid.New(), + Name: "다운로드", + IsAllowed: helper.BoolP(false), + Children: []*Permission{}, + }, }, }, { ID: uuid.New(), - Name: "앱 서빙", + Name: "정책 알림", + Children: []*Permission{ + { + ID: uuid.New(), + Name: "조회", + IsAllowed: helper.BoolP(false), + Children: []*Permission{}, + }, + { + ID: uuid.New(), + Name: "다운로드", + IsAllowed: helper.BoolP(false), + Children: []*Permission{}, + }, + }, + }, + }, + } + + return notification +} + +func newProjectManagement() *Permission { + projectManagement := &Permission{ + ID: uuid.New(), + Name: string(ProjectManagementPermission), + Children: []*Permission{ + { + ID: uuid.New(), + Name: "프로젝트", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.GetAppServeApps, - api.GetAppServeApp, - api.GetNumOfAppsOnStack, - api.GetAppServeAppLatestTask, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, + api.GetProjects, + api.GetProject, + api.GetProjectKubeconfig, ), }, { ID: uuid.New(), - Name: "빌드", + Name: "생성", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, + api.CreateProject, ), }, { ID: uuid.New(), - Name: "배포", + Name: "수정", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, + api.UpdateProject, ), }, { @@ -301,14 +432,14 @@ func newProjectManagement() *Permission { Name: "삭제", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.DeleteAppServeApp, + api.DeleteProject, ), }, }, }, { ID: uuid.New(), - Name: "설정-일반", + Name: "일반 설정", Children: []*Permission{ { ID: uuid.New(), @@ -330,19 +461,11 @@ func newProjectManagement() *Permission { api.UpdateProject, ), }, - { - ID: uuid.New(), - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProject, - ), - }, }, }, { ID: uuid.New(), - Name: "설정-멤버", + Name: "구성원 설정", Children: []*Permission{ { ID: uuid.New(), @@ -383,7 +506,7 @@ func newProjectManagement() *Permission { }, { ID: uuid.New(), - Name: "설정-네임스페이스", + Name: "네임스페이스", Children: []*Permission{ { ID: uuid.New(), @@ -392,6 +515,7 @@ func newProjectManagement() *Permission { Endpoints: endpointObjects( api.GetProjectNamespaces, api.GetProjectNamespace, + api.GetProjectNamespaceK8sResources, ), }, { @@ -406,7 +530,9 @@ func newProjectManagement() *Permission { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects(), + Endpoints: endpointObjects( + api.UpdateProjectNamespace, + ), }, { ID: uuid.New(), @@ -418,43 +544,67 @@ func newProjectManagement() *Permission { }, }, }, - }, - } - - return projectManagement -} - -func newNotification() *Permission { - notification := &Permission{ - ID: uuid.New(), - Name: string(NotificationPermission), - Children: []*Permission{ { ID: uuid.New(), - Name: "시스템 경고", + Name: "앱 서빙", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetAppServeApps, + api.GetAppServeApp, + api.GetNumOfAppsOnStack, + api.GetAppServeAppLatestTask, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.GetAppServeAppTaskDetail, + api.GetAppServeAppTasksByAppId, + ), }, - }, - }, - { - ID: uuid.New(), - Name: "보안/정책 감사로그", - Children: []*Permission{ { ID: uuid.New(), - Name: "조회", + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + ID: uuid.New(), + Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + ID: uuid.New(), + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteAppServeApp, + ), }, }, }, }, } - return notification + return projectManagement } func newConfiguration() *Permission { @@ -486,38 +636,44 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetCloudAccounts, + api.GetCloudAccount, + api.CheckCloudAccountName, + api.CheckAwsAccountId, + api.GetResourceQuota, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateCloudAccount, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateCloudAccount, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteCloudAccount, + api.DeleteForceCloudAccount, + ), }, }, }, { ID: uuid.New(), - Name: "스택 템플릿", - Children: []*Permission{ - { - ID: uuid.New(), - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - ID: uuid.New(), - Name: "프로젝트 관리", + Name: "프로젝트", Children: []*Permission{ { ID: uuid.New(), @@ -529,16 +685,6 @@ func newConfiguration() *Permission { Name: "생성", IsAllowed: helper.BoolP(false), }, - { - ID: uuid.New(), - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - ID: uuid.New(), - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, }, }, { @@ -549,73 +695,120 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.ListUser, + api.GetUser, + api.CheckId, + api.CheckEmail, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateUser, + api.CheckId, + api.CheckEmail, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateUser, + api.ResetPassword, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteUser, + ), }, }, }, { ID: uuid.New(), - Name: "사용자 권한 관리", + Name: "역할 및 권한", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.ListTksRoles, + api.GetTksRole, + api.GetPermissionsByRoleId, + api.GetPermissionTemplates, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateTksRole, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateTksRole, + api.UpdatePermissionsByRoleId, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteTksRole, + ), }, }, }, { ID: uuid.New(), - Name: "알림 설정", + Name: "시스템 알림", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetSystemNotificationRules, + api.GetSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteSystemNotificationRule, + ), }, }, }, @@ -625,6 +818,110 @@ func newConfiguration() *Permission { return configuration } +func newCommon() *Permission { + common := &Permission{ + ID: uuid.New(), + Name: "공통", + IsAllowed: helper.BoolP(true), + Endpoints: endpointObjects( + // Auth + api.Login, + api.Logout, + api.RefreshToken, + api.FindId, + api.FindPassword, + api.VerifyIdentityForLostId, + api.VerifyIdentityForLostPassword, + api.VerifyToken, + + // Stack + api.SetFavoriteStack, + api.DeleteFavoriteStack, + + // Project + api.SetFavoriteProject, + api.SetFavoriteProjectNamespace, + api.UnSetFavoriteProject, + api.UnSetFavoriteProjectNamespace, + + // MyProfile + api.GetMyProfile, + api.UpdateMyProfile, + api.UpdateMyPassword, + api.RenewPasswordExpiredDate, + api.DeleteMyProfile, + + // StackTemplate + api.GetOrganizationStackTemplates, + api.GetOrganizationStackTemplate, + + // Utiliy + api.CompileRego, + ), + } + + return common + +} + +func newAdmin() *Permission { + admin := &Permission{ + ID: uuid.New(), + Name: "관리자", + IsAllowed: helper.BoolP(true), + Endpoints: endpointObjects( + // Organization + api.Admin_CreateOrganization, + api.Admin_DeleteOrganization, + api.UpdateOrganization, + api.GetOrganization, + api.GetOrganizations, + api.UpdatePrimaryCluster, + api.CheckOrganizationName, + + // User + api.ResetPassword, + api.CheckId, + api.CheckEmail, + + // StackTemplate + api.Admin_GetStackTemplates, + api.Admin_GetStackTemplate, + api.Admin_GetStackTemplateServices, + api.Admin_CreateStackTemplate, + api.Admin_UpdateStackTemplate, + api.Admin_DeleteStackTemplate, + api.Admin_UpdateStackTemplateOrganizations, + api.Admin_CheckStackTemplateName, + + // Admin + api.Admin_GetUser, + api.Admin_ListUser, + api.Admin_CreateUser, + api.Admin_UpdateUser, + api.Admin_DeleteUser, + api.Admin_GetSystemNotificationTemplate, + api.Admin_CreateSystemNotificationTemplate, + api.Admin_ListUser, + api.Admin_GetTksRole, + api.Admin_GetProjects, + api.Admin_UpdateSystemNotificationTemplate, + api.Admin_ListTksRoles, + api.Admin_GetSystemNotificationTemplates, + + // Audit + api.GetAudits, + api.GetAudit, + api.DeleteAudit, + + api.CreateSystemNotification, + api.DeleteSystemNotification, + ), + } + + return admin +} + func (p *PermissionSet) SetAllowedPermissionSet() { edgePermissions := make([]*Permission, 0) edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index e2a2127d..33acdc92 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -1,10 +1,6 @@ package domain -import "time" - type EndpointResponse struct { - Name string `json:"name"` - Group string `json:"group"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + Name string `json:"name"` + Group string `json:"group"` } diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index f7b69f40..8be227a2 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -8,11 +8,7 @@ type PermissionResponse struct { ID uuid.UUID `json:"ID"` Name string `json:"name"` IsAllowed *bool `json:"is_allowed,omitempty"` - RoleID *string `json:"role_id,omitempty"` - Role *RoleResponse `json:"role,omitempty"` Endpoints []*EndpointResponse `json:"endpoints,omitempty"` - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Parent *PermissionResponse `json:"parent,omitempty"` Children []*PermissionResponse `json:"children,omitempty"` } From 4b23ce03f342d3d4f97ee059688383e48cfca188 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 17:41:55 +0900 Subject: [PATCH 158/502] change permission API --- internal/delivery/api/endpoint.go | 1 + .../delivery/api/endpoints_permission_test.go | 2 +- .../delivery/api/generated_endpoints.go.go | 16 ++ internal/delivery/http/permission.go | 168 +++++++++++++++--- internal/model/permission.go | 153 +++++++++++++--- internal/route/route.go | 1 + internal/usecase/permission.go | 44 ++++- pkg/domain/permission.go | 60 +++++-- 8 files changed, 379 insertions(+), 66 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2364a2ea..81e11753 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -195,6 +195,7 @@ const ( GetPermissionTemplates GetPermissionsByRoleId UpdatePermissionsByRoleId + GetPermissionsByAccountId // Admin_User Admin_CreateUser diff --git a/internal/delivery/api/endpoints_permission_test.go b/internal/delivery/api/endpoints_permission_test.go index e6033894..b012f456 100644 --- a/internal/delivery/api/endpoints_permission_test.go +++ b/internal/delivery/api/endpoints_permission_test.go @@ -24,7 +24,7 @@ func TestEndpointsUsage(t *testing.T) { ps.Configuration, ps.ProjectManagement, ps.Stack, - ps.SecurityPolicy, + ps.Policy, ps.Common, ps.Admin, } diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index ede19eb8..4d5dccdb 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -35,6 +35,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "VerifyToken", Group: "Auth", }, + DeleteToken: { + Name: "DeleteToken", + Group: "Auth", + }, CreateUser: { Name: "CreateUser", Group: "User", @@ -599,6 +603,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdatePermissionsByRoleId", Group: "Permission", }, + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", + Group: "Permission", + }, Admin_CreateUser: { Name: "Admin_CreateUser", Group: "Admin_User", @@ -822,6 +830,8 @@ func (e Endpoint) String() string { return "VerifyIdentityForLostPassword" case VerifyToken: return "VerifyToken" + case DeleteToken: + return "DeleteToken" case CreateUser: return "CreateUser" case ListUser: @@ -1104,6 +1114,8 @@ func (e Endpoint) String() string { return "GetPermissionsByRoleId" case UpdatePermissionsByRoleId: return "UpdatePermissionsByRoleId" + case GetPermissionsByAccountId: + return "GetPermissionsByAccountId" case Admin_CreateUser: return "Admin_CreateUser" case Admin_ListUser: @@ -1228,6 +1240,8 @@ func GetEndpoint(name string) Endpoint { return VerifyIdentityForLostPassword case "VerifyToken": return VerifyToken + case "DeleteToken": + return DeleteToken case "CreateUser": return CreateUser case "ListUser": @@ -1510,6 +1524,8 @@ func GetEndpoint(name string) Endpoint { return GetPermissionsByRoleId case "UpdatePermissionsByRoleId": return UpdatePermissionsByRoleId + case "GetPermissionsByAccountId": + return GetPermissionsByAccountId case "Admin_CreateUser": return Admin_CreateUser case "Admin_ListUser": diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 9e660850..8ec9b7e9 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -1,15 +1,14 @@ package http import ( + "context" "net/http" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/model" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" ) type IPermissionHandler interface { @@ -20,11 +19,13 @@ type IPermissionHandler interface { type PermissionHandler struct { permissionUsecase usecase.IPermissionUsecase + userUsecase usecase.IUserUsecase } func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { return &PermissionHandler{ permissionUsecase: usecase.Permission, + userUsecase: usecase.User, } } @@ -41,20 +42,110 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { permissionSet := model.NewDefaultPermissionSet() - var premissionSetResponse domain.PermissionSetResponse - if err := serializer.Map(r.Context(), permissionSet, &premissionSetResponse); err != nil { - log.Info(r.Context(), err) + var out domain.GetPermissionTemplatesResponse + out.Permissions = new(domain.PermissionTemplateResponse) + + out.Permissions.Dashboard = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Dashboard) + out.Permissions.Stack = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Stack) + out.Permissions.Policy = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Policy) + out.Permissions.ProjectManagement = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.ProjectManagement) + out.Permissions.Notification = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Notification) + out.Permissions.Configuration = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Configuration) + + ResponseJSON(w, r, http.StatusOK, out) +} + +func convertModelToPermissionTemplateResponse(ctx context.Context, permission *model.Permission) *domain.TemplateResponse { + var permissionResponse domain.TemplateResponse + + permissionResponse.Key = permission.Key + permissionResponse.Name = permission.Name + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed } - var out domain.GetPermissionTemplatesResponse - out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) - out.Permissions = append(out.Permissions, premissionSetResponse.Stack) - out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) - out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) - out.Permissions = append(out.Permissions, premissionSetResponse.Notification) - out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionTemplateResponse(ctx, child)) + } + + return &permissionResponse +} + +// GetPermissionsByAccountId godoc +// +// @Tags Permission +// @Summary Get Permissions By Account ID +// @Description Get Permissions By Account ID +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetUsersPermissionsResponse +// @Router /organizations/{organizationId}/users/{accountId}/permissions [get] +// @Security JWT +func (h PermissionHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) { + var organizationId, accountId string + + vars := mux.Vars(r) + if v, ok := vars["accountId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + accountId = v + } + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + user, err := h.userUsecase.GetByAccountId(r.Context(), accountId, organizationId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + var roles []*model.Role + roles = append(roles, &user.Role) + + var permissionSets []*model.PermissionSet + for _, role := range roles { + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + permissionSets = append(permissionSets, permissionSet) + } + + mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) + + var permissions domain.MergedPermissionSetResponse + permissions.Dashboard = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard) + permissions.Stack = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack) + permissions.Policy = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy) + permissions.ProjectManagement = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement) + permissions.Notification = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification) + permissions.Configuration = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration) + + var out domain.GetUsersPermissionsResponse + out.Permissions = &permissions ResponseJSON(w, r, http.StatusOK, out) + +} + +func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { + var permissionResponse domain.MergePermissionResponse + + permissionResponse.Key = permission.Key + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } + + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child)) + } + + return &permissionResponse } // GetPermissionsByRoleId godoc @@ -85,22 +176,50 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http return } - var premissionSetResponse domain.PermissionSetResponse - if err := serializer.Map(r.Context(), permissionSet, &premissionSetResponse); err != nil { - log.Info(r.Context(), err) - } + var permissionSetResponse domain.PermissionSetResponse + permissionSetResponse.Dashboard = convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard) + permissionSetResponse.Stack = convertModelToPermissionResponse(r.Context(), permissionSet.Stack) + permissionSetResponse.Policy = convertModelToPermissionResponse(r.Context(), permissionSet.Policy) + permissionSetResponse.ProjectManagement = convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement) + permissionSetResponse.Notification = convertModelToPermissionResponse(r.Context(), permissionSet.Notification) + permissionSetResponse.Configuration = convertModelToPermissionResponse(r.Context(), permissionSet.Configuration) var out domain.GetPermissionsByRoleIdResponse - out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) - out.Permissions = append(out.Permissions, premissionSetResponse.Stack) - out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) - out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) - out.Permissions = append(out.Permissions, premissionSetResponse.Notification) - out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) + out.Permissions = &permissionSetResponse ResponseJSON(w, r, http.StatusOK, out) } +func convertModelToPermissionResponse(ctx context.Context, permission *model.Permission) *domain.PermissionResponse { + var permissionResponse domain.PermissionResponse + + permissionResponse.ID = permission.ID + permissionResponse.Key = permission.Key + permissionResponse.Name = permission.Name + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } + + for _, endpoint := range permission.Endpoints { + permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint)) + } + + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child)) + } + + return &permissionResponse +} + +func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { + var endpointResponse domain.EndpointResponse + + endpointResponse.Name = endpoint.Name + endpointResponse.Group = endpoint.Group + + return &endpointResponse +} + // UpdatePermissionsByRoleId godoc // // @Tags Permission @@ -124,9 +243,8 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h for _, permissionResponse := range input.Permissions { var permission model.Permission - if err := serializer.Map(r.Context(), permissionResponse, &permission); err != nil { - log.Info(r.Context(), err) - } + permission.ID = permissionResponse.ID + permission.IsAllowed = permissionResponse.IsAllowed if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) diff --git a/internal/model/permission.go b/internal/model/permission.go index 746b1257..87e06b6e 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -10,12 +10,42 @@ import ( type PermissionKind string const ( - DashBoardPermission PermissionKind = "대시보드" - StackPermission PermissionKind = "스택" - SecurityPolicyPermission PermissionKind = "정책" - ProjectManagementPermission PermissionKind = "프로젝트" - NotificationPermission PermissionKind = "알림" - ConfigurationPermission PermissionKind = "설정" + DashBoardPermission PermissionKind = "대시보드" + StackPermission PermissionKind = "스택" + PolicyPermission PermissionKind = "정책" + ProjectPermission PermissionKind = "프로젝트" + NotificationPermission PermissionKind = "알림" + ConfigurationPermission PermissionKind = "설정" + + OperationRead = "READ" + OperationCreate = "CREATE" + OperationUpdate = "UPDATE" + OperationDelete = "DELETE" + OperationDownload = "DOWNLOAD" + + // Key + TopDashboardKey = "DASHBOARD" + MiddleDashboardKey = "DASHBOARD-DASHBOARD" + TopStackKey = "STACK" + MiddleStackKey = "STACK-STACK" + TopPolicyKey = "POLICY" + MiddlePolicyKey = "POLICY-POLICY" + TopNotificationKey = "NOTIFICATION" + MiddleNotificationKey = "NOTIFICATION-SYSTEM_NOTIFICATION" + MiddlePolicyNotificationKey = "NOTIFICATION-POLICY_NOTIFICATION" + TopProjectKey = "PROJECT" + MiddleProjectKey = "PROJECT-PROJECT_LIST" + MiddleProjectCommonConfigurationKey = "PROJECT-PROJECT_COMMON_CONFIGURATION" + MiddleProjectMemberConfigurationKey = "PROJECT-PROJECT_MEMBER_CONFIGURATION" + MiddleProjectNamespaceKey = "PROJECT-PROJECT_NAMESPACE" + MiddleProjectAppServeKey = "PROJECT-PROJECT_APP_SERVE" + TopConfigurationKey = "CONFIGURATION" + MiddleConfigurationKey = "CONFIGURATION-CONFIGURATION" + MiddleConfigurationCloudAccountKey = "CONFIGURATION-CLOUD_ACCOUNT" + MiddleConfigurationProjectKey = "CONFIGURATION-PROJECT" + MiddleConfigurationUserKey = "CONFIGURATION-USER" + MiddleConfigurationRoleKey = "CONFIGURATION-ROLE" + MiddleConfigurationSystemNotificationKey = "CONFIGURATION-SYSTEM_NOTIFICATION" ) type Permission struct { @@ -23,6 +53,7 @@ type Permission struct { ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` Name string `json:"name"` + Key string `gorm:"type:text;" json:"key,omitempty"` IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` RoleID *string `json:"role_id,omitempty"` @@ -38,7 +69,7 @@ type Permission struct { type PermissionSet struct { Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` Stack *Permission `gorm:"-:all" json:"stack,omitempty"` - SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` + Policy *Permission `gorm:"-:all" json:"policy,omitempty"` ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` Notification *Permission `gorm:"-:all" json:"notification,omitempty"` Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` @@ -50,11 +81,12 @@ func NewDefaultPermissionSet() *PermissionSet { return &PermissionSet{ Dashboard: newDashboard(), Stack: newStack(), - SecurityPolicy: newSecurityPolicy(), - ProjectManagement: newProjectManagement(), + Policy: newPolicy(), + ProjectManagement: newProject(), Notification: newNotification(), Configuration: newConfiguration(), Common: newCommon(), + Admin: nil, } } @@ -63,8 +95,8 @@ func NewAdminPermissionSet() *PermissionSet { Admin: newAdmin(), Dashboard: newDashboard(), Stack: newStack(), - SecurityPolicy: newSecurityPolicy(), - ProjectManagement: newProjectManagement(), + Policy: newPolicy(), + ProjectManagement: newProject(), Notification: newNotification(), Configuration: newConfiguration(), Common: newCommon(), @@ -101,14 +133,17 @@ func newDashboard() *Permission { dashboard := &Permission{ ID: uuid.New(), Name: string(DashBoardPermission), + Key: TopDashboardKey, Children: []*Permission{ { ID: uuid.New(), Name: "대시보드", + Key: MiddleDashboardKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetChartsDashboard, @@ -120,6 +155,7 @@ func newDashboard() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), }, }, @@ -134,14 +170,17 @@ func newStack() *Permission { stack := &Permission{ ID: uuid.New(), Name: string(StackPermission), + Key: TopStackKey, Children: []*Permission{ { ID: uuid.New(), Name: "스택", + Key: MiddleStackKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetStacks, @@ -169,6 +208,7 @@ func newStack() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateStack, @@ -189,6 +229,7 @@ func newStack() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateStack, @@ -197,6 +238,7 @@ func newStack() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteStack, @@ -216,18 +258,21 @@ func newStack() *Permission { return stack } -func newSecurityPolicy() *Permission { - security_policy := &Permission{ +func newPolicy() *Permission { + policy := &Permission{ ID: uuid.New(), - Name: string(SecurityPolicyPermission), + Name: string(PolicyPermission), + Key: TopPolicyKey, Children: []*Permission{ { ID: uuid.New(), Name: "정책", + Key: MiddlePolicyKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate @@ -268,6 +313,7 @@ func newSecurityPolicy() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate @@ -286,6 +332,7 @@ func newSecurityPolicy() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate @@ -308,6 +355,7 @@ func newSecurityPolicy() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate @@ -330,21 +378,24 @@ func newSecurityPolicy() *Permission { }, } - return security_policy + return policy } func newNotification() *Permission { notification := &Permission{ ID: uuid.New(), Name: string(NotificationPermission), + Key: TopNotificationKey, Children: []*Permission{ { ID: uuid.New(), Name: "시스템 알림", + Key: MiddleNotificationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetSystemNotification, @@ -354,6 +405,7 @@ func newNotification() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateSystemNotification, @@ -363,6 +415,7 @@ func newNotification() *Permission { { ID: uuid.New(), Name: "다운로드", + Key: OperationDownload, IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -371,16 +424,19 @@ func newNotification() *Permission { { ID: uuid.New(), Name: "정책 알림", + Key: MiddlePolicyNotificationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, { ID: uuid.New(), Name: "다운로드", + Key: OperationDownload, IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -392,18 +448,21 @@ func newNotification() *Permission { return notification } -func newProjectManagement() *Permission { - projectManagement := &Permission{ +func newProject() *Permission { + project := &Permission{ ID: uuid.New(), - Name: string(ProjectManagementPermission), + Name: string(ProjectPermission), + Key: TopProjectKey, Children: []*Permission{ { ID: uuid.New(), - Name: "프로젝트", + Name: "프로젝트 목록", + Key: MiddleProjectKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetProjects, @@ -414,6 +473,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateProject, @@ -422,6 +482,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateProject, @@ -430,6 +491,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteProject, @@ -440,10 +502,12 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "일반 설정", + Key: MiddleProjectCommonConfigurationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetProjects, @@ -456,6 +520,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateProject, @@ -466,10 +531,12 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "구성원 설정", + Key: MiddleProjectMemberConfigurationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetProjectMembers, @@ -481,6 +548,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.AddProjectMember, @@ -489,6 +557,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateProjectMemberRole, @@ -497,6 +566,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.RemoveProjectMember, @@ -507,10 +577,12 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "네임스페이스", + Key: MiddleProjectNamespaceKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetProjectNamespaces, @@ -521,6 +593,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateProjectNamespace, @@ -529,6 +602,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateProjectNamespace, @@ -537,6 +611,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteProjectNamespace, @@ -547,10 +622,12 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "앱 서빙", + Key: MiddleProjectAppServeKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetAppServeApps, @@ -566,6 +643,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateAppServeApp, @@ -580,6 +658,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateAppServeApp, @@ -594,6 +673,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteAppServeApp, @@ -604,26 +684,30 @@ func newProjectManagement() *Permission { }, } - return projectManagement + return project } func newConfiguration() *Permission { configuration := &Permission{ ID: uuid.New(), Name: string(ConfigurationPermission), + Key: TopConfigurationKey, Children: []*Permission{ { ID: uuid.New(), Name: "일반", + Key: MiddleConfigurationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), }, { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), }, }, @@ -631,10 +715,12 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "클라우드 계정", + Key: MiddleConfigurationCloudAccountKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetCloudAccounts, @@ -647,6 +733,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateCloudAccount, @@ -655,6 +742,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateCloudAccount, @@ -663,6 +751,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteCloudAccount, @@ -674,15 +763,18 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "프로젝트", + Key: MiddleConfigurationProjectKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), }, { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), }, }, @@ -690,10 +782,12 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "사용자", + Key: MiddleConfigurationUserKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.ListUser, @@ -705,6 +799,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateUser, @@ -715,6 +810,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateUser, @@ -724,6 +820,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteUser, @@ -734,10 +831,12 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "역할 및 권한", + Key: MiddleConfigurationRoleKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.ListTksRoles, @@ -749,6 +848,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateTksRole, @@ -757,6 +857,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateTksRole, @@ -766,6 +867,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteTksRole, @@ -776,10 +878,12 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "시스템 알림", + Key: MiddleConfigurationSystemNotificationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetSystemNotificationRules, @@ -789,6 +893,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateSystemNotificationRule, @@ -797,6 +902,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateSystemNotificationRule, @@ -805,6 +911,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteSystemNotificationRule, @@ -926,7 +1033,7 @@ func (p *PermissionSet) SetAllowedPermissionSet() { edgePermissions := make([]*Permission, 0) edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Policy, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) @@ -943,7 +1050,7 @@ func (p *PermissionSet) SetUserPermissionSet() { edgePermissions := make([]*Permission, 0) edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Policy, edgePermissions, &f)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) @@ -956,7 +1063,7 @@ func (p *PermissionSet) SetUserPermissionSet() { func (p *PermissionSet) SetRoleId(roleId string) { setRoleIdToPermission(p.Dashboard, roleId) setRoleIdToPermission(p.Stack, roleId) - setRoleIdToPermission(p.SecurityPolicy, roleId) + setRoleIdToPermission(p.Policy, roleId) setRoleIdToPermission(p.ProjectManagement, roleId) setRoleIdToPermission(p.Notification, roleId) setRoleIdToPermission(p.Configuration, roleId) diff --git a/internal/route/route.go b/internal/route/route.go index bb00ba3b..acaf2a65 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -291,6 +291,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(permissionHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByAccountId, http.HandlerFunc(permissionHandler.GetPermissionsByAccountId))).Methods(http.MethodGet) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index 32b6bf0d..7db6be5d 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -15,6 +15,7 @@ type IPermissionUsecase interface { GetAllowedPermissionSet(ctx context.Context) *model.PermissionSet GetUserPermissionSet(ctx context.Context) *model.PermissionSet UpdatePermission(ctx context.Context, permission *model.Permission) error + MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet } type PermissionUsecase struct { @@ -35,7 +36,7 @@ func (p PermissionUsecase) CreatePermissionSet(ctx context.Context, permissionSe if err = p.repo.Create(ctx, permissionSet.Stack); err != nil { return err } - if err = p.repo.Create(ctx, permissionSet.SecurityPolicy); err != nil { + if err = p.repo.Create(ctx, permissionSet.Policy); err != nil { return err } if err = p.repo.Create(ctx, permissionSet.ProjectManagement); err != nil { @@ -54,7 +55,7 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(ctx context.Context, roleId permissionSet := &model.PermissionSet{ Dashboard: nil, Stack: nil, - SecurityPolicy: nil, + Policy: nil, ProjectManagement: nil, Notification: nil, Configuration: nil, @@ -70,9 +71,9 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(ctx context.Context, roleId permissionSet.Dashboard = permission case string(model.StackPermission): permissionSet.Stack = permission - case string(model.SecurityPolicyPermission): - permissionSet.SecurityPolicy = permission - case string(model.ProjectManagementPermission): + case string(model.PolicyPermission): + permissionSet.Policy = permission + case string(model.ProjectPermission): permissionSet.ProjectManagement = permission case string(model.NotificationPermission): permissionSet.Notification = permission @@ -115,3 +116,36 @@ func (p PermissionUsecase) GetUserPermissionSet(ctx context.Context) *model.Perm permissionSet.SetUserPermissionSet() return permissionSet } + +func (p PermissionUsecase) MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet { + var out *model.PermissionSet + for i, ps := range permissionSet { + if i == 0 { + out = ps + continue + } + + out.Dashboard = p.mergePermission(out.Dashboard, ps.Dashboard) + out.Stack = p.mergePermission(out.Stack, ps.Stack) + out.Policy = p.mergePermission(out.Policy, ps.Policy) + out.ProjectManagement = p.mergePermission(out.ProjectManagement, ps.ProjectManagement) + out.Notification = p.mergePermission(out.Notification, ps.Notification) + out.Configuration = p.mergePermission(out.Configuration, ps.Configuration) + } + + return out +} + +func (p PermissionUsecase) mergePermission(mergedPermission, permission *model.Permission) *model.Permission { + var mergedEdgePermissions []*model.Permission + mergedEdgePermissions = model.GetEdgePermission(mergedPermission, mergedEdgePermissions, nil) + + var rightEdgePermissions []*model.Permission + rightEdgePermissions = model.GetEdgePermission(permission, rightEdgePermissions, nil) + + for i, rightEdgePermission := range rightEdgePermissions { + *(mergedEdgePermissions[i].IsAllowed) = *(mergedEdgePermissions[i].IsAllowed) || *(rightEdgePermission.IsAllowed) + } + + return mergedPermission +} diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index 8be227a2..d9e83240 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -4,31 +4,67 @@ import ( "github.com/google/uuid" ) -type PermissionResponse struct { - ID uuid.UUID `json:"ID"` - Name string `json:"name"` - IsAllowed *bool `json:"is_allowed,omitempty"` - Endpoints []*EndpointResponse `json:"endpoints,omitempty"` - Children []*PermissionResponse `json:"children,omitempty"` +type GetPermissionTemplatesResponse struct { + Permissions *PermissionTemplateResponse `json:"permissions"` +} + +type PermissionTemplateResponse struct { + Dashboard *TemplateResponse `json:"dashboard,omitempty"` + Stack *TemplateResponse `json:"stack,omitempty"` + Policy *TemplateResponse `json:"policy,omitempty"` + ProjectManagement *TemplateResponse `json:"project_management,omitempty"` + Notification *TemplateResponse `json:"notification,omitempty"` + Configuration *TemplateResponse `json:"configuration,omitempty"` +} + +type TemplateResponse struct { + Name string `json:"name"` + Key string `json:"key"` + IsAllowed *bool `json:"is_allowed,omitempty"` + Children []*TemplateResponse `json:"children,omitempty"` +} + +type GetPermissionsByRoleIdResponse struct { + Permissions *PermissionSetResponse `json:"permissions"` } type PermissionSetResponse struct { Dashboard *PermissionResponse `json:"dashboard,omitempty"` Stack *PermissionResponse `json:"stack,omitempty"` - SecurityPolicy *PermissionResponse `json:"security_policy,omitempty"` + Policy *PermissionResponse `json:"policy,omitempty"` ProjectManagement *PermissionResponse `json:"project_management,omitempty"` Notification *PermissionResponse `json:"notification,omitempty"` Configuration *PermissionResponse `json:"configuration,omitempty"` } -type GetPermissionTemplatesResponse struct { - Permissions []*PermissionResponse `json:"permissions"` +type PermissionResponse struct { + ID uuid.UUID `json:"ID"` + Name string `json:"name"` + Key string `json:"key"` + IsAllowed *bool `json:"is_allowed,omitempty"` + Endpoints []*EndpointResponse `json:"endpoints,omitempty"` + Children []*PermissionResponse `json:"children,omitempty"` } -type GetPermissionsByRoleIdResponse struct { +type UpdatePermissionsByRoleIdRequest struct { Permissions []*PermissionResponse `json:"permissions"` } -type UpdatePermissionsByRoleIdRequest struct { - Permissions []*PermissionResponse `json:"permissions"` +type GetUsersPermissionsResponse struct { + Permissions *MergedPermissionSetResponse `json:"permissions"` +} + +type MergedPermissionSetResponse struct { + Dashboard *MergePermissionResponse `json:"dashboard,omitempty"` + Stack *MergePermissionResponse `json:"stack,omitempty"` + Policy *MergePermissionResponse `json:"policy,omitempty"` + ProjectManagement *MergePermissionResponse `json:"project_management,omitempty"` + Notification *MergePermissionResponse `json:"notification,omitempty"` + Configuration *MergePermissionResponse `json:"configuration,omitempty"` +} + +type MergePermissionResponse struct { + Key string `json:"key"` + IsAllowed *bool `json:"is_allowed,omitempty"` + Children []*MergePermissionResponse `json:"children,omitempty"` } From 05aaf0cbd1c67952d780a0d32eac402f4a1872a5 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 17:43:27 +0900 Subject: [PATCH 159/502] lint fix --- internal/usecase/organization.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index ff7c59d0..9fa70a56 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -35,7 +35,6 @@ type OrganizationUsecase struct { roleRepo repository.IRoleRepository clusterRepo repository.IClusterRepository stackTemplateRepo repository.IStackTemplateRepository - policyTemplateRepo repository.IPolicyTemplateRepository systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository argo argowf.ArgoClient kc keycloak.IKeycloak From 0d331e034e1cfececbd7ae100cd9a5dad50fd1db Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 17:45:42 +0900 Subject: [PATCH 160/502] trimming --- internal/delivery/api/endpoint.go | 1 - internal/delivery/api/generated_endpoints.go.go | 8 -------- 2 files changed, 9 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 81e11753..42c5d270 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -19,7 +19,6 @@ const ( VerifyIdentityForLostId VerifyIdentityForLostPassword VerifyToken - DeleteToken // User CreateUser diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 4d5dccdb..df0278f0 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -35,10 +35,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "VerifyToken", Group: "Auth", }, - DeleteToken: { - Name: "DeleteToken", - Group: "Auth", - }, CreateUser: { Name: "CreateUser", Group: "User", @@ -830,8 +826,6 @@ func (e Endpoint) String() string { return "VerifyIdentityForLostPassword" case VerifyToken: return "VerifyToken" - case DeleteToken: - return "DeleteToken" case CreateUser: return "CreateUser" case ListUser: @@ -1240,8 +1234,6 @@ func GetEndpoint(name string) Endpoint { return VerifyIdentityForLostPassword case "VerifyToken": return VerifyToken - case "DeleteToken": - return DeleteToken case "CreateUser": return CreateUser case "ListUser": From 47fff120c9c9188703e42383183085d3c02d9dde Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 17:57:13 +0900 Subject: [PATCH 161/502] minor fix. --- internal/delivery/http/permission.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 8ec9b7e9..04c8a947 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -15,6 +15,7 @@ type IPermissionHandler interface { GetPermissionTemplates(w http.ResponseWriter, r *http.Request) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) + GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) } type PermissionHandler struct { @@ -22,7 +23,7 @@ type PermissionHandler struct { userUsecase usecase.IUserUsecase } -func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { +func NewPermissionHandler(usecase usecase.Usecase) IPermissionHandler { return &PermissionHandler{ permissionUsecase: usecase.Permission, userUsecase: usecase.User, From a4d9e364f687018a7785b8cae6de69792d6bf8a0 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 19:38:34 +0900 Subject: [PATCH 162/502] Require users to obtain a new access token after changes to their TKS role or project role --- go.mod | 1 - internal/database/database.go | 5 +- internal/delivery/http/auth.go | 2 +- internal/delivery/http/project.go | 59 ++++++++++++-- internal/helper/jwt.go | 18 ++++- internal/keycloak/config.go | 6 +- internal/keycloak/keycloak.go | 6 +- .../auth/authenticator/authenticator.go | 24 +++++- .../authenticator/custom/authenticator.go | 80 +++++++++++++++++++ .../auth/authenticator/keycloak/keycloak.go | 21 +++-- internal/model/auth.go | 23 ++++++ internal/repository/auth.go | 47 +++++++---- internal/route/route.go | 3 +- internal/usecase/auth.go | 24 ++++-- internal/usecase/user.go | 13 ++- 15 files changed, 278 insertions(+), 54 deletions(-) create mode 100644 internal/middleware/auth/authenticator/custom/authenticator.go create mode 100644 internal/model/auth.go diff --git a/go.mod b/go.mod index a1014793..47e17ec0 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/ses v1.21.0 github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 github.com/deckarep/golang-set/v2 v2.6.0 - github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 github.com/go-playground/validator/v10 v10.18.0 diff --git a/internal/database/database.go b/internal/database/database.go index a6d9cb85..111941e5 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -61,7 +61,10 @@ func InitDB() (*gorm.DB, error) { func migrateSchema(db *gorm.DB) error { // Auth - if err := db.AutoMigrate(&repository.CacheEmailCode{}); err != nil { + if err := db.AutoMigrate(&model.CacheEmailCode{}); err != nil { + return err + } + if err := db.AutoMigrate(&model.ExpiredTokenTime{}); err != nil { return err } if err := db.AutoMigrate(&model.User{}); err != nil { diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index f817f8ba..c3a785c3 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -310,7 +310,7 @@ func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { } if !isActive { - ErrorJSON(w, r, httpErrors.NewUnauthorizedError(fmt.Errorf("token is not active"), "A_UNUSABLE_TOKEN", "")) + ErrorJSON(w, r, httpErrors.NewUnauthorizedError(fmt.Errorf("token is not active"), "A_EXPIRED_TOKEN", "")) return } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index ba66719a..e5712505 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -58,12 +58,14 @@ type IProjectHandler interface { } type ProjectHandler struct { - usecase usecase.IProjectUsecase + usecase usecase.IProjectUsecase + authUsecase usecase.IAuthUsecase } func NewProjectHandler(u usecase.Usecase) IProjectHandler { return &ProjectHandler{ - usecase: u.Project, + usecase: u.Project, + authUsecase: u.Auth, } } @@ -624,6 +626,13 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } } + + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pmr.ProjectUserId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } } out := domain.CommonProjectResponse{Result: "OK"} @@ -898,6 +907,20 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } } + pm, err := p.usecase.GetProjectMember(r.Context(), projectMemberId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, projectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -956,8 +979,8 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ } // TODO: change multi row delete - for _, pm := range projectMemberReq.ProjectMember { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pm.ProjectMemberId); err != nil { + for _, pmId := range projectMemberReq.ProjectMember { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pmId.ProjectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -965,14 +988,22 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pm.ProjectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pmId.ProjectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } } - if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, pm.ProjectMemberId); err != nil { + pm, err := p.usecase.GetProjectMember(r.Context(), pmId.ProjectMemberId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + + if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, pmId.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1088,6 +1119,14 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } } + // update token expired time + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } @@ -1190,6 +1229,14 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } } + + // update token expired time + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } } ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) diff --git a/internal/helper/jwt.go b/internal/helper/jwt.go index 68170a55..3db7184a 100644 --- a/internal/helper/jwt.go +++ b/internal/helper/jwt.go @@ -1,9 +1,10 @@ package helper import ( + "fmt" "time" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v4" "github.com/spf13/viper" ) @@ -37,3 +38,18 @@ func VerifyToken(tokenString string) (*jwt.Token, error) { } return token, err } + +func StringToTokenWithoutVerification(tokenString string) (*jwt.Token, error) { + token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{}) + if err != nil { + return nil, fmt.Errorf("invalid token") + } + return token, nil +} +func RetrieveClaims(token *jwt.Token) (map[string]interface{}, error) { + claims, ok := token.Claims.(jwt.MapClaims) + if !ok { + return nil, fmt.Errorf("invalid token") + } + return claims, nil +} diff --git a/internal/keycloak/config.go b/internal/keycloak/config.go index 212748c1..eb26042c 100644 --- a/internal/keycloak/config.go +++ b/internal/keycloak/config.go @@ -12,7 +12,7 @@ const ( DefaultClientID = "tks" DefaultClientSecret = "secret" AdminCliClientID = "admin-cli" - accessTokenLifespan = 60 * 60 * 24 // 1 day - ssoSessionIdleTimeout = 60 * 60 * 24 // 1 day - ssoSessionMaxLifespan = 60 * 60 * 24 // 1 day + AccessTokenLifespan = 60 * 60 * 24 // 1 day + SsoSessionIdleTimeout = 60 * 60 * 24 // 1 day + SsoSessionMaxLifespan = 60 * 60 * 24 // 1 day ) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index ff69db1c..d7618fee 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -927,9 +927,9 @@ func defaultRealmSetting(realmId string) gocloak.RealmRepresentation { return gocloak.RealmRepresentation{ Realm: gocloak.StringP(realmId), Enabled: gocloak.BoolP(true), - AccessTokenLifespan: gocloak.IntP(accessTokenLifespan), - SsoSessionIdleTimeout: gocloak.IntP(ssoSessionIdleTimeout), - SsoSessionMaxLifespan: gocloak.IntP(ssoSessionMaxLifespan), + AccessTokenLifespan: gocloak.IntP(AccessTokenLifespan), + SsoSessionIdleTimeout: gocloak.IntP(SsoSessionIdleTimeout), + SsoSessionMaxLifespan: gocloak.IntP(SsoSessionMaxLifespan), } } diff --git a/internal/middleware/auth/authenticator/authenticator.go b/internal/middleware/auth/authenticator/authenticator.go index 80ea6bba..8f8ab1b3 100644 --- a/internal/middleware/auth/authenticator/authenticator.go +++ b/internal/middleware/auth/authenticator/authenticator.go @@ -2,6 +2,7 @@ package authenticator import ( "fmt" + "github.com/openinfradev/tks-api/internal/repository" "net/http" internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" @@ -19,23 +20,38 @@ type Request interface { } type defaultAuthenticator struct { - auth Request + kcAuth Request + customAuth Request + repo repository.Repository } -func NewAuthenticator(kc Request) *defaultAuthenticator { +func NewAuthenticator(kc Request, repo repository.Repository, c Request) *defaultAuthenticator { return &defaultAuthenticator{ - auth: kc, + kcAuth: kc, + repo: repo, + customAuth: c, } } func (a *defaultAuthenticator) WithAuthentication(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - resp, ok, err := a.auth.AuthenticateRequest(r) + resp, ok, err := a.kcAuth.AuthenticateRequest(r) if !ok { log.Error(r.Context(), err) internalHttp.ErrorJSON(w, r, err) return } + if err != nil { + internalHttp.ErrorJSON(w, r, err) + return + } + + _, ok, err = a.customAuth.AuthenticateRequest(r) + if !ok { + internalHttp.ErrorJSON(w, r, err) + return + } + r = r.WithContext(request.WithUser(r.Context(), resp.User)) _, ok = request.UserFrom(r.Context()) diff --git a/internal/middleware/auth/authenticator/custom/authenticator.go b/internal/middleware/auth/authenticator/custom/authenticator.go new file mode 100644 index 00000000..f92f218a --- /dev/null +++ b/internal/middleware/auth/authenticator/custom/authenticator.go @@ -0,0 +1,80 @@ +package custom + +import ( + "fmt" + "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "net/http" + "strings" +) + +type CustomAuthenticator struct { + repo repository.Repository +} + +func NewCustomAuthenticator(repo repository.Repository) *CustomAuthenticator { + return &CustomAuthenticator{ + repo: repo, + } +} +func (a *CustomAuthenticator) AuthenticateRequest(r *http.Request) (*authenticator.Response, bool, error) { + authHeader := strings.TrimSpace(r.Header.Get("Authorization")) + if authHeader == "" { + return nil, false, fmt.Errorf("authorizer header is invalid") + } + parts := strings.SplitN(authHeader, " ", 3) + if len(parts) < 2 || strings.ToLower(parts[0]) != "bearer" { + return nil, false, fmt.Errorf("authorizer header is invalid") + } + token := parts[1] + + if len(token) == 0 { + // The space before the token case + if len(parts) == 3 { + log.Warn(r.Context(), "the provided Authorization header contains extra space before the bearer token, and is ignored") + } + return nil, false, fmt.Errorf("token is empty") + } + + parsedToken, err := helper.StringToTokenWithoutVerification(token) + if err != nil { + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + claims, err := helper.RetrieveClaims(parsedToken) + if err != nil { + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + organizationId, ok := claims["organization"].(string) + if !ok { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("organizationId is not found"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + userId, ok := claims["sub"].(string) + if !ok { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("userId is not found"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + expiredTime, err := a.repo.Auth.GetExpiredTimeOnToken(r.Context(), organizationId, userId) + if expiredTime == nil { + return nil, true, nil + } + if err != nil { + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + iat, ok := claims["iat"].(float64) + if !ok { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("iat is not found"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + if int64(iat) < expiredTime.ExpiredTime.Unix() { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("token is changed"), "A_UNUSABLE_TOKEN", "토큰이 변경되었습니다.") + } + + return nil, true, nil +} diff --git a/internal/middleware/auth/authenticator/keycloak/keycloak.go b/internal/middleware/auth/authenticator/keycloak/keycloak.go index 8f0ee136..dcc649a8 100644 --- a/internal/middleware/auth/authenticator/keycloak/keycloak.go +++ b/internal/middleware/auth/authenticator/keycloak/keycloak.go @@ -2,11 +2,11 @@ package keycloak import ( "fmt" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/pkg/httpErrors" "net/http" "strings" - jwtWithouKey "github.com/dgrijalva/jwt-go" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" @@ -49,12 +49,17 @@ func (a *keycloakAuthenticator) AuthenticateRequest(r *http.Request) (*authentic } func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) (*authenticator.Response, bool, error) { - parsedToken, _, err := new(jwtWithouKey.Parser).ParseUnverified(token, jwtWithouKey.MapClaims{}) + parsedToken, err := helper.StringToTokenWithoutVerification(token) if err != nil { return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } - organizationId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["organization"].(string) + claims, err := helper.RetrieveClaims(parsedToken) + if err != nil { + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + organizationId, ok := claims["organization"].(string) if !ok { return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("organization is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } @@ -70,7 +75,7 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) // tks role extraction roleOrganizationMapping := make(map[string]string) - if roles, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["tks-role"]; !ok { + if roles, ok := claims["tks-role"]; !ok { log.Errorf(r.Context(), "tks-role is not found in token") return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("tks-role is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") @@ -90,7 +95,7 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) // project role extraction projectIds := make([]string, 0) roleProjectMapping := make(map[string]string) - if roles, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["project-role"]; ok { + if roles, ok := claims["project-role"]; ok { for _, role := range roles.([]interface{}) { slice := strings.Split(role.(string), "@") if len(slice) != 2 { @@ -104,18 +109,18 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) } } - userId, err := uuid.Parse(parsedToken.Claims.(jwtWithouKey.MapClaims)["sub"].(string)) + userId, err := uuid.Parse(claims["sub"].(string)) if err != nil { log.Errorf(r.Context(), "failed to verify access token: %v", err) return nil, false, httpErrors.NewUnauthorizedError(err, "C_INTERNAL_ERROR", "") } - requestSessionId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["sid"].(string) + requestSessionId, ok := claims["sid"].(string) if !ok { return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("session id is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } - userAccountId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["preferred_username"].(string) + userAccountId, ok := claims["preferred_username"].(string) if !ok { return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("preferred_username is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } diff --git a/internal/model/auth.go b/internal/model/auth.go new file mode 100644 index 00000000..b2866816 --- /dev/null +++ b/internal/model/auth.go @@ -0,0 +1,23 @@ +package model + +import ( + "github.com/google/uuid" + "gorm.io/gorm" + "time" +) + +// Models +type ExpiredTokenTime struct { + gorm.Model + + OrganizationId string `gorm:"index:idx_org_id_subject_id,unique;not null"` + SubjectId string `gorm:"index:idx_org_id_subject_id,unique;not null"` + ExpiredTime time.Time +} + +type CacheEmailCode struct { + gorm.Model + + UserId uuid.UUID `gorm:"not null"` + Code string `gorm:"type:varchar(6);not null"` +} diff --git a/internal/repository/auth.go b/internal/repository/auth.go index d9c86a59..c59d4c7f 100644 --- a/internal/repository/auth.go +++ b/internal/repository/auth.go @@ -3,29 +3,25 @@ package repository import ( "context" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "gorm.io/gorm" + "gorm.io/gorm/clause" + "time" ) type IAuthRepository interface { CreateEmailCode(ctx context.Context, userId uuid.UUID, code string) error - GetEmailCode(ctx context.Context, userId uuid.UUID) (CacheEmailCode, error) + GetEmailCode(ctx context.Context, userId uuid.UUID) (model.CacheEmailCode, error) UpdateEmailCode(ctx context.Context, userId uuid.UUID, code string) error DeleteEmailCode(ctx context.Context, userId uuid.UUID) error + GetExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) (*model.ExpiredTokenTime, error) + UpdateExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) error } type AuthRepository struct { db *gorm.DB } -// Models - -type CacheEmailCode struct { - gorm.Model - - UserId uuid.UUID `gorm:"not null"` - Code string `gorm:"type:varchar(6);not null"` -} - func NewAuthRepository(db *gorm.DB) IAuthRepository { return &AuthRepository{ db: db, @@ -33,25 +29,44 @@ func NewAuthRepository(db *gorm.DB) IAuthRepository { } func (r *AuthRepository) CreateEmailCode(ctx context.Context, userId uuid.UUID, code string) error { - cacheEmailCode := CacheEmailCode{ + cacheEmailCode := model.CacheEmailCode{ UserId: userId, Code: code, } return r.db.WithContext(ctx).Create(&cacheEmailCode).Error } -func (r *AuthRepository) GetEmailCode(ctx context.Context, userId uuid.UUID) (CacheEmailCode, error) { - var cacheEmailCode CacheEmailCode +func (r *AuthRepository) GetEmailCode(ctx context.Context, userId uuid.UUID) (model.CacheEmailCode, error) { + var cacheEmailCode model.CacheEmailCode if err := r.db.WithContext(ctx).Where("user_id = ?", userId).First(&cacheEmailCode).Error; err != nil { - return CacheEmailCode{}, err + return model.CacheEmailCode{}, err } return cacheEmailCode, nil } func (r *AuthRepository) UpdateEmailCode(ctx context.Context, userId uuid.UUID, code string) error { - return r.db.WithContext(ctx).Model(&CacheEmailCode{}).Where("user_id = ?", userId).Update("code", code).Error + return r.db.WithContext(ctx).Model(&model.CacheEmailCode{}).Where("user_id = ?", userId).Update("code", code).Error } func (r *AuthRepository) DeleteEmailCode(ctx context.Context, userId uuid.UUID) error { - return r.db.WithContext(ctx).Unscoped().Where("user_id = ?", userId).Delete(&CacheEmailCode{}).Error + return r.db.WithContext(ctx).Unscoped().Where("user_id = ?", userId).Delete(&model.CacheEmailCode{}).Error +} + +func (r *AuthRepository) GetExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) (*model.ExpiredTokenTime, error) { + var expiredTokenTime model.ExpiredTokenTime + if err := r.db.WithContext(ctx).Where("organization_id = ? AND subject_id = ?", organizationId, userId).First(&expiredTokenTime).Error; err != nil { + return nil, err + } + return &expiredTokenTime, nil +} +func (r *AuthRepository) UpdateExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) error { + // set expired time to now + return r.db.WithContext(ctx).Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "subject_id"}, {Name: "organization_id"}}, + DoUpdates: clause.AssignmentColumns([]string{"expired_time"}), + }).Create(&model.ExpiredTokenTime{ + SubjectId: userId, + ExpiredTime: time.Now(), + OrganizationId: organizationId, + }).Error } diff --git a/internal/route/route.go b/internal/route/route.go index bb00ba3b..f531aa02 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -16,6 +16,7 @@ import ( "github.com/openinfradev/tks-api/internal/keycloak" internalMiddleware "github.com/openinfradev/tks-api/internal/middleware" "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" + authCustom "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator/custom" authKeycloak "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator/keycloak" "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" "github.com/openinfradev/tks-api/internal/repository" @@ -83,7 +84,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa } customMiddleware := internalMiddleware.NewMiddleware( - authenticator.NewAuthenticator(authKeycloak.NewKeycloakAuthenticator(kc)), + authenticator.NewAuthenticator(authKeycloak.NewKeycloakAuthenticator(kc), repoFactory, authCustom.NewCustomAuthenticator(repoFactory)), authorizer.NewDefaultAuthorization(repoFactory), requestRecoder.NewDefaultRequestRecoder(), audit.NewDefaultAudit(repoFactory)) diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 485a60a6..f8edf598 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -12,8 +12,6 @@ import ( "strings" "time" - jwtWithouKey "github.com/dgrijalva/jwt-go" - "github.com/openinfradev/tks-api/pkg/log" "github.com/spf13/viper" "golang.org/x/net/html" @@ -32,13 +30,14 @@ import ( type IAuthUsecase interface { Login(ctx context.Context, accountId string, password string, organizationId string) (model.User, error) - Logout(ctx context.Context, accessToken string, organizationId string) error + Logout(ctx context.Context, sessionId string, organizationId string) error FindId(ctx context.Context, code string, email string, userName string, organizationId string) (string, error) FindPassword(ctx context.Context, code string, accountId string, email string, userName string, organizationId string) error VerifyIdentity(ctx context.Context, accountId string, email string, userName string, organizationId string) error SingleSignIn(ctx context.Context, organizationId, accountId, password string) ([]*http.Cookie, error) SingleSignOut(ctx context.Context, organizationId string) (string, []*http.Cookie, error) VerifyToken(ctx context.Context, token string) (bool, error) + UpdateExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) error } const ( @@ -96,9 +95,9 @@ func (u *AuthUsecase) Login(ctx context.Context, accountId string, password stri return user, nil } -func (u *AuthUsecase) Logout(ctx context.Context, accessToken string, organizationName string) error { +func (u *AuthUsecase) Logout(ctx context.Context, sessionId string, organizationName string) error { // [TODO] refresh token 을 추가하고, session timeout 을 줄이는 방향으로 고려할 것 - err := u.kc.Logout(ctx, accessToken, organizationName) + err := u.kc.Logout(ctx, sessionId, organizationName) if err != nil { return err } @@ -305,11 +304,16 @@ func (u *AuthUsecase) SingleSignOut(ctx context.Context, organizationId string) } func (u *AuthUsecase) VerifyToken(ctx context.Context, token string) (bool, error) { - parsedToken, _, err := new(jwtWithouKey.Parser).ParseUnverified(token, jwtWithouKey.MapClaims{}) + parsedToken, err := helper.StringToTokenWithoutVerification(token) + if err != nil { + return false, err + } + claims, err := helper.RetrieveClaims(parsedToken) if err != nil { return false, err } - org, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["organization"].(string) + + org, ok := claims["organization"].(string) if !ok { return false, fmt.Errorf("organization is not found in token") } @@ -325,7 +329,11 @@ func (u *AuthUsecase) VerifyToken(ctx context.Context, token string) (bool, erro return true, nil } -func (u *AuthUsecase) isExpiredEmailCode(code repository.CacheEmailCode) bool { +func (u *AuthUsecase) UpdateExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) error { + return u.authRepository.UpdateExpiredTimeOnToken(ctx, organizationId, userId) +} + +func (u *AuthUsecase) isExpiredEmailCode(code model.CacheEmailCode) bool { return !helper.IsDurationExpired(code.UpdatedAt, internal.EmailCodeExpireTime) } diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 5730e87d..ad8308f3 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -29,7 +29,7 @@ type IUserUsecase interface { Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) ResetPassword(ctx context.Context, userId uuid.UUID) error ResetPasswordByAccountId(ctx context.Context, accountId string, organizationId string) error - GenerateRandomPassword(ctx context.Context, ) string + GenerateRandomPassword(ctx context.Context) string Delete(ctx context.Context, userId uuid.UUID, organizationId string) error GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) @@ -47,6 +47,7 @@ type IUserUsecase interface { } type UserUsecase struct { + authRepository repository.IAuthRepository userRepository repository.IUserRepository roleRepository repository.IRoleRepository organizationRepository repository.IOrganizationRepository @@ -510,6 +511,15 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st log.Errorf(ctx, "join group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } + + targetUser, err := u.userRepository.Get(ctx, newUser.AccountId, newUser.Organization.ID) + if err != nil { + return nil, err + } + err = u.authRepository.UpdateExpiredTimeOnToken(ctx, newUser.Organization.ID, targetUser.ID.String()) + if err != nil { + return nil, err + } } *user, err = u.userRepository.UpdateWithUuid(ctx, user.ID, user.AccountId, user.Name, newUser.Role.ID, user.Email, @@ -523,6 +533,7 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st func NewUserUsecase(r repository.Repository, kc keycloak.IKeycloak) IUserUsecase { return &UserUsecase{ + authRepository: r.Auth, userRepository: r.User, roleRepository: r.Role, kc: kc, From 26efeab963f3cf9d9e32ccde635123f44216553c Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 19:49:59 +0900 Subject: [PATCH 163/502] lint fix --- internal/delivery/http/project.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index e5712505..c5405eed 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1002,6 +1002,11 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ return } err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, pmId.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) From 4ac97849e0bc0f8871e07007deb9e76dc086485c Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 20:18:58 +0900 Subject: [PATCH 164/502] Add project role to the response of login endpoint --- internal/delivery/http/auth.go | 25 +++++++++++++++++++++---- pkg/domain/auth.go | 26 +++++++++++++++++++------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index f817f8ba..ee87d823 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -28,14 +28,16 @@ type IAuthHandler interface { //Authenticate(next http.Handler) http.Handler } type AuthHandler struct { - usecase usecase.IAuthUsecase - auditUsecase usecase.IAuditUsecase + usecase usecase.IAuthUsecase + auditUsecase usecase.IAuditUsecase + projectUsecase usecase.IProjectUsecase } func NewAuthHandler(h usecase.Usecase) IAuthHandler { return &AuthHandler{ - usecase: h.Auth, - auditUsecase: h.Audit, + usecase: h.Auth, + auditUsecase: h.Audit, + projectUsecase: h.Project, } } @@ -95,11 +97,26 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { } } + projects, err := h.projectUsecase.GetProjects(r.Context(), input.OrganizationId, user.ID.String(), true, nil) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + var out domain.LoginResponse if err = serializer.Map(r.Context(), user, &out.User); err != nil { log.Error(r.Context(), err) } + for _, project := range projects { + var projectRole domain.ProjectIdProjectRoleResponse + projectRole.ID = project.ID + projectRole.ProjectRoleId = project.ProjectRoleId + projectRole.ProjectRoleName = project.ProjectRoleName + out.User.Projects = append(out.User.Projects, &projectRole) + } + ResponseJSON(w, r, http.StatusOK, out) } diff --git a/pkg/domain/auth.go b/pkg/domain/auth.go index d88da980..8d8983e3 100644 --- a/pkg/domain/auth.go +++ b/pkg/domain/auth.go @@ -8,16 +8,28 @@ type LoginRequest struct { type LoginResponse struct { User struct { - AccountId string `json:"accountId"` - Name string `json:"name"` - Token string `json:"token"` - Role RoleResponse `json:"role"` - Department string `json:"department"` - Organization OrganizationResponse `json:"organization"` - PasswordExpired bool `json:"passwordExpired"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Token string `json:"token"` + Role RoleIdRoleNameResponse `json:"role"` + Projects []*ProjectIdProjectRoleResponse `json:"projects"` + Department string `json:"department"` + Organization OrganizationResponse `json:"organization"` + PasswordExpired bool `json:"passwordExpired"` } `json:"user"` } +type RoleIdRoleNameResponse struct { + ID string `json:"roleId"` + Name string `json:"roleName"` +} + +type ProjectIdProjectRoleResponse struct { + ID string `json:"projectId"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` +} + type LogoutResponse struct { SsoUrls map[string][]string `json:"ssoUrls"` } From 0035251959c5ea2a83384c19b909c55eff6cd7dc Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 22 Mar 2024 00:35:00 +0900 Subject: [PATCH 165/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20api=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy.go | 534 ++++++++++++++++++++++++++++++ internal/kubernetes/kubernetes.go | 20 +- internal/model/policy.go | 75 +++++ internal/repository/policy.go | 213 ++++++++++++ internal/repository/repository.go | 1 + internal/route/route.go | 13 + internal/usecase/policy.go | 258 +++++++++++++++ internal/usecase/usecase.go | 1 + pkg/domain/policy.go | 120 +++++++ pkg/httpErrors/errorCode.go | 6 + 10 files changed, 1240 insertions(+), 1 deletion(-) create mode 100644 internal/delivery/http/policy.go create mode 100644 internal/model/policy.go create mode 100644 internal/repository/policy.go create mode 100644 internal/usecase/policy.go create mode 100644 pkg/domain/policy.go diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go new file mode 100644 index 00000000..93433286 --- /dev/null +++ b/internal/delivery/http/policy.go @@ -0,0 +1,534 @@ +package http + +import ( + "fmt" + "net/http" + + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" +) + +type PolicyHandler struct { + usecase usecase.IPolicyUsecase +} + +type IPolicyHandler interface { + CreatePolicy(w http.ResponseWriter, r *http.Request) + UpdatePolicy(w http.ResponseWriter, r *http.Request) + DeletePolicy(w http.ResponseWriter, r *http.Request) + GetPolicy(w http.ResponseWriter, r *http.Request) + ListPolicy(w http.ResponseWriter, r *http.Request) + UpdatePolicyTargetClusters(w http.ResponseWriter, r *http.Request) + GetMandatoryPolicies(w http.ResponseWriter, r *http.Request) + SetMandatoryPolicies(w http.ResponseWriter, r *http.Request) + ExistsPolicyName(w http.ResponseWriter, r *http.Request) +} + +func NewPolicyHandler(u usecase.Usecase) IPolicyHandler { + return &PolicyHandler{ + usecase: u.Policy, + } +} + +// CreatePolicy godoc +// +// @Tags Policy +// @Summary [CreatePolicy] 정책 생성 +// @Description 새로운 정책을 생성한다. targetClusterIds가 명시되지 않으면 정책은 활성화되지 않은 상태로 생성된다. 다른 클러스터에 동일한 정책이 존재한다면 정책 생성이 아닌 정책 업데이트를 통해 targetClusterIds를 수정해야 한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param body body domain.CreatePolicyRequest true "create policy request" +// @Success 200 {object} domain.CreatePolicyResponse +// @Router /organizations/{organizationId}/policies [post] +// @Security JWT +func (h *PolicyHandler) CreatePolicy(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.CreatePolicyRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto model.Policy + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + + policyId, err := h.usecase.Create(r.Context(), organizationId, dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CreatePolicyResponse + out.ID = policyId.String() + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdatePolicy godoc +// +// @Tags Policy +// @Summary [UpdatePolicy] 정책을 업데이트 +// @Description 정책의 내용을 업데이트 한다. 업데이트할 필드만 명시하면 된다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyId path string true "정책 식별자(uuid)" +// @Param body body domain.UpdatePolicyRequest true "update policy set request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/policies/{policyId} [patch] +// @Security JWT +func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyId, ok := vars["policyId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + id, err := uuid.Parse(policyId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + input := domain.UpdatePolicyRequest{} + + err = UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + var templateId *uuid.UUID = nil + + if input.TemplateId != nil { + tuuid, err := uuid.Parse(*input.TemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + templateId = &tuuid + + } + + err = h.usecase.Update(r.Context(), organizationId, id, + input.Mandatory, input.PolicyName, &input.Description, templateId, input.EnforcementAction, + input.Parameters, input.Match, input.TargetClusterIds) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +// DeletePolicy godoc +// +// @Tags Policy +// @Summary [DeletePolicy] 정책 삭제 +// @Description 정첵을 삭제한다. 정책이 적용된 클러스터가 있으면 삭제되지 않으므로 삭제 전 적용된 클러스터가 비어있어야 한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyId path string true "정책 식별자(uuid)" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/policies/{policyId} [delete] +// @Security JWT +func (h *PolicyHandler) DeletePolicy(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyId, ok := vars["policyId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + id, err := uuid.Parse(policyId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + err = h.usecase.Delete(r.Context(), organizationId, id) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, "") +} + +// GetPolicy godoc +// +// @Tags Policy +// @Summary [GetPolicy] 정책 조회 +// @Description 정책 정보를 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyId path string true "정책 식별자(uuid)" +// @Success 200 {object} domain.GetPolicyResponse +// @Router /organizations/{organizationId}/policies/{policyId} [get] +// @Security JWT +func (h *PolicyHandler) GetPolicy(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyId, ok := vars["policyId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + id, err := uuid.Parse(policyId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_ID", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + policy, err := h.usecase.Get(r.Context(), organizationId, id) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "P_NOT_FOUND_POLICY", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + if policy == nil { + ResponseJSON(w, r, http.StatusNotFound, nil) + return + } + + var out domain.GetPolicyResponse + if err = serializer.Map(r.Context(), *policy, &out.Policy); err != nil { + log.Error(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ListPolicy godoc +// +// @Tags Policy +// @Summary [ListPolicy] 정책 목록 조회 +// @Description 정책 목록을 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.ListPolicyResponse +// @Router /organizations/{organizationId}/policies [get] +// @Security JWT +func (h *PolicyHandler) ListPolicy(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + urlParams := r.URL.Query() + + pg := pagination.NewPagination(&urlParams) + + policies, err := h.usecase.Fetch(r.Context(), organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ListPolicyResponse + out.Policies = make([]domain.PolicyResponse, len(*policies)) + for i, policy := range *policies { + if err := serializer.Map(r.Context(), policy, &out.Policies[i]); err != nil { + log.Info(r.Context(), err) + continue + } + } + + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdatePolicyTargetClusters godoc +// +// @Tags Policy +// @Summary [UpdatePolicyTargetClusters] 정책 적용 대상 클러스터 수정 +// @Description 정책 적용 대상 클러스터를 수정한다. 추가할 클러스터 목록과 제거할 클러스터 목록 중 하나만 명시되어야 한다. 현재 정책이 배포된 클러스터를 확인하지 않고도 특정 클러스터를 추가하거나 제거할 수 있는 편의 API이다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyId path string true "정책 식별자(uuid)" +// @Param body body domain.UpdatePolicyClustersRequest true "update policy set request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/policies/{policyId}/clusters [patch] +// @Security JWT +func (h *PolicyHandler) UpdatePolicyTargetClusters(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyId, ok := vars["policyId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + id, err := uuid.Parse(policyId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_ID", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + input := domain.UpdatePolicyClustersRequest{} + + err = UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + err = h.usecase.UpdatePolicyTargetClusters(r.Context(), organizationId, id, + input.CurrentTargetClusterIds, input.NewTargetClusterIds) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +// GetMandatoryPolicies godoc +// +// @Tags Policy +// @Summary [GetMandatoryPolicies] 필수 정책 템플릿, 정책을 조회 +// @Description 템플릿, 정책이 필수 인지 여부를 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Success 200 {object} domain.GetMandatoryPoliciesResponse +// @Router /organizations/{organizationId}/mandatory-policies [get] +// @Security JWT +func (h *PolicyHandler) GetMandatoryPolicies(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + out, err := h.usecase.GetMandatoryPolicies(r.Context(), organizationId) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// SetMandatoryPolicies godoc +// +// @Tags Policy +// @Summary [SetMandatoryPolicies] 필수 정책 템플릿, 정책을 설정 +// @Description 템플릿, 정책이 필수 인지 여부를 설정한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param body body domain.SetMandatoryPoliciesRequest true "update mandatory policy/policy template request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/mandatory-policies [patch] +// @Security JWT +func (h *PolicyHandler) SetMandatoryPolicies(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + input := domain.SetMandatoryPoliciesRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + mandatoryPolicyIds := []uuid.UUID{} + nonMandatoryPolicyIds := []uuid.UUID{} + for _, policy := range input.Policies { + policyId, err := uuid.Parse(policy.PolicyId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_ID", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + if policy.Mandatory { + mandatoryPolicyIds = append(mandatoryPolicyIds, policyId) + } else { + nonMandatoryPolicyIds = append(nonMandatoryPolicyIds, policyId) + } + } + + err = h.usecase.SetMandatoryPolicies(r.Context(), organizationId, mandatoryPolicyIds, nonMandatoryPolicyIds) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } +} + +// ExistsPolicyName godoc +// +// @Tags Policy +// @Summary [ExistsPolicyName] 정책 아름 존재 여부 확인 +// @Description 해당 이름을 가진 정책이 이미 존재하는지 확인한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyName path string true "정책 이름" +// @Success 200 {object} domain.ExistenceResponse +// @Router /organizations/{organizationId}/policies/name/{policyName}/existence [get] +// @Security JWT +func (h *PolicyHandler) ExistsPolicyName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyName, ok := vars["policyName"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyTemplateName not found in path"), + "P_INVALID_POLICY_NAME", "")) + return + } + + exist, err := h.usecase.IsPolicyNameExist(r.Context(), organizationId, policyName) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CheckExistedResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go index 7559ea26..00555cad 100644 --- a/internal/kubernetes/kubernetes.go +++ b/internal/kubernetes/kubernetes.go @@ -4,16 +4,18 @@ import ( "bytes" "context" "fmt" - "gopkg.in/yaml.v3" "os" "strings" + "gopkg.in/yaml.v3" + "github.com/spf13/viper" rbacV1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -57,6 +59,22 @@ func GetClientAdminCluster(ctx context.Context) (*kubernetes.Clientset, error) { return clientset, nil } +// 쿠버네티스 기본 타입 이외의 타입(예: 정책 템플릿, 정책 등)을 처리하기 위한 dynamic client 생성 +func GetDynamicClientAdminCluster(ctx context.Context) (*dynamic.DynamicClient, error) { + config, err := getAdminConfig(ctx) + if err != nil { + log.Error(ctx, "Failed to load kubeconfig") + return nil, err + } + + // create the dynamic client + dynamicClient, err := dynamic.NewForConfig(config) + if err != nil { + return nil, err + } + return dynamicClient, nil +} + func GetAwsSecret(ctx context.Context) (awsAccessKeyId string, awsSecretAccessKey string, err error) { clientset, err := GetClientAdminCluster(ctx) if err != nil { diff --git a/internal/model/policy.go b/internal/model/policy.go new file mode 100644 index 00000000..2514c860 --- /dev/null +++ b/internal/model/policy.go @@ -0,0 +1,75 @@ +package model + +import ( + "encoding/json" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" + "gorm.io/gorm" +) + +type Policy struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` + OrganizationId string + + PolicyName string + Mandatory bool + Description string + + TargetClusterIds []string `gorm:"-:all"` + TargetClusters []Cluster `gorm:"many2many:policy_target_clusters"` + + EnforcementAction string + + Parameters string `gorm:"type:text"` + PolicyMatch string `gorm:"type:text"` + Match *domain.Match `gorm:"-:all"` + + TemplateName string `gorm:"-:all"` + TemplateId uuid.UUID `gorm:"type:uuid"` + PolicyTemplate PolicyTemplate `gorm:"foreignKey:TemplateId"` + + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` +} + +func (p *Policy) BeforeCreate(tx *gorm.DB) (err error) { + p.ID = uuid.New() + + if p.Match != nil { + jsonBytes, err := json.Marshal(p.Match) + + if err != nil { + return err + } + + p.PolicyMatch = string(jsonBytes) + } + + return nil +} + +func (p *Policy) AfterFind(tx *gorm.DB) (err error) { + p.TemplateName = p.PolicyTemplate.TemplateName + + if len(p.PolicyMatch) > 0 { + // 목록 조회 시 에러가 발생해서 전체 조회가 실패하는 것을 방지하기 위해서 에러는 무시 + _ = json.Unmarshal([]byte(p.PolicyMatch), p.Match) + } + + p.TargetClusterIds = make([]string, len(p.TargetClusters)) + for i, cluster := range p.TargetClusters { + p.TargetClusterIds[i] = cluster.ID.String() + } + + return +} + +type PolicyTargetCluster struct { + PolicyId uuid.UUID `gorm:"primarykey"` + ClusterId domain.ClusterId `gorm:"primarykey"` +} diff --git a/internal/repository/policy.go b/internal/repository/policy.go new file mode 100644 index 00000000..4a59b2c6 --- /dev/null +++ b/internal/repository/policy.go @@ -0,0 +1,213 @@ +package repository + +import ( + "context" + "fmt" + + mapset "github.com/deckarep/golang-set/v2" + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +type IPolicyRepository interface { + Create(ctx context.Context, dto model.Policy) (policyId uuid.UUID, err error) + Update(ctx context.Context, organizationId string, policyId uuid.UUID, + updateMap map[string]interface{}, TargetClusters *[]model.Cluster) (err error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out *[]model.Policy, err error) + ExistByName(ctx context.Context, organizationId string, policyName string) (exist bool, err error) + ExistByID(ctx context.Context, organizationId string, policyId uuid.UUID) (exist bool, err error) + GetByName(ctx context.Context, organizationId string, policyName string) (out *model.Policy, err error) + GetByID(ctx context.Context, organizationId string, policyId uuid.UUID) (out *model.Policy, err error) + Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) + UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusters []model.Cluster) (err error) + SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) +} + +type PolicyRepository struct { + db *gorm.DB +} + +func NewPolicyRepository(db *gorm.DB) IPolicyRepository { + return &PolicyRepository{ + db: db, + } +} + +func (r *PolicyRepository) Create(ctx context.Context, dto model.Policy) (policyId uuid.UUID, err error) { + err = r.db.WithContext(ctx).Create(&dto).Error + + if err != nil { + return uuid.Nil, err + } + + return dto.ID, nil +} + +func (r *PolicyRepository) Update(ctx context.Context, organizationId string, policyId uuid.UUID, + updateMap map[string]interface{}, targetClusters *[]model.Cluster) (err error) { + + var policy model.Policy + policy.ID = policyId + + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if targetClusters != nil { + err = tx.WithContext(ctx).Model(&policy).Limit(1). + Association("TargetClusters").Replace(targetClusters) + + if err != nil { + return err + } + } + + if len(updateMap) > 0 { + err = tx.WithContext(ctx).Model(&policy).Limit(1). + Where("id = ?", policyId). + Updates(updateMap).Error + + if err != nil { + return err + } + } + + // return nil will commit the whole transaction + return nil + }) +} + +func (r *PolicyRepository) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out *[]model.Policy, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations). + Where("organization_id = ?", organizationId), &out) + + if res.Error != nil { + return nil, res.Error + } + return +} + +func (r *PolicyRepository) ExistBy(ctx context.Context, organizationId string, key string, value interface{}) (exists bool, err error) { + query := fmt.Sprintf("organization_id = ? and %s = ?", value) + + var policy model.Policy + res := r.db.WithContext(ctx).Where(query, organizationId, value). + First(&policy) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Infof(ctx, "Not found policy %s='%v'", key, value) + return false, nil + } else { + log.Error(ctx, res.Error) + return false, res.Error + } + } + + return true, nil +} + +func (r *PolicyRepository) ExistByName(ctx context.Context, organizationId string, policyName string) (exist bool, err error) { + return r.ExistBy(ctx, "policy_name", organizationId, policyName) +} + +func (r *PolicyRepository) ExistByID(ctx context.Context, organizationId string, policyId uuid.UUID) (exist bool, err error) { + return r.ExistBy(ctx, "id", organizationId, policyId) +} + +func (r *PolicyRepository) GetBy(ctx context.Context, organizationId string, key string, value interface{}) (out *model.Policy, err error) { + query := fmt.Sprintf("organization_id = ? and %s = ?", value) + + var policy model.Policy + res := r.db.WithContext(ctx).Preload(clause.Associations). + Where(query, organizationId, value).First(&policy) + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Infof(ctx, "Not found policy %s='%v'", key, value) + return nil, nil + } else { + log.Error(ctx, res.Error) + return nil, res.Error + } + } + + return &policy, nil +} + +func (r *PolicyRepository) GetByName(ctx context.Context, organizationId string, policyName string) (out *model.Policy, err error) { + return r.GetBy(ctx, organizationId, "policy_name", policyName) +} + +func (r *PolicyRepository) GetByID(ctx context.Context, organizationId string, policyId uuid.UUID) (out *model.Policy, err error) { + return r.GetBy(ctx, organizationId, "id", policyId) +} + +func (r *PolicyRepository) Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) { + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if err := tx.Model(&model.Policy{ID: policyId}).Association("TargetClusters").Clear(); err != nil { + return err + } + + if err := tx.Where("organization_id = ? and id = ?", organizationId, policyId).Delete(&model.Policy{}).Error; err != nil { + return err + } + + return nil + }) +} + +func (r *PolicyRepository) UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusters []model.Cluster) (err error) { + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + var policy model.Policy + res := tx.Preload("TargetClusters").Where("organization_id = ? and id = ?", organizationId, policyId).First(&policy) + + if res.Error != nil { + return res.Error + } + + if len(policy.TargetClusterIds) == 0 && len(currentClusterIds) != 0 { + return errors.New("concurrent modification of target clusters") + } + + actualCurrentClusterIdSet := mapset.NewSet(policy.TargetClusterIds...) + knownCurrentClusterIdSet := mapset.NewSet(currentClusterIds...) + + if !actualCurrentClusterIdSet.Equal(knownCurrentClusterIdSet) { + return errors.New("concurrent modification of target clusters") + } + + err = tx.Model(&policy).Limit(1). + Association("TargetClusters").Replace(targetClusters) + + if err != nil { + return err + } + + // return nil will commit the whole transaction + return nil + }) +} + +func (r *PolicyRepository) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) { + return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if err = tx.Model(&model.Policy{}). + Where("organization_id = ? id in ?", organizationId, mandatoryPolicyIds). + Update("mandatory", true).Error; err != nil { + return err + } + + if err = tx.Model(&model.Policy{}). + Where("organization_id = ? id in ?", organizationId, nonMandatoryPolicyIds). + Update("mandatory", false).Error; err != nil { + return err + } + + return nil + }) +} diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 0114cf59..bee291a5 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -21,6 +21,7 @@ type Repository struct { Project IProjectRepository Audit IAuditRepository PolicyTemplate IPolicyTemplateRepository + Policy IPolicyRepository SystemNotification ISystemNotificationRepository SystemNotificationTemplate ISystemNotificationTemplateRepository SystemNotificationRule ISystemNotificationRuleRepository diff --git a/internal/route/route.go b/internal/route/route.go index bb00ba3b..8c73bb75 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -58,6 +58,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Endpoint: repository.NewEndpointRepository(db), Audit: repository.NewAuditRepository(db), PolicyTemplate: repository.NewPolicyTemplateRepository(db), + Policy: repository.NewPolicyRepository(db), Dashboard: repository.NewDashboardRepository(db), } @@ -80,6 +81,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Role: usecase.NewRoleUsecase(repoFactory), Permission: usecase.NewPermissionUsecase(repoFactory), PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), + Policy: usecase.NewPolicyUsecase(repoFactory), } customMiddleware := internalMiddleware.NewMiddleware( @@ -308,6 +310,17 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/policy-templates/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(policyTemplateHandler.RegoCompile))).Methods(http.MethodPost) + policyHandler := delivery.NewPolicyHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/mandatory-policies", customMiddleware.Handle(internalApi.GetMandatoryPolicies, http.HandlerFunc(policyHandler.GetMandatoryPolicies))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/mandatory-policies", customMiddleware.Handle(internalApi.SetMandatoryPolicies, http.HandlerFunc(policyHandler.SetMandatoryPolicies))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies", customMiddleware.Handle(internalApi.ListPolicy, http.HandlerFunc(policyHandler.ListPolicy))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies", customMiddleware.Handle(internalApi.CreatePolicy, http.HandlerFunc(policyHandler.CreatePolicy))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.GetPolicy, http.HandlerFunc(policyHandler.GetPolicy))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.DeletePolicy, http.HandlerFunc(policyHandler.DeletePolicy))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.UpdatePolicy, http.HandlerFunc(policyHandler.UpdatePolicy))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}/clusters", customMiddleware.Handle(internalApi.UpdatePolicyTargetClusters, http.HandlerFunc(policyHandler.UpdatePolicyTargetClusters))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyName, http.HandlerFunc(policyHandler.ExistsPolicyName))).Methods(http.MethodGet) + // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) r.PathPrefix("/").Handler(httpSwagger.WrapHandler).Methods(http.MethodGet) diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go new file mode 100644 index 00000000..4f7da889 --- /dev/null +++ b/internal/usecase/policy.go @@ -0,0 +1,258 @@ +package usecase + +import ( + "context" + "fmt" + + mapset "github.com/deckarep/golang-set/v2" + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" +) + +type IPolicyUsecase interface { + Create(ctx context.Context, organizationId string, dto model.Policy) (policyId uuid.UUID, err error) + Update(ctx context.Context, organizationId string, policyId uuid.UUID, + mandatory *bool, policyName *string, description *string, templateId *uuid.UUID, enforcementAction *string, + parameters *string, match *domain.Match, targetClusterIds *[]string) (err error) + Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) + Get(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.Policy, error) + IsPolicyIdExist(ctx context.Context, organizationId string, policyId uuid.UUID) (exists bool, err error) + IsPolicyNameExist(ctx context.Context, organizationId string, policyName string) (exists bool, err error) + UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusterIds []string) (err error) + SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) + GetMandatoryPolicies(ctx context.Context, organizationId string) (response *domain.GetMandatoryPoliciesResponse, err error) +} + +type PolicyUsecase struct { + organizationRepo repository.IOrganizationRepository + clusterRepo repository.IClusterRepository + templateRepo repository.IPolicyTemplateRepository + repo repository.IPolicyRepository +} + +func NewPolicyUsecase(r repository.Repository) IPolicyUsecase { + return &PolicyUsecase{ + repo: r.Policy, + templateRepo: r.PolicyTemplate, + organizationRepo: r.Organization, + clusterRepo: r.Cluster, + } +} + +func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto model.Policy) (policyId uuid.UUID, err error) { + dto.OrganizationId = organizationId + + user, ok := request.UserFrom(ctx) + if !ok { + return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") + } + + exists, err := u.repo.ExistByName(ctx, dto.OrganizationId, dto.TemplateName) + if err != nil { + return uuid.Nil, err + } + + if exists { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") + } + + dto.TargetClusters = make([]model.Cluster, len(dto.TargetClusterIds)) + for i, clusterId := range dto.TargetClusterIds { + + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) + if err != nil { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + dto.TargetClusters[i] = cluster + } + + userId := user.GetUserId() + dto.CreatorId = &userId + + id, err := u.repo.Create(ctx, dto) + + if err != nil { + return uuid.Nil, err + } + + return id, nil +} + +func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, policyId uuid.UUID, + mandatory *bool, policyName *string, description *string, templateId *uuid.UUID, enforcementAction *string, + parameters *string, match *domain.Match, targetClusterIds *[]string) (err error) { + + user, ok := request.UserFrom(ctx) + if !ok { + return httpErrors.NewBadRequestError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") + } + + _, err = u.repo.GetByID(ctx, organizationId, policyId) + if err != nil { + return httpErrors.NewNotFoundError(err, "P_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + updateMap := make(map[string]interface{}) + + if mandatory != nil { + updateMap["mandatory"] = mandatory + } + + if policyName != nil { + exists, err := u.repo.ExistByName(ctx, organizationId, *policyName) + if err == nil && exists { + return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY__NAME", "policy template name already exists") + } + updateMap["policy_name"] = policyName + } + + if description != nil { + updateMap["description"] = description + } + + if templateId != nil { + updateMap["template_id"] = templateId + } + + if enforcementAction != nil { + updateMap["enforcement_action"] = enforcementAction + } + + if parameters != nil { + updateMap["parameters"] = parameters + } + + if parameters != nil { + updateMap["policy_match"] = match.JSON() + } + + var newTargetClusters *[]model.Cluster = nil + + if targetClusterIds != nil { + targetClusters := make([]model.Cluster, len(*targetClusterIds)) + + for i, clusterId := range *targetClusterIds { + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) + if err != nil { + return httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), "C_INVALID_CLUSTER_ID", "") + } + + targetClusters[i] = cluster + } + newTargetClusters = &targetClusters + } else if len(updateMap) == 0 { + // 허용된 조직도 필드 속성도 업데이트되지 않았으므로 아무것도 업데이트할 것이 없음 + return nil + } + + updatorId := user.GetUserId() + updateMap["updator_id"] = updatorId + + err = u.repo.Update(ctx, organizationId, policyId, updateMap, newTargetClusters) + if err != nil { + return err + } + + return nil +} + +func (u *PolicyUsecase) Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) { + return u.repo.Delete(ctx, organizationId, policyId) +} + +func (u *PolicyUsecase) Get(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) { + return u.repo.GetByID(ctx, organizationId, policyId) +} + +func (u *PolicyUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.Policy, error) { + return u.repo.Fetch(ctx, organizationId, pg) +} + +func (u *PolicyUsecase) IsPolicyNameExist(ctx context.Context, organizationId string, policyName string) (exists bool, err error) { + return u.repo.ExistByName(ctx, organizationId, policyName) +} + +func (u *PolicyUsecase) IsPolicyIdExist(ctx context.Context, organizationId string, policyId uuid.UUID) (exists bool, err error) { + return u.repo.ExistByID(ctx, organizationId, policyId) +} + +func (u *PolicyUsecase) UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusterIds []string) (err error) { + targetClusters := make([]model.Cluster, len(targetClusterIds)) + + for i, clusterId := range targetClusterIds { + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) + if err != nil { + return httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), "C_INVALID_CLUSTER_ID", "") + } + + targetClusters[i] = cluster + } + + return u.repo.UpdatePolicyTargetClusters(ctx, organizationId, policyId, currentClusterIds, targetClusters) +} + +func (u *PolicyUsecase) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) { + return u.repo.SetMandatoryPolicies(ctx, organizationId, mandatoryPolicyIds, nonMandatoryPolicyIds) +} + +func (u *PolicyUsecase) GetMandatoryPolicies(ctx context.Context, organizationId string) (response *domain.GetMandatoryPoliciesResponse, err error) { + + var out domain.GetMandatoryPoliciesResponse + + policyTemplates, err := u.templateRepo.Fetch(ctx, nil) + + if err != nil { + return nil, err + } + + templateMaps := map[string]*domain.MandatoryTemplateInfo{} + + for _, policyTemplate := range policyTemplates { + templateId := policyTemplate.ID.String() + + if len(policyTemplate.PermittedOrganizationIds) == 0 || + mapset.NewSet(policyTemplate.PermittedOrganizationIds...).Contains(organizationId) { + templateMaps[templateId] = &domain.MandatoryTemplateInfo{ + TemplateName: policyTemplate.TemplateName, + TemplateId: templateId, + Description: policyTemplate.Description, + Policies: []domain.MandatoryPolicyInfo{}, + } + } + } + + policies, err := u.repo.Fetch(ctx, organizationId, nil) + + if err != nil { + return nil, err + } + + for _, policy := range *policies { + template, ok := templateMaps[policy.TemplateId.String()] + + if ok { + template.Policies = append(template.Policies, domain.MandatoryPolicyInfo{ + PolicyName: policy.PolicyName, + PolicyId: policy.ID.String(), + Description: policy.Description, + Mandatory: policy.Mandatory, + }) + + if policy.Mandatory { + template.Mandatory = true + } + } + } + + for _, template := range templateMaps { + out.Templates = append(out.Templates, *template) + } + + return &out, nil +} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index 181d1f31..46302b69 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -19,4 +19,5 @@ type Usecase struct { Permission IPermissionUsecase Audit IAuditUsecase PolicyTemplate IPolicyTemplateUsecase + Policy IPolicyUsecase } diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go new file mode 100644 index 00000000..e2ccf0e0 --- /dev/null +++ b/pkg/domain/policy.go @@ -0,0 +1,120 @@ +package domain + +import ( + "encoding/json" + "time" +) + +type Kinds struct { + APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,1,rep,name=apiGroups"` + Kinds []string `json:"kinds,omitempty"` +} + +type Match struct { + Namespaces []string `json:"namespaces,omitempty"` + ExcludedNamespaces []string `json:"excludedNamespaces,omitempty"` + Kinds []Kinds `json:"kinds,omitempty"` +} + +func (m *Match) JSON() string { + jsonBytes, err := json.Marshal(m) + + if err != nil { + return "" + } + + return string(jsonBytes) +} + +type PolicyResponse struct { + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + Creator SimpleUserResponse `json:"creator,omitempty"` + Updator SimpleUserResponse `json:"updator,omitempty"` + CreatedAt time.Time `json:"createdAt" format:"date-time"` + UpdatedAt time.Time `json:"updatedAt" format:"date-time"` + + TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` + Mandatory bool `json:"mandatory"` + + PolicyName string `json:"policyName" example:"label 정책"` + Description string `json:"description"` + TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + TemplateName string `json:"templateName" example:"필수 Label 검사"` + EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun"` + Parameters string `json:"parameters" example:"\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\""` + Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` + //Tags []string `json:"tags,omitempty" example:"k8s,label"` +} + +type CreatePolicyRequest struct { + TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` + Mandatory bool `json:"mandatory"` + + PolicyName string `json:"policyName" example:"label 정책"` + Description string `json:"description"` + TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + TemplateName string `json:"templateName" example:"필수 Label 검사"` + EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun"` + Parameters string `json:"parameters" example:"\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\""` + Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` + //Tags []string `json:"tags,omitempty" example:"k8s,label"` +} + +type CreatePolicyResponse struct { + ID string `json:"id"` +} + +type UpdatePolicyRequest struct { + TargetClusterIds *[]string `json:"targetClusterIds,omitempty" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` + Mandatory *bool `json:"mandatory,omitempty"` + + PolicyName *string `json:"policyName,omitempty" example:"label 정책"` + Description string `json:"description"` + TemplateId *string `json:"templateId,omitempty" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + EnforcementAction *string `json:"enforcementAction,omitempty" enum:"warn,deny,dryrun"` + Parameters *string `json:"parameters,omitempty" example:"\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\""` + Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` + //Tags []string `json:"tags,omitempty" example:"k8s,label"` +} + +type UpdatePolicyClustersRequest struct { + CurrentTargetClusterIds []string `json:"currentTargetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90"` + NewTargetClusterIds []string `json:"newTargetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` +} + +type GetPolicyResponse struct { + Policy PolicyResponse `json:"policy"` +} + +type ListPolicyResponse struct { + Policies []PolicyResponse `json:"policies"` + Pagination PaginationResponse `json:"pagination"` +} + +type MandatoryPolicyInfo struct { + PolicyName string `json:"policyName" example:"org 레이블 요구"` + PolicyId string `json:"policyId" example:"0091fe9b-e44b-423d-9562-ac2b73089593"` + Description string `json:"description" example:"org 레이블 설정 여부 검사"` + Mandatory bool `json:"mandatory"` +} + +type MandatoryTemplateInfo struct { + TemplateName string `json:"templateName" example:"레이블 요구"` + TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` + Description string `json:"description" example:"파라미터로 설정된 레이블 검사"` + Mandatory bool `json:"mandatory"` + Policies []MandatoryPolicyInfo `json:"policies"` +} + +type GetMandatoryPoliciesResponse struct { + Templates []MandatoryTemplateInfo `json:"templates"` +} + +type MandatoryPolicyPatchInfo struct { + PolicyId string `json:"policyId" example:"0091fe9b-e44b-423d-9562-ac2b73089593"` + Mandatory bool `json:"mandatory"` +} + +type SetMandatoryPoliciesRequest struct { + Policies []MandatoryPolicyPatchInfo `json:"policies"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 5dff7467..f8e1b961 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -19,6 +19,7 @@ var errorMap = map[ErrorCode]string{ "C_INVALID_CLOUD_SERVICE": "유효하지 않은 클라우드서비스입니다.", "C_INVALID_AUDIT_ID": "유효하지 않은 로그 아이디입니다. 로그 아이디를 확인하세요.", "C_INVALID_POLICY_TEMPLATE_ID": "유효하지 않은 정책 템플릿 아이디입니다. 정책 템플릿 아이디를 확인하세요.", + "C_INVALID_POLICY_ID": "유효하지 않은 정책 아이디입니다. 정책 아이디를 확인하세요.", "C_FAILED_TO_CALL_WORKFLOW": "워크플로우 호출에 실패했습니다.", // Auth @@ -122,6 +123,11 @@ var errorMap = map[ErrorCode]string{ "PT_INVALID_POLICY_TEMPLATE_NAME": "유효하지 않은 정책 템플릿 이름입니다. 정책 템플릿 이름을 확인하세요.", "PT_INVALID_POLICY_TEMPLATE_KIND": "유효하지 않은 정책 템플릿 유형입니다. 정책 템플릿 유형을 확인하세요.", "PT_INVALID_REGO_PARSEPARAMETER": "유효하지 않은 Rego 파싱 설정입니다. Rego 파싱 설정을 확인하세요.", + + // Policy + "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", + "P_NOT_FOUND_POLICY": "정책이 존재하지 않습니다.", + "P_INVALID_POLICY_NAME": "유효하지 않은 정책 이름입니다. 정책 이름을 확인하세요.", } func (m ErrorCode) GetText() string { From 8aa80744c3db9b6d7de90cf970310745cc9f6c53 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 22 Mar 2024 01:20:07 +0900 Subject: [PATCH 166/502] =?UTF-8?q?Policy=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?migrate=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/database/database.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/database/database.go b/internal/database/database.go index a6d9cb85..d70511cd 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -176,6 +176,10 @@ func migrateSchema(db *gorm.DB) error { return err } + if err := db.AutoMigrate(&model.Policy{}); err != nil { + return err + } + if err := db.AutoMigrate(&model.Dashboard{}); err != nil { return err } From bad071cb8b9dc769dc3ddda14edeaac147a32552 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 22 Mar 2024 02:03:29 +0900 Subject: [PATCH 167/502] =?UTF-8?q?parameterdef=20<->=20json=20schema=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=84=ED=84=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/paramdef-util.go | 85 +++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 internal/policy-template/paramdef-util.go diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go new file mode 100644 index 00000000..04ca850c --- /dev/null +++ b/internal/policy-template/paramdef-util.go @@ -0,0 +1,85 @@ +package policytemplate + +import ( + "strings" + + "github.com/openinfradev/tks-api/pkg/domain" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" +) + +func ParamDefsToJSONSchemaProeprties(paramdefs []*domain.ParameterDef) *apiextensionsv1.JSONSchemaProps { + if paramdefs == nil { + return nil + } + + result := apiextensionsv1.JSONSchemaProps{Type: "object", Properties: convert(paramdefs)} + + return &result +} + +func convert(paramdefs []*domain.ParameterDef) map[string]apiextensionsv1.JSONSchemaProps { + result := map[string]apiextensionsv1.JSONSchemaProps{} + + for _, paramdef := range paramdefs { + isArary := paramdef.IsArray + isObject := len(paramdef.Children) > 0 + + switch { + case isArary && isObject: + result[paramdef.Key] = apiextensionsv1.JSONSchemaProps{ + Type: "array", + Items: &apiextensionsv1.JSONSchemaPropsOrArray{ + Schema: ParamDefsToJSONSchemaProeprties(paramdef.Children), + }, + } + case isArary: + result[paramdef.Key] = apiextensionsv1.JSONSchemaProps{ + Type: "array", + Items: &apiextensionsv1.JSONSchemaPropsOrArray{ + Schema: &apiextensionsv1.JSONSchemaProps{Type: strings.TrimSuffix(paramdef.Type, "[]")}, + }, + } + case isObject: + result[paramdef.Key] = *ParamDefsToJSONSchemaProeprties(paramdef.Children) + _: + result[paramdef.Key] = apiextensionsv1.JSONSchemaProps{Type: paramdef.Type} + } + + } + + return result +} + +func JSONSchemaProeprtiesToParamDefs(jsschema *apiextensionsv1.JSONSchemaProps) []*domain.ParameterDef { + return convertToParameterDef(jsschema).Children +} + +func convertToParameterDef(jsschema *apiextensionsv1.JSONSchemaProps) *domain.ParameterDef { + // result := []ParameterDef{} + // fmt.Println(jsschema.Properties) + switch jsschema.Type { + case "array": + itemDef := convertToParameterDef(jsschema.Items.Schema) + itemDef.Type = jsschema.Items.Schema.Type + "[]" + itemDef.IsArray = true + + return itemDef + case "object": + children := []*domain.ParameterDef{} + for kc, vc := range jsschema.Properties { + converted := convertToParameterDef(&vc) + converted.Key = kc + children = append(children, converted) + } + return &domain.ParameterDef{Key: jsschema.ID, Type: jsschema.Type, DefaultValue: "", + Children: children} + default: + defaultValue := "" + + if jsschema.Default != nil { + defaultValue = string(jsschema.Default.Raw) + } + + return &domain.ParameterDef{Key: jsschema.ID, Type: jsschema.Type, DefaultValue: defaultValue, Children: []*domain.ParameterDef{}} + } +} From ea6dde400d242d3fb34a8f4c46f76f1c2f7525b8 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 22 Mar 2024 08:54:47 +0900 Subject: [PATCH 168/502] =?UTF-8?q?swagger=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy-template.go | 2 +- internal/delivery/http/policy.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 5b0dfa3e..27bb93ce 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -615,7 +615,7 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, // @Accept json // @Produce json // @Param policyTemplateKind path string true "정책 템플릿 이름" -// @Success 200 {object} domain.ExistsPolicyTemplateKindResponse +// @Success 200 {object} domain.CheckExistedResponse // @Router /admin/policy-templates/kind/{policyTemplateKind}/existence [get] // @Security JWT func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 93433286..972648c8 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -502,7 +502,7 @@ func (h *PolicyHandler) SetMandatoryPolicies(w http.ResponseWriter, r *http.Requ // @Produce json // @Param organizationId path string true "조직 식별자(o로 시작)" // @Param policyName path string true "정책 이름" -// @Success 200 {object} domain.ExistenceResponse +// @Success 200 {object} domain.CheckExistedResponse // @Router /organizations/{organizationId}/policies/name/{policyName}/existence [get] // @Security JWT func (h *PolicyHandler) ExistsPolicyName(w http.ResponseWriter, r *http.Request) { From 5454e10e031eeffa1dd7331ad3f637a38b59fbb0 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 22 Mar 2024 10:43:21 +0900 Subject: [PATCH 169/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EB=93=B1=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/model/policy.go | 6 +++++- internal/repository/policy.go | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/internal/model/policy.go b/internal/model/policy.go index 2514c860..9eb86264 100644 --- a/internal/model/policy.go +++ b/internal/model/policy.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "fmt" "github.com/google/uuid" "github.com/openinfradev/tks-api/pkg/domain" @@ -58,7 +59,10 @@ func (p *Policy) AfterFind(tx *gorm.DB) (err error) { if len(p.PolicyMatch) > 0 { // 목록 조회 시 에러가 발생해서 전체 조회가 실패하는 것을 방지하기 위해서 에러는 무시 - _ = json.Unmarshal([]byte(p.PolicyMatch), p.Match) + var match domain.Match + err = json.Unmarshal([]byte(p.PolicyMatch), &match) + p.Match = &match + fmt.Printf("!!!!!!!!!!!! err=%+v, p.Match=%+v p.PolicyMatch=%+v\n", err, p.Match, p.PolicyMatch) } p.TargetClusterIds = make([]string, len(p.TargetClusters)) diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 4a59b2c6..9ceda1aa 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -94,7 +94,7 @@ func (r *PolicyRepository) Fetch(ctx context.Context, organizationId string, pg } func (r *PolicyRepository) ExistBy(ctx context.Context, organizationId string, key string, value interface{}) (exists bool, err error) { - query := fmt.Sprintf("organization_id = ? and %s = ?", value) + query := fmt.Sprintf("organization_id = ? and %s = ?", key) var policy model.Policy res := r.db.WithContext(ctx).Where(query, organizationId, value). @@ -114,15 +114,15 @@ func (r *PolicyRepository) ExistBy(ctx context.Context, organizationId string, k } func (r *PolicyRepository) ExistByName(ctx context.Context, organizationId string, policyName string) (exist bool, err error) { - return r.ExistBy(ctx, "policy_name", organizationId, policyName) + return r.ExistBy(ctx, organizationId, "policy_name", policyName) } func (r *PolicyRepository) ExistByID(ctx context.Context, organizationId string, policyId uuid.UUID) (exist bool, err error) { - return r.ExistBy(ctx, "id", organizationId, policyId) + return r.ExistBy(ctx, organizationId, "id", policyId) } func (r *PolicyRepository) GetBy(ctx context.Context, organizationId string, key string, value interface{}) (out *model.Policy, err error) { - query := fmt.Sprintf("organization_id = ? and %s = ?", value) + query := fmt.Sprintf("organization_id = ? and %s = ?", key) var policy model.Policy res := r.db.WithContext(ctx).Preload(clause.Associations). From 3f9f286a2a1a5d88ed6aac9ac924c1b90900aa07 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sun, 24 Mar 2024 15:21:41 +0900 Subject: [PATCH 170/502] =?UTF-8?q?=EC=BF=A0=EB=B2=84=EB=84=A4=ED=8B=B0?= =?UTF-8?q?=EC=8A=A4=20=EC=A0=95=EC=B1=85=20=EA=B4=80=EB=A6=AC=20develop?= =?UTF-8?q?=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EB=B3=91=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/model/policy.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/model/policy.go b/internal/model/policy.go index 9eb86264..1a05c5ef 100644 --- a/internal/model/policy.go +++ b/internal/model/policy.go @@ -2,7 +2,6 @@ package model import ( "encoding/json" - "fmt" "github.com/google/uuid" "github.com/openinfradev/tks-api/pkg/domain" @@ -62,7 +61,6 @@ func (p *Policy) AfterFind(tx *gorm.DB) (err error) { var match domain.Match err = json.Unmarshal([]byte(p.PolicyMatch), &match) p.Match = &match - fmt.Printf("!!!!!!!!!!!! err=%+v, p.Match=%+v p.PolicyMatch=%+v\n", err, p.Match, p.PolicyMatch) } p.TargetClusterIds = make([]string, len(p.TargetClusters)) From 71f26c4b852e2c6a6e117e8daabda8b654221bfc Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 22 Mar 2024 15:19:32 +0900 Subject: [PATCH 171/502] feature. implemntation systemnotification conditions --- api/swagger/docs.go | 201 +++++++++++++++++- api/swagger/swagger.json | 201 +++++++++++++++++- api/swagger/swagger.yaml | 140 +++++++++++- internal/database/database.go | 5 +- .../delivery/http/system-notification-rule.go | 71 ++++++- internal/model/system-notification-rule.go | 51 ++--- .../repository/system-notification-rule.go | 45 ++-- internal/route/route.go | 8 +- internal/usecase/organization.go | 1 - internal/usecase/system-notification-rule.go | 73 +++++-- pkg/domain/system-notification-rule.go | 71 ++++++- pkg/httpErrors/errorCode.go | 8 +- 12 files changed, 761 insertions(+), 114 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0b44751f..b7ccdc0d 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -394,7 +394,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates": { + "/admin/policy-templates": { "get": { "security": [ { @@ -495,7 +495,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "/admin/policy-templates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { @@ -532,7 +532,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/name/{policyTemplateName}/existence": { + "/admin/policy-templates/name/{policyTemplateName}/existence": { "get": { "security": [ { @@ -569,7 +569,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}": { + "/admin/policy-templates/{policyTemplateId}": { "get": { "security": [ { @@ -679,7 +679,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/deploy": { + "/admin/policy-templates/{policyTemplateId}/deploy": { "get": { "security": [ { @@ -716,7 +716,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/statistics": { + "/admin/policy-templates/{policyTemplateId}/statistics": { "get": { "security": [ { @@ -753,7 +753,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/versions": { + "/admin/policy-templates/{policyTemplateId}/versions": { "get": { "security": [ { @@ -834,7 +834,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/versions/{version}": { + "/admin/policy-templates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { @@ -7385,7 +7385,7 @@ const docTemplate = `{ } } }, - "/policytemplates/rego-compile": { + "/policy-templates/rego-compile": { "post": { "security": [ { @@ -9000,14 +9000,68 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { "type": "object", "required": [ - "name" + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" ], "properties": { "description": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, @@ -11305,6 +11359,46 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter": { + "type": "object", + "properties": { + "operator": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse": { "type": "object", "properties": { @@ -11391,9 +11485,36 @@ const docTemplate = `{ "id": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" }, + "systemNotificationConditions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" + } + }, + "systemNotificationTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" + }, + "targetUsers": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + }, "updatedAt": { "type": "string" }, @@ -11837,9 +11958,69 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", + "required": [ + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" + ], "properties": { "description": { "type": "string" + }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, + "name": { + "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 58f58a56..6a9be303 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -388,7 +388,7 @@ } } }, - "/admin/policytemplates": { + "/admin/policy-templates": { "get": { "security": [ { @@ -489,7 +489,7 @@ } } }, - "/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "/admin/policy-templates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { @@ -526,7 +526,7 @@ } } }, - "/admin/policytemplates/name/{policyTemplateName}/existence": { + "/admin/policy-templates/name/{policyTemplateName}/existence": { "get": { "security": [ { @@ -563,7 +563,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}": { + "/admin/policy-templates/{policyTemplateId}": { "get": { "security": [ { @@ -673,7 +673,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/deploy": { + "/admin/policy-templates/{policyTemplateId}/deploy": { "get": { "security": [ { @@ -710,7 +710,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/statistics": { + "/admin/policy-templates/{policyTemplateId}/statistics": { "get": { "security": [ { @@ -747,7 +747,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/versions": { + "/admin/policy-templates/{policyTemplateId}/versions": { "get": { "security": [ { @@ -828,7 +828,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/versions/{version}": { + "/admin/policy-templates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { @@ -7379,7 +7379,7 @@ } } }, - "/policytemplates/rego-compile": { + "/policy-templates/rego-compile": { "post": { "security": [ { @@ -8994,14 +8994,68 @@ "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { "type": "object", "required": [ - "name" + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" ], "properties": { "description": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, @@ -11299,6 +11353,46 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter": { + "type": "object", + "properties": { + "operator": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse": { "type": "object", "properties": { @@ -11385,9 +11479,36 @@ "id": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" }, + "systemNotificationConditions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" + } + }, + "systemNotificationTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" + }, + "targetUsers": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + }, "updatedAt": { "type": "string" }, @@ -11831,9 +11952,69 @@ }, "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", + "required": [ + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" + ], "properties": { "description": { "type": "string" + }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, + "name": { + "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 71ac2318..1dc24bd5 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1060,10 +1060,47 @@ definitions: properties: description: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string name: type: string + systemNotificationConditions: + items: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + type: array + systemNotificationTemplateId: + type: string + targetUserIds: + items: + type: string + type: array required: + - messageCondition + - messageContent + - messageTitle - name + - systemNotificationTemplateId type: object github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse: properties: @@ -2576,6 +2613,32 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter: + properties: + operator: + type: string + order: + type: integer + value: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse: properties: closedAt: @@ -2633,8 +2696,26 @@ definitions: type: string id: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string name: type: string + systemNotificationConditions: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse' + type: array + systemNotificationTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse' + targetUsers: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + type: array updatedAt: type: string updator: @@ -2930,6 +3011,47 @@ definitions: properties: description: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string + name: + type: string + systemNotificationConditions: + items: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + type: array + systemNotificationTemplateId: + type: string + targetUserIds: + items: + type: string + type: array + required: + - messageCondition + - messageContent + - messageTitle + - name + - systemNotificationTemplateId type: object github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest: properties: @@ -3397,7 +3519,7 @@ paths: summary: Update user by admin tags: - Admin - /admin/policytemplates: + /admin/policy-templates: get: consumes: - application/json @@ -3461,7 +3583,7 @@ paths: summary: '[CreatePolicyTemplate] 정책 템플릿 신규 생성' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}: + /admin/policy-templates/{policyTemplateId}: delete: consumes: - application/json @@ -3530,7 +3652,7 @@ paths: summary: '[UpdatePolicyTemplate] 정책 템플릿 업데이트' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/deploy: + /admin/policy-templates/{policyTemplateId}/deploy: get: consumes: - application/json @@ -3553,7 +3675,7 @@ paths: summary: '[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/statistics: + /admin/policy-templates/{policyTemplateId}/statistics: get: consumes: - application/json @@ -3577,7 +3699,7 @@ paths: summary: '[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/versions: + /admin/policy-templates/{policyTemplateId}/versions: get: consumes: - application/json @@ -3628,7 +3750,7 @@ paths: summary: '[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/versions/{version}: + /admin/policy-templates/{policyTemplateId}/versions/{version}: delete: consumes: - application/json @@ -3681,7 +3803,7 @@ paths: summary: '[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' tags: - PolicyTemplate - /admin/policytemplates/kind/{policyTemplateKind}/existence: + /admin/policy-templates/kind/{policyTemplateKind}/existence: get: consumes: - application/json @@ -3704,7 +3826,7 @@ paths: summary: '[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인' tags: - PolicyTemplate - /admin/policytemplates/name/{policyTemplateName}/existence: + /admin/policy-templates/name/{policyTemplateName}/existence: get: consumes: - application/json @@ -7860,7 +7982,7 @@ paths: summary: Get Permission Templates tags: - Permission - /policytemplates/rego-compile: + /policy-templates/rego-compile: post: consumes: - application/json diff --git a/internal/database/database.go b/internal/database/database.go index a6d9cb85..5af01cbb 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -127,13 +127,10 @@ func migrateSchema(db *gorm.DB) error { } // SystemNotificationRule - if err := db.AutoMigrate(&model.SystemNotificationRule{}); err != nil { - return err - } if err := db.AutoMigrate(&model.SystemNotificationCondition{}); err != nil { return err } - if err := db.AutoMigrate(&model.SystemNotificationMessage{}); err != nil { + if err := db.AutoMigrate(&model.SystemNotificationRule{}); err != nil { return err } diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 068966bc..2c27207c 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -1,6 +1,7 @@ package http import ( + "encoding/json" "fmt" "net/http" @@ -38,6 +39,13 @@ func NewSystemNotificationRuleHandler(h usecase.Usecase) *SystemNotificationRule // @Router /organizations/{organizationId}/system-notification-rules [post] // @Security JWT func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + input := domain.CreateSystemNotificationRuleRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { @@ -49,6 +57,14 @@ func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.Resp if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } + dto.OrganizationId = organizationId + + dto.SystemNotificationConditions = make([]model.SystemNotificationCondition, len(input.SystemNotificationConditions)) + for i, systemNotificationCondition := range input.SystemNotificationConditions { + if err := serializer.Map(r.Context(), systemNotificationCondition, &dto.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + } id, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -99,6 +115,25 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.Respon if err := serializer.Map(r.Context(), systemNotificationRule, &out.SystemNotificationRules[i]); err != nil { log.Info(r.Context(), err) } + + out.SystemNotificationRules[i].TargetUsers = make([]domain.SimpleUserResponse, len(systemNotificationRule.TargetUsers)) + for j, targetUser := range systemNotificationRule.TargetUsers { + if err := serializer.Map(r.Context(), targetUser, &out.SystemNotificationRules[i].TargetUsers[j]); err != nil { + log.Info(r.Context(), err) + } + } + + out.SystemNotificationRules[i].SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) + for j, condition := range systemNotificationRule.SystemNotificationConditions { + if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRules[i].SystemNotificationConditions[j]); err != nil { + log.Info(r.Context(), err) + } + log.Info(r.Context(), condition.Parameter) + err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRules[i].SystemNotificationConditions[j].Parameters) + if err != nil { + log.Error(r.Context(), err) + } + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { @@ -144,6 +179,18 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons log.Info(r.Context(), err) } + out.SystemNotificationRule.SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) + for i, condition := range systemNotificationRule.SystemNotificationConditions { + if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRule.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + log.Info(r.Context(), condition.Parameter) + err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRule.SystemNotificationConditions[i].Parameters) + if err != nil { + log.Error(r.Context(), err) + } + } + ResponseJSON(w, r, http.StatusOK, out) } @@ -160,24 +207,44 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons // @Security JWT func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + strId, ok := vars["systemNotificationRuleId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) return } - systemNotificationRuleId, err := uuid.Parse(strId) if err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) return } + input := domain.UpdateSystemNotificationRuleRequest{} + err = UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + var dto model.SystemNotificationRule - if err := serializer.Map(r.Context(), r, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } + dto.OrganizationId = organizationId dto.ID = systemNotificationRuleId + dto.SystemNotificationConditions = make([]model.SystemNotificationCondition, len(input.SystemNotificationConditions)) + for i, systemNotificationCondition := range input.SystemNotificationConditions { + if err := serializer.Map(r.Context(), systemNotificationCondition, &dto.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + } + err = h.usecase.Update(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index b1ddee30..9ab63c37 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -2,40 +2,43 @@ package model import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/datatypes" "gorm.io/gorm" ) type SystemNotificationCondition struct { - SystemNotificationRuleId uuid.UUID `gorm:"primarykey"` - Order int `gorm:"primarykey"` + gorm.Model + + SystemNotificationRuleId uuid.UUID + Order int Severity string Duration int - Condition datatypes.JSON - EnableEmail bool `gorm:"default:false"` - EnablePortal bool `gorm:"default:true"` -} - -type SystemNotificationMessage struct { - SystemNotificationRuleId uuid.UUID `gorm:"primarykey"` - Title string - Content int - Condition datatypes.JSON - ActionProposal string - TargetUsers []User `gorm:"many2many:system_notification_message_users"` + Parameter datatypes.JSON + Parameters []domain.SystemNotificationParameter `gorm:"-:all"` + EnableEmail bool `gorm:"default:false"` + EnablePortal bool `gorm:"default:true"` } type SystemNotificationRule struct { gorm.Model - ID uuid.UUID `gorm:"primarykey"` - Name string `gorm:"index,unique"` - Description string - Templates []SystemNotificationTemplate `gorm:"many2many:system_notification_rule_system_notification_templates"` - Messages []SystemNotificationMessage `gorm:"many2many:system_notification_rule_system_notification_messages"` - - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator *User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator *User `gorm:"foreignKey:UpdatorId"` + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index,unique"` + Description string + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + SystemNotificationTemplate SystemNotificationTemplate `gorm:"foreignKey:SystemNotificationTemplateId"` + SystemNotificationTemplateId string + SystemNotificationConditions []SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId"` + TargetUsers []User `gorm:"many2many:system_notification_rule_users"` + TargetUserIds []string `gorm:"-:all"` + MessageTitle string + MessageContent string + MessageCondition datatypes.JSON + MessageActionProposal string + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator *User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator *User `gorm:"foreignKey:UpdatorId"` } diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 3e07db21..84ed1063 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -20,7 +20,6 @@ type ISystemNotificationRuleRepository interface { Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRuleId uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) - UpdateOrganizations(ctx context.Context, systemNotificationRuleId uuid.UUID, organizationIds []model.Organization) (err error) } type SystemNotificationRuleRepository struct { @@ -83,40 +82,48 @@ func (r *SystemNotificationRuleRepository) Create(ctx context.Context, dto model if res.Error != nil { return uuid.Nil, res.Error } + return dto.ID, nil } func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) { - res := r.db.WithContext(ctx).Model(&model.SystemNotificationRule{}). - Where("id = ?", dto.ID). - Updates(map[string]interface{}{ - "Name": dto.Name, - "Description": dto.Description, - "UpdatorId": dto.UpdatorId}) + var m model.SystemNotificationRule + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&m, "id = ?", dto.ID) if res.Error != nil { return res.Error } - return nil -} -func (r *SystemNotificationRuleRepository) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { - res := r.db.WithContext(ctx).Delete(&model.SystemNotificationRule{}, "id = ?", dto.ID) + m.Name = dto.Name + m.Description = dto.Description + m.SystemNotificationTemplateId = dto.SystemNotificationTemplateId + //m.SystemNotificationConditions = dto.SystemNotificationConditions + m.MessageTitle = dto.MessageTitle + m.MessageContent = dto.MessageContent + m.MessageCondition = dto.MessageCondition + m.MessageActionProposal = dto.MessageActionProposal + m.UpdatorId = dto.UpdatorId + + res = r.db.WithContext(ctx).Session(&gorm.Session{FullSaveAssociations: true}).Updates(&m) if res.Error != nil { return res.Error } - return nil -} -func (r *SystemNotificationRuleRepository) UpdateOrganizations(ctx context.Context, systemNotificationRuleId uuid.UUID, organizations []model.Organization) (err error) { - var systemNotificationRule = model.SystemNotificationRule{} - res := r.db.WithContext(ctx).Preload("Organizations").First(&systemNotificationRule, "id = ?", systemNotificationRuleId) - if res.Error != nil { - return res.Error + err = r.db.WithContext(ctx).Model(&m).Association("TargetUsers").Replace(dto.TargetUsers) + if err != nil { + return err } - err = r.db.WithContext(ctx).Model(&systemNotificationRule).Association("Organizations").Replace(organizations) + err = r.db.WithContext(ctx).Model(&m).Association("SystemNotificationConditions").Replace(dto.SystemNotificationConditions) if err != nil { return err } return nil } + +func (r *SystemNotificationRuleRepository) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { + res := r.db.WithContext(ctx).Delete(&model.SystemNotificationRule{}, "id = ?", dto.ID) + if res.Error != nil { + return res.Error + } + return nil +} diff --git a/internal/route/route.go b/internal/route/route.go index bb00ba3b..be0ef533 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -225,10 +225,10 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.RemoveOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.RemoveOrganizationSystemNotificationTemplates))).Methods(http.MethodPut) systemNotificationRuleHandler := delivery.NewSystemNotificationRuleHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index ff7c59d0..9fa70a56 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -35,7 +35,6 @@ type OrganizationUsecase struct { roleRepo repository.IRoleRepository clusterRepo repository.IClusterRepository stackTemplateRepo repository.IStackTemplateRepository - policyTemplateRepo repository.IPolicyTemplateRepository systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository argo argowf.ArgoClient kc keycloak.IKeycloak diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 8aa4c384..d69c5c15 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -20,19 +21,22 @@ type ISystemNotificationRuleUsecase interface { Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRule uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationRule) error Delete(ctx context.Context, dto model.SystemNotificationRule) error - UpdateOrganizations(ctx context.Context, dto model.SystemNotificationRule) error GetByName(ctx context.Context, name string) (model.SystemNotificationRule, error) } type SystemNotificationRuleUsecase struct { - repo repository.ISystemNotificationRuleRepository - organizationRepo repository.IOrganizationRepository + repo repository.ISystemNotificationRuleRepository + organizationRepo repository.IOrganizationRepository + userRepo repository.IUserRepository + systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository } func NewSystemNotificationRuleUsecase(r repository.Repository) ISystemNotificationRuleUsecase { return &SystemNotificationRuleUsecase{ - repo: r.SystemNotificationRule, - organizationRepo: r.Organization, + repo: r.SystemNotificationRule, + organizationRepo: r.Organization, + userRepo: r.User, + systemNotificationTemplateRepo: r.SystemNotificationTemplate, } } @@ -46,10 +50,34 @@ func (u *SystemNotificationRuleUsecase) Create(ctx context.Context, dto model.Sy dto.UpdatorId = &userId if _, err = u.GetByName(ctx, dto.Name); err == nil { - return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate systemNotificationRule name"), "ST_CREATE_ALREADY_EXISTED_NAME", "") + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate systemNotificationRule name"), "SNR_CREATE_ALREADY_EXISTED_NAME", "") } - return systemNotificationRuleId, nil + // Users + dto.TargetUsers = make([]model.User, 0) + for _, strId := range dto.TargetUserIds { + userId, err := uuid.Parse(strId) + if err == nil { + user, err := u.userRepo.GetByUuid(ctx, userId) + if err == nil { + dto.TargetUsers = append(dto.TargetUsers, user) + } + } + } + + // Make parameters + for i, condition := range dto.SystemNotificationConditions { + dto.SystemNotificationConditions[i].Parameter = []byte(helper.ModelToJson(condition.Parameters)) + } + + systemNotificationRuleId, err = u.repo.Create(ctx, dto) + if err != nil { + return uuid.Nil, err + } + + // [TODO] update kubernetes resources + + return } func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.SystemNotificationRule) error { @@ -58,10 +86,30 @@ func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.Sy return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") } + // Users + dto.TargetUsers = make([]model.User, 0) + for _, strId := range dto.TargetUserIds { + userId, err := uuid.Parse(strId) + if err == nil { + user, err := u.userRepo.GetByUuid(ctx, userId) + if err == nil { + dto.TargetUsers = append(dto.TargetUsers, user) + } + } + } + + for i, condition := range dto.SystemNotificationConditions { + dto.SystemNotificationConditions[i].SystemNotificationRuleId = dto.ID + dto.SystemNotificationConditions[i].Parameter = []byte(helper.ModelToJson(condition.Parameters)) + } + err = u.repo.Update(ctx, dto) if err != nil { return err } + + // [TODO] update kubernetes resources + return nil } @@ -77,7 +125,7 @@ func (u *SystemNotificationRuleUsecase) GetByName(ctx context.Context, name stri out, err = u.repo.GetByName(ctx, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return out, httpErrors.NewNotFoundError(err, "SNR_FAILED_FETCH_STACK_TEMPLATE", "") + return out, httpErrors.NewNotFoundError(err, "SNR_FAILED_FETCH_SYSTEM_NOTIFICATION_RULE", "") } return out, err } @@ -96,12 +144,3 @@ func (u *SystemNotificationRuleUsecase) Fetch(ctx context.Context, organizationI func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { return nil } - -func (u *SystemNotificationRuleUsecase) UpdateOrganizations(ctx context.Context, dto model.SystemNotificationRule) error { - _, err := u.repo.Get(ctx, dto.ID) - if err != nil { - return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") - } - - return nil -} diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index e21e3477..d891799a 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -5,13 +5,35 @@ import ( ) type SystemNotificationRuleResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Creator SimpleUserResponse `json:"creator"` - Updator SimpleUserResponse `json:"updator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle"` + MessageContent string `json:"messageContent"` + MessageCondition string `json:"messageCondition"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUsers []SimpleUserResponse `json:"targetUsers"` + SystemNotificationTemplate SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplate"` + SystemNotificationConditions []SystemNotificationConditionResponse `json:"systemNotificationConditions"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type SystemNotificationParameter struct { + Order int `json:"order"` + Operator string `json:"operator"` + Value string `json:"value"` +} + +type SystemNotificationConditionResponse struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` } type SimpleSystemNotificationRuleResponse struct { @@ -30,8 +52,22 @@ type GetSystemNotificationRuleResponse struct { } type CreateSystemNotificationRuleRequest struct { - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle" validate:"required"` + MessageContent string `json:"messageContent" validate:"required"` + MessageCondition string `json:"messageCondition" validate:"required"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUserIds []string `json:"targetUserIds"` + SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` + SystemNotificationConditions []struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` + } `json:"systemNotificationConditions"` } type CreateSystemNotificationRuleResponse struct { @@ -39,7 +75,22 @@ type CreateSystemNotificationRuleResponse struct { } type UpdateSystemNotificationRuleRequest struct { - Description string `json:"description"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle" validate:"required"` + MessageContent string `json:"messageContent" validate:"required"` + MessageCondition string `json:"messageCondition" validate:"required"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUserIds []string `json:"targetUserIds"` + SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` + SystemNotificationConditions []struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` + } `json:"systemNotificationConditions"` } type CheckSystemNotificationRuleNameResponse struct { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 5dff7467..2db07ce1 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -88,10 +88,10 @@ var errorMap = map[ErrorCode]string{ "SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.", // SystemNotificationRule - "SNR_CREATE_ALREADY_EXISTED_NAME": "알림템플릿 설정에 이미 존재하는 이름입니다.", - "SNR_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿 설정을 가져오는데 실패했습니다.", - "SNR_FAILED_UPDATE_ORGANIZATION": "알림템플릿 설정에 조직을 설정하는데 실패했습니다.", - "SNR_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿 설정이 존재하지 않습니다.", + "SNR_CREATE_ALREADY_EXISTED_NAME": "알림 설정에 이미 존재하는 이름입니다.", + "SNR_FAILED_FETCH_SYSTEM_NOTIFICATION_RULE": "알림 설정을 가져오는데 실패했습니다.", + "SNR_FAILED_UPDATE_ORGANIZATION": "알림 설정에 조직을 설정하는데 실패했습니다.", + "SNR_NOT_EXISTED_SYSTEM_NOTIFICATION_RULE": "업데이트할 알림 설정이 존재하지 않습니다.", // AppGroup "AG_NOT_FOUND_CLUSTER": "지장한 클러스터가 존재하지 않습니다.", From 9f6ec65188bf20620c3bbe3d943038717bee60c3 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 25 Mar 2024 13:44:37 +0900 Subject: [PATCH 172/502] =?UTF-8?q?Admin=20API=EB=93=A4Admin=5F=20Prefix?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/swagger/docs.go | 772 +++++++++++++++++- api/swagger/swagger.json | 772 +++++++++++++++++- api/swagger/swagger.yaml | 492 ++++++++++- internal/delivery/api/endpoint.go | 26 +- .../delivery/api/generated_endpoints.go.go | 156 ++-- internal/delivery/http/policy-template.go | 78 +- internal/middleware/audit/audit-map.go | 2 +- internal/route/route.go | 26 +- 8 files changed, 2106 insertions(+), 218 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0b44751f..e3c7dc34 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -394,7 +394,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates": { + "/admin/policy-templates": { "get": { "security": [ { @@ -495,7 +495,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "/admin/policy-templates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { @@ -526,13 +526,13 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } } }, - "/admin/policytemplates/name/{policyTemplateName}/existence": { + "/admin/policy-templates/name/{policyTemplateName}/existence": { "get": { "security": [ { @@ -569,7 +569,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}": { + "/admin/policy-templates/{policyTemplateId}": { "get": { "security": [ { @@ -679,7 +679,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/deploy": { + "/admin/policy-templates/{policyTemplateId}/deploy": { "get": { "security": [ { @@ -716,7 +716,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/statistics": { + "/admin/policy-templates/{policyTemplateId}/statistics": { "get": { "security": [ { @@ -753,7 +753,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/versions": { + "/admin/policy-templates/{policyTemplateId}/versions": { "get": { "security": [ { @@ -834,7 +834,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/versions/{version}": { + "/admin/policy-templates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { @@ -3224,6 +3224,84 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/mandatory-policies": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿, 정책이 필수 인지 여부를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[GetMandatoryPolicies] 필수 정책 템플릿, 정책을 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse" + } + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿, 정책이 필수 인지 여부를 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[SetMandatoryPolicies] 필수 정책 템플릿, 정책을 설정", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update mandatory policy/policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SetMandatoryPoliciesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/my-profile": { "get": { "security": [ @@ -3347,7 +3425,330 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Update user's password expired date to current date", + "description": "Update user's password expired date to current date", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update user's password expired date to current date", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" + } + } + } + } + }, + "/organizations/{organizationId}/my-profile/password": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user password detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update user password detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update user password request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/policies": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[ListPolicy] 정책 목록 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "새로운 정책을 생성한다. targetClusterIds가 명시되지 않으면 정책은 활성화되지 않은 상태로 생성된다. 다른 클러스터에 동일한 정책이 존재한다면 정책 생성이 아닌 정책 업데이트를 통해 targetClusterIds를 수정해야 한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[CreatePolicy] 정책 생성", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create policy request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse" + } + } + } + } + }, + "/organizations/{organizationId}/policies/name/{policyName}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 이름을 가진 정책이 이미 존재하는지 확인한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[ExistsPolicyName] 정책 아름 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 이름", + "name": "policyName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/policies/{policyId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 정보를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[GetPolicy] 정책 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "정첵을 삭제한다. 정책이 적용된 클러스터가 있으면 삭제되지 않으므로 삭제 전 적용된 클러스터가 비어있어야 한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[DeletePolicy] 정책 삭제", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책의 내용을 업데이트 한다. 업데이트할 필드만 명시하면 된다.", "consumes": [ "application/json" ], @@ -3355,39 +3756,49 @@ const docTemplate = `{ "application/json" ], "tags": [ - "My-profile" + "Policy" ], - "summary": "Update user's password expired date to current date", + "summary": "[UpdatePolicy] 정책을 업데이트", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + }, + { + "description": "update policy set request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest" + } } ], "responses": { "200": { "description": "OK" - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" - } } } } }, - "/organizations/{organizationId}/my-profile/password": { - "put": { + "/organizations/{organizationId}/policies/{policyId}/clusters": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Update user password detail", + "description": "정책 적용 대상 클러스터를 수정한다. 추가할 클러스터 목록과 제거할 클러스터 목록 중 하나만 명시되어야 한다. 현재 정책이 배포된 클러스터를 확인하지 않고도 특정 클러스터를 추가하거나 제거할 수 있는 편의 API이다.", "consumes": [ "application/json" ], @@ -3395,24 +3806,31 @@ const docTemplate = `{ "application/json" ], "tags": [ - "My-profile" + "Policy" ], - "summary": "Update user password detail", + "summary": "[UpdatePolicyTargetClusters] 정책 적용 대상 클러스터 수정", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { - "description": "update user password request", + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + }, + { + "description": "update policy set request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest" } } ], @@ -7385,7 +7803,7 @@ const docTemplate = `{ } } }, - "/policytemplates/rego-compile": { + "/policy-templates/rego-compile": { "post": { "security": [ { @@ -8693,6 +9111,63 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "enforcementAction": { + "type": "string" + }, + "mandatory": { + "type": "boolean" + }, + "match": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "refer": "match.Match" + } + }, + "parameters": { + "type": "string", + "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + }, + "policyName": { + "type": "string", + "example": "label 정책" + }, + "targetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "templateId": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse": { "type": "object", "properties": { @@ -9260,9 +9735,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse": { - "type": "object" - }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -9559,6 +10031,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse": { + "type": "object", + "properties": { + "templates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryTemplateInfo" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse": { "type": "object", "properties": { @@ -9598,6 +10081,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse": { + "type": "object", + "properties": { + "policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse": { "type": "object", "properties": { @@ -10016,6 +10507,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListPolicyResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "policies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse": { "type": "object", "properties": { @@ -10173,6 +10678,64 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo": { + "type": "object", + "properties": { + "description": { + "type": "string", + "example": "org 레이블 설정 여부 검사" + }, + "mandatory": { + "type": "boolean" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyName": { + "type": "string", + "example": "org 레이블 요구" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyPatchInfo": { + "type": "object", + "properties": { + "mandatory": { + "type": "boolean" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.MandatoryTemplateInfo": { + "type": "object", + "properties": { + "description": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "mandatory": { + "type": "boolean" + }, + "policies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo" + } + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { "type": "object", "required": [ @@ -10383,6 +10946,73 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string", + "format": "date-time" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "enforcementAction": { + "type": "string" + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "mandatory": { + "type": "boolean" + }, + "match": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "refer": "match.Match" + } + }, + "parameters": { + "type": "string", + "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + }, + "policyName": { + "type": "string", + "example": "label 정책" + }, + "targetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "templateId": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse": { "type": "object", "properties": { @@ -10889,6 +11519,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SetMandatoryPoliciesRequest": { + "type": "object", + "properties": { + "policies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyPatchInfo" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse": { "type": "object", "properties": { @@ -11676,6 +12317,75 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest": { + "type": "object", + "properties": { + "currentTargetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "newTargetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "enforcementAction": { + "type": "string" + }, + "mandatory": { + "type": "boolean" + }, + "match": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "refer": "match.Match" + } + }, + "parameters": { + "type": "string", + "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + }, + "policyName": { + "type": "string", + "example": "label 정책" + }, + "targetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "templateId": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 58f58a56..4011501e 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -388,7 +388,7 @@ } } }, - "/admin/policytemplates": { + "/admin/policy-templates": { "get": { "security": [ { @@ -489,7 +489,7 @@ } } }, - "/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "/admin/policy-templates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { @@ -520,13 +520,13 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } } }, - "/admin/policytemplates/name/{policyTemplateName}/existence": { + "/admin/policy-templates/name/{policyTemplateName}/existence": { "get": { "security": [ { @@ -563,7 +563,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}": { + "/admin/policy-templates/{policyTemplateId}": { "get": { "security": [ { @@ -673,7 +673,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/deploy": { + "/admin/policy-templates/{policyTemplateId}/deploy": { "get": { "security": [ { @@ -710,7 +710,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/statistics": { + "/admin/policy-templates/{policyTemplateId}/statistics": { "get": { "security": [ { @@ -747,7 +747,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/versions": { + "/admin/policy-templates/{policyTemplateId}/versions": { "get": { "security": [ { @@ -828,7 +828,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/versions/{version}": { + "/admin/policy-templates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { @@ -3218,6 +3218,84 @@ } } }, + "/organizations/{organizationId}/mandatory-policies": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿, 정책이 필수 인지 여부를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[GetMandatoryPolicies] 필수 정책 템플릿, 정책을 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse" + } + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿, 정책이 필수 인지 여부를 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[SetMandatoryPolicies] 필수 정책 템플릿, 정책을 설정", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update mandatory policy/policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SetMandatoryPoliciesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/my-profile": { "get": { "security": [ @@ -3341,7 +3419,330 @@ "JWT": [] } ], - "description": "Update user's password expired date to current date", + "description": "Update user's password expired date to current date", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update user's password expired date to current date", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" + } + } + } + } + }, + "/organizations/{organizationId}/my-profile/password": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user password detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "My-profile" + ], + "summary": "Update user password detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update user password request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/policies": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[ListPolicy] 정책 목록 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyResponse" + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "새로운 정책을 생성한다. targetClusterIds가 명시되지 않으면 정책은 활성화되지 않은 상태로 생성된다. 다른 클러스터에 동일한 정책이 존재한다면 정책 생성이 아닌 정책 업데이트를 통해 targetClusterIds를 수정해야 한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[CreatePolicy] 정책 생성", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create policy request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse" + } + } + } + } + }, + "/organizations/{organizationId}/policies/name/{policyName}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 이름을 가진 정책이 이미 존재하는지 확인한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[ExistsPolicyName] 정책 아름 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 이름", + "name": "policyName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/policies/{policyId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 정보를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[GetPolicy] 정책 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "정첵을 삭제한다. 정책이 적용된 클러스터가 있으면 삭제되지 않으므로 삭제 전 적용된 클러스터가 비어있어야 한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[DeletePolicy] 정책 삭제", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책의 내용을 업데이트 한다. 업데이트할 필드만 명시하면 된다.", "consumes": [ "application/json" ], @@ -3349,39 +3750,49 @@ "application/json" ], "tags": [ - "My-profile" + "Policy" ], - "summary": "Update user's password expired date to current date", + "summary": "[UpdatePolicy] 정책을 업데이트", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + }, + { + "description": "update policy set request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest" + } } ], "responses": { "200": { "description": "OK" - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_httpErrors.RestError" - } } } } }, - "/organizations/{organizationId}/my-profile/password": { - "put": { + "/organizations/{organizationId}/policies/{policyId}/clusters": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Update user password detail", + "description": "정책 적용 대상 클러스터를 수정한다. 추가할 클러스터 목록과 제거할 클러스터 목록 중 하나만 명시되어야 한다. 현재 정책이 배포된 클러스터를 확인하지 않고도 특정 클러스터를 추가하거나 제거할 수 있는 편의 API이다.", "consumes": [ "application/json" ], @@ -3389,24 +3800,31 @@ "application/json" ], "tags": [ - "My-profile" + "Policy" ], - "summary": "Update user password detail", + "summary": "[UpdatePolicyTargetClusters] 정책 적용 대상 클러스터 수정", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { - "description": "update user password request", + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + }, + { + "description": "update policy set request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest" } } ], @@ -7379,7 +7797,7 @@ } } }, - "/policytemplates/rego-compile": { + "/policy-templates/rego-compile": { "post": { "security": [ { @@ -8687,6 +9105,63 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "enforcementAction": { + "type": "string" + }, + "mandatory": { + "type": "boolean" + }, + "match": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "refer": "match.Match" + } + }, + "parameters": { + "type": "string", + "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + }, + "policyName": { + "type": "string", + "example": "label 정책" + }, + "targetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "templateId": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse": { "type": "object", "properties": { @@ -9254,9 +9729,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse": { - "type": "object" - }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -9553,6 +10025,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse": { + "type": "object", + "properties": { + "templates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryTemplateInfo" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse": { "type": "object", "properties": { @@ -9592,6 +10075,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse": { + "type": "object", + "properties": { + "policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse": { "type": "object", "properties": { @@ -10010,6 +10501,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListPolicyResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "policies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse": { "type": "object", "properties": { @@ -10167,6 +10672,64 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo": { + "type": "object", + "properties": { + "description": { + "type": "string", + "example": "org 레이블 설정 여부 검사" + }, + "mandatory": { + "type": "boolean" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyName": { + "type": "string", + "example": "org 레이블 요구" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyPatchInfo": { + "type": "object", + "properties": { + "mandatory": { + "type": "boolean" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.MandatoryTemplateInfo": { + "type": "object", + "properties": { + "description": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "mandatory": { + "type": "boolean" + }, + "policies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo" + } + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { "type": "object", "required": [ @@ -10377,6 +10940,73 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string", + "format": "date-time" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "description": { + "type": "string" + }, + "enforcementAction": { + "type": "string" + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "mandatory": { + "type": "boolean" + }, + "match": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "refer": "match.Match" + } + }, + "parameters": { + "type": "string", + "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + }, + "policyName": { + "type": "string", + "example": "label 정책" + }, + "targetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "templateId": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse": { "type": "object", "properties": { @@ -10883,6 +11513,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SetMandatoryPoliciesRequest": { + "type": "object", + "properties": { + "policies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyPatchInfo" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse": { "type": "object", "properties": { @@ -11670,6 +12311,75 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest": { + "type": "object", + "properties": { + "currentTargetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "newTargetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "enforcementAction": { + "type": "string" + }, + "mandatory": { + "type": "boolean" + }, + "match": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "refer": "match.Match" + } + }, + "parameters": { + "type": "string", + "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + }, + "policyName": { + "type": "string", + "example": "label 정책" + }, + "targetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "templateId": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 71ac2318..3950feae 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -846,6 +846,45 @@ definitions: - adminEmail - name type: object + github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest: + properties: + description: + type: string + enforcementAction: + type: string + mandatory: + type: boolean + match: + additionalProperties: + type: string + example: + refer: match.Match + type: object + parameters: + example: '"labels":{"key":"owner","allowedRegex:^[a-zA-Z]+.agilebank.demo$}"' + type: string + policyName: + example: label 정책 + type: string + targetClusterIds: + example: + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + items: + type: string + type: array + templateId: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + templateName: + example: 필수 Label 검사 + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse: + properties: + id: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse: properties: id: @@ -1232,8 +1271,6 @@ definitions: updatedAt: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse: - type: object github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: column: @@ -1426,6 +1463,13 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse: + properties: + templates: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryTemplateInfo' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetMyProfileResponse: properties: user: @@ -1451,6 +1495,11 @@ definitions: organization: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse: + properties: + policy: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse: properties: deployVersion: @@ -1719,6 +1768,15 @@ definitions: pagination: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.ListPolicyResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + policies: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse: properties: pagination: @@ -1822,6 +1880,46 @@ definitions: type: array type: object type: object + github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo: + properties: + description: + example: org 레이블 설정 여부 검사 + type: string + mandatory: + type: boolean + policyId: + example: 0091fe9b-e44b-423d-9562-ac2b73089593 + type: string + policyName: + example: org 레이블 요구 + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyPatchInfo: + properties: + mandatory: + type: boolean + policyId: + example: 0091fe9b-e44b-423d-9562-ac2b73089593 + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.MandatoryTemplateInfo: + properties: + description: + example: 파라미터로 설정된 레이블 검사 + type: string + mandatory: + type: boolean + policies: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo' + type: array + templateId: + example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 + type: string + templateName: + example: 레이블 요구 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse: properties: key: @@ -1960,6 +2058,53 @@ definitions: value: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyResponse: + properties: + createdAt: + format: date-time + type: string + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + description: + type: string + enforcementAction: + type: string + id: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + mandatory: + type: boolean + match: + additionalProperties: + type: string + example: + refer: match.Match + type: object + parameters: + example: '"labels":{"key":"owner","allowedRegex:^[a-zA-Z]+.agilebank.demo$}"' + type: string + policyName: + example: label 정책 + type: string + targetClusterIds: + example: + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + items: + type: string + type: array + templateId: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + templateName: + example: 필수 Label 검사 + type: string + updatedAt: + format: date-time + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse: properties: createdAt: @@ -2300,6 +2445,13 @@ definitions: taskId: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SetMandatoryPoliciesRequest: + properties: + policies: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyPatchInfo' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse: properties: awsAccountId: @@ -2822,6 +2974,53 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest: + properties: + currentTargetClusterIds: + example: + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + items: + type: string + type: array + newTargetClusterIds: + example: + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + items: + type: string + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest: + properties: + description: + type: string + enforcementAction: + type: string + mandatory: + type: boolean + match: + additionalProperties: + type: string + example: + refer: match.Match + type: object + parameters: + example: '"labels":{"key":"owner","allowedRegex:^[a-zA-Z]+.agilebank.demo$}"' + type: string + policyName: + example: label 정책 + type: string + targetClusterIds: + example: + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + items: + type: string + type: array + templateId: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest: properties: deprecated: @@ -3397,7 +3596,7 @@ paths: summary: Update user by admin tags: - Admin - /admin/policytemplates: + /admin/policy-templates: get: consumes: - application/json @@ -3461,7 +3660,7 @@ paths: summary: '[CreatePolicyTemplate] 정책 템플릿 신규 생성' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}: + /admin/policy-templates/{policyTemplateId}: delete: consumes: - application/json @@ -3530,7 +3729,7 @@ paths: summary: '[UpdatePolicyTemplate] 정책 템플릿 업데이트' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/deploy: + /admin/policy-templates/{policyTemplateId}/deploy: get: consumes: - application/json @@ -3553,7 +3752,7 @@ paths: summary: '[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/statistics: + /admin/policy-templates/{policyTemplateId}/statistics: get: consumes: - application/json @@ -3577,7 +3776,7 @@ paths: summary: '[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/versions: + /admin/policy-templates/{policyTemplateId}/versions: get: consumes: - application/json @@ -3628,7 +3827,7 @@ paths: summary: '[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/versions/{version}: + /admin/policy-templates/{policyTemplateId}/versions/{version}: delete: consumes: - application/json @@ -3681,7 +3880,7 @@ paths: summary: '[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' tags: - PolicyTemplate - /admin/policytemplates/kind/{policyTemplateKind}/existence: + /admin/policy-templates/kind/{policyTemplateKind}/existence: get: consumes: - application/json @@ -3698,13 +3897,13 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' security: - JWT: [] summary: '[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인' tags: - PolicyTemplate - /admin/policytemplates/name/{policyTemplateName}/existence: + /admin/policy-templates/name/{policyTemplateName}/existence: get: consumes: - application/json @@ -5171,6 +5370,55 @@ paths: summary: Update dashboard tags: - Dashboards + /organizations/{organizationId}/mandatory-policies: + get: + consumes: + - application/json + description: 템플릿, 정책이 필수 인지 여부를 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse' + security: + - JWT: [] + summary: '[GetMandatoryPolicies] 필수 정책 템플릿, 정책을 조회' + tags: + - Policy + patch: + consumes: + - application/json + description: 템플릿, 정책이 필수 인지 여부를 설정한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: update mandatory policy/policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SetMandatoryPoliciesRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[SetMandatoryPolicies] 필수 정책 템플릿, 정책을 설정' + tags: + - Policy /organizations/{organizationId}/my-profile: delete: consumes: @@ -5296,6 +5544,226 @@ paths: summary: Update user password detail tags: - My-profile + /organizations/{organizationId}/policies: + get: + consumes: + - application/json + description: 정책 목록을 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyResponse' + security: + - JWT: [] + summary: '[ListPolicy] 정책 목록 조회' + tags: + - Policy + post: + consumes: + - application/json + description: 새로운 정책을 생성한다. targetClusterIds가 명시되지 않으면 정책은 활성화되지 않은 상태로 생성된다. + 다른 클러스터에 동일한 정책이 존재한다면 정책 생성이 아닌 정책 업데이트를 통해 targetClusterIds를 수정해야 한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: create policy request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse' + security: + - JWT: [] + summary: '[CreatePolicy] 정책 생성' + tags: + - Policy + /organizations/{organizationId}/policies/{policyId}: + delete: + consumes: + - application/json + description: 정첵을 삭제한다. 정책이 적용된 클러스터가 있으면 삭제되지 않으므로 삭제 전 적용된 클러스터가 비어있어야 한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 식별자(uuid) + in: path + name: policyId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[DeletePolicy] 정책 삭제' + tags: + - Policy + get: + consumes: + - application/json + description: 정책 정보를 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 식별자(uuid) + in: path + name: policyId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse' + security: + - JWT: [] + summary: '[GetPolicy] 정책 조회' + tags: + - Policy + patch: + consumes: + - application/json + description: 정책의 내용을 업데이트 한다. 업데이트할 필드만 명시하면 된다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 식별자(uuid) + in: path + name: policyId + required: true + type: string + - description: update policy set request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[UpdatePolicy] 정책을 업데이트' + tags: + - Policy + /organizations/{organizationId}/policies/{policyId}/clusters: + patch: + consumes: + - application/json + description: 정책 적용 대상 클러스터를 수정한다. 추가할 클러스터 목록과 제거할 클러스터 목록 중 하나만 명시되어야 한다. 현재 + 정책이 배포된 클러스터를 확인하지 않고도 특정 클러스터를 추가하거나 제거할 수 있는 편의 API이다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 식별자(uuid) + in: path + name: policyId + required: true + type: string + - description: update policy set request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[UpdatePolicyTargetClusters] 정책 적용 대상 클러스터 수정' + tags: + - Policy + /organizations/{organizationId}/policies/name/{policyName}/existence: + get: + consumes: + - application/json + description: 해당 이름을 가진 정책이 이미 존재하는지 확인한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 이름 + in: path + name: policyName + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' + security: + - JWT: [] + summary: '[ExistsPolicyName] 정책 아름 존재 여부 확인' + tags: + - Policy /organizations/{organizationId}/primary-cluster: patch: consumes: @@ -7860,7 +8328,7 @@ paths: summary: Get Permission Templates tags: - Permission - /policytemplates/rego-compile: + /policy-templates/rego-compile: post: consumes: - application/json diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2364a2ea..e07171e6 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -211,19 +211,19 @@ const ( Admin_GetProjects // PolicyTemplate - ListPolicyTemplate - CreatePolicyTemplate - DeletePolicyTemplate - GetPolicyTemplate - UpdatePolicyTemplate - GetPolicyTemplateDeploy - ListPolicyTemplateStatistics - ListPolicyTemplateVersions - CreatePolicyTemplateVersion - DeletePolicyTemplateVersion - GetPolicyTemplateVersion - ExistsPolicyTemplateKind - ExistsPolicyTemplateName + Admin_ListPolicyTemplate + Admin_CreatePolicyTemplate + Admin_DeletePolicyTemplate + Admin_GetPolicyTemplate + Admin_UpdatePolicyTemplate + Admin_GetPolicyTemplateDeploy + Admin_ListPolicyTemplateStatistics + Admin_ListPolicyTemplateVersions + Admin_CreatePolicyTemplateVersion + Admin_DeletePolicyTemplateVersion + Admin_GetPolicyTemplateVersion + Admin_ExistsPolicyTemplateKind + Admin_ExistsPolicyTemplateName // ClusterPolicyStatus ListClusterPolicyStatus diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 891ac188..ee43f07f 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -635,56 +635,56 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_GetProjects", Group: "Admin Project", }, - ListPolicyTemplate: { - Name: "ListPolicyTemplate", + Admin_ListPolicyTemplate: { + Name: "Admin_ListPolicyTemplate", Group: "PolicyTemplate", }, - CreatePolicyTemplate: { - Name: "CreatePolicyTemplate", + Admin_CreatePolicyTemplate: { + Name: "Admin_CreatePolicyTemplate", Group: "PolicyTemplate", }, - DeletePolicyTemplate: { - Name: "DeletePolicyTemplate", + Admin_DeletePolicyTemplate: { + Name: "Admin_DeletePolicyTemplate", Group: "PolicyTemplate", }, - GetPolicyTemplate: { - Name: "GetPolicyTemplate", + Admin_GetPolicyTemplate: { + Name: "Admin_GetPolicyTemplate", Group: "PolicyTemplate", }, - UpdatePolicyTemplate: { - Name: "UpdatePolicyTemplate", + Admin_UpdatePolicyTemplate: { + Name: "Admin_UpdatePolicyTemplate", Group: "PolicyTemplate", }, - GetPolicyTemplateDeploy: { - Name: "GetPolicyTemplateDeploy", + Admin_GetPolicyTemplateDeploy: { + Name: "Admin_GetPolicyTemplateDeploy", Group: "PolicyTemplate", }, - ListPolicyTemplateStatistics: { - Name: "ListPolicyTemplateStatistics", + Admin_ListPolicyTemplateStatistics: { + Name: "Admin_ListPolicyTemplateStatistics", Group: "PolicyTemplate", }, - ListPolicyTemplateVersions: { - Name: "ListPolicyTemplateVersions", + Admin_ListPolicyTemplateVersions: { + Name: "Admin_ListPolicyTemplateVersions", Group: "PolicyTemplate", }, - CreatePolicyTemplateVersion: { - Name: "CreatePolicyTemplateVersion", + Admin_CreatePolicyTemplateVersion: { + Name: "Admin_CreatePolicyTemplateVersion", Group: "PolicyTemplate", }, - DeletePolicyTemplateVersion: { - Name: "DeletePolicyTemplateVersion", + Admin_DeletePolicyTemplateVersion: { + Name: "Admin_DeletePolicyTemplateVersion", Group: "PolicyTemplate", }, - GetPolicyTemplateVersion: { - Name: "GetPolicyTemplateVersion", + Admin_GetPolicyTemplateVersion: { + Name: "Admin_GetPolicyTemplateVersion", Group: "PolicyTemplate", }, - ExistsPolicyTemplateKind: { - Name: "ExistsPolicyTemplateKind", + Admin_ExistsPolicyTemplateKind: { + Name: "Admin_ExistsPolicyTemplateKind", Group: "PolicyTemplate", }, - ExistsPolicyTemplateName: { - Name: "ExistsPolicyTemplateName", + Admin_ExistsPolicyTemplateName: { + Name: "Admin_ExistsPolicyTemplateName", Group: "PolicyTemplate", }, ListClusterPolicyStatus: { @@ -1126,32 +1126,32 @@ func (e Endpoint) String() string { return "Admin_GetTksRole" case Admin_GetProjects: return "Admin_GetProjects" - case ListPolicyTemplate: - return "ListPolicyTemplate" - case CreatePolicyTemplate: - return "CreatePolicyTemplate" - case DeletePolicyTemplate: - return "DeletePolicyTemplate" - case GetPolicyTemplate: - return "GetPolicyTemplate" - case UpdatePolicyTemplate: - return "UpdatePolicyTemplate" - case GetPolicyTemplateDeploy: - return "GetPolicyTemplateDeploy" - case ListPolicyTemplateStatistics: - return "ListPolicyTemplateStatistics" - case ListPolicyTemplateVersions: - return "ListPolicyTemplateVersions" - case CreatePolicyTemplateVersion: - return "CreatePolicyTemplateVersion" - case DeletePolicyTemplateVersion: - return "DeletePolicyTemplateVersion" - case GetPolicyTemplateVersion: - return "GetPolicyTemplateVersion" - case ExistsPolicyTemplateKind: - return "ExistsPolicyTemplateKind" - case ExistsPolicyTemplateName: - return "ExistsPolicyTemplateName" + case Admin_ListPolicyTemplate: + return "Admin_ListPolicyTemplate" + case Admin_CreatePolicyTemplate: + return "Admin_CreatePolicyTemplate" + case Admin_DeletePolicyTemplate: + return "Admin_DeletePolicyTemplate" + case Admin_GetPolicyTemplate: + return "Admin_GetPolicyTemplate" + case Admin_UpdatePolicyTemplate: + return "Admin_UpdatePolicyTemplate" + case Admin_GetPolicyTemplateDeploy: + return "Admin_GetPolicyTemplateDeploy" + case Admin_ListPolicyTemplateStatistics: + return "Admin_ListPolicyTemplateStatistics" + case Admin_ListPolicyTemplateVersions: + return "Admin_ListPolicyTemplateVersions" + case Admin_CreatePolicyTemplateVersion: + return "Admin_CreatePolicyTemplateVersion" + case Admin_DeletePolicyTemplateVersion: + return "Admin_DeletePolicyTemplateVersion" + case Admin_GetPolicyTemplateVersion: + return "Admin_GetPolicyTemplateVersion" + case Admin_ExistsPolicyTemplateKind: + return "Admin_ExistsPolicyTemplateKind" + case Admin_ExistsPolicyTemplateName: + return "Admin_ExistsPolicyTemplateName" case ListClusterPolicyStatus: return "ListClusterPolicyStatus" case GetClusterPolicyTemplateStatus: @@ -1534,32 +1534,32 @@ func GetEndpoint(name string) Endpoint { return Admin_GetTksRole case "Admin_GetProjects": return Admin_GetProjects - case "ListPolicyTemplate": - return ListPolicyTemplate - case "CreatePolicyTemplate": - return CreatePolicyTemplate - case "DeletePolicyTemplate": - return DeletePolicyTemplate - case "GetPolicyTemplate": - return GetPolicyTemplate - case "UpdatePolicyTemplate": - return UpdatePolicyTemplate - case "GetPolicyTemplateDeploy": - return GetPolicyTemplateDeploy - case "ListPolicyTemplateStatistics": - return ListPolicyTemplateStatistics - case "ListPolicyTemplateVersions": - return ListPolicyTemplateVersions - case "CreatePolicyTemplateVersion": - return CreatePolicyTemplateVersion - case "DeletePolicyTemplateVersion": - return DeletePolicyTemplateVersion - case "GetPolicyTemplateVersion": - return GetPolicyTemplateVersion - case "ExistsPolicyTemplateKind": - return ExistsPolicyTemplateKind - case "ExistsPolicyTemplateName": - return ExistsPolicyTemplateName + case "Admin_ListPolicyTemplate": + return Admin_ListPolicyTemplate + case "Admin_CreatePolicyTemplate": + return Admin_CreatePolicyTemplate + case "Admin_DeletePolicyTemplate": + return Admin_DeletePolicyTemplate + case "Admin_GetPolicyTemplate": + return Admin_GetPolicyTemplate + case "Admin_UpdatePolicyTemplate": + return Admin_UpdatePolicyTemplate + case "Admin_GetPolicyTemplateDeploy": + return Admin_GetPolicyTemplateDeploy + case "Admin_ListPolicyTemplateStatistics": + return Admin_ListPolicyTemplateStatistics + case "Admin_ListPolicyTemplateVersions": + return Admin_ListPolicyTemplateVersions + case "Admin_CreatePolicyTemplateVersion": + return Admin_CreatePolicyTemplateVersion + case "Admin_DeletePolicyTemplateVersion": + return Admin_DeletePolicyTemplateVersion + case "Admin_GetPolicyTemplateVersion": + return Admin_GetPolicyTemplateVersion + case "Admin_ExistsPolicyTemplateKind": + return Admin_ExistsPolicyTemplateKind + case "Admin_ExistsPolicyTemplateName": + return Admin_ExistsPolicyTemplateName case "ListClusterPolicyStatus": return ListClusterPolicyStatus case "GetClusterPolicyTemplateStatus": diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 27bb93ce..bc66d83b 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -24,19 +24,19 @@ type PolicyTemplateHandler struct { } type IPolicyTemplateHandler interface { - CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) - UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) - DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) - GetPolicyTemplate(w http.ResponseWriter, r *http.Request) - ListPolicyTemplate(w http.ResponseWriter, r *http.Request) - ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) - ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) - ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) - GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) - CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) - GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) - DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) - ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) + Admin_CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) + Admin_UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) + Admin_DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) + Admin_GetPolicyTemplate(w http.ResponseWriter, r *http.Request) + Admin_ListPolicyTemplate(w http.ResponseWriter, r *http.Request) + Admin_ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) + Admin_ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) + Admin_ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) + Admin_GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) + Admin_CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + Admin_GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + Admin_DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + Admin_ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) RegoCompile(w http.ResponseWriter, r *http.Request) } @@ -46,7 +46,7 @@ func NewPolicyTemplateHandler(u usecase.Usecase) IPolicyTemplateHandler { } } -// CreatePolicyTemplate godoc +// Admin_CreatePolicyTemplate godoc // // @Tags PolicyTemplate // @Summary [CreatePolicyTemplate] 정책 템플릿 신규 생성 @@ -57,7 +57,7 @@ func NewPolicyTemplateHandler(u usecase.Usecase) IPolicyTemplateHandler { // @Success 200 {object} domain.CreatePolicyTemplateReponse // @Router /admin/policy-templates [post] // @Security JWT -func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) { input := domain.CreatePolicyTemplateRequest{} err := UnmarshalRequestInput(r, &input) @@ -84,7 +84,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h ResponseJSON(w, r, http.StatusOK, out) } -// UpdatePolicyTemplate godoc +// Admin_UpdatePolicyTemplate godoc // // @Tags PolicyTemplate // @Summary [UpdatePolicyTemplate] 정책 템플릿 업데이트 @@ -96,7 +96,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h // @Success 200 {object} nil // @Router /admin/policy-templates/{policyTemplateId} [patch] // @Security JWT -func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { @@ -137,7 +137,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h ResponseJSON(w, r, http.StatusOK, nil) } -// DeletePolicyTemplate godoc +// Admin_DeletePolicyTemplate godoc // // @Tags PolicyTemplate // @Summary [DeletePolicyTemplate] 정책 템플릿 삭제 @@ -148,7 +148,7 @@ func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *h // @Success 200 {object} nil // @Router /admin/policy-templates/{policyTemplateId} [delete] // @Security JWT -func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { @@ -184,7 +184,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *h ResponseJSON(w, r, http.StatusOK, "") } -// GetPolicyTemplate godoc +// Admin_GetPolicyTemplate godoc // // @Tags PolicyTemplate // @Summary [GetPolicyTemplate] 정책 템플릿 조회(최신 버전) @@ -195,7 +195,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *h // @Success 200 {object} domain.GetPolicyTemplateResponse // @Router /admin/policy-templates/{policyTemplateId} [get] // @Security JWT -func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_GetPolicyTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { @@ -244,7 +244,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http ResponseJSON(w, r, http.StatusOK, out) } -// ListPolicyTemplate godoc +// Admin_ListPolicyTemplate godoc // // @Tags PolicyTemplate // @Summary [ListPolicyTemplate] 정책 템플릿 목록 조회 @@ -259,7 +259,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http // @Success 200 {object} domain.ListPolicyTemplateResponse // @Router /admin/policy-templates [get] // @Security JWT -func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_ListPolicyTemplate(w http.ResponseWriter, r *http.Request) { urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) @@ -290,7 +290,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt ResponseJSON(w, r, http.StatusOK, out) } -// ListPolicyTemplateVersions godoc +// Admin_ListPolicyTemplateVersions godoc // // @Tags PolicyTemplate // @Summary [ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회 @@ -301,7 +301,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt // @Success 200 {object} domain.ListPolicyTemplateVersionsResponse // @Router /admin/policy-templates/{policyTemplateId}/versions [get] // @Security JWT -func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] @@ -338,7 +338,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter ResponseJSON(w, r, http.StatusOK, out) } -// ListPolicyTemplateStatistics godoc +// Admin_ListPolicyTemplateStatistics godoc // // @Tags PolicyTemplate // @Summary [ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회 @@ -349,7 +349,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter // @Success 200 {object} domain.ListPolicyTemplateStatisticsResponse // @Router /admin/policy-templates/{policyTemplateId}/statistics [get] // @Security JWT -func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { // result := domain.ListPolicyTemplateStatisticsResponse{ // PolicyTemplateStatistics: []domain.PolicyTemplateStatistics{ // { @@ -367,7 +367,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWrit // util.JsonResponse(w, result) } -// GetPolicyTemplateDeploy godoc +// Admin_GetPolicyTemplateDeploy godoc // // @Tags PolicyTemplate // @Summary [GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회 @@ -378,7 +378,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWrit // @Success 200 {object} domain.GetPolicyTemplateDeployResponse // @Router /admin/policy-templates/{policyTemplateId}/deploy [get] // @Security JWT -func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { // c1 := util.UUIDGen() // c2 := util.UUIDGen() // c3 := util.UUIDGen() @@ -393,7 +393,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r // util.JsonResponse(w, result) } -// GetPolicyTemplateVersion godoc +// Admin_GetPolicyTemplateVersion godoc // // @Tags PolicyTemplate // @Summary [GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회 @@ -405,7 +405,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r // @Success 200 {object} domain.GetPolicyTemplateVersionResponse // @Router /admin/policy-templates/{policyTemplateId}/versions/{version} [get] // @Security JWT -func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { @@ -450,7 +450,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, ResponseJSON(w, r, http.StatusOK, out) } -// CreatePolicyTemplateVersion godoc +// Admin_CreatePolicyTemplateVersion godoc // // @Tags PolicyTemplate // @Summary [CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장 @@ -462,7 +462,7 @@ func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, // @Success 200 {object} domain.CreatePolicyTemplateVersionResponse // @Router /admin/policy-templates/{policyTemplateId}/versions [post] // @Security JWT -func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { @@ -526,7 +526,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite ResponseJSON(w, r, http.StatusOK, out) } -// DeletePolicyTemplateVersion godoc +// Admin_DeletePolicyTemplateVersion godoc // // @Tags PolicyTemplate // @Summary [DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제 @@ -538,7 +538,7 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite // @Success 200 {object} nil // @Router /admin/policy-templates/{policyTemplateId}/versions/{version} [delete] // @Security JWT -func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateId, ok := vars["policyTemplateId"] if !ok { @@ -575,7 +575,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite ResponseJSON(w, r, http.StatusOK, "") } -// ExistsPolicyTemplateName godoc +// Admin_ExistsPolicyTemplateName godoc // // @Tags PolicyTemplate // @Summary [ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인 @@ -586,7 +586,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite // @Success 200 {object} domain.CheckExistedResponse // @Router /admin/policy-templates/name/{policyTemplateName}/existence [get] // @Security JWT -func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateName, ok := vars["policyTemplateName"] if !ok { @@ -607,7 +607,7 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, ResponseJSON(w, r, http.StatusOK, out) } -// ExistsPolicyTemplateKind godoc +// Admin_ExistsPolicyTemplateKind godoc // // @Tags PolicyTemplate // @Summary [ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인 @@ -618,7 +618,7 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, // @Success 200 {object} domain.CheckExistedResponse // @Router /admin/policy-templates/kind/{policyTemplateKind}/existence [get] // @Security JWT -func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) { +func (h *PolicyTemplateHandler) Admin_ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) policyTemplateKind, ok := vars["policyTemplateKind"] if !ok { diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index d7c70439..9029b11b 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -116,7 +116,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreatePolicyTemplate: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreatePolicyTemplate: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreatePolicyTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) diff --git a/internal/route/route.go b/internal/route/route.go index 8c73bb75..1bd7beb8 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -295,19 +295,19 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplate))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.DeletePolicyTemplate, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplate))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetPolicyTemplate, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplate))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.UpdatePolicyTemplate))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/deploy ", customMiddleware.Handle(internalApi.GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateDeploy))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/statistics", customMiddleware.Handle(internalApi.ListPolicyTemplateStatistics, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateStatistics))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.ListPolicyTemplateVersions, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateVersions))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplateVersion))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.DeletePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplateVersion))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateVersion))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateKind))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.Admin_CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_CreatePolicyTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.Admin_DeletePolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_DeletePolicyTemplate))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.Admin_GetPolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_GetPolicyTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_UpdatePolicyTemplate))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/deploy ", customMiddleware.Handle(internalApi.Admin_GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.Admin_GetPolicyTemplateDeploy))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/statistics", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplateStatistics, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplateStatistics))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplateVersions, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplateVersions))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.Admin_CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.Admin_CreatePolicyTemplateVersion))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.Admin_DeletePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.Admin_DeletePolicyTemplateVersion))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.Admin_GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.Admin_GetPolicyTemplateVersion))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.Admin_ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.Admin_ExistsPolicyTemplateKind))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.Admin_ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.Admin_ExistsPolicyTemplateName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/policy-templates/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(policyTemplateHandler.RegoCompile))).Methods(http.MethodPost) policyHandler := delivery.NewPolicyHandler(usecaseFactory) From 699ceffcdf747822560fa20ae0e0a9ba255a0eea Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 25 Mar 2024 14:41:03 +0900 Subject: [PATCH 173/502] fix api docs --- api/swagger/docs.go | 193 +++++++++++++++--- api/swagger/swagger.json | 193 +++++++++++++++--- api/swagger/swagger.yaml | 137 ++++++++++--- go.mod | 2 +- go.sum | 6 +- internal/delivery/api/endpoint.go | 6 +- .../delivery/api/generated_endpoints.go.go | 32 +-- internal/delivery/http/permission.go | 189 ----------------- internal/delivery/http/role.go | 127 +++++++++++- internal/delivery/http/user.go | 104 +++++++++- internal/route/route.go | 6 +- 11 files changed, 665 insertions(+), 330 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index b7ccdc0d..c4b07133 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -246,7 +246,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Admin List Tks Roles", "parameters": [ @@ -275,7 +275,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Admin Get Tks Role", "parameters": [ @@ -314,7 +314,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Admin" + "Users" ], "summary": "Get user detail by admin", "parameters": [ @@ -356,7 +356,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Admin" + "Users" ], "summary": "Update user by admin", "parameters": [ @@ -5508,7 +5508,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "List Tks Roles", "parameters": [ @@ -5543,7 +5543,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Create Tks Role", "parameters": [ @@ -5586,7 +5586,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Get Tks Role", "parameters": [ @@ -5628,7 +5628,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Update Tks Role", "parameters": [ @@ -5673,7 +5673,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Delete Tks Role", "parameters": [ @@ -5707,16 +5707,29 @@ const docTemplate = `{ } ], "description": "Get Permissions By Role ID", - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], "tags": [ - "Permission" + "Roles" ], "summary": "Get Permissions By Role ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -5740,10 +5753,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Permission" + "Roles" ], "summary": "Update Permissions By Role ID", "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "Role ID", @@ -7316,6 +7336,47 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/users/{accountId}/permissions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permissions By Account ID", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get Permissions By Account ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse" + } + } + } + } + }, "/organizations/{organizationId}/users/{accountId}/reset-password": { "put": { "security": [ @@ -9300,17 +9361,11 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" - }, "group": { "type": "string" }, "name": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, @@ -10014,6 +10069,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse": { + "type": "object", + "properties": { + "permissions": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest": { "type": "object", "required": [ @@ -10203,8 +10266,14 @@ const docTemplate = `{ "passwordExpired": { "type": "boolean" }, + "projects": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse" + } + }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse" }, "token": { "type": "string" @@ -10227,6 +10296,46 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } + }, + "is_allowed": { + "type": "boolean" + }, + "key": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse": { + "type": "object", + "properties": { + "configuration": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "dashboard": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "notification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "project_management": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "stack": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { "type": "object", "required": [ @@ -10372,19 +10481,10 @@ const docTemplate = `{ "is_allowed": { "type": "boolean" }, - "name": { - "type": "string" - }, - "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "parent_id": { + "key": { "type": "string" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "role_id": { + "name": { "type": "string" } } @@ -10401,10 +10501,10 @@ const docTemplate = `{ "notification": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, - "project_management": { + "policy": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, - "security_policy": { + "project_management": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "stack": { @@ -10576,6 +10676,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + }, + "projectRoleName": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest": { "type": "object", "required": [ @@ -10903,6 +11017,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse": { + "type": "object", + "properties": { + "roleId": { + "type": "string" + }, + "roleName": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 6a9be303..d2f02ba9 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -240,7 +240,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Admin List Tks Roles", "parameters": [ @@ -269,7 +269,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Admin Get Tks Role", "parameters": [ @@ -308,7 +308,7 @@ "application/json" ], "tags": [ - "Admin" + "Users" ], "summary": "Get user detail by admin", "parameters": [ @@ -350,7 +350,7 @@ "application/json" ], "tags": [ - "Admin" + "Users" ], "summary": "Update user by admin", "parameters": [ @@ -5502,7 +5502,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "List Tks Roles", "parameters": [ @@ -5537,7 +5537,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Create Tks Role", "parameters": [ @@ -5580,7 +5580,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Get Tks Role", "parameters": [ @@ -5622,7 +5622,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Update Tks Role", "parameters": [ @@ -5667,7 +5667,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Delete Tks Role", "parameters": [ @@ -5701,16 +5701,29 @@ } ], "description": "Get Permissions By Role ID", - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], "tags": [ - "Permission" + "Roles" ], "summary": "Get Permissions By Role ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -5734,10 +5747,17 @@ "application/json" ], "tags": [ - "Permission" + "Roles" ], "summary": "Update Permissions By Role ID", "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "Role ID", @@ -7310,6 +7330,47 @@ } } }, + "/organizations/{organizationId}/users/{accountId}/permissions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permissions By Account ID", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get Permissions By Account ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse" + } + } + } + } + }, "/organizations/{organizationId}/users/{accountId}/reset-password": { "put": { "security": [ @@ -9294,17 +9355,11 @@ "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" - }, "group": { "type": "string" }, "name": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, @@ -10008,6 +10063,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse": { + "type": "object", + "properties": { + "permissions": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest": { "type": "object", "required": [ @@ -10197,8 +10260,14 @@ "passwordExpired": { "type": "boolean" }, + "projects": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse" + } + }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse" }, "token": { "type": "string" @@ -10221,6 +10290,46 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } + }, + "is_allowed": { + "type": "boolean" + }, + "key": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse": { + "type": "object", + "properties": { + "configuration": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "dashboard": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "notification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "project_management": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "stack": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { "type": "object", "required": [ @@ -10366,19 +10475,10 @@ "is_allowed": { "type": "boolean" }, - "name": { - "type": "string" - }, - "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "parent_id": { + "key": { "type": "string" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "role_id": { + "name": { "type": "string" } } @@ -10395,10 +10495,10 @@ "notification": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, - "project_management": { + "policy": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, - "security_policy": { + "project_management": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "stack": { @@ -10570,6 +10670,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + }, + "projectRoleName": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest": { "type": "object", "required": [ @@ -10897,6 +11011,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse": { + "type": "object", + "properties": { + "roleId": { + "type": "string" + }, + "roleName": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 1dc24bd5..60fd3f67 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1260,14 +1260,10 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.EndpointResponse: properties: - createdAt: - type: string group: type: string name: type: string - updatedAt: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse: type: object @@ -1719,6 +1715,11 @@ definitions: type: string type: object type: object + github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse: + properties: + permissions: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest: properties: cloudService: @@ -1844,8 +1845,12 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' passwordExpired: type: boolean + projects: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse' + type: array role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse' token: type: string type: object @@ -1859,6 +1864,32 @@ definitions: type: array type: object type: object + github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse: + properties: + children: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + type: array + is_allowed: + type: boolean + key: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse: + properties: + configuration: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + dashboard: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + notification: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + policy: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + project_management: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + stack: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse: properties: key: @@ -1955,15 +1986,9 @@ definitions: type: array is_allowed: type: boolean - name: - type: string - parent: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - parent_id: + key: type: string - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' - role_id: + name: type: string type: object github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse: @@ -1974,9 +1999,9 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' notification: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - project_management: + policy: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - security_policy: + project_management: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' stack: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' @@ -2096,6 +2121,15 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse: + properties: + projectId: + type: string + projectRoleId: + type: string + projectRoleName: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest: properties: projectRoleId: @@ -2311,6 +2345,13 @@ definitions: usage: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse: + properties: + roleId: + type: string + roleName: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.RoleResponse: properties: createdAt: @@ -3435,7 +3476,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' summary: Admin List Tks Roles tags: - - Role + - Roles /admin/organizations/{organizationId}/roles/{roleId}: get: description: Admin Get Tks Role @@ -3459,7 +3500,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse' summary: Admin Get Tks Role tags: - - Role + - Roles /admin/organizations/{organizationId}/users/{accountId}: get: consumes: @@ -3485,7 +3526,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse' summary: Get user detail by admin tags: - - Admin + - Users put: consumes: - application/json @@ -3518,7 +3559,7 @@ paths: - JWT: [] summary: Update user by admin tags: - - Admin + - Users /admin/policy-templates: get: consumes: @@ -6782,7 +6823,7 @@ paths: - JWT: [] summary: List Tks Roles tags: - - Role + - Roles post: consumes: - application/json @@ -6810,7 +6851,7 @@ paths: - JWT: [] summary: Create Tks Role tags: - - Role + - Roles /organizations/{organizationId}/roles/{roleId}: delete: description: Delete Tks Role @@ -6834,7 +6875,7 @@ paths: - JWT: [] summary: Delete Tks Role tags: - - Role + - Roles get: description: Get Tks Role parameters: @@ -6859,7 +6900,7 @@ paths: - JWT: [] summary: Get Tks Role tags: - - Role + - Roles put: consumes: - application/json @@ -6890,12 +6931,21 @@ paths: - JWT: [] summary: Update Tks Role tags: - - Role + - Roles /organizations/{organizationId}/roles/{roleId}/permissions: get: - consumes: - - application/json description: Get Permissions By Role ID + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string produces: - application/json responses: @@ -6907,12 +6957,17 @@ paths: - JWT: [] summary: Get Permissions By Role ID tags: - - Permission + - Roles put: consumes: - application/json description: Update Permissions By Role ID parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string - description: Role ID in: path name: roleId @@ -6933,7 +6988,7 @@ paths: - JWT: [] summary: Update Permissions By Role ID tags: - - Permission + - Roles /organizations/{organizationId}/stack-templates: get: consumes: @@ -7865,6 +7920,32 @@ paths: summary: Update user tags: - Users + /organizations/{organizationId}/users/{accountId}/permissions: + get: + description: Get Permissions By Account ID + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Account ID + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse' + security: + - JWT: [] + summary: Get Permissions By Account ID + tags: + - Users /organizations/{organizationId}/users/{accountId}/reset-password: put: consumes: diff --git a/go.mod b/go.mod index 47e17ec0..92db160f 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 github.com/go-playground/validator/v10 v10.18.0 - github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/golang-jwt/jwt/v4 v4.5.0 github.com/golang/mock v1.6.0 github.com/google/uuid v1.6.0 github.com/gorilla/handlers v1.5.2 diff --git a/go.sum b/go.sum index d3bf874f..9a81524e 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -132,8 +130,8 @@ github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 42c5d270..df9fe7da 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -29,6 +29,7 @@ const ( ResetPassword CheckId CheckEmail + GetPermissionsByAccountId // MyProfile GetMyProfile @@ -189,12 +190,11 @@ const ( GetTksRole DeleteTksRole UpdateTksRole + GetPermissionsByRoleId + UpdatePermissionsByRoleId // Permission GetPermissionTemplates - GetPermissionsByRoleId - UpdatePermissionsByRoleId - GetPermissionsByAccountId // Admin_User Admin_CreateUser diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index df0278f0..88eb4d7e 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -67,6 +67,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CheckEmail", Group: "User", }, + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", + Group: "User", + }, GetMyProfile: { Name: "GetMyProfile", Group: "MyProfile", @@ -587,20 +591,16 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdateTksRole", Group: "Role", }, - GetPermissionTemplates: { - Name: "GetPermissionTemplates", - Group: "Permission", - }, GetPermissionsByRoleId: { Name: "GetPermissionsByRoleId", - Group: "Permission", + Group: "Role", }, UpdatePermissionsByRoleId: { Name: "UpdatePermissionsByRoleId", - Group: "Permission", + Group: "Role", }, - GetPermissionsByAccountId: { - Name: "GetPermissionsByAccountId", + GetPermissionTemplates: { + Name: "GetPermissionTemplates", Group: "Permission", }, Admin_CreateUser: { @@ -842,6 +842,8 @@ func (e Endpoint) String() string { return "CheckId" case CheckEmail: return "CheckEmail" + case GetPermissionsByAccountId: + return "GetPermissionsByAccountId" case GetMyProfile: return "GetMyProfile" case UpdateMyProfile: @@ -1102,14 +1104,12 @@ func (e Endpoint) String() string { return "DeleteTksRole" case UpdateTksRole: return "UpdateTksRole" - case GetPermissionTemplates: - return "GetPermissionTemplates" case GetPermissionsByRoleId: return "GetPermissionsByRoleId" case UpdatePermissionsByRoleId: return "UpdatePermissionsByRoleId" - case GetPermissionsByAccountId: - return "GetPermissionsByAccountId" + case GetPermissionTemplates: + return "GetPermissionTemplates" case Admin_CreateUser: return "Admin_CreateUser" case Admin_ListUser: @@ -1250,6 +1250,8 @@ func GetEndpoint(name string) Endpoint { return CheckId case "CheckEmail": return CheckEmail + case "GetPermissionsByAccountId": + return GetPermissionsByAccountId case "GetMyProfile": return GetMyProfile case "UpdateMyProfile": @@ -1510,14 +1512,12 @@ func GetEndpoint(name string) Endpoint { return DeleteTksRole case "UpdateTksRole": return UpdateTksRole - case "GetPermissionTemplates": - return GetPermissionTemplates case "GetPermissionsByRoleId": return GetPermissionsByRoleId case "UpdatePermissionsByRoleId": return UpdatePermissionsByRoleId - case "GetPermissionsByAccountId": - return GetPermissionsByAccountId + case "GetPermissionTemplates": + return GetPermissionTemplates case "Admin_CreateUser": return Admin_CreateUser case "Admin_ListUser": diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 04c8a947..f298a394 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -4,18 +4,13 @@ import ( "context" "net/http" - "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/httpErrors" ) type IPermissionHandler interface { GetPermissionTemplates(w http.ResponseWriter, r *http.Request) - GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) - UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) - GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) } type PermissionHandler struct { @@ -71,187 +66,3 @@ func convertModelToPermissionTemplateResponse(ctx context.Context, permission *m return &permissionResponse } - -// GetPermissionsByAccountId godoc -// -// @Tags Permission -// @Summary Get Permissions By Account ID -// @Description Get Permissions By Account ID -// @Accept json -// @Produce json -// @Success 200 {object} domain.GetUsersPermissionsResponse -// @Router /organizations/{organizationId}/users/{accountId}/permissions [get] -// @Security JWT -func (h PermissionHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) { - var organizationId, accountId string - - vars := mux.Vars(r) - if v, ok := vars["accountId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - accountId = v - } - if v, ok := vars["organizationId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - organizationId = v - } - - user, err := h.userUsecase.GetByAccountId(r.Context(), accountId, organizationId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - - var roles []*model.Role - roles = append(roles, &user.Role) - - var permissionSets []*model.PermissionSet - for _, role := range roles { - permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - permissionSets = append(permissionSets, permissionSet) - } - - mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) - - var permissions domain.MergedPermissionSetResponse - permissions.Dashboard = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard) - permissions.Stack = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack) - permissions.Policy = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy) - permissions.ProjectManagement = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement) - permissions.Notification = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification) - permissions.Configuration = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration) - - var out domain.GetUsersPermissionsResponse - out.Permissions = &permissions - ResponseJSON(w, r, http.StatusOK, out) - -} - -func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { - var permissionResponse domain.MergePermissionResponse - - permissionResponse.Key = permission.Key - if permission.IsAllowed != nil { - permissionResponse.IsAllowed = permission.IsAllowed - } - - for _, child := range permission.Children { - permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child)) - } - - return &permissionResponse -} - -// GetPermissionsByRoleId godoc -// -// @Tags Permission -// @Summary Get Permissions By Role ID -// @Description Get Permissions By Role ID -// @Accept json -// @Produce json -// @Success 200 {object} domain.PermissionSetResponse -// @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] -// @Security JWT -func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { - // path parameter - var roleId string - - vars := mux.Vars(r) - if v, ok := vars["roleId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - roleId = v - } - - permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), roleId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - - var permissionSetResponse domain.PermissionSetResponse - permissionSetResponse.Dashboard = convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard) - permissionSetResponse.Stack = convertModelToPermissionResponse(r.Context(), permissionSet.Stack) - permissionSetResponse.Policy = convertModelToPermissionResponse(r.Context(), permissionSet.Policy) - permissionSetResponse.ProjectManagement = convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement) - permissionSetResponse.Notification = convertModelToPermissionResponse(r.Context(), permissionSet.Notification) - permissionSetResponse.Configuration = convertModelToPermissionResponse(r.Context(), permissionSet.Configuration) - - var out domain.GetPermissionsByRoleIdResponse - out.Permissions = &permissionSetResponse - - ResponseJSON(w, r, http.StatusOK, out) -} - -func convertModelToPermissionResponse(ctx context.Context, permission *model.Permission) *domain.PermissionResponse { - var permissionResponse domain.PermissionResponse - - permissionResponse.ID = permission.ID - permissionResponse.Key = permission.Key - permissionResponse.Name = permission.Name - if permission.IsAllowed != nil { - permissionResponse.IsAllowed = permission.IsAllowed - } - - for _, endpoint := range permission.Endpoints { - permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint)) - } - - for _, child := range permission.Children { - permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child)) - } - - return &permissionResponse -} - -func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { - var endpointResponse domain.EndpointResponse - - endpointResponse.Name = endpoint.Name - endpointResponse.Group = endpoint.Group - - return &endpointResponse -} - -// UpdatePermissionsByRoleId godoc -// -// @Tags Permission -// @Summary Update Permissions By Role ID -// @Description Update Permissions By Role ID -// @Accept json -// @Produce json -// @Param roleId path string true "Role ID" -// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" -// @Success 200 -// @Router /organizations/{organizationId}/roles/{roleId}/permissions [put] -// @Security JWT -func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { - // request - input := domain.UpdatePermissionsByRoleIdRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - for _, permissionResponse := range input.Permissions { - var permission model.Permission - permission.ID = permissionResponse.ID - permission.IsAllowed = permissionResponse.IsAllowed - - if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - } - - ResponseJSON(w, r, http.StatusOK, nil) -} diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 8aebd4ab..e43a2c30 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -1,6 +1,7 @@ package http import ( + "context" "net/http" "github.com/gorilla/mux" @@ -20,6 +21,9 @@ type IRoleHandler interface { DeleteTksRole(w http.ResponseWriter, r *http.Request) UpdateTksRole(w http.ResponseWriter, r *http.Request) + GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) + UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) + Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) } @@ -38,7 +42,7 @@ func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { // CreateTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Create Tks Role // @Description Create Tks Role // @Accept json @@ -98,7 +102,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { // ListTksRoles godoc // -// @Tags Role +// @Tags Roles // @Summary List Tks Roles // @Description List Tks Roles // @Produce json @@ -153,7 +157,7 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { // GetTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Get Tks Role // @Description Get Tks Role // @Produce json @@ -195,7 +199,7 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // DeleteTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Delete Tks Role // @Description Delete Tks Role // @Produce json @@ -227,7 +231,7 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { // UpdateTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Update Tks Role // @Description Update Tks Role // @Accept json @@ -273,9 +277,118 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, nil) } +// GetPermissionsByRoleId godoc +// +// @Tags Roles +// @Summary Get Permissions By Role ID +// @Description Get Permissions By Role ID +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 {object} domain.PermissionSetResponse +// @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] +// @Security JWT +func (h RoleHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { + // path parameter + var roleId string + + vars := mux.Vars(r) + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), roleId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + var permissionSetResponse domain.PermissionSetResponse + permissionSetResponse.Dashboard = convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard) + permissionSetResponse.Stack = convertModelToPermissionResponse(r.Context(), permissionSet.Stack) + permissionSetResponse.Policy = convertModelToPermissionResponse(r.Context(), permissionSet.Policy) + permissionSetResponse.ProjectManagement = convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement) + permissionSetResponse.Notification = convertModelToPermissionResponse(r.Context(), permissionSet.Notification) + permissionSetResponse.Configuration = convertModelToPermissionResponse(r.Context(), permissionSet.Configuration) + + var out domain.GetPermissionsByRoleIdResponse + out.Permissions = &permissionSetResponse + + ResponseJSON(w, r, http.StatusOK, out) +} + +func convertModelToPermissionResponse(ctx context.Context, permission *model.Permission) *domain.PermissionResponse { + var permissionResponse domain.PermissionResponse + + permissionResponse.ID = permission.ID + permissionResponse.Key = permission.Key + permissionResponse.Name = permission.Name + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } + + for _, endpoint := range permission.Endpoints { + permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint)) + } + + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child)) + } + + return &permissionResponse +} + +func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { + var endpointResponse domain.EndpointResponse + + endpointResponse.Name = endpoint.Name + endpointResponse.Group = endpoint.Group + + return &endpointResponse +} + +// UpdatePermissionsByRoleId godoc +// +// @Tags Roles +// @Summary Update Permissions By Role ID +// @Description Update Permissions By Role ID +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" +// @Success 200 +// @Router /organizations/{organizationId}/roles/{roleId}/permissions [put] +// @Security JWT +func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { + // request + input := domain.UpdatePermissionsByRoleIdRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + for _, permissionResponse := range input.Permissions { + var permission model.Permission + permission.ID = permissionResponse.ID + permission.IsAllowed = permissionResponse.IsAllowed + + if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + // Admin_ListTksRoles godoc // -// @Tags Role +// @Tags Roles // @Summary Admin List Tks Roles // @Description Admin List Tks Roles // @Produce json @@ -330,7 +443,7 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) // Admin_GetTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Admin Get Tks Role // @Description Admin Get Tks Role // @Produce json diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 9d6f09ef..92d423d1 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -1,6 +1,7 @@ package http import ( + "context" "fmt" "net/http" "strings" @@ -34,6 +35,7 @@ type IUserHandler interface { CheckId(w http.ResponseWriter, r *http.Request) CheckEmail(w http.ResponseWriter, r *http.Request) + GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) // Admin Admin_Create(w http.ResponseWriter, r *http.Request) @@ -44,16 +46,18 @@ type IUserHandler interface { } type UserHandler struct { - usecase usecase.IUserUsecase - authUsecase usecase.IAuthUsecase - roleUsecase usecase.IRoleUsecase + usecase usecase.IUserUsecase + authUsecase usecase.IAuthUsecase + roleUsecase usecase.IRoleUsecase + permissionUsecase usecase.IPermissionUsecase } func NewUserHandler(h usecase.Usecase) IUserHandler { return &UserHandler{ - usecase: h.User, - authUsecase: h.Auth, - roleUsecase: h.Role, + usecase: h.User, + authUsecase: h.Auth, + roleUsecase: h.Role, + permissionUsecase: h.Permission, } } @@ -667,8 +671,86 @@ func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } +// GetPermissionsByAccountId godoc +// +// @Tags Users +// @Summary Get Permissions By Account ID +// @Description Get Permissions By Account ID +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param accountId path string true "Account ID" +// @Success 200 {object} domain.GetUsersPermissionsResponse +// @Router /organizations/{organizationId}/users/{accountId}/permissions [get] +// @Security JWT +func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) { + var organizationId, accountId string + + vars := mux.Vars(r) + if v, ok := vars["accountId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + accountId = v + } + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + user, err := u.usecase.GetByAccountId(r.Context(), accountId, organizationId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + var roles []*model.Role + roles = append(roles, &user.Role) + + var permissionSets []*model.PermissionSet + for _, role := range roles { + permissionSet, err := u.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + permissionSets = append(permissionSets, permissionSet) + } + + mergedPermissionSet := u.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) + + var permissions domain.MergedPermissionSetResponse + permissions.Dashboard = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard) + permissions.Stack = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack) + permissions.Policy = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy) + permissions.ProjectManagement = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement) + permissions.Notification = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification) + permissions.Configuration = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration) + + var out domain.GetUsersPermissionsResponse + out.Permissions = &permissions + ResponseJSON(w, r, http.StatusOK, out) + +} + +func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { + var permissionResponse domain.MergePermissionResponse + + permissionResponse.Key = permission.Key + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } + + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child)) + } + + return &permissionResponse +} + // Admin_Create godoc -// @Tags Admin +// @Tags Users // @Summary Create user by admin // @Description Create user by admin // @Accept json @@ -766,7 +848,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } // Admin_List godoc -// @Tags Admin +// @Tags Users // @Summary Get user list by admin // @Description Get user list by admin // @Accept json @@ -815,7 +897,7 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { // Admin_Get godoc // -// @Tags Admin +// @Tags Users // @Summary Get user detail by admin // @Description Get user detail by admin // @Accept json @@ -859,7 +941,7 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { } // Admin_Delete godoc -// @Tags Admin +// @Tags Users // @Summary Delete user by admin // @Description Delete user by admin // @Accept json @@ -925,7 +1007,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { // Admin_Update godoc // -// @Tags Admin +// @Tags Users // @Summary Update user by admin // @Description Update user by admin // @Accept json diff --git a/internal/route/route.go b/internal/route/route.go index 00f0385f..bb922dea 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -121,6 +121,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/password", customMiddleware.Handle(internalApi.UpdateMyPassword, http.HandlerFunc(userHandler.UpdateMyPassword))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/next-password-change", customMiddleware.Handle(internalApi.RenewPasswordExpiredDate, http.HandlerFunc(userHandler.RenewPasswordExpiredDate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.DeleteMyProfile, http.HandlerFunc(userHandler.DeleteMyProfile))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByAccountId, http.HandlerFunc(userHandler.GetPermissionsByAccountId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_CreateUser, http.HandlerFunc(userHandler.Admin_Create))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_ListUser, http.HandlerFunc(userHandler.Admin_List))).Methods(http.MethodGet) @@ -282,6 +283,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.GetTksRole, http.HandlerFunc(roleHandler.GetTksRole))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.DeleteTksRole, http.HandlerFunc(roleHandler.DeleteTksRole))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateTksRole, http.HandlerFunc(roleHandler.UpdateTksRole))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(roleHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(roleHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) // Admin r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.Admin_ListTksRoles, http.HandlerFunc(roleHandler.Admin_ListTksRoles))).Methods(http.MethodGet) @@ -290,9 +293,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa permissionHandler := delivery.NewPermissionHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(permissionHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByAccountId, http.HandlerFunc(permissionHandler.GetPermissionsByAccountId))).Methods(http.MethodGet) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) From 3a48bd6bd14a0f3fd9f9ded39de6d9bf7b8b5425 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 25 Mar 2024 15:21:21 +0900 Subject: [PATCH 174/502] tirivial. fix swagger error --- api/swagger/docs.go | 29 +++++++++++++++++-- api/swagger/swagger.json | 29 +++++++++++++++++-- api/swagger/swagger.yaml | 22 ++++++++++++-- internal/delivery/http/role.go | 12 ++++---- .../http/system-notification-template.go | 2 +- internal/delivery/http/user.go | 6 ++-- 6 files changed, 81 insertions(+), 19 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index c4b07133..3ce6bb87 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1306,7 +1306,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest" } } } @@ -9134,11 +9134,34 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest": { "type": "object", + "required": [ + "metricQuery", + "name", + "organizationIds" + ], "properties": { - "id": { + "description": { "type": "string" + }, + "metricParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + } + }, + "metricQuery": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index d2f02ba9..2da9eb49 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1300,7 +1300,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest" } } } @@ -9128,11 +9128,34 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest": { "type": "object", + "required": [ + "metricQuery", + "name", + "organizationIds" + ], "properties": { - "id": { + "description": { "type": "string" + }, + "metricParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + } + }, + "metricQuery": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 60fd3f67..527db22c 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1107,10 +1107,26 @@ definitions: id: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest: properties: - id: + description: + type: string + metricParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse' + type: array + metricQuery: + type: string + name: type: string + organizationIds: + items: + type: string + type: array + required: + - metricQuery + - name + - organizationIds type: object github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest: properties: @@ -4131,7 +4147,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest' security: - JWT: [] summary: Create alert template. ADMIN ONLY diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index e43a2c30..21658fd9 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -283,9 +283,9 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // @Summary Get Permissions By Role ID // @Description Get Permissions By Role ID // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" -// @Success 200 {object} domain.PermissionSetResponse +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 {object} domain.PermissionSetResponse // @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] // @Security JWT func (h RoleHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { @@ -357,9 +357,9 @@ func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoin // @Description Update Permissions By Role ID // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" -// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId}/permissions [put] // @Security JWT diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index 73053e17..e4b11b01 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -33,7 +33,7 @@ func NewSystemNotificationTemplateHandler(h usecase.Usecase) *SystemNotification // @Description Create alert template. ADMIN ONLY // @Accept json // @Produce json -// @Success 200 {object} domain.CreateSystemNotificationTemplateResponse +// @Success 200 {object} domain.CreateSystemNotificationTemplateRequest // @Router /admin/system-notification-templates [post] // @Security JWT func (h *SystemNotificationTemplateHandler) CreateSystemNotificationTemplate(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 92d423d1..f9764f05 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -677,9 +677,9 @@ func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { // @Summary Get Permissions By Account ID // @Description Get Permissions By Account ID // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param accountId path string true "Account ID" -// @Success 200 {object} domain.GetUsersPermissionsResponse +// @Param organizationId path string true "Organization ID" +// @Param accountId path string true "Account ID" +// @Success 200 {object} domain.GetUsersPermissionsResponse // @Router /organizations/{organizationId}/users/{accountId}/permissions [get] // @Security JWT func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) { From 8900a959ebd75798cfadaea1bdfa18c067e1cb4a Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 25 Mar 2024 15:57:27 +0900 Subject: [PATCH 175/502] minor fix. filter error fix --- internal/repository/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/repository/user.go b/internal/repository/user.go index 451271e0..bdacb03b 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -118,7 +118,7 @@ func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination. pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.WithContext(ctx).Preload("Organization").Preload("Role").Model(&model.User{}).Where("organization_id = ?", organizationId), &users) + _, res := pg.Fetch(r.db.WithContext(ctx).Preload("Organization").Preload("Role").Model(&model.User{}).Where("users.organization_id = ?", organizationId), &users) if res.Error != nil { log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error From 82d1466b583cf8f204e84db654d3eac1a5775172 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 20 Mar 2024 17:33:47 +0900 Subject: [PATCH 176/502] re mapping permissions --- .../delivery/api/endpoints_permission_test.go | 70 +++ .../delivery/api/generated_endpoints.go.go | 8 - internal/model/permission.go | 585 +++++++++++++----- pkg/domain/endpoint.go | 8 +- pkg/domain/permission.go | 4 - 5 files changed, 513 insertions(+), 162 deletions(-) create mode 100644 internal/delivery/api/endpoints_permission_test.go diff --git a/internal/delivery/api/endpoints_permission_test.go b/internal/delivery/api/endpoints_permission_test.go new file mode 100644 index 00000000..e6033894 --- /dev/null +++ b/internal/delivery/api/endpoints_permission_test.go @@ -0,0 +1,70 @@ +package api_test + +import ( + "github.com/openinfradev/tks-api/internal/delivery/api" + "github.com/openinfradev/tks-api/internal/model" + "testing" +) + +func TestEndpointsUsage(t *testing.T) { + var allEndpoints []string + for _, v := range api.ApiMap { + allEndpoints = append(allEndpoints, v.Name) + } + //allEndpoints := []Endpoint{ + // Login, Logout, RefreshToken, FindId, // 계속해서 모든 Endpoint 추가 + // // 나머지 Endpoint 상수들을 여기에 추가 + //} + usageCount := make(map[string]int) + ps := model.NewAdminPermissionSet() + + permissions := []*model.Permission{ + ps.Dashboard, + ps.Notification, + ps.Configuration, + ps.ProjectManagement, + ps.Stack, + ps.SecurityPolicy, + ps.Common, + ps.Admin, + } + + leafPermissions := make([]*model.Permission, 0) + + for _, perm := range permissions { + leafPermissions = model.GetEdgePermission(perm, leafPermissions, nil) + } + + // Permission 설정에서 Endpoint 사용 횟수 카운트 + for _, perm := range leafPermissions { + countEndpoints(perm, usageCount) + } + + var unusedEndpoints, duplicatedEndpoints []string + + // 미사용 또는 중복 사용된 Endpoint 확인 및 출력 + for _, endpoint := range allEndpoints { + count, exists := usageCount[endpoint] + if !exists { + unusedEndpoints = append(unusedEndpoints, endpoint) + } else if count > 1 { + duplicatedEndpoints = append(duplicatedEndpoints, endpoint) + } + } + + for _, endpoint := range unusedEndpoints { + t.Logf("Unused Endpoint: %s", endpoint) + } + + t.Logf("\n") + for _, endpoint := range duplicatedEndpoints { + t.Logf("Duplicated Endpoint: %s", endpoint) + } + +} + +func countEndpoints(perm *model.Permission, usageCount map[string]int) { + for _, endpoint := range perm.Endpoints { + usageCount[endpoint.Name]++ + } +} diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index ee43f07f..16484548 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -35,10 +35,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "VerifyToken", Group: "Auth", }, - DeleteToken: { - Name: "DeleteToken", - Group: "Auth", - }, CreateUser: { Name: "CreateUser", Group: "User", @@ -826,8 +822,6 @@ func (e Endpoint) String() string { return "VerifyIdentityForLostPassword" case VerifyToken: return "VerifyToken" - case DeleteToken: - return "DeleteToken" case CreateUser: return "CreateUser" case ListUser: @@ -1234,8 +1228,6 @@ func GetEndpoint(name string) Endpoint { return VerifyIdentityForLostPassword case "VerifyToken": return VerifyToken - case "DeleteToken": - return DeleteToken case "CreateUser": return CreateUser case "ListUser": diff --git a/internal/model/permission.go b/internal/model/permission.go index 5025d766..746b1257 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -11,9 +11,9 @@ type PermissionKind string const ( DashBoardPermission PermissionKind = "대시보드" - StackPermission PermissionKind = "스택 관리" - SecurityPolicyPermission PermissionKind = "보안/정책 관리" - ProjectManagementPermission PermissionKind = "프로젝트 관리" + StackPermission PermissionKind = "스택" + SecurityPolicyPermission PermissionKind = "정책" + ProjectManagementPermission PermissionKind = "프로젝트" NotificationPermission PermissionKind = "알림" ConfigurationPermission PermissionKind = "설정" ) @@ -42,6 +42,8 @@ type PermissionSet struct { ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` Notification *Permission `gorm:"-:all" json:"notification,omitempty"` Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` + Common *Permission `gorm:"-:all" json:"common,omitempty"` + Admin *Permission `gorm:"-:all" json:"admin,omitempty"` } func NewDefaultPermissionSet() *PermissionSet { @@ -52,6 +54,20 @@ func NewDefaultPermissionSet() *PermissionSet { ProjectManagement: newProjectManagement(), Notification: newNotification(), Configuration: newConfiguration(), + Common: newCommon(), + } +} + +func NewAdminPermissionSet() *PermissionSet { + return &PermissionSet{ + Admin: newAdmin(), + Dashboard: newDashboard(), + Stack: newStack(), + SecurityPolicy: newSecurityPolicy(), + ProjectManagement: newProjectManagement(), + Notification: newNotification(), + Configuration: newConfiguration(), + Common: newCommon(), } } @@ -101,84 +117,98 @@ func newDashboard() *Permission { api.GetResourcesDashboard, ), }, + { + ID: uuid.New(), + Name: "수정", + IsAllowed: helper.BoolP(false), + }, }, }, + }, + } + + return dashboard +} + +func newStack() *Permission { + stack := &Permission{ + ID: uuid.New(), + Name: string(StackPermission), + Children: []*Permission{ { ID: uuid.New(), - Name: "대시보드 설정", + Name: "스택", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetStacks, + api.GetStack, + api.CheckStackName, + api.GetStackStatus, + api.GetStackKubeConfig, + + api.SetFavoriteStack, + api.DeleteFavoriteStack, + + // Cluster + api.GetCluster, + api.GetClusters, + api.GetClusterSiteValues, + api.GetBootstrapKubeconfig, + api.GetNodes, + + // AppGroup + api.GetAppgroups, + api.GetAppgroup, + api.GetApplications, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateStack, + api.InstallStack, + api.CreateAppgroup, + + // Cluster + api.CreateCluster, + api.ImportCluster, + api.InstallCluster, + api.CreateBootstrapKubeconfig, + + // AppGroup + api.CreateAppgroup, + api.CreateApplication, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateStack, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), - }, - }, - }, - }, - } + Endpoints: endpointObjects( + api.DeleteStack, - return dashboard -} + // Cluster + api.DeleteCluster, -func newStack() *Permission { - stack := &Permission{ - ID: uuid.New(), - Name: string(StackPermission), - Children: []*Permission{ - { - ID: uuid.New(), - Name: "조회", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetStacks, - api.GetStack, - api.CheckStackName, - api.GetStackStatus, - api.GetStackKubeConfig, - - api.SetFavoriteStack, - api.DeleteFavoriteStack, - ), - }, - { - ID: uuid.New(), - Name: "생성", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateStack, - api.InstallStack, - ), - }, - { - ID: uuid.New(), - Name: "수정", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateStack, - ), - }, - { - ID: uuid.New(), - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteStack, - ), + // AppGroup + api.DeleteAppgroup, + ), + }, + }, }, }, } @@ -193,27 +223,107 @@ func newSecurityPolicy() *Permission { Children: []*Permission{ { ID: uuid.New(), - Name: "보안/정책", + Name: "정책", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.ListPolicyTemplate, + api.GetPolicyTemplate, + api.GetPolicyTemplateDeploy, + api.ListPolicyTemplateStatistics, + api.ListPolicyTemplateVersions, + api.GetPolicyTemplateVersion, + api.ExistsPolicyTemplateName, + api.ExistsPolicyTemplateKind, + + // ClusterPolicyStatus + api.ListClusterPolicyStatus, + api.GetClusterPolicyTemplateStatus, + + // Policy + api.GetMandatoryPolicies, + api.ListPolicy, + api.GetPolicy, + api.ExistsPolicyName, + + // OrganizationPolicyTemplate + api.ListOrganizationPolicyTemplate, + api.GetOrganizationPolicyTemplate, + api.GetOrganizationPolicyTemplateDeploy, + api.ListOrganizationPolicyTemplateStatistics, + api.ListOrganizationPolicyTemplateVersions, + api.GetOrganizationPolicyTemplateVersion, + api.ExistsOrganizationPolicyTemplateKind, + api.ExistsOrganizationPolicyTemplateName, + + // PolicyTemplateExample + api.ListPolicyTemplateExample, + api.GetPolicyTemplateExample, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.CreatePolicyTemplate, + api.CreatePolicyTemplateVersion, + + // Policy + api.SetMandatoryPolicies, + api.CreatePolicy, + + // OrganizationPolicyTemplate + api.CreateOrganizationPolicyTemplate, + api.CreateOrganizationPolicyTemplateVersion, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.UpdatePolicyTemplate, + + // ClusterPolicyStatus + api.UpdateClusterPolicyTemplateStatus, + + // Policy + api.UpdatePolicy, + api.UpdatePolicyTargetClusters, + + // OrganizationPolicyTemplate + api.UpdateOrganizationPolicyTemplate, + + // PolicyTemplateExample + api.UpdatePolicyTemplateExample, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.DeletePolicyTemplate, + api.DeletePolicyTemplateVersion, + + // Policy + api.DeletePolicy, + + // OrganizationPolicyTemplate + api.DeleteOrganizationPolicyTemplate, + api.DeleteOrganizationPolicyTemplateVersion, + + // PolicyTemplateExample + api.DeletePolicyTemplateExample, + ), }, }, }, @@ -223,77 +333,98 @@ func newSecurityPolicy() *Permission { return security_policy } -func newProjectManagement() *Permission { - projectManagement := &Permission{ +func newNotification() *Permission { + notification := &Permission{ ID: uuid.New(), - Name: string(ProjectManagementPermission), + Name: string(NotificationPermission), Children: []*Permission{ { ID: uuid.New(), - Name: "프로젝트", + Name: "시스템 알림", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, + api.GetSystemNotification, + api.GetSystemNotifications, ), }, { ID: uuid.New(), - Name: "생성", + Name: "수정", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.CreateProject, + api.UpdateSystemNotification, + api.CreateSystemNotificationAction, ), }, + { + ID: uuid.New(), + Name: "다운로드", + IsAllowed: helper.BoolP(false), + Children: []*Permission{}, + }, }, }, { ID: uuid.New(), - Name: "앱 서빙", + Name: "정책 알림", + Children: []*Permission{ + { + ID: uuid.New(), + Name: "조회", + IsAllowed: helper.BoolP(false), + Children: []*Permission{}, + }, + { + ID: uuid.New(), + Name: "다운로드", + IsAllowed: helper.BoolP(false), + Children: []*Permission{}, + }, + }, + }, + }, + } + + return notification +} + +func newProjectManagement() *Permission { + projectManagement := &Permission{ + ID: uuid.New(), + Name: string(ProjectManagementPermission), + Children: []*Permission{ + { + ID: uuid.New(), + Name: "프로젝트", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.GetAppServeApps, - api.GetAppServeApp, - api.GetNumOfAppsOnStack, - api.GetAppServeAppLatestTask, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, + api.GetProjects, + api.GetProject, + api.GetProjectKubeconfig, ), }, { ID: uuid.New(), - Name: "빌드", + Name: "생성", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, + api.CreateProject, ), }, { ID: uuid.New(), - Name: "배포", + Name: "수정", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, + api.UpdateProject, ), }, { @@ -301,14 +432,14 @@ func newProjectManagement() *Permission { Name: "삭제", IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( - api.DeleteAppServeApp, + api.DeleteProject, ), }, }, }, { ID: uuid.New(), - Name: "설정-일반", + Name: "일반 설정", Children: []*Permission{ { ID: uuid.New(), @@ -330,19 +461,11 @@ func newProjectManagement() *Permission { api.UpdateProject, ), }, - { - ID: uuid.New(), - Name: "삭제", - IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProject, - ), - }, }, }, { ID: uuid.New(), - Name: "설정-멤버", + Name: "구성원 설정", Children: []*Permission{ { ID: uuid.New(), @@ -383,7 +506,7 @@ func newProjectManagement() *Permission { }, { ID: uuid.New(), - Name: "설정-네임스페이스", + Name: "네임스페이스", Children: []*Permission{ { ID: uuid.New(), @@ -392,6 +515,7 @@ func newProjectManagement() *Permission { Endpoints: endpointObjects( api.GetProjectNamespaces, api.GetProjectNamespace, + api.GetProjectNamespaceK8sResources, ), }, { @@ -406,7 +530,9 @@ func newProjectManagement() *Permission { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects(), + Endpoints: endpointObjects( + api.UpdateProjectNamespace, + ), }, { ID: uuid.New(), @@ -418,43 +544,67 @@ func newProjectManagement() *Permission { }, }, }, - }, - } - - return projectManagement -} - -func newNotification() *Permission { - notification := &Permission{ - ID: uuid.New(), - Name: string(NotificationPermission), - Children: []*Permission{ { ID: uuid.New(), - Name: "시스템 경고", + Name: "앱 서빙", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetAppServeApps, + api.GetAppServeApp, + api.GetNumOfAppsOnStack, + api.GetAppServeAppLatestTask, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.GetAppServeAppTaskDetail, + api.GetAppServeAppTasksByAppId, + ), }, - }, - }, - { - ID: uuid.New(), - Name: "보안/정책 감사로그", - Children: []*Permission{ { ID: uuid.New(), - Name: "조회", + Name: "생성", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + ID: uuid.New(), + Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + }, + { + ID: uuid.New(), + Name: "삭제", + IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteAppServeApp, + ), }, }, }, }, } - return notification + return projectManagement } func newConfiguration() *Permission { @@ -486,38 +636,44 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetCloudAccounts, + api.GetCloudAccount, + api.CheckCloudAccountName, + api.CheckAwsAccountId, + api.GetResourceQuota, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateCloudAccount, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateCloudAccount, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteCloudAccount, + api.DeleteForceCloudAccount, + ), }, }, }, { ID: uuid.New(), - Name: "스택 템플릿", - Children: []*Permission{ - { - ID: uuid.New(), - Name: "조회", - IsAllowed: helper.BoolP(false), - }, - }, - }, - { - ID: uuid.New(), - Name: "프로젝트 관리", + Name: "프로젝트", Children: []*Permission{ { ID: uuid.New(), @@ -529,16 +685,6 @@ func newConfiguration() *Permission { Name: "생성", IsAllowed: helper.BoolP(false), }, - { - ID: uuid.New(), - Name: "수정", - IsAllowed: helper.BoolP(false), - }, - { - ID: uuid.New(), - Name: "삭제", - IsAllowed: helper.BoolP(false), - }, }, }, { @@ -549,73 +695,120 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.ListUser, + api.GetUser, + api.CheckId, + api.CheckEmail, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateUser, + api.CheckId, + api.CheckEmail, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateUser, + api.ResetPassword, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteUser, + ), }, }, }, { ID: uuid.New(), - Name: "사용자 권한 관리", + Name: "역할 및 권한", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.ListTksRoles, + api.GetTksRole, + api.GetPermissionsByRoleId, + api.GetPermissionTemplates, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateTksRole, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateTksRole, + api.UpdatePermissionsByRoleId, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteTksRole, + ), }, }, }, { ID: uuid.New(), - Name: "알림 설정", + Name: "시스템 알림", Children: []*Permission{ { ID: uuid.New(), Name: "조회", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetSystemNotificationRules, + api.GetSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "생성", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "수정", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "삭제", IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteSystemNotificationRule, + ), }, }, }, @@ -625,6 +818,110 @@ func newConfiguration() *Permission { return configuration } +func newCommon() *Permission { + common := &Permission{ + ID: uuid.New(), + Name: "공통", + IsAllowed: helper.BoolP(true), + Endpoints: endpointObjects( + // Auth + api.Login, + api.Logout, + api.RefreshToken, + api.FindId, + api.FindPassword, + api.VerifyIdentityForLostId, + api.VerifyIdentityForLostPassword, + api.VerifyToken, + + // Stack + api.SetFavoriteStack, + api.DeleteFavoriteStack, + + // Project + api.SetFavoriteProject, + api.SetFavoriteProjectNamespace, + api.UnSetFavoriteProject, + api.UnSetFavoriteProjectNamespace, + + // MyProfile + api.GetMyProfile, + api.UpdateMyProfile, + api.UpdateMyPassword, + api.RenewPasswordExpiredDate, + api.DeleteMyProfile, + + // StackTemplate + api.GetOrganizationStackTemplates, + api.GetOrganizationStackTemplate, + + // Utiliy + api.CompileRego, + ), + } + + return common + +} + +func newAdmin() *Permission { + admin := &Permission{ + ID: uuid.New(), + Name: "관리자", + IsAllowed: helper.BoolP(true), + Endpoints: endpointObjects( + // Organization + api.Admin_CreateOrganization, + api.Admin_DeleteOrganization, + api.UpdateOrganization, + api.GetOrganization, + api.GetOrganizations, + api.UpdatePrimaryCluster, + api.CheckOrganizationName, + + // User + api.ResetPassword, + api.CheckId, + api.CheckEmail, + + // StackTemplate + api.Admin_GetStackTemplates, + api.Admin_GetStackTemplate, + api.Admin_GetStackTemplateServices, + api.Admin_CreateStackTemplate, + api.Admin_UpdateStackTemplate, + api.Admin_DeleteStackTemplate, + api.Admin_UpdateStackTemplateOrganizations, + api.Admin_CheckStackTemplateName, + + // Admin + api.Admin_GetUser, + api.Admin_ListUser, + api.Admin_CreateUser, + api.Admin_UpdateUser, + api.Admin_DeleteUser, + api.Admin_GetSystemNotificationTemplate, + api.Admin_CreateSystemNotificationTemplate, + api.Admin_ListUser, + api.Admin_GetTksRole, + api.Admin_GetProjects, + api.Admin_UpdateSystemNotificationTemplate, + api.Admin_ListTksRoles, + api.Admin_GetSystemNotificationTemplates, + + // Audit + api.GetAudits, + api.GetAudit, + api.DeleteAudit, + + api.CreateSystemNotification, + api.DeleteSystemNotification, + ), + } + + return admin +} + func (p *PermissionSet) SetAllowedPermissionSet() { edgePermissions := make([]*Permission, 0) edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index e2a2127d..33acdc92 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -1,10 +1,6 @@ package domain -import "time" - type EndpointResponse struct { - Name string `json:"name"` - Group string `json:"group"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + Name string `json:"name"` + Group string `json:"group"` } diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index f7b69f40..8be227a2 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -8,11 +8,7 @@ type PermissionResponse struct { ID uuid.UUID `json:"ID"` Name string `json:"name"` IsAllowed *bool `json:"is_allowed,omitempty"` - RoleID *string `json:"role_id,omitempty"` - Role *RoleResponse `json:"role,omitempty"` Endpoints []*EndpointResponse `json:"endpoints,omitempty"` - ParentID *uuid.UUID `json:"parent_id,omitempty"` - Parent *PermissionResponse `json:"parent,omitempty"` Children []*PermissionResponse `json:"children,omitempty"` } From a2c09a6e0df1e5fc4e18709833064f20b62e4442 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 17:41:55 +0900 Subject: [PATCH 177/502] change permission API --- internal/delivery/api/endpoint.go | 1 + .../delivery/api/endpoints_permission_test.go | 2 +- .../delivery/api/generated_endpoints.go.go | 16 ++ internal/delivery/http/permission.go | 168 +++++++++++++++--- internal/model/permission.go | 153 +++++++++++++--- internal/route/route.go | 1 + internal/usecase/permission.go | 44 ++++- pkg/domain/permission.go | 60 +++++-- 8 files changed, 379 insertions(+), 66 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index e07171e6..c5874faf 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -195,6 +195,7 @@ const ( GetPermissionTemplates GetPermissionsByRoleId UpdatePermissionsByRoleId + GetPermissionsByAccountId // Admin_User Admin_CreateUser diff --git a/internal/delivery/api/endpoints_permission_test.go b/internal/delivery/api/endpoints_permission_test.go index e6033894..b012f456 100644 --- a/internal/delivery/api/endpoints_permission_test.go +++ b/internal/delivery/api/endpoints_permission_test.go @@ -24,7 +24,7 @@ func TestEndpointsUsage(t *testing.T) { ps.Configuration, ps.ProjectManagement, ps.Stack, - ps.SecurityPolicy, + ps.Policy, ps.Common, ps.Admin, } diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 16484548..b4b8549e 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -35,6 +35,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "VerifyToken", Group: "Auth", }, + DeleteToken: { + Name: "DeleteToken", + Group: "Auth", + }, CreateUser: { Name: "CreateUser", Group: "User", @@ -599,6 +603,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdatePermissionsByRoleId", Group: "Permission", }, + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", + Group: "Permission", + }, Admin_CreateUser: { Name: "Admin_CreateUser", Group: "Admin_User", @@ -822,6 +830,8 @@ func (e Endpoint) String() string { return "VerifyIdentityForLostPassword" case VerifyToken: return "VerifyToken" + case DeleteToken: + return "DeleteToken" case CreateUser: return "CreateUser" case ListUser: @@ -1104,6 +1114,8 @@ func (e Endpoint) String() string { return "GetPermissionsByRoleId" case UpdatePermissionsByRoleId: return "UpdatePermissionsByRoleId" + case GetPermissionsByAccountId: + return "GetPermissionsByAccountId" case Admin_CreateUser: return "Admin_CreateUser" case Admin_ListUser: @@ -1228,6 +1240,8 @@ func GetEndpoint(name string) Endpoint { return VerifyIdentityForLostPassword case "VerifyToken": return VerifyToken + case "DeleteToken": + return DeleteToken case "CreateUser": return CreateUser case "ListUser": @@ -1510,6 +1524,8 @@ func GetEndpoint(name string) Endpoint { return GetPermissionsByRoleId case "UpdatePermissionsByRoleId": return UpdatePermissionsByRoleId + case "GetPermissionsByAccountId": + return GetPermissionsByAccountId case "Admin_CreateUser": return Admin_CreateUser case "Admin_ListUser": diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 9e660850..8ec9b7e9 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -1,15 +1,14 @@ package http import ( + "context" "net/http" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/model" - "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" ) type IPermissionHandler interface { @@ -20,11 +19,13 @@ type IPermissionHandler interface { type PermissionHandler struct { permissionUsecase usecase.IPermissionUsecase + userUsecase usecase.IUserUsecase } func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { return &PermissionHandler{ permissionUsecase: usecase.Permission, + userUsecase: usecase.User, } } @@ -41,20 +42,110 @@ func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { permissionSet := model.NewDefaultPermissionSet() - var premissionSetResponse domain.PermissionSetResponse - if err := serializer.Map(r.Context(), permissionSet, &premissionSetResponse); err != nil { - log.Info(r.Context(), err) + var out domain.GetPermissionTemplatesResponse + out.Permissions = new(domain.PermissionTemplateResponse) + + out.Permissions.Dashboard = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Dashboard) + out.Permissions.Stack = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Stack) + out.Permissions.Policy = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Policy) + out.Permissions.ProjectManagement = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.ProjectManagement) + out.Permissions.Notification = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Notification) + out.Permissions.Configuration = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Configuration) + + ResponseJSON(w, r, http.StatusOK, out) +} + +func convertModelToPermissionTemplateResponse(ctx context.Context, permission *model.Permission) *domain.TemplateResponse { + var permissionResponse domain.TemplateResponse + + permissionResponse.Key = permission.Key + permissionResponse.Name = permission.Name + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed } - var out domain.GetPermissionTemplatesResponse - out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) - out.Permissions = append(out.Permissions, premissionSetResponse.Stack) - out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) - out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) - out.Permissions = append(out.Permissions, premissionSetResponse.Notification) - out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionTemplateResponse(ctx, child)) + } + + return &permissionResponse +} + +// GetPermissionsByAccountId godoc +// +// @Tags Permission +// @Summary Get Permissions By Account ID +// @Description Get Permissions By Account ID +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetUsersPermissionsResponse +// @Router /organizations/{organizationId}/users/{accountId}/permissions [get] +// @Security JWT +func (h PermissionHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) { + var organizationId, accountId string + + vars := mux.Vars(r) + if v, ok := vars["accountId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + accountId = v + } + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + user, err := h.userUsecase.GetByAccountId(r.Context(), accountId, organizationId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + var roles []*model.Role + roles = append(roles, &user.Role) + + var permissionSets []*model.PermissionSet + for _, role := range roles { + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + permissionSets = append(permissionSets, permissionSet) + } + + mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) + + var permissions domain.MergedPermissionSetResponse + permissions.Dashboard = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard) + permissions.Stack = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack) + permissions.Policy = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy) + permissions.ProjectManagement = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement) + permissions.Notification = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification) + permissions.Configuration = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration) + + var out domain.GetUsersPermissionsResponse + out.Permissions = &permissions ResponseJSON(w, r, http.StatusOK, out) + +} + +func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { + var permissionResponse domain.MergePermissionResponse + + permissionResponse.Key = permission.Key + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } + + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child)) + } + + return &permissionResponse } // GetPermissionsByRoleId godoc @@ -85,22 +176,50 @@ func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http return } - var premissionSetResponse domain.PermissionSetResponse - if err := serializer.Map(r.Context(), permissionSet, &premissionSetResponse); err != nil { - log.Info(r.Context(), err) - } + var permissionSetResponse domain.PermissionSetResponse + permissionSetResponse.Dashboard = convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard) + permissionSetResponse.Stack = convertModelToPermissionResponse(r.Context(), permissionSet.Stack) + permissionSetResponse.Policy = convertModelToPermissionResponse(r.Context(), permissionSet.Policy) + permissionSetResponse.ProjectManagement = convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement) + permissionSetResponse.Notification = convertModelToPermissionResponse(r.Context(), permissionSet.Notification) + permissionSetResponse.Configuration = convertModelToPermissionResponse(r.Context(), permissionSet.Configuration) var out domain.GetPermissionsByRoleIdResponse - out.Permissions = append(out.Permissions, premissionSetResponse.Dashboard) - out.Permissions = append(out.Permissions, premissionSetResponse.Stack) - out.Permissions = append(out.Permissions, premissionSetResponse.SecurityPolicy) - out.Permissions = append(out.Permissions, premissionSetResponse.ProjectManagement) - out.Permissions = append(out.Permissions, premissionSetResponse.Notification) - out.Permissions = append(out.Permissions, premissionSetResponse.Configuration) + out.Permissions = &permissionSetResponse ResponseJSON(w, r, http.StatusOK, out) } +func convertModelToPermissionResponse(ctx context.Context, permission *model.Permission) *domain.PermissionResponse { + var permissionResponse domain.PermissionResponse + + permissionResponse.ID = permission.ID + permissionResponse.Key = permission.Key + permissionResponse.Name = permission.Name + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } + + for _, endpoint := range permission.Endpoints { + permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint)) + } + + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child)) + } + + return &permissionResponse +} + +func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { + var endpointResponse domain.EndpointResponse + + endpointResponse.Name = endpoint.Name + endpointResponse.Group = endpoint.Group + + return &endpointResponse +} + // UpdatePermissionsByRoleId godoc // // @Tags Permission @@ -124,9 +243,8 @@ func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *h for _, permissionResponse := range input.Permissions { var permission model.Permission - if err := serializer.Map(r.Context(), permissionResponse, &permission); err != nil { - log.Info(r.Context(), err) - } + permission.ID = permissionResponse.ID + permission.IsAllowed = permissionResponse.IsAllowed if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) diff --git a/internal/model/permission.go b/internal/model/permission.go index 746b1257..87e06b6e 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -10,12 +10,42 @@ import ( type PermissionKind string const ( - DashBoardPermission PermissionKind = "대시보드" - StackPermission PermissionKind = "스택" - SecurityPolicyPermission PermissionKind = "정책" - ProjectManagementPermission PermissionKind = "프로젝트" - NotificationPermission PermissionKind = "알림" - ConfigurationPermission PermissionKind = "설정" + DashBoardPermission PermissionKind = "대시보드" + StackPermission PermissionKind = "스택" + PolicyPermission PermissionKind = "정책" + ProjectPermission PermissionKind = "프로젝트" + NotificationPermission PermissionKind = "알림" + ConfigurationPermission PermissionKind = "설정" + + OperationRead = "READ" + OperationCreate = "CREATE" + OperationUpdate = "UPDATE" + OperationDelete = "DELETE" + OperationDownload = "DOWNLOAD" + + // Key + TopDashboardKey = "DASHBOARD" + MiddleDashboardKey = "DASHBOARD-DASHBOARD" + TopStackKey = "STACK" + MiddleStackKey = "STACK-STACK" + TopPolicyKey = "POLICY" + MiddlePolicyKey = "POLICY-POLICY" + TopNotificationKey = "NOTIFICATION" + MiddleNotificationKey = "NOTIFICATION-SYSTEM_NOTIFICATION" + MiddlePolicyNotificationKey = "NOTIFICATION-POLICY_NOTIFICATION" + TopProjectKey = "PROJECT" + MiddleProjectKey = "PROJECT-PROJECT_LIST" + MiddleProjectCommonConfigurationKey = "PROJECT-PROJECT_COMMON_CONFIGURATION" + MiddleProjectMemberConfigurationKey = "PROJECT-PROJECT_MEMBER_CONFIGURATION" + MiddleProjectNamespaceKey = "PROJECT-PROJECT_NAMESPACE" + MiddleProjectAppServeKey = "PROJECT-PROJECT_APP_SERVE" + TopConfigurationKey = "CONFIGURATION" + MiddleConfigurationKey = "CONFIGURATION-CONFIGURATION" + MiddleConfigurationCloudAccountKey = "CONFIGURATION-CLOUD_ACCOUNT" + MiddleConfigurationProjectKey = "CONFIGURATION-PROJECT" + MiddleConfigurationUserKey = "CONFIGURATION-USER" + MiddleConfigurationRoleKey = "CONFIGURATION-ROLE" + MiddleConfigurationSystemNotificationKey = "CONFIGURATION-SYSTEM_NOTIFICATION" ) type Permission struct { @@ -23,6 +53,7 @@ type Permission struct { ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` Name string `json:"name"` + Key string `gorm:"type:text;" json:"key,omitempty"` IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` RoleID *string `json:"role_id,omitempty"` @@ -38,7 +69,7 @@ type Permission struct { type PermissionSet struct { Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` Stack *Permission `gorm:"-:all" json:"stack,omitempty"` - SecurityPolicy *Permission `gorm:"-:all" json:"security_policy,omitempty"` + Policy *Permission `gorm:"-:all" json:"policy,omitempty"` ProjectManagement *Permission `gorm:"-:all" json:"project_management,omitempty"` Notification *Permission `gorm:"-:all" json:"notification,omitempty"` Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` @@ -50,11 +81,12 @@ func NewDefaultPermissionSet() *PermissionSet { return &PermissionSet{ Dashboard: newDashboard(), Stack: newStack(), - SecurityPolicy: newSecurityPolicy(), - ProjectManagement: newProjectManagement(), + Policy: newPolicy(), + ProjectManagement: newProject(), Notification: newNotification(), Configuration: newConfiguration(), Common: newCommon(), + Admin: nil, } } @@ -63,8 +95,8 @@ func NewAdminPermissionSet() *PermissionSet { Admin: newAdmin(), Dashboard: newDashboard(), Stack: newStack(), - SecurityPolicy: newSecurityPolicy(), - ProjectManagement: newProjectManagement(), + Policy: newPolicy(), + ProjectManagement: newProject(), Notification: newNotification(), Configuration: newConfiguration(), Common: newCommon(), @@ -101,14 +133,17 @@ func newDashboard() *Permission { dashboard := &Permission{ ID: uuid.New(), Name: string(DashBoardPermission), + Key: TopDashboardKey, Children: []*Permission{ { ID: uuid.New(), Name: "대시보드", + Key: MiddleDashboardKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetChartsDashboard, @@ -120,6 +155,7 @@ func newDashboard() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), }, }, @@ -134,14 +170,17 @@ func newStack() *Permission { stack := &Permission{ ID: uuid.New(), Name: string(StackPermission), + Key: TopStackKey, Children: []*Permission{ { ID: uuid.New(), Name: "스택", + Key: MiddleStackKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetStacks, @@ -169,6 +208,7 @@ func newStack() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateStack, @@ -189,6 +229,7 @@ func newStack() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateStack, @@ -197,6 +238,7 @@ func newStack() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteStack, @@ -216,18 +258,21 @@ func newStack() *Permission { return stack } -func newSecurityPolicy() *Permission { - security_policy := &Permission{ +func newPolicy() *Permission { + policy := &Permission{ ID: uuid.New(), - Name: string(SecurityPolicyPermission), + Name: string(PolicyPermission), + Key: TopPolicyKey, Children: []*Permission{ { ID: uuid.New(), Name: "정책", + Key: MiddlePolicyKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate @@ -268,6 +313,7 @@ func newSecurityPolicy() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate @@ -286,6 +332,7 @@ func newSecurityPolicy() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate @@ -308,6 +355,7 @@ func newSecurityPolicy() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate @@ -330,21 +378,24 @@ func newSecurityPolicy() *Permission { }, } - return security_policy + return policy } func newNotification() *Permission { notification := &Permission{ ID: uuid.New(), Name: string(NotificationPermission), + Key: TopNotificationKey, Children: []*Permission{ { ID: uuid.New(), Name: "시스템 알림", + Key: MiddleNotificationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetSystemNotification, @@ -354,6 +405,7 @@ func newNotification() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateSystemNotification, @@ -363,6 +415,7 @@ func newNotification() *Permission { { ID: uuid.New(), Name: "다운로드", + Key: OperationDownload, IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -371,16 +424,19 @@ func newNotification() *Permission { { ID: uuid.New(), Name: "정책 알림", + Key: MiddlePolicyNotificationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, { ID: uuid.New(), Name: "다운로드", + Key: OperationDownload, IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -392,18 +448,21 @@ func newNotification() *Permission { return notification } -func newProjectManagement() *Permission { - projectManagement := &Permission{ +func newProject() *Permission { + project := &Permission{ ID: uuid.New(), - Name: string(ProjectManagementPermission), + Name: string(ProjectPermission), + Key: TopProjectKey, Children: []*Permission{ { ID: uuid.New(), - Name: "프로젝트", + Name: "프로젝트 목록", + Key: MiddleProjectKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetProjects, @@ -414,6 +473,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateProject, @@ -422,6 +482,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateProject, @@ -430,6 +491,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteProject, @@ -440,10 +502,12 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "일반 설정", + Key: MiddleProjectCommonConfigurationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetProjects, @@ -456,6 +520,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateProject, @@ -466,10 +531,12 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "구성원 설정", + Key: MiddleProjectMemberConfigurationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetProjectMembers, @@ -481,6 +548,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.AddProjectMember, @@ -489,6 +557,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateProjectMemberRole, @@ -497,6 +566,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.RemoveProjectMember, @@ -507,10 +577,12 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "네임스페이스", + Key: MiddleProjectNamespaceKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetProjectNamespaces, @@ -521,6 +593,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateProjectNamespace, @@ -529,6 +602,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateProjectNamespace, @@ -537,6 +611,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteProjectNamespace, @@ -547,10 +622,12 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "앱 서빙", + Key: MiddleProjectAppServeKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetAppServeApps, @@ -566,6 +643,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateAppServeApp, @@ -580,6 +658,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateAppServeApp, @@ -594,6 +673,7 @@ func newProjectManagement() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteAppServeApp, @@ -604,26 +684,30 @@ func newProjectManagement() *Permission { }, } - return projectManagement + return project } func newConfiguration() *Permission { configuration := &Permission{ ID: uuid.New(), Name: string(ConfigurationPermission), + Key: TopConfigurationKey, Children: []*Permission{ { ID: uuid.New(), Name: "일반", + Key: MiddleConfigurationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), }, { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), }, }, @@ -631,10 +715,12 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "클라우드 계정", + Key: MiddleConfigurationCloudAccountKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetCloudAccounts, @@ -647,6 +733,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateCloudAccount, @@ -655,6 +742,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateCloudAccount, @@ -663,6 +751,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteCloudAccount, @@ -674,15 +763,18 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "프로젝트", + Key: MiddleConfigurationProjectKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), }, { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), }, }, @@ -690,10 +782,12 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "사용자", + Key: MiddleConfigurationUserKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.ListUser, @@ -705,6 +799,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateUser, @@ -715,6 +810,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateUser, @@ -724,6 +820,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteUser, @@ -734,10 +831,12 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "역할 및 권한", + Key: MiddleConfigurationRoleKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.ListTksRoles, @@ -749,6 +848,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateTksRole, @@ -757,6 +857,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateTksRole, @@ -766,6 +867,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteTksRole, @@ -776,10 +878,12 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "시스템 알림", + Key: MiddleConfigurationSystemNotificationKey, Children: []*Permission{ { ID: uuid.New(), Name: "조회", + Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.GetSystemNotificationRules, @@ -789,6 +893,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "생성", + Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateSystemNotificationRule, @@ -797,6 +902,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "수정", + Key: OperationUpdate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.UpdateSystemNotificationRule, @@ -805,6 +911,7 @@ func newConfiguration() *Permission { { ID: uuid.New(), Name: "삭제", + Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.DeleteSystemNotificationRule, @@ -926,7 +1033,7 @@ func (p *PermissionSet) SetAllowedPermissionSet() { edgePermissions := make([]*Permission, 0) edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, nil)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Policy, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, nil)...) @@ -943,7 +1050,7 @@ func (p *PermissionSet) SetUserPermissionSet() { edgePermissions := make([]*Permission, 0) edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.SecurityPolicy, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Policy, edgePermissions, &f)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) @@ -956,7 +1063,7 @@ func (p *PermissionSet) SetUserPermissionSet() { func (p *PermissionSet) SetRoleId(roleId string) { setRoleIdToPermission(p.Dashboard, roleId) setRoleIdToPermission(p.Stack, roleId) - setRoleIdToPermission(p.SecurityPolicy, roleId) + setRoleIdToPermission(p.Policy, roleId) setRoleIdToPermission(p.ProjectManagement, roleId) setRoleIdToPermission(p.Notification, roleId) setRoleIdToPermission(p.Configuration, roleId) diff --git a/internal/route/route.go b/internal/route/route.go index 1bd7beb8..04d93110 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -293,6 +293,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(permissionHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByAccountId, http.HandlerFunc(permissionHandler.GetPermissionsByAccountId))).Methods(http.MethodGet) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplate))).Methods(http.MethodGet) diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index 32b6bf0d..7db6be5d 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -15,6 +15,7 @@ type IPermissionUsecase interface { GetAllowedPermissionSet(ctx context.Context) *model.PermissionSet GetUserPermissionSet(ctx context.Context) *model.PermissionSet UpdatePermission(ctx context.Context, permission *model.Permission) error + MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet } type PermissionUsecase struct { @@ -35,7 +36,7 @@ func (p PermissionUsecase) CreatePermissionSet(ctx context.Context, permissionSe if err = p.repo.Create(ctx, permissionSet.Stack); err != nil { return err } - if err = p.repo.Create(ctx, permissionSet.SecurityPolicy); err != nil { + if err = p.repo.Create(ctx, permissionSet.Policy); err != nil { return err } if err = p.repo.Create(ctx, permissionSet.ProjectManagement); err != nil { @@ -54,7 +55,7 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(ctx context.Context, roleId permissionSet := &model.PermissionSet{ Dashboard: nil, Stack: nil, - SecurityPolicy: nil, + Policy: nil, ProjectManagement: nil, Notification: nil, Configuration: nil, @@ -70,9 +71,9 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(ctx context.Context, roleId permissionSet.Dashboard = permission case string(model.StackPermission): permissionSet.Stack = permission - case string(model.SecurityPolicyPermission): - permissionSet.SecurityPolicy = permission - case string(model.ProjectManagementPermission): + case string(model.PolicyPermission): + permissionSet.Policy = permission + case string(model.ProjectPermission): permissionSet.ProjectManagement = permission case string(model.NotificationPermission): permissionSet.Notification = permission @@ -115,3 +116,36 @@ func (p PermissionUsecase) GetUserPermissionSet(ctx context.Context) *model.Perm permissionSet.SetUserPermissionSet() return permissionSet } + +func (p PermissionUsecase) MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet { + var out *model.PermissionSet + for i, ps := range permissionSet { + if i == 0 { + out = ps + continue + } + + out.Dashboard = p.mergePermission(out.Dashboard, ps.Dashboard) + out.Stack = p.mergePermission(out.Stack, ps.Stack) + out.Policy = p.mergePermission(out.Policy, ps.Policy) + out.ProjectManagement = p.mergePermission(out.ProjectManagement, ps.ProjectManagement) + out.Notification = p.mergePermission(out.Notification, ps.Notification) + out.Configuration = p.mergePermission(out.Configuration, ps.Configuration) + } + + return out +} + +func (p PermissionUsecase) mergePermission(mergedPermission, permission *model.Permission) *model.Permission { + var mergedEdgePermissions []*model.Permission + mergedEdgePermissions = model.GetEdgePermission(mergedPermission, mergedEdgePermissions, nil) + + var rightEdgePermissions []*model.Permission + rightEdgePermissions = model.GetEdgePermission(permission, rightEdgePermissions, nil) + + for i, rightEdgePermission := range rightEdgePermissions { + *(mergedEdgePermissions[i].IsAllowed) = *(mergedEdgePermissions[i].IsAllowed) || *(rightEdgePermission.IsAllowed) + } + + return mergedPermission +} diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index 8be227a2..d9e83240 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -4,31 +4,67 @@ import ( "github.com/google/uuid" ) -type PermissionResponse struct { - ID uuid.UUID `json:"ID"` - Name string `json:"name"` - IsAllowed *bool `json:"is_allowed,omitempty"` - Endpoints []*EndpointResponse `json:"endpoints,omitempty"` - Children []*PermissionResponse `json:"children,omitempty"` +type GetPermissionTemplatesResponse struct { + Permissions *PermissionTemplateResponse `json:"permissions"` +} + +type PermissionTemplateResponse struct { + Dashboard *TemplateResponse `json:"dashboard,omitempty"` + Stack *TemplateResponse `json:"stack,omitempty"` + Policy *TemplateResponse `json:"policy,omitempty"` + ProjectManagement *TemplateResponse `json:"project_management,omitempty"` + Notification *TemplateResponse `json:"notification,omitempty"` + Configuration *TemplateResponse `json:"configuration,omitempty"` +} + +type TemplateResponse struct { + Name string `json:"name"` + Key string `json:"key"` + IsAllowed *bool `json:"is_allowed,omitempty"` + Children []*TemplateResponse `json:"children,omitempty"` +} + +type GetPermissionsByRoleIdResponse struct { + Permissions *PermissionSetResponse `json:"permissions"` } type PermissionSetResponse struct { Dashboard *PermissionResponse `json:"dashboard,omitempty"` Stack *PermissionResponse `json:"stack,omitempty"` - SecurityPolicy *PermissionResponse `json:"security_policy,omitempty"` + Policy *PermissionResponse `json:"policy,omitempty"` ProjectManagement *PermissionResponse `json:"project_management,omitempty"` Notification *PermissionResponse `json:"notification,omitempty"` Configuration *PermissionResponse `json:"configuration,omitempty"` } -type GetPermissionTemplatesResponse struct { - Permissions []*PermissionResponse `json:"permissions"` +type PermissionResponse struct { + ID uuid.UUID `json:"ID"` + Name string `json:"name"` + Key string `json:"key"` + IsAllowed *bool `json:"is_allowed,omitempty"` + Endpoints []*EndpointResponse `json:"endpoints,omitempty"` + Children []*PermissionResponse `json:"children,omitempty"` } -type GetPermissionsByRoleIdResponse struct { +type UpdatePermissionsByRoleIdRequest struct { Permissions []*PermissionResponse `json:"permissions"` } -type UpdatePermissionsByRoleIdRequest struct { - Permissions []*PermissionResponse `json:"permissions"` +type GetUsersPermissionsResponse struct { + Permissions *MergedPermissionSetResponse `json:"permissions"` +} + +type MergedPermissionSetResponse struct { + Dashboard *MergePermissionResponse `json:"dashboard,omitempty"` + Stack *MergePermissionResponse `json:"stack,omitempty"` + Policy *MergePermissionResponse `json:"policy,omitempty"` + ProjectManagement *MergePermissionResponse `json:"project_management,omitempty"` + Notification *MergePermissionResponse `json:"notification,omitempty"` + Configuration *MergePermissionResponse `json:"configuration,omitempty"` +} + +type MergePermissionResponse struct { + Key string `json:"key"` + IsAllowed *bool `json:"is_allowed,omitempty"` + Children []*MergePermissionResponse `json:"children,omitempty"` } From 6a2a4286a099371987c8267a4f5a67710290b071 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 17:43:27 +0900 Subject: [PATCH 178/502] lint fix --- internal/usecase/organization.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index ff7c59d0..9fa70a56 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -35,7 +35,6 @@ type OrganizationUsecase struct { roleRepo repository.IRoleRepository clusterRepo repository.IClusterRepository stackTemplateRepo repository.IStackTemplateRepository - policyTemplateRepo repository.IPolicyTemplateRepository systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository argo argowf.ArgoClient kc keycloak.IKeycloak From efb9b597f3936ad5d9a7b60f9db3f32727fe91b0 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 17:45:42 +0900 Subject: [PATCH 179/502] trimming --- internal/delivery/api/endpoint.go | 1 - internal/delivery/api/generated_endpoints.go.go | 8 -------- 2 files changed, 9 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index c5874faf..1bd43ae1 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -19,7 +19,6 @@ const ( VerifyIdentityForLostId VerifyIdentityForLostPassword VerifyToken - DeleteToken // User CreateUser diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index b4b8549e..8d1efb92 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -35,10 +35,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "VerifyToken", Group: "Auth", }, - DeleteToken: { - Name: "DeleteToken", - Group: "Auth", - }, CreateUser: { Name: "CreateUser", Group: "User", @@ -830,8 +826,6 @@ func (e Endpoint) String() string { return "VerifyIdentityForLostPassword" case VerifyToken: return "VerifyToken" - case DeleteToken: - return "DeleteToken" case CreateUser: return "CreateUser" case ListUser: @@ -1240,8 +1234,6 @@ func GetEndpoint(name string) Endpoint { return VerifyIdentityForLostPassword case "VerifyToken": return VerifyToken - case "DeleteToken": - return DeleteToken case "CreateUser": return CreateUser case "ListUser": From db0da2dcef1dc5c6a86fe5cfa362522db9ae45eb Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 17:57:13 +0900 Subject: [PATCH 180/502] minor fix. --- internal/delivery/http/permission.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 8ec9b7e9..04c8a947 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -15,6 +15,7 @@ type IPermissionHandler interface { GetPermissionTemplates(w http.ResponseWriter, r *http.Request) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) + GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) } type PermissionHandler struct { @@ -22,7 +23,7 @@ type PermissionHandler struct { userUsecase usecase.IUserUsecase } -func NewPermissionHandler(usecase usecase.Usecase) *PermissionHandler { +func NewPermissionHandler(usecase usecase.Usecase) IPermissionHandler { return &PermissionHandler{ permissionUsecase: usecase.Permission, userUsecase: usecase.User, From 7bb99f1d68cd85a0c2de1b242c63ad9347645b9e Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 20:18:58 +0900 Subject: [PATCH 181/502] Add project role to the response of login endpoint --- internal/delivery/http/auth.go | 25 +++++++++++++++++++++---- pkg/domain/auth.go | 26 +++++++++++++++++++------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index f817f8ba..ee87d823 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -28,14 +28,16 @@ type IAuthHandler interface { //Authenticate(next http.Handler) http.Handler } type AuthHandler struct { - usecase usecase.IAuthUsecase - auditUsecase usecase.IAuditUsecase + usecase usecase.IAuthUsecase + auditUsecase usecase.IAuditUsecase + projectUsecase usecase.IProjectUsecase } func NewAuthHandler(h usecase.Usecase) IAuthHandler { return &AuthHandler{ - usecase: h.Auth, - auditUsecase: h.Audit, + usecase: h.Auth, + auditUsecase: h.Audit, + projectUsecase: h.Project, } } @@ -95,11 +97,26 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { } } + projects, err := h.projectUsecase.GetProjects(r.Context(), input.OrganizationId, user.ID.String(), true, nil) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + var out domain.LoginResponse if err = serializer.Map(r.Context(), user, &out.User); err != nil { log.Error(r.Context(), err) } + for _, project := range projects { + var projectRole domain.ProjectIdProjectRoleResponse + projectRole.ID = project.ID + projectRole.ProjectRoleId = project.ProjectRoleId + projectRole.ProjectRoleName = project.ProjectRoleName + out.User.Projects = append(out.User.Projects, &projectRole) + } + ResponseJSON(w, r, http.StatusOK, out) } diff --git a/pkg/domain/auth.go b/pkg/domain/auth.go index d88da980..8d8983e3 100644 --- a/pkg/domain/auth.go +++ b/pkg/domain/auth.go @@ -8,16 +8,28 @@ type LoginRequest struct { type LoginResponse struct { User struct { - AccountId string `json:"accountId"` - Name string `json:"name"` - Token string `json:"token"` - Role RoleResponse `json:"role"` - Department string `json:"department"` - Organization OrganizationResponse `json:"organization"` - PasswordExpired bool `json:"passwordExpired"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Token string `json:"token"` + Role RoleIdRoleNameResponse `json:"role"` + Projects []*ProjectIdProjectRoleResponse `json:"projects"` + Department string `json:"department"` + Organization OrganizationResponse `json:"organization"` + PasswordExpired bool `json:"passwordExpired"` } `json:"user"` } +type RoleIdRoleNameResponse struct { + ID string `json:"roleId"` + Name string `json:"roleName"` +} + +type ProjectIdProjectRoleResponse struct { + ID string `json:"projectId"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` +} + type LogoutResponse struct { SsoUrls map[string][]string `json:"ssoUrls"` } From 81a1bebf962d68601fbdcd7c36ba713b13dd571e Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 19:38:34 +0900 Subject: [PATCH 182/502] Require users to obtain a new access token after changes to their TKS role or project role --- go.mod | 1 - internal/database/database.go | 5 +- internal/delivery/http/auth.go | 2 +- internal/delivery/http/project.go | 59 ++++++++++++-- internal/helper/jwt.go | 18 ++++- internal/keycloak/config.go | 6 +- internal/keycloak/keycloak.go | 6 +- .../auth/authenticator/authenticator.go | 24 +++++- .../authenticator/custom/authenticator.go | 80 +++++++++++++++++++ .../auth/authenticator/keycloak/keycloak.go | 21 +++-- internal/model/auth.go | 23 ++++++ internal/repository/auth.go | 47 +++++++---- internal/route/route.go | 3 +- internal/usecase/auth.go | 24 ++++-- internal/usecase/user.go | 13 ++- 15 files changed, 278 insertions(+), 54 deletions(-) create mode 100644 internal/middleware/auth/authenticator/custom/authenticator.go create mode 100644 internal/model/auth.go diff --git a/go.mod b/go.mod index a1014793..47e17ec0 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/ses v1.21.0 github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 github.com/deckarep/golang-set/v2 v2.6.0 - github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 github.com/go-playground/validator/v10 v10.18.0 diff --git a/internal/database/database.go b/internal/database/database.go index d70511cd..fbc85aac 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -61,7 +61,10 @@ func InitDB() (*gorm.DB, error) { func migrateSchema(db *gorm.DB) error { // Auth - if err := db.AutoMigrate(&repository.CacheEmailCode{}); err != nil { + if err := db.AutoMigrate(&model.CacheEmailCode{}); err != nil { + return err + } + if err := db.AutoMigrate(&model.ExpiredTokenTime{}); err != nil { return err } if err := db.AutoMigrate(&model.User{}); err != nil { diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index ee87d823..eec9d560 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -327,7 +327,7 @@ func (h *AuthHandler) VerifyToken(w http.ResponseWriter, r *http.Request) { } if !isActive { - ErrorJSON(w, r, httpErrors.NewUnauthorizedError(fmt.Errorf("token is not active"), "A_UNUSABLE_TOKEN", "")) + ErrorJSON(w, r, httpErrors.NewUnauthorizedError(fmt.Errorf("token is not active"), "A_EXPIRED_TOKEN", "")) return } diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index ba66719a..e5712505 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -58,12 +58,14 @@ type IProjectHandler interface { } type ProjectHandler struct { - usecase usecase.IProjectUsecase + usecase usecase.IProjectUsecase + authUsecase usecase.IAuthUsecase } func NewProjectHandler(u usecase.Usecase) IProjectHandler { return &ProjectHandler{ - usecase: u.Project, + usecase: u.Project, + authUsecase: u.Auth, } } @@ -624,6 +626,13 @@ func (p ProjectHandler) AddProjectMember(w http.ResponseWriter, r *http.Request) return } } + + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pmr.ProjectUserId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } } out := domain.CommonProjectResponse{Result: "OK"} @@ -898,6 +907,20 @@ func (p ProjectHandler) RemoveProjectMember(w http.ResponseWriter, r *http.Reque } } + pm, err := p.usecase.GetProjectMember(r.Context(), projectMemberId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, projectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -956,8 +979,8 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ } // TODO: change multi row delete - for _, pm := range projectMemberReq.ProjectMember { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pm.ProjectMemberId); err != nil { + for _, pmId := range projectMemberReq.ProjectMember { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, keycloak.DefaultClientID, pmId.ProjectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -965,14 +988,22 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ // tasks for keycloak & k8s for stackId := range stackIds { - if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pm.ProjectMemberId); err != nil { + if err := p.usecase.UnassignKeycloakClientRoleToMember(r.Context(), organizationId, projectId, stackId+"-k8s-api", pmId.ProjectMemberId); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } } - if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, pm.ProjectMemberId); err != nil { + pm, err := p.usecase.GetProjectMember(r.Context(), pmId.ProjectMemberId) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + + if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, pmId.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } @@ -1088,6 +1119,14 @@ func (p ProjectHandler) UpdateProjectMemberRole(w http.ResponseWriter, r *http.R } } + // update token expired time + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) } @@ -1190,6 +1229,14 @@ func (p ProjectHandler) UpdateProjectMembersRole(w http.ResponseWriter, r *http. return } } + + // update token expired time + err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } } ResponseJSON(w, r, http.StatusOK, domain.CommonProjectResponse{Result: "OK"}) diff --git a/internal/helper/jwt.go b/internal/helper/jwt.go index 68170a55..3db7184a 100644 --- a/internal/helper/jwt.go +++ b/internal/helper/jwt.go @@ -1,9 +1,10 @@ package helper import ( + "fmt" "time" - "github.com/golang-jwt/jwt" + "github.com/golang-jwt/jwt/v4" "github.com/spf13/viper" ) @@ -37,3 +38,18 @@ func VerifyToken(tokenString string) (*jwt.Token, error) { } return token, err } + +func StringToTokenWithoutVerification(tokenString string) (*jwt.Token, error) { + token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{}) + if err != nil { + return nil, fmt.Errorf("invalid token") + } + return token, nil +} +func RetrieveClaims(token *jwt.Token) (map[string]interface{}, error) { + claims, ok := token.Claims.(jwt.MapClaims) + if !ok { + return nil, fmt.Errorf("invalid token") + } + return claims, nil +} diff --git a/internal/keycloak/config.go b/internal/keycloak/config.go index 212748c1..eb26042c 100644 --- a/internal/keycloak/config.go +++ b/internal/keycloak/config.go @@ -12,7 +12,7 @@ const ( DefaultClientID = "tks" DefaultClientSecret = "secret" AdminCliClientID = "admin-cli" - accessTokenLifespan = 60 * 60 * 24 // 1 day - ssoSessionIdleTimeout = 60 * 60 * 24 // 1 day - ssoSessionMaxLifespan = 60 * 60 * 24 // 1 day + AccessTokenLifespan = 60 * 60 * 24 // 1 day + SsoSessionIdleTimeout = 60 * 60 * 24 // 1 day + SsoSessionMaxLifespan = 60 * 60 * 24 // 1 day ) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index ff69db1c..d7618fee 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -927,9 +927,9 @@ func defaultRealmSetting(realmId string) gocloak.RealmRepresentation { return gocloak.RealmRepresentation{ Realm: gocloak.StringP(realmId), Enabled: gocloak.BoolP(true), - AccessTokenLifespan: gocloak.IntP(accessTokenLifespan), - SsoSessionIdleTimeout: gocloak.IntP(ssoSessionIdleTimeout), - SsoSessionMaxLifespan: gocloak.IntP(ssoSessionMaxLifespan), + AccessTokenLifespan: gocloak.IntP(AccessTokenLifespan), + SsoSessionIdleTimeout: gocloak.IntP(SsoSessionIdleTimeout), + SsoSessionMaxLifespan: gocloak.IntP(SsoSessionMaxLifespan), } } diff --git a/internal/middleware/auth/authenticator/authenticator.go b/internal/middleware/auth/authenticator/authenticator.go index 80ea6bba..8f8ab1b3 100644 --- a/internal/middleware/auth/authenticator/authenticator.go +++ b/internal/middleware/auth/authenticator/authenticator.go @@ -2,6 +2,7 @@ package authenticator import ( "fmt" + "github.com/openinfradev/tks-api/internal/repository" "net/http" internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" @@ -19,23 +20,38 @@ type Request interface { } type defaultAuthenticator struct { - auth Request + kcAuth Request + customAuth Request + repo repository.Repository } -func NewAuthenticator(kc Request) *defaultAuthenticator { +func NewAuthenticator(kc Request, repo repository.Repository, c Request) *defaultAuthenticator { return &defaultAuthenticator{ - auth: kc, + kcAuth: kc, + repo: repo, + customAuth: c, } } func (a *defaultAuthenticator) WithAuthentication(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - resp, ok, err := a.auth.AuthenticateRequest(r) + resp, ok, err := a.kcAuth.AuthenticateRequest(r) if !ok { log.Error(r.Context(), err) internalHttp.ErrorJSON(w, r, err) return } + if err != nil { + internalHttp.ErrorJSON(w, r, err) + return + } + + _, ok, err = a.customAuth.AuthenticateRequest(r) + if !ok { + internalHttp.ErrorJSON(w, r, err) + return + } + r = r.WithContext(request.WithUser(r.Context(), resp.User)) _, ok = request.UserFrom(r.Context()) diff --git a/internal/middleware/auth/authenticator/custom/authenticator.go b/internal/middleware/auth/authenticator/custom/authenticator.go new file mode 100644 index 00000000..f92f218a --- /dev/null +++ b/internal/middleware/auth/authenticator/custom/authenticator.go @@ -0,0 +1,80 @@ +package custom + +import ( + "fmt" + "github.com/openinfradev/tks-api/internal/helper" + "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "net/http" + "strings" +) + +type CustomAuthenticator struct { + repo repository.Repository +} + +func NewCustomAuthenticator(repo repository.Repository) *CustomAuthenticator { + return &CustomAuthenticator{ + repo: repo, + } +} +func (a *CustomAuthenticator) AuthenticateRequest(r *http.Request) (*authenticator.Response, bool, error) { + authHeader := strings.TrimSpace(r.Header.Get("Authorization")) + if authHeader == "" { + return nil, false, fmt.Errorf("authorizer header is invalid") + } + parts := strings.SplitN(authHeader, " ", 3) + if len(parts) < 2 || strings.ToLower(parts[0]) != "bearer" { + return nil, false, fmt.Errorf("authorizer header is invalid") + } + token := parts[1] + + if len(token) == 0 { + // The space before the token case + if len(parts) == 3 { + log.Warn(r.Context(), "the provided Authorization header contains extra space before the bearer token, and is ignored") + } + return nil, false, fmt.Errorf("token is empty") + } + + parsedToken, err := helper.StringToTokenWithoutVerification(token) + if err != nil { + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + claims, err := helper.RetrieveClaims(parsedToken) + if err != nil { + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + organizationId, ok := claims["organization"].(string) + if !ok { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("organizationId is not found"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + userId, ok := claims["sub"].(string) + if !ok { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("userId is not found"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + expiredTime, err := a.repo.Auth.GetExpiredTimeOnToken(r.Context(), organizationId, userId) + if expiredTime == nil { + return nil, true, nil + } + if err != nil { + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + iat, ok := claims["iat"].(float64) + if !ok { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("iat is not found"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + if int64(iat) < expiredTime.ExpiredTime.Unix() { + return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("token is changed"), "A_UNUSABLE_TOKEN", "토큰이 변경되었습니다.") + } + + return nil, true, nil +} diff --git a/internal/middleware/auth/authenticator/keycloak/keycloak.go b/internal/middleware/auth/authenticator/keycloak/keycloak.go index 8f0ee136..dcc649a8 100644 --- a/internal/middleware/auth/authenticator/keycloak/keycloak.go +++ b/internal/middleware/auth/authenticator/keycloak/keycloak.go @@ -2,11 +2,11 @@ package keycloak import ( "fmt" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/pkg/httpErrors" "net/http" "strings" - jwtWithouKey "github.com/dgrijalva/jwt-go" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" @@ -49,12 +49,17 @@ func (a *keycloakAuthenticator) AuthenticateRequest(r *http.Request) (*authentic } func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) (*authenticator.Response, bool, error) { - parsedToken, _, err := new(jwtWithouKey.Parser).ParseUnverified(token, jwtWithouKey.MapClaims{}) + parsedToken, err := helper.StringToTokenWithoutVerification(token) if err != nil { return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } - organizationId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["organization"].(string) + claims, err := helper.RetrieveClaims(parsedToken) + if err != nil { + return nil, false, httpErrors.NewUnauthorizedError(err, "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") + } + + organizationId, ok := claims["organization"].(string) if !ok { return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("organization is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } @@ -70,7 +75,7 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) // tks role extraction roleOrganizationMapping := make(map[string]string) - if roles, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["tks-role"]; !ok { + if roles, ok := claims["tks-role"]; !ok { log.Errorf(r.Context(), "tks-role is not found in token") return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("tks-role is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") @@ -90,7 +95,7 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) // project role extraction projectIds := make([]string, 0) roleProjectMapping := make(map[string]string) - if roles, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["project-role"]; ok { + if roles, ok := claims["project-role"]; ok { for _, role := range roles.([]interface{}) { slice := strings.Split(role.(string), "@") if len(slice) != 2 { @@ -104,18 +109,18 @@ func (a *keycloakAuthenticator) AuthenticateToken(r *http.Request, token string) } } - userId, err := uuid.Parse(parsedToken.Claims.(jwtWithouKey.MapClaims)["sub"].(string)) + userId, err := uuid.Parse(claims["sub"].(string)) if err != nil { log.Errorf(r.Context(), "failed to verify access token: %v", err) return nil, false, httpErrors.NewUnauthorizedError(err, "C_INTERNAL_ERROR", "") } - requestSessionId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["sid"].(string) + requestSessionId, ok := claims["sid"].(string) if !ok { return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("session id is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } - userAccountId, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["preferred_username"].(string) + userAccountId, ok := claims["preferred_username"].(string) if !ok { return nil, false, httpErrors.NewUnauthorizedError(fmt.Errorf("preferred_username is not found in token"), "A_INVALID_TOKEN", "토큰이 유효하지 않습니다.") } diff --git a/internal/model/auth.go b/internal/model/auth.go new file mode 100644 index 00000000..b2866816 --- /dev/null +++ b/internal/model/auth.go @@ -0,0 +1,23 @@ +package model + +import ( + "github.com/google/uuid" + "gorm.io/gorm" + "time" +) + +// Models +type ExpiredTokenTime struct { + gorm.Model + + OrganizationId string `gorm:"index:idx_org_id_subject_id,unique;not null"` + SubjectId string `gorm:"index:idx_org_id_subject_id,unique;not null"` + ExpiredTime time.Time +} + +type CacheEmailCode struct { + gorm.Model + + UserId uuid.UUID `gorm:"not null"` + Code string `gorm:"type:varchar(6);not null"` +} diff --git a/internal/repository/auth.go b/internal/repository/auth.go index d9c86a59..c59d4c7f 100644 --- a/internal/repository/auth.go +++ b/internal/repository/auth.go @@ -3,29 +3,25 @@ package repository import ( "context" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/model" "gorm.io/gorm" + "gorm.io/gorm/clause" + "time" ) type IAuthRepository interface { CreateEmailCode(ctx context.Context, userId uuid.UUID, code string) error - GetEmailCode(ctx context.Context, userId uuid.UUID) (CacheEmailCode, error) + GetEmailCode(ctx context.Context, userId uuid.UUID) (model.CacheEmailCode, error) UpdateEmailCode(ctx context.Context, userId uuid.UUID, code string) error DeleteEmailCode(ctx context.Context, userId uuid.UUID) error + GetExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) (*model.ExpiredTokenTime, error) + UpdateExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) error } type AuthRepository struct { db *gorm.DB } -// Models - -type CacheEmailCode struct { - gorm.Model - - UserId uuid.UUID `gorm:"not null"` - Code string `gorm:"type:varchar(6);not null"` -} - func NewAuthRepository(db *gorm.DB) IAuthRepository { return &AuthRepository{ db: db, @@ -33,25 +29,44 @@ func NewAuthRepository(db *gorm.DB) IAuthRepository { } func (r *AuthRepository) CreateEmailCode(ctx context.Context, userId uuid.UUID, code string) error { - cacheEmailCode := CacheEmailCode{ + cacheEmailCode := model.CacheEmailCode{ UserId: userId, Code: code, } return r.db.WithContext(ctx).Create(&cacheEmailCode).Error } -func (r *AuthRepository) GetEmailCode(ctx context.Context, userId uuid.UUID) (CacheEmailCode, error) { - var cacheEmailCode CacheEmailCode +func (r *AuthRepository) GetEmailCode(ctx context.Context, userId uuid.UUID) (model.CacheEmailCode, error) { + var cacheEmailCode model.CacheEmailCode if err := r.db.WithContext(ctx).Where("user_id = ?", userId).First(&cacheEmailCode).Error; err != nil { - return CacheEmailCode{}, err + return model.CacheEmailCode{}, err } return cacheEmailCode, nil } func (r *AuthRepository) UpdateEmailCode(ctx context.Context, userId uuid.UUID, code string) error { - return r.db.WithContext(ctx).Model(&CacheEmailCode{}).Where("user_id = ?", userId).Update("code", code).Error + return r.db.WithContext(ctx).Model(&model.CacheEmailCode{}).Where("user_id = ?", userId).Update("code", code).Error } func (r *AuthRepository) DeleteEmailCode(ctx context.Context, userId uuid.UUID) error { - return r.db.WithContext(ctx).Unscoped().Where("user_id = ?", userId).Delete(&CacheEmailCode{}).Error + return r.db.WithContext(ctx).Unscoped().Where("user_id = ?", userId).Delete(&model.CacheEmailCode{}).Error +} + +func (r *AuthRepository) GetExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) (*model.ExpiredTokenTime, error) { + var expiredTokenTime model.ExpiredTokenTime + if err := r.db.WithContext(ctx).Where("organization_id = ? AND subject_id = ?", organizationId, userId).First(&expiredTokenTime).Error; err != nil { + return nil, err + } + return &expiredTokenTime, nil +} +func (r *AuthRepository) UpdateExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) error { + // set expired time to now + return r.db.WithContext(ctx).Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "subject_id"}, {Name: "organization_id"}}, + DoUpdates: clause.AssignmentColumns([]string{"expired_time"}), + }).Create(&model.ExpiredTokenTime{ + SubjectId: userId, + ExpiredTime: time.Now(), + OrganizationId: organizationId, + }).Error } diff --git a/internal/route/route.go b/internal/route/route.go index 04d93110..3783f41f 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -16,6 +16,7 @@ import ( "github.com/openinfradev/tks-api/internal/keycloak" internalMiddleware "github.com/openinfradev/tks-api/internal/middleware" "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator" + authCustom "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator/custom" authKeycloak "github.com/openinfradev/tks-api/internal/middleware/auth/authenticator/keycloak" "github.com/openinfradev/tks-api/internal/middleware/auth/authorizer" "github.com/openinfradev/tks-api/internal/repository" @@ -85,7 +86,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa } customMiddleware := internalMiddleware.NewMiddleware( - authenticator.NewAuthenticator(authKeycloak.NewKeycloakAuthenticator(kc)), + authenticator.NewAuthenticator(authKeycloak.NewKeycloakAuthenticator(kc), repoFactory, authCustom.NewCustomAuthenticator(repoFactory)), authorizer.NewDefaultAuthorization(repoFactory), requestRecoder.NewDefaultRequestRecoder(), audit.NewDefaultAudit(repoFactory)) diff --git a/internal/usecase/auth.go b/internal/usecase/auth.go index 485a60a6..f8edf598 100644 --- a/internal/usecase/auth.go +++ b/internal/usecase/auth.go @@ -12,8 +12,6 @@ import ( "strings" "time" - jwtWithouKey "github.com/dgrijalva/jwt-go" - "github.com/openinfradev/tks-api/pkg/log" "github.com/spf13/viper" "golang.org/x/net/html" @@ -32,13 +30,14 @@ import ( type IAuthUsecase interface { Login(ctx context.Context, accountId string, password string, organizationId string) (model.User, error) - Logout(ctx context.Context, accessToken string, organizationId string) error + Logout(ctx context.Context, sessionId string, organizationId string) error FindId(ctx context.Context, code string, email string, userName string, organizationId string) (string, error) FindPassword(ctx context.Context, code string, accountId string, email string, userName string, organizationId string) error VerifyIdentity(ctx context.Context, accountId string, email string, userName string, organizationId string) error SingleSignIn(ctx context.Context, organizationId, accountId, password string) ([]*http.Cookie, error) SingleSignOut(ctx context.Context, organizationId string) (string, []*http.Cookie, error) VerifyToken(ctx context.Context, token string) (bool, error) + UpdateExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) error } const ( @@ -96,9 +95,9 @@ func (u *AuthUsecase) Login(ctx context.Context, accountId string, password stri return user, nil } -func (u *AuthUsecase) Logout(ctx context.Context, accessToken string, organizationName string) error { +func (u *AuthUsecase) Logout(ctx context.Context, sessionId string, organizationName string) error { // [TODO] refresh token 을 추가하고, session timeout 을 줄이는 방향으로 고려할 것 - err := u.kc.Logout(ctx, accessToken, organizationName) + err := u.kc.Logout(ctx, sessionId, organizationName) if err != nil { return err } @@ -305,11 +304,16 @@ func (u *AuthUsecase) SingleSignOut(ctx context.Context, organizationId string) } func (u *AuthUsecase) VerifyToken(ctx context.Context, token string) (bool, error) { - parsedToken, _, err := new(jwtWithouKey.Parser).ParseUnverified(token, jwtWithouKey.MapClaims{}) + parsedToken, err := helper.StringToTokenWithoutVerification(token) + if err != nil { + return false, err + } + claims, err := helper.RetrieveClaims(parsedToken) if err != nil { return false, err } - org, ok := parsedToken.Claims.(jwtWithouKey.MapClaims)["organization"].(string) + + org, ok := claims["organization"].(string) if !ok { return false, fmt.Errorf("organization is not found in token") } @@ -325,7 +329,11 @@ func (u *AuthUsecase) VerifyToken(ctx context.Context, token string) (bool, erro return true, nil } -func (u *AuthUsecase) isExpiredEmailCode(code repository.CacheEmailCode) bool { +func (u *AuthUsecase) UpdateExpiredTimeOnToken(ctx context.Context, organizationId string, userId string) error { + return u.authRepository.UpdateExpiredTimeOnToken(ctx, organizationId, userId) +} + +func (u *AuthUsecase) isExpiredEmailCode(code model.CacheEmailCode) bool { return !helper.IsDurationExpired(code.UpdatedAt, internal.EmailCodeExpireTime) } diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 5730e87d..ad8308f3 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -29,7 +29,7 @@ type IUserUsecase interface { Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) ResetPassword(ctx context.Context, userId uuid.UUID) error ResetPasswordByAccountId(ctx context.Context, accountId string, organizationId string) error - GenerateRandomPassword(ctx context.Context, ) string + GenerateRandomPassword(ctx context.Context) string Delete(ctx context.Context, userId uuid.UUID, organizationId string) error GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) @@ -47,6 +47,7 @@ type IUserUsecase interface { } type UserUsecase struct { + authRepository repository.IAuthRepository userRepository repository.IUserRepository roleRepository repository.IRoleRepository organizationRepository repository.IOrganizationRepository @@ -510,6 +511,15 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st log.Errorf(ctx, "join group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } + + targetUser, err := u.userRepository.Get(ctx, newUser.AccountId, newUser.Organization.ID) + if err != nil { + return nil, err + } + err = u.authRepository.UpdateExpiredTimeOnToken(ctx, newUser.Organization.ID, targetUser.ID.String()) + if err != nil { + return nil, err + } } *user, err = u.userRepository.UpdateWithUuid(ctx, user.ID, user.AccountId, user.Name, newUser.Role.ID, user.Email, @@ -523,6 +533,7 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId st func NewUserUsecase(r repository.Repository, kc keycloak.IKeycloak) IUserUsecase { return &UserUsecase{ + authRepository: r.Auth, userRepository: r.User, roleRepository: r.Role, kc: kc, From e92b58f1a80705bf6a8f580c95055b2534bdbf13 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 22 Mar 2024 19:49:59 +0900 Subject: [PATCH 183/502] lint fix --- internal/delivery/http/project.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index e5712505..c5405eed 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1002,6 +1002,11 @@ func (p ProjectHandler) RemoveProjectMembers(w http.ResponseWriter, r *http.Requ return } err = p.authUsecase.UpdateExpiredTimeOnToken(r.Context(), organizationId, pm.ProjectUserId.String()) + if err != nil { + log.Error(r.Context(), err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } if err := p.usecase.RemoveProjectMember(r.Context(), organizationId, pmId.ProjectMemberId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) From 14e63bcc6248dd1afcd4c339142acecff5305cbb Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 22 Mar 2024 15:19:32 +0900 Subject: [PATCH 184/502] feature. implemntation systemnotification conditions --- api/swagger/docs.go | 183 +++++++++++++++++- api/swagger/swagger.json | 183 +++++++++++++++++- api/swagger/swagger.yaml | 122 ++++++++++++ internal/database/database.go | 5 +- .../delivery/http/system-notification-rule.go | 71 ++++++- internal/model/system-notification-rule.go | 51 ++--- .../repository/system-notification-rule.go | 45 +++-- internal/route/route.go | 8 +- internal/usecase/system-notification-rule.go | 73 +++++-- pkg/domain/system-notification-rule.go | 71 ++++++- pkg/httpErrors/errorCode.go | 8 +- 11 files changed, 734 insertions(+), 86 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index e3c7dc34..45504123 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -9475,14 +9475,68 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { "type": "object", "required": [ - "name" + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" ], "properties": { "description": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, @@ -11946,6 +12000,46 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter": { + "type": "object", + "properties": { + "operator": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse": { "type": "object", "properties": { @@ -12032,9 +12126,36 @@ const docTemplate = `{ "id": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" }, + "systemNotificationConditions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" + } + }, + "systemNotificationTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" + }, + "targetUsers": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + }, "updatedAt": { "type": "string" }, @@ -12547,9 +12668,69 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", + "required": [ + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" + ], "properties": { "description": { "type": "string" + }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, + "name": { + "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 4011501e..d04a4c49 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -9469,14 +9469,68 @@ "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { "type": "object", "required": [ - "name" + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" ], "properties": { "description": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, @@ -11940,6 +11994,46 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter": { + "type": "object", + "properties": { + "operator": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse": { "type": "object", "properties": { @@ -12026,9 +12120,36 @@ "id": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" }, + "systemNotificationConditions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" + } + }, + "systemNotificationTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" + }, + "targetUsers": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + }, "updatedAt": { "type": "string" }, @@ -12541,9 +12662,69 @@ }, "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", + "required": [ + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" + ], "properties": { "description": { "type": "string" + }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, + "name": { + "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 3950feae..865f2519 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1099,10 +1099,47 @@ definitions: properties: description: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string name: type: string + systemNotificationConditions: + items: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + type: array + systemNotificationTemplateId: + type: string + targetUserIds: + items: + type: string + type: array required: + - messageCondition + - messageContent + - messageTitle - name + - systemNotificationTemplateId type: object github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse: properties: @@ -2728,6 +2765,32 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter: + properties: + operator: + type: string + order: + type: integer + value: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse: properties: closedAt: @@ -2785,8 +2848,26 @@ definitions: type: string id: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string name: type: string + systemNotificationConditions: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse' + type: array + systemNotificationTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse' + targetUsers: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + type: array updatedAt: type: string updator: @@ -3129,6 +3210,47 @@ definitions: properties: description: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string + name: + type: string + systemNotificationConditions: + items: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + type: array + systemNotificationTemplateId: + type: string + targetUserIds: + items: + type: string + type: array + required: + - messageCondition + - messageContent + - messageTitle + - name + - systemNotificationTemplateId type: object github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest: properties: diff --git a/internal/database/database.go b/internal/database/database.go index fbc85aac..4a480a4e 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -130,13 +130,10 @@ func migrateSchema(db *gorm.DB) error { } // SystemNotificationRule - if err := db.AutoMigrate(&model.SystemNotificationRule{}); err != nil { - return err - } if err := db.AutoMigrate(&model.SystemNotificationCondition{}); err != nil { return err } - if err := db.AutoMigrate(&model.SystemNotificationMessage{}); err != nil { + if err := db.AutoMigrate(&model.SystemNotificationRule{}); err != nil { return err } diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 068966bc..2c27207c 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -1,6 +1,7 @@ package http import ( + "encoding/json" "fmt" "net/http" @@ -38,6 +39,13 @@ func NewSystemNotificationRuleHandler(h usecase.Usecase) *SystemNotificationRule // @Router /organizations/{organizationId}/system-notification-rules [post] // @Security JWT func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + input := domain.CreateSystemNotificationRuleRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { @@ -49,6 +57,14 @@ func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.Resp if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } + dto.OrganizationId = organizationId + + dto.SystemNotificationConditions = make([]model.SystemNotificationCondition, len(input.SystemNotificationConditions)) + for i, systemNotificationCondition := range input.SystemNotificationConditions { + if err := serializer.Map(r.Context(), systemNotificationCondition, &dto.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + } id, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -99,6 +115,25 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.Respon if err := serializer.Map(r.Context(), systemNotificationRule, &out.SystemNotificationRules[i]); err != nil { log.Info(r.Context(), err) } + + out.SystemNotificationRules[i].TargetUsers = make([]domain.SimpleUserResponse, len(systemNotificationRule.TargetUsers)) + for j, targetUser := range systemNotificationRule.TargetUsers { + if err := serializer.Map(r.Context(), targetUser, &out.SystemNotificationRules[i].TargetUsers[j]); err != nil { + log.Info(r.Context(), err) + } + } + + out.SystemNotificationRules[i].SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) + for j, condition := range systemNotificationRule.SystemNotificationConditions { + if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRules[i].SystemNotificationConditions[j]); err != nil { + log.Info(r.Context(), err) + } + log.Info(r.Context(), condition.Parameter) + err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRules[i].SystemNotificationConditions[j].Parameters) + if err != nil { + log.Error(r.Context(), err) + } + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { @@ -144,6 +179,18 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons log.Info(r.Context(), err) } + out.SystemNotificationRule.SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) + for i, condition := range systemNotificationRule.SystemNotificationConditions { + if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRule.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + log.Info(r.Context(), condition.Parameter) + err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRule.SystemNotificationConditions[i].Parameters) + if err != nil { + log.Error(r.Context(), err) + } + } + ResponseJSON(w, r, http.StatusOK, out) } @@ -160,24 +207,44 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons // @Security JWT func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + strId, ok := vars["systemNotificationRuleId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) return } - systemNotificationRuleId, err := uuid.Parse(strId) if err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) return } + input := domain.UpdateSystemNotificationRuleRequest{} + err = UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + var dto model.SystemNotificationRule - if err := serializer.Map(r.Context(), r, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } + dto.OrganizationId = organizationId dto.ID = systemNotificationRuleId + dto.SystemNotificationConditions = make([]model.SystemNotificationCondition, len(input.SystemNotificationConditions)) + for i, systemNotificationCondition := range input.SystemNotificationConditions { + if err := serializer.Map(r.Context(), systemNotificationCondition, &dto.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + } + err = h.usecase.Update(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index b1ddee30..9ab63c37 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -2,40 +2,43 @@ package model import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/datatypes" "gorm.io/gorm" ) type SystemNotificationCondition struct { - SystemNotificationRuleId uuid.UUID `gorm:"primarykey"` - Order int `gorm:"primarykey"` + gorm.Model + + SystemNotificationRuleId uuid.UUID + Order int Severity string Duration int - Condition datatypes.JSON - EnableEmail bool `gorm:"default:false"` - EnablePortal bool `gorm:"default:true"` -} - -type SystemNotificationMessage struct { - SystemNotificationRuleId uuid.UUID `gorm:"primarykey"` - Title string - Content int - Condition datatypes.JSON - ActionProposal string - TargetUsers []User `gorm:"many2many:system_notification_message_users"` + Parameter datatypes.JSON + Parameters []domain.SystemNotificationParameter `gorm:"-:all"` + EnableEmail bool `gorm:"default:false"` + EnablePortal bool `gorm:"default:true"` } type SystemNotificationRule struct { gorm.Model - ID uuid.UUID `gorm:"primarykey"` - Name string `gorm:"index,unique"` - Description string - Templates []SystemNotificationTemplate `gorm:"many2many:system_notification_rule_system_notification_templates"` - Messages []SystemNotificationMessage `gorm:"many2many:system_notification_rule_system_notification_messages"` - - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator *User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator *User `gorm:"foreignKey:UpdatorId"` + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index,unique"` + Description string + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + SystemNotificationTemplate SystemNotificationTemplate `gorm:"foreignKey:SystemNotificationTemplateId"` + SystemNotificationTemplateId string + SystemNotificationConditions []SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId"` + TargetUsers []User `gorm:"many2many:system_notification_rule_users"` + TargetUserIds []string `gorm:"-:all"` + MessageTitle string + MessageContent string + MessageCondition datatypes.JSON + MessageActionProposal string + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator *User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator *User `gorm:"foreignKey:UpdatorId"` } diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 3e07db21..84ed1063 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -20,7 +20,6 @@ type ISystemNotificationRuleRepository interface { Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRuleId uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) - UpdateOrganizations(ctx context.Context, systemNotificationRuleId uuid.UUID, organizationIds []model.Organization) (err error) } type SystemNotificationRuleRepository struct { @@ -83,40 +82,48 @@ func (r *SystemNotificationRuleRepository) Create(ctx context.Context, dto model if res.Error != nil { return uuid.Nil, res.Error } + return dto.ID, nil } func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) { - res := r.db.WithContext(ctx).Model(&model.SystemNotificationRule{}). - Where("id = ?", dto.ID). - Updates(map[string]interface{}{ - "Name": dto.Name, - "Description": dto.Description, - "UpdatorId": dto.UpdatorId}) + var m model.SystemNotificationRule + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&m, "id = ?", dto.ID) if res.Error != nil { return res.Error } - return nil -} -func (r *SystemNotificationRuleRepository) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { - res := r.db.WithContext(ctx).Delete(&model.SystemNotificationRule{}, "id = ?", dto.ID) + m.Name = dto.Name + m.Description = dto.Description + m.SystemNotificationTemplateId = dto.SystemNotificationTemplateId + //m.SystemNotificationConditions = dto.SystemNotificationConditions + m.MessageTitle = dto.MessageTitle + m.MessageContent = dto.MessageContent + m.MessageCondition = dto.MessageCondition + m.MessageActionProposal = dto.MessageActionProposal + m.UpdatorId = dto.UpdatorId + + res = r.db.WithContext(ctx).Session(&gorm.Session{FullSaveAssociations: true}).Updates(&m) if res.Error != nil { return res.Error } - return nil -} -func (r *SystemNotificationRuleRepository) UpdateOrganizations(ctx context.Context, systemNotificationRuleId uuid.UUID, organizations []model.Organization) (err error) { - var systemNotificationRule = model.SystemNotificationRule{} - res := r.db.WithContext(ctx).Preload("Organizations").First(&systemNotificationRule, "id = ?", systemNotificationRuleId) - if res.Error != nil { - return res.Error + err = r.db.WithContext(ctx).Model(&m).Association("TargetUsers").Replace(dto.TargetUsers) + if err != nil { + return err } - err = r.db.WithContext(ctx).Model(&systemNotificationRule).Association("Organizations").Replace(organizations) + err = r.db.WithContext(ctx).Model(&m).Association("SystemNotificationConditions").Replace(dto.SystemNotificationConditions) if err != nil { return err } return nil } + +func (r *SystemNotificationRuleRepository) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { + res := r.db.WithContext(ctx).Delete(&model.SystemNotificationRule{}, "id = ?", dto.ID) + if res.Error != nil { + return res.Error + } + return nil +} diff --git a/internal/route/route.go b/internal/route/route.go index 3783f41f..51e639c5 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -228,10 +228,10 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.RemoveOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.RemoveOrganizationSystemNotificationTemplates))).Methods(http.MethodPut) systemNotificationRuleHandler := delivery.NewSystemNotificationRuleHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 8aa4c384..d69c5c15 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -20,19 +21,22 @@ type ISystemNotificationRuleUsecase interface { Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRule uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationRule) error Delete(ctx context.Context, dto model.SystemNotificationRule) error - UpdateOrganizations(ctx context.Context, dto model.SystemNotificationRule) error GetByName(ctx context.Context, name string) (model.SystemNotificationRule, error) } type SystemNotificationRuleUsecase struct { - repo repository.ISystemNotificationRuleRepository - organizationRepo repository.IOrganizationRepository + repo repository.ISystemNotificationRuleRepository + organizationRepo repository.IOrganizationRepository + userRepo repository.IUserRepository + systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository } func NewSystemNotificationRuleUsecase(r repository.Repository) ISystemNotificationRuleUsecase { return &SystemNotificationRuleUsecase{ - repo: r.SystemNotificationRule, - organizationRepo: r.Organization, + repo: r.SystemNotificationRule, + organizationRepo: r.Organization, + userRepo: r.User, + systemNotificationTemplateRepo: r.SystemNotificationTemplate, } } @@ -46,10 +50,34 @@ func (u *SystemNotificationRuleUsecase) Create(ctx context.Context, dto model.Sy dto.UpdatorId = &userId if _, err = u.GetByName(ctx, dto.Name); err == nil { - return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate systemNotificationRule name"), "ST_CREATE_ALREADY_EXISTED_NAME", "") + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate systemNotificationRule name"), "SNR_CREATE_ALREADY_EXISTED_NAME", "") } - return systemNotificationRuleId, nil + // Users + dto.TargetUsers = make([]model.User, 0) + for _, strId := range dto.TargetUserIds { + userId, err := uuid.Parse(strId) + if err == nil { + user, err := u.userRepo.GetByUuid(ctx, userId) + if err == nil { + dto.TargetUsers = append(dto.TargetUsers, user) + } + } + } + + // Make parameters + for i, condition := range dto.SystemNotificationConditions { + dto.SystemNotificationConditions[i].Parameter = []byte(helper.ModelToJson(condition.Parameters)) + } + + systemNotificationRuleId, err = u.repo.Create(ctx, dto) + if err != nil { + return uuid.Nil, err + } + + // [TODO] update kubernetes resources + + return } func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.SystemNotificationRule) error { @@ -58,10 +86,30 @@ func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.Sy return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") } + // Users + dto.TargetUsers = make([]model.User, 0) + for _, strId := range dto.TargetUserIds { + userId, err := uuid.Parse(strId) + if err == nil { + user, err := u.userRepo.GetByUuid(ctx, userId) + if err == nil { + dto.TargetUsers = append(dto.TargetUsers, user) + } + } + } + + for i, condition := range dto.SystemNotificationConditions { + dto.SystemNotificationConditions[i].SystemNotificationRuleId = dto.ID + dto.SystemNotificationConditions[i].Parameter = []byte(helper.ModelToJson(condition.Parameters)) + } + err = u.repo.Update(ctx, dto) if err != nil { return err } + + // [TODO] update kubernetes resources + return nil } @@ -77,7 +125,7 @@ func (u *SystemNotificationRuleUsecase) GetByName(ctx context.Context, name stri out, err = u.repo.GetByName(ctx, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return out, httpErrors.NewNotFoundError(err, "SNR_FAILED_FETCH_STACK_TEMPLATE", "") + return out, httpErrors.NewNotFoundError(err, "SNR_FAILED_FETCH_SYSTEM_NOTIFICATION_RULE", "") } return out, err } @@ -96,12 +144,3 @@ func (u *SystemNotificationRuleUsecase) Fetch(ctx context.Context, organizationI func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { return nil } - -func (u *SystemNotificationRuleUsecase) UpdateOrganizations(ctx context.Context, dto model.SystemNotificationRule) error { - _, err := u.repo.Get(ctx, dto.ID) - if err != nil { - return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") - } - - return nil -} diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index e21e3477..d891799a 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -5,13 +5,35 @@ import ( ) type SystemNotificationRuleResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Creator SimpleUserResponse `json:"creator"` - Updator SimpleUserResponse `json:"updator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle"` + MessageContent string `json:"messageContent"` + MessageCondition string `json:"messageCondition"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUsers []SimpleUserResponse `json:"targetUsers"` + SystemNotificationTemplate SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplate"` + SystemNotificationConditions []SystemNotificationConditionResponse `json:"systemNotificationConditions"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type SystemNotificationParameter struct { + Order int `json:"order"` + Operator string `json:"operator"` + Value string `json:"value"` +} + +type SystemNotificationConditionResponse struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` } type SimpleSystemNotificationRuleResponse struct { @@ -30,8 +52,22 @@ type GetSystemNotificationRuleResponse struct { } type CreateSystemNotificationRuleRequest struct { - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle" validate:"required"` + MessageContent string `json:"messageContent" validate:"required"` + MessageCondition string `json:"messageCondition" validate:"required"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUserIds []string `json:"targetUserIds"` + SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` + SystemNotificationConditions []struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` + } `json:"systemNotificationConditions"` } type CreateSystemNotificationRuleResponse struct { @@ -39,7 +75,22 @@ type CreateSystemNotificationRuleResponse struct { } type UpdateSystemNotificationRuleRequest struct { - Description string `json:"description"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle" validate:"required"` + MessageContent string `json:"messageContent" validate:"required"` + MessageCondition string `json:"messageCondition" validate:"required"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUserIds []string `json:"targetUserIds"` + SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` + SystemNotificationConditions []struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` + } `json:"systemNotificationConditions"` } type CheckSystemNotificationRuleNameResponse struct { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index f8e1b961..63fe9dfd 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -89,10 +89,10 @@ var errorMap = map[ErrorCode]string{ "SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.", // SystemNotificationRule - "SNR_CREATE_ALREADY_EXISTED_NAME": "알림템플릿 설정에 이미 존재하는 이름입니다.", - "SNR_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿 설정을 가져오는데 실패했습니다.", - "SNR_FAILED_UPDATE_ORGANIZATION": "알림템플릿 설정에 조직을 설정하는데 실패했습니다.", - "SNR_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿 설정이 존재하지 않습니다.", + "SNR_CREATE_ALREADY_EXISTED_NAME": "알림 설정에 이미 존재하는 이름입니다.", + "SNR_FAILED_FETCH_SYSTEM_NOTIFICATION_RULE": "알림 설정을 가져오는데 실패했습니다.", + "SNR_FAILED_UPDATE_ORGANIZATION": "알림 설정에 조직을 설정하는데 실패했습니다.", + "SNR_NOT_EXISTED_SYSTEM_NOTIFICATION_RULE": "업데이트할 알림 설정이 존재하지 않습니다.", // AppGroup "AG_NOT_FOUND_CLUSTER": "지장한 클러스터가 존재하지 않습니다.", From 8f58fc4cce71bce422444596356d273f5abd0efe Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 25 Mar 2024 14:41:03 +0900 Subject: [PATCH 185/502] fix api docs --- api/swagger/docs.go | 193 +++++++++++++++--- api/swagger/swagger.json | 193 +++++++++++++++--- api/swagger/swagger.yaml | 137 ++++++++++--- go.mod | 2 +- go.sum | 6 +- internal/delivery/api/endpoint.go | 6 +- .../delivery/api/generated_endpoints.go.go | 32 +-- internal/delivery/http/permission.go | 189 ----------------- internal/delivery/http/role.go | 127 +++++++++++- internal/delivery/http/user.go | 104 +++++++++- internal/model/permission.go | 26 +-- internal/route/route.go | 6 +- 12 files changed, 678 insertions(+), 343 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 45504123..e2878fbc 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -246,7 +246,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Admin List Tks Roles", "parameters": [ @@ -275,7 +275,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Admin Get Tks Role", "parameters": [ @@ -314,7 +314,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Admin" + "Users" ], "summary": "Get user detail by admin", "parameters": [ @@ -356,7 +356,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Admin" + "Users" ], "summary": "Update user by admin", "parameters": [ @@ -5926,7 +5926,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "List Tks Roles", "parameters": [ @@ -5961,7 +5961,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Create Tks Role", "parameters": [ @@ -6004,7 +6004,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Get Tks Role", "parameters": [ @@ -6046,7 +6046,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Update Tks Role", "parameters": [ @@ -6091,7 +6091,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Delete Tks Role", "parameters": [ @@ -6125,16 +6125,29 @@ const docTemplate = `{ } ], "description": "Get Permissions By Role ID", - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], "tags": [ - "Permission" + "Roles" ], "summary": "Get Permissions By Role ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -6158,10 +6171,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Permission" + "Roles" ], "summary": "Update Permissions By Role ID", "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "Role ID", @@ -7734,6 +7754,47 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/users/{accountId}/permissions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permissions By Account ID", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get Permissions By Account ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse" + } + } + } + } + }, "/organizations/{organizationId}/users/{accountId}/reset-password": { "put": { "security": [ @@ -9775,17 +9836,11 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" - }, "group": { "type": "string" }, "name": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, @@ -10505,6 +10560,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse": { + "type": "object", + "properties": { + "permissions": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest": { "type": "object", "required": [ @@ -10708,8 +10771,14 @@ const docTemplate = `{ "passwordExpired": { "type": "boolean" }, + "projects": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse" + } + }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse" }, "token": { "type": "string" @@ -10790,6 +10859,46 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } + }, + "is_allowed": { + "type": "boolean" + }, + "key": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse": { + "type": "object", + "properties": { + "configuration": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "dashboard": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "notification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "project_management": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "stack": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { "type": "object", "required": [ @@ -10935,19 +11044,10 @@ const docTemplate = `{ "is_allowed": { "type": "boolean" }, - "name": { - "type": "string" - }, - "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "parent_id": { + "key": { "type": "string" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "role_id": { + "name": { "type": "string" } } @@ -10964,10 +11064,10 @@ const docTemplate = `{ "notification": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, - "project_management": { + "policy": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, - "security_policy": { + "project_management": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "stack": { @@ -11206,6 +11306,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + }, + "projectRoleName": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest": { "type": "object", "required": [ @@ -11533,6 +11647,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse": { + "type": "object", + "properties": { + "roleId": { + "type": "string" + }, + "roleName": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index d04a4c49..27347d15 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -240,7 +240,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Admin List Tks Roles", "parameters": [ @@ -269,7 +269,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Admin Get Tks Role", "parameters": [ @@ -308,7 +308,7 @@ "application/json" ], "tags": [ - "Admin" + "Users" ], "summary": "Get user detail by admin", "parameters": [ @@ -350,7 +350,7 @@ "application/json" ], "tags": [ - "Admin" + "Users" ], "summary": "Update user by admin", "parameters": [ @@ -5920,7 +5920,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "List Tks Roles", "parameters": [ @@ -5955,7 +5955,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Create Tks Role", "parameters": [ @@ -5998,7 +5998,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Get Tks Role", "parameters": [ @@ -6040,7 +6040,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Update Tks Role", "parameters": [ @@ -6085,7 +6085,7 @@ "application/json" ], "tags": [ - "Role" + "Roles" ], "summary": "Delete Tks Role", "parameters": [ @@ -6119,16 +6119,29 @@ } ], "description": "Get Permissions By Role ID", - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], "tags": [ - "Permission" + "Roles" ], "summary": "Get Permissions By Role ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -6152,10 +6165,17 @@ "application/json" ], "tags": [ - "Permission" + "Roles" ], "summary": "Update Permissions By Role ID", "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "Role ID", @@ -7728,6 +7748,47 @@ } } }, + "/organizations/{organizationId}/users/{accountId}/permissions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permissions By Account ID", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get Permissions By Account ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse" + } + } + } + } + }, "/organizations/{organizationId}/users/{accountId}/reset-password": { "put": { "security": [ @@ -9769,17 +9830,11 @@ "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { - "createdAt": { - "type": "string" - }, "group": { "type": "string" }, "name": { "type": "string" - }, - "updatedAt": { - "type": "string" } } }, @@ -10499,6 +10554,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse": { + "type": "object", + "properties": { + "permissions": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest": { "type": "object", "required": [ @@ -10702,8 +10765,14 @@ "passwordExpired": { "type": "boolean" }, + "projects": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse" + } + }, "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse" }, "token": { "type": "string" @@ -10784,6 +10853,46 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } + }, + "is_allowed": { + "type": "boolean" + }, + "key": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse": { + "type": "object", + "properties": { + "configuration": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "dashboard": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "notification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "policy": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "project_management": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + }, + "stack": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { "type": "object", "required": [ @@ -10929,19 +11038,10 @@ "is_allowed": { "type": "boolean" }, - "name": { - "type": "string" - }, - "parent": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "parent_id": { + "key": { "type": "string" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "role_id": { + "name": { "type": "string" } } @@ -10958,10 +11058,10 @@ "notification": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, - "project_management": { + "policy": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, - "security_policy": { + "project_management": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" }, "stack": { @@ -11200,6 +11300,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse": { + "type": "object", + "properties": { + "projectId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + }, + "projectRoleName": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest": { "type": "object", "required": [ @@ -11527,6 +11641,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse": { + "type": "object", + "properties": { + "roleId": { + "type": "string" + }, + "roleName": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 865f2519..b4b04e01 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1299,14 +1299,10 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.EndpointResponse: properties: - createdAt: - type: string group: type: string name: type: string - updatedAt: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: @@ -1768,6 +1764,11 @@ definitions: type: string type: object type: object + github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse: + properties: + permissions: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest: properties: cloudService: @@ -1902,8 +1903,12 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' passwordExpired: type: boolean + projects: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse' + type: array role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse' token: type: string type: object @@ -1957,6 +1962,32 @@ definitions: example: 레이블 요구 type: string type: object + github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse: + properties: + children: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + type: array + is_allowed: + type: boolean + key: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse: + properties: + configuration: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + dashboard: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + notification: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + policy: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + project_management: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + stack: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse: properties: key: @@ -2053,15 +2084,9 @@ definitions: type: array is_allowed: type: boolean - name: - type: string - parent: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - parent_id: + key: type: string - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' - role_id: + name: type: string type: object github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse: @@ -2072,9 +2097,9 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' notification: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - project_management: + policy: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - security_policy: + project_management: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' stack: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' @@ -2241,6 +2266,15 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse: + properties: + projectId: + type: string + projectRoleId: + type: string + projectRoleName: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest: properties: projectRoleId: @@ -2456,6 +2490,13 @@ definitions: usage: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse: + properties: + roleId: + type: string + roleName: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.RoleResponse: properties: createdAt: @@ -3634,7 +3675,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' summary: Admin List Tks Roles tags: - - Role + - Roles /admin/organizations/{organizationId}/roles/{roleId}: get: description: Admin Get Tks Role @@ -3658,7 +3699,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse' summary: Admin Get Tks Role tags: - - Role + - Roles /admin/organizations/{organizationId}/users/{accountId}: get: consumes: @@ -3684,7 +3725,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse' summary: Get user detail by admin tags: - - Admin + - Users put: consumes: - application/json @@ -3717,7 +3758,7 @@ paths: - JWT: [] summary: Update user by admin tags: - - Admin + - Users /admin/policy-templates: get: consumes: @@ -7250,7 +7291,7 @@ paths: - JWT: [] summary: List Tks Roles tags: - - Role + - Roles post: consumes: - application/json @@ -7278,7 +7319,7 @@ paths: - JWT: [] summary: Create Tks Role tags: - - Role + - Roles /organizations/{organizationId}/roles/{roleId}: delete: description: Delete Tks Role @@ -7302,7 +7343,7 @@ paths: - JWT: [] summary: Delete Tks Role tags: - - Role + - Roles get: description: Get Tks Role parameters: @@ -7327,7 +7368,7 @@ paths: - JWT: [] summary: Get Tks Role tags: - - Role + - Roles put: consumes: - application/json @@ -7358,12 +7399,21 @@ paths: - JWT: [] summary: Update Tks Role tags: - - Role + - Roles /organizations/{organizationId}/roles/{roleId}/permissions: get: - consumes: - - application/json description: Get Permissions By Role ID + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string produces: - application/json responses: @@ -7375,12 +7425,17 @@ paths: - JWT: [] summary: Get Permissions By Role ID tags: - - Permission + - Roles put: consumes: - application/json description: Update Permissions By Role ID parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string - description: Role ID in: path name: roleId @@ -7401,7 +7456,7 @@ paths: - JWT: [] summary: Update Permissions By Role ID tags: - - Permission + - Roles /organizations/{organizationId}/stack-templates: get: consumes: @@ -8333,6 +8388,32 @@ paths: summary: Update user tags: - Users + /organizations/{organizationId}/users/{accountId}/permissions: + get: + description: Get Permissions By Account ID + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Account ID + in: path + name: accountId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse' + security: + - JWT: [] + summary: Get Permissions By Account ID + tags: + - Users /organizations/{organizationId}/users/{accountId}/reset-password: put: consumes: diff --git a/go.mod b/go.mod index 47e17ec0..92db160f 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 github.com/go-playground/validator/v10 v10.18.0 - github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/golang-jwt/jwt/v4 v4.5.0 github.com/golang/mock v1.6.0 github.com/google/uuid v1.6.0 github.com/gorilla/handlers v1.5.2 diff --git a/go.sum b/go.sum index d3bf874f..9a81524e 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -132,8 +130,8 @@ github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 1bd43ae1..e740b404 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -29,6 +29,7 @@ const ( ResetPassword CheckId CheckEmail + GetPermissionsByAccountId // MyProfile GetMyProfile @@ -189,12 +190,11 @@ const ( GetTksRole DeleteTksRole UpdateTksRole + GetPermissionsByRoleId + UpdatePermissionsByRoleId // Permission GetPermissionTemplates - GetPermissionsByRoleId - UpdatePermissionsByRoleId - GetPermissionsByAccountId // Admin_User Admin_CreateUser diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 8d1efb92..9e2c008d 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -67,6 +67,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CheckEmail", Group: "User", }, + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", + Group: "User", + }, GetMyProfile: { Name: "GetMyProfile", Group: "MyProfile", @@ -587,20 +591,16 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdateTksRole", Group: "Role", }, - GetPermissionTemplates: { - Name: "GetPermissionTemplates", - Group: "Permission", - }, GetPermissionsByRoleId: { Name: "GetPermissionsByRoleId", - Group: "Permission", + Group: "Role", }, UpdatePermissionsByRoleId: { Name: "UpdatePermissionsByRoleId", - Group: "Permission", + Group: "Role", }, - GetPermissionsByAccountId: { - Name: "GetPermissionsByAccountId", + GetPermissionTemplates: { + Name: "GetPermissionTemplates", Group: "Permission", }, Admin_CreateUser: { @@ -842,6 +842,8 @@ func (e Endpoint) String() string { return "CheckId" case CheckEmail: return "CheckEmail" + case GetPermissionsByAccountId: + return "GetPermissionsByAccountId" case GetMyProfile: return "GetMyProfile" case UpdateMyProfile: @@ -1102,14 +1104,12 @@ func (e Endpoint) String() string { return "DeleteTksRole" case UpdateTksRole: return "UpdateTksRole" - case GetPermissionTemplates: - return "GetPermissionTemplates" case GetPermissionsByRoleId: return "GetPermissionsByRoleId" case UpdatePermissionsByRoleId: return "UpdatePermissionsByRoleId" - case GetPermissionsByAccountId: - return "GetPermissionsByAccountId" + case GetPermissionTemplates: + return "GetPermissionTemplates" case Admin_CreateUser: return "Admin_CreateUser" case Admin_ListUser: @@ -1250,6 +1250,8 @@ func GetEndpoint(name string) Endpoint { return CheckId case "CheckEmail": return CheckEmail + case "GetPermissionsByAccountId": + return GetPermissionsByAccountId case "GetMyProfile": return GetMyProfile case "UpdateMyProfile": @@ -1510,14 +1512,12 @@ func GetEndpoint(name string) Endpoint { return DeleteTksRole case "UpdateTksRole": return UpdateTksRole - case "GetPermissionTemplates": - return GetPermissionTemplates case "GetPermissionsByRoleId": return GetPermissionsByRoleId case "UpdatePermissionsByRoleId": return UpdatePermissionsByRoleId - case "GetPermissionsByAccountId": - return GetPermissionsByAccountId + case "GetPermissionTemplates": + return GetPermissionTemplates case "Admin_CreateUser": return Admin_CreateUser case "Admin_ListUser": diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 04c8a947..f298a394 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -4,18 +4,13 @@ import ( "context" "net/http" - "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/httpErrors" ) type IPermissionHandler interface { GetPermissionTemplates(w http.ResponseWriter, r *http.Request) - GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) - UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) - GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) } type PermissionHandler struct { @@ -71,187 +66,3 @@ func convertModelToPermissionTemplateResponse(ctx context.Context, permission *m return &permissionResponse } - -// GetPermissionsByAccountId godoc -// -// @Tags Permission -// @Summary Get Permissions By Account ID -// @Description Get Permissions By Account ID -// @Accept json -// @Produce json -// @Success 200 {object} domain.GetUsersPermissionsResponse -// @Router /organizations/{organizationId}/users/{accountId}/permissions [get] -// @Security JWT -func (h PermissionHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) { - var organizationId, accountId string - - vars := mux.Vars(r) - if v, ok := vars["accountId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - accountId = v - } - if v, ok := vars["organizationId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - organizationId = v - } - - user, err := h.userUsecase.GetByAccountId(r.Context(), accountId, organizationId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - - var roles []*model.Role - roles = append(roles, &user.Role) - - var permissionSets []*model.PermissionSet - for _, role := range roles { - permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - permissionSets = append(permissionSets, permissionSet) - } - - mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) - - var permissions domain.MergedPermissionSetResponse - permissions.Dashboard = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard) - permissions.Stack = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack) - permissions.Policy = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy) - permissions.ProjectManagement = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement) - permissions.Notification = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification) - permissions.Configuration = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration) - - var out domain.GetUsersPermissionsResponse - out.Permissions = &permissions - ResponseJSON(w, r, http.StatusOK, out) - -} - -func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { - var permissionResponse domain.MergePermissionResponse - - permissionResponse.Key = permission.Key - if permission.IsAllowed != nil { - permissionResponse.IsAllowed = permission.IsAllowed - } - - for _, child := range permission.Children { - permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child)) - } - - return &permissionResponse -} - -// GetPermissionsByRoleId godoc -// -// @Tags Permission -// @Summary Get Permissions By Role ID -// @Description Get Permissions By Role ID -// @Accept json -// @Produce json -// @Success 200 {object} domain.PermissionSetResponse -// @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] -// @Security JWT -func (h PermissionHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { - // path parameter - var roleId string - - vars := mux.Vars(r) - if v, ok := vars["roleId"]; !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) - return - } else { - roleId = v - } - - permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), roleId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - - var permissionSetResponse domain.PermissionSetResponse - permissionSetResponse.Dashboard = convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard) - permissionSetResponse.Stack = convertModelToPermissionResponse(r.Context(), permissionSet.Stack) - permissionSetResponse.Policy = convertModelToPermissionResponse(r.Context(), permissionSet.Policy) - permissionSetResponse.ProjectManagement = convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement) - permissionSetResponse.Notification = convertModelToPermissionResponse(r.Context(), permissionSet.Notification) - permissionSetResponse.Configuration = convertModelToPermissionResponse(r.Context(), permissionSet.Configuration) - - var out domain.GetPermissionsByRoleIdResponse - out.Permissions = &permissionSetResponse - - ResponseJSON(w, r, http.StatusOK, out) -} - -func convertModelToPermissionResponse(ctx context.Context, permission *model.Permission) *domain.PermissionResponse { - var permissionResponse domain.PermissionResponse - - permissionResponse.ID = permission.ID - permissionResponse.Key = permission.Key - permissionResponse.Name = permission.Name - if permission.IsAllowed != nil { - permissionResponse.IsAllowed = permission.IsAllowed - } - - for _, endpoint := range permission.Endpoints { - permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint)) - } - - for _, child := range permission.Children { - permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child)) - } - - return &permissionResponse -} - -func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { - var endpointResponse domain.EndpointResponse - - endpointResponse.Name = endpoint.Name - endpointResponse.Group = endpoint.Group - - return &endpointResponse -} - -// UpdatePermissionsByRoleId godoc -// -// @Tags Permission -// @Summary Update Permissions By Role ID -// @Description Update Permissions By Role ID -// @Accept json -// @Produce json -// @Param roleId path string true "Role ID" -// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" -// @Success 200 -// @Router /organizations/{organizationId}/roles/{roleId}/permissions [put] -// @Security JWT -func (h PermissionHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { - // request - input := domain.UpdatePermissionsByRoleIdRequest{} - err := UnmarshalRequestInput(r, &input) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - for _, permissionResponse := range input.Permissions { - var permission model.Permission - permission.ID = permissionResponse.ID - permission.IsAllowed = permissionResponse.IsAllowed - - if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - } - - ResponseJSON(w, r, http.StatusOK, nil) -} diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 8aebd4ab..21658fd9 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -1,6 +1,7 @@ package http import ( + "context" "net/http" "github.com/gorilla/mux" @@ -20,6 +21,9 @@ type IRoleHandler interface { DeleteTksRole(w http.ResponseWriter, r *http.Request) UpdateTksRole(w http.ResponseWriter, r *http.Request) + GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) + UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) + Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) } @@ -38,7 +42,7 @@ func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { // CreateTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Create Tks Role // @Description Create Tks Role // @Accept json @@ -98,7 +102,7 @@ func (h RoleHandler) CreateTksRole(w http.ResponseWriter, r *http.Request) { // ListTksRoles godoc // -// @Tags Role +// @Tags Roles // @Summary List Tks Roles // @Description List Tks Roles // @Produce json @@ -153,7 +157,7 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { // GetTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Get Tks Role // @Description Get Tks Role // @Produce json @@ -195,7 +199,7 @@ func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // DeleteTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Delete Tks Role // @Description Delete Tks Role // @Produce json @@ -227,7 +231,7 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { // UpdateTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Update Tks Role // @Description Update Tks Role // @Accept json @@ -273,9 +277,118 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, nil) } +// GetPermissionsByRoleId godoc +// +// @Tags Roles +// @Summary Get Permissions By Role ID +// @Description Get Permissions By Role ID +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Success 200 {object} domain.PermissionSetResponse +// @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] +// @Security JWT +func (h RoleHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { + // path parameter + var roleId string + + vars := mux.Vars(r) + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), roleId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + var permissionSetResponse domain.PermissionSetResponse + permissionSetResponse.Dashboard = convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard) + permissionSetResponse.Stack = convertModelToPermissionResponse(r.Context(), permissionSet.Stack) + permissionSetResponse.Policy = convertModelToPermissionResponse(r.Context(), permissionSet.Policy) + permissionSetResponse.ProjectManagement = convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement) + permissionSetResponse.Notification = convertModelToPermissionResponse(r.Context(), permissionSet.Notification) + permissionSetResponse.Configuration = convertModelToPermissionResponse(r.Context(), permissionSet.Configuration) + + var out domain.GetPermissionsByRoleIdResponse + out.Permissions = &permissionSetResponse + + ResponseJSON(w, r, http.StatusOK, out) +} + +func convertModelToPermissionResponse(ctx context.Context, permission *model.Permission) *domain.PermissionResponse { + var permissionResponse domain.PermissionResponse + + permissionResponse.ID = permission.ID + permissionResponse.Key = permission.Key + permissionResponse.Name = permission.Name + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } + + for _, endpoint := range permission.Endpoints { + permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint)) + } + + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child)) + } + + return &permissionResponse +} + +func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { + var endpointResponse domain.EndpointResponse + + endpointResponse.Name = endpoint.Name + endpointResponse.Group = endpoint.Group + + return &endpointResponse +} + +// UpdatePermissionsByRoleId godoc +// +// @Tags Roles +// @Summary Update Permissions By Role ID +// @Description Update Permissions By Role ID +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Param body body domain.UpdatePermissionsByRoleIdRequest true "Update Permissions By Role ID Request" +// @Success 200 +// @Router /organizations/{organizationId}/roles/{roleId}/permissions [put] +// @Security JWT +func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { + // request + input := domain.UpdatePermissionsByRoleIdRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + for _, permissionResponse := range input.Permissions { + var permission model.Permission + permission.ID = permissionResponse.ID + permission.IsAllowed = permissionResponse.IsAllowed + + if err := h.permissionUsecase.UpdatePermission(r.Context(), &permission); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + // Admin_ListTksRoles godoc // -// @Tags Role +// @Tags Roles // @Summary Admin List Tks Roles // @Description Admin List Tks Roles // @Produce json @@ -330,7 +443,7 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) // Admin_GetTksRole godoc // -// @Tags Role +// @Tags Roles // @Summary Admin Get Tks Role // @Description Admin Get Tks Role // @Produce json diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 9d6f09ef..f9764f05 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -1,6 +1,7 @@ package http import ( + "context" "fmt" "net/http" "strings" @@ -34,6 +35,7 @@ type IUserHandler interface { CheckId(w http.ResponseWriter, r *http.Request) CheckEmail(w http.ResponseWriter, r *http.Request) + GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) // Admin Admin_Create(w http.ResponseWriter, r *http.Request) @@ -44,16 +46,18 @@ type IUserHandler interface { } type UserHandler struct { - usecase usecase.IUserUsecase - authUsecase usecase.IAuthUsecase - roleUsecase usecase.IRoleUsecase + usecase usecase.IUserUsecase + authUsecase usecase.IAuthUsecase + roleUsecase usecase.IRoleUsecase + permissionUsecase usecase.IPermissionUsecase } func NewUserHandler(h usecase.Usecase) IUserHandler { return &UserHandler{ - usecase: h.User, - authUsecase: h.Auth, - roleUsecase: h.Role, + usecase: h.User, + authUsecase: h.Auth, + roleUsecase: h.Role, + permissionUsecase: h.Permission, } } @@ -667,8 +671,86 @@ func (u UserHandler) CheckEmail(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } +// GetPermissionsByAccountId godoc +// +// @Tags Users +// @Summary Get Permissions By Account ID +// @Description Get Permissions By Account ID +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param accountId path string true "Account ID" +// @Success 200 {object} domain.GetUsersPermissionsResponse +// @Router /organizations/{organizationId}/users/{accountId}/permissions [get] +// @Security JWT +func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Request) { + var organizationId, accountId string + + vars := mux.Vars(r) + if v, ok := vars["accountId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + accountId = v + } + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + user, err := u.usecase.GetByAccountId(r.Context(), accountId, organizationId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + var roles []*model.Role + roles = append(roles, &user.Role) + + var permissionSets []*model.PermissionSet + for _, role := range roles { + permissionSet, err := u.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + permissionSets = append(permissionSets, permissionSet) + } + + mergedPermissionSet := u.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) + + var permissions domain.MergedPermissionSetResponse + permissions.Dashboard = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard) + permissions.Stack = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack) + permissions.Policy = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy) + permissions.ProjectManagement = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement) + permissions.Notification = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification) + permissions.Configuration = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration) + + var out domain.GetUsersPermissionsResponse + out.Permissions = &permissions + ResponseJSON(w, r, http.StatusOK, out) + +} + +func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { + var permissionResponse domain.MergePermissionResponse + + permissionResponse.Key = permission.Key + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } + + for _, child := range permission.Children { + permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child)) + } + + return &permissionResponse +} + // Admin_Create godoc -// @Tags Admin +// @Tags Users // @Summary Create user by admin // @Description Create user by admin // @Accept json @@ -766,7 +848,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } // Admin_List godoc -// @Tags Admin +// @Tags Users // @Summary Get user list by admin // @Description Get user list by admin // @Accept json @@ -815,7 +897,7 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { // Admin_Get godoc // -// @Tags Admin +// @Tags Users // @Summary Get user detail by admin // @Description Get user detail by admin // @Accept json @@ -859,7 +941,7 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { } // Admin_Delete godoc -// @Tags Admin +// @Tags Users // @Summary Delete user by admin // @Description Delete user by admin // @Accept json @@ -925,7 +1007,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { // Admin_Update godoc // -// @Tags Admin +// @Tags Users // @Summary Update user by admin // @Description Update user by admin // @Accept json diff --git a/internal/model/permission.go b/internal/model/permission.go index 87e06b6e..7fafc931 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -276,14 +276,14 @@ func newPolicy() *Permission { IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate - api.ListPolicyTemplate, - api.GetPolicyTemplate, - api.GetPolicyTemplateDeploy, - api.ListPolicyTemplateStatistics, - api.ListPolicyTemplateVersions, - api.GetPolicyTemplateVersion, - api.ExistsPolicyTemplateName, - api.ExistsPolicyTemplateKind, + api.Admin_ListPolicyTemplate, + api.Admin_GetPolicyTemplate, + api.Admin_GetPolicyTemplateDeploy, + api.Admin_ListPolicyTemplateStatistics, + api.Admin_ListPolicyTemplateVersions, + api.Admin_GetPolicyTemplateVersion, + api.Admin_ExistsPolicyTemplateName, + api.Admin_ExistsPolicyTemplateKind, // ClusterPolicyStatus api.ListClusterPolicyStatus, @@ -317,8 +317,8 @@ func newPolicy() *Permission { IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate - api.CreatePolicyTemplate, - api.CreatePolicyTemplateVersion, + api.Admin_CreatePolicyTemplate, + api.Admin_CreatePolicyTemplateVersion, // Policy api.SetMandatoryPolicies, @@ -336,7 +336,7 @@ func newPolicy() *Permission { IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate - api.UpdatePolicyTemplate, + api.Admin_UpdatePolicyTemplate, // ClusterPolicyStatus api.UpdateClusterPolicyTemplateStatus, @@ -359,8 +359,8 @@ func newPolicy() *Permission { IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( // PolicyTemplate - api.DeletePolicyTemplate, - api.DeletePolicyTemplateVersion, + api.Admin_DeletePolicyTemplate, + api.Admin_DeletePolicyTemplateVersion, // Policy api.DeletePolicy, diff --git a/internal/route/route.go b/internal/route/route.go index 51e639c5..36a6fbd4 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -123,6 +123,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/password", customMiddleware.Handle(internalApi.UpdateMyPassword, http.HandlerFunc(userHandler.UpdateMyPassword))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/next-password-change", customMiddleware.Handle(internalApi.RenewPasswordExpiredDate, http.HandlerFunc(userHandler.RenewPasswordExpiredDate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.DeleteMyProfile, http.HandlerFunc(userHandler.DeleteMyProfile))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByAccountId, http.HandlerFunc(userHandler.GetPermissionsByAccountId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_CreateUser, http.HandlerFunc(userHandler.Admin_Create))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_ListUser, http.HandlerFunc(userHandler.Admin_List))).Methods(http.MethodGet) @@ -284,6 +285,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.GetTksRole, http.HandlerFunc(roleHandler.GetTksRole))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.DeleteTksRole, http.HandlerFunc(roleHandler.DeleteTksRole))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateTksRole, http.HandlerFunc(roleHandler.UpdateTksRole))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(roleHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(roleHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) // Admin r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.Admin_ListTksRoles, http.HandlerFunc(roleHandler.Admin_ListTksRoles))).Methods(http.MethodGet) @@ -292,9 +295,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa permissionHandler := delivery.NewPermissionHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(permissionHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(permissionHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByAccountId, http.HandlerFunc(permissionHandler.GetPermissionsByAccountId))).Methods(http.MethodGet) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplate))).Methods(http.MethodGet) From 46b43877b38465da280c99fe98e85d9743896031 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 25 Mar 2024 15:21:21 +0900 Subject: [PATCH 186/502] tirivial. fix swagger error --- api/swagger/docs.go | 29 +++++++++++++++++-- api/swagger/swagger.json | 29 +++++++++++++++++-- api/swagger/swagger.yaml | 22 ++++++++++++-- .../http/system-notification-template.go | 2 +- 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index e2878fbc..c11e1f95 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1306,7 +1306,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest" } } } @@ -9609,11 +9609,34 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest": { "type": "object", + "required": [ + "metricQuery", + "name", + "organizationIds" + ], "properties": { - "id": { + "description": { "type": "string" + }, + "metricParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + } + }, + "metricQuery": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 27347d15..2dc52e14 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1300,7 +1300,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest" } } } @@ -9603,11 +9603,34 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse": { + "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest": { "type": "object", + "required": [ + "metricQuery", + "name", + "organizationIds" + ], "properties": { - "id": { + "description": { "type": "string" + }, + "metricParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + } + }, + "metricQuery": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index b4b04e01..b879b812 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1146,10 +1146,26 @@ definitions: id: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse: + github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest: properties: - id: + description: + type: string + metricParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse' + type: array + metricQuery: + type: string + name: type: string + organizationIds: + items: + type: string + type: array + required: + - metricQuery + - name + - organizationIds type: object github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest: properties: @@ -4330,7 +4346,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationTemplateRequest' security: - JWT: [] summary: Create alert template. ADMIN ONLY diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index 73053e17..e4b11b01 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -33,7 +33,7 @@ func NewSystemNotificationTemplateHandler(h usecase.Usecase) *SystemNotification // @Description Create alert template. ADMIN ONLY // @Accept json // @Produce json -// @Success 200 {object} domain.CreateSystemNotificationTemplateResponse +// @Success 200 {object} domain.CreateSystemNotificationTemplateRequest // @Router /admin/system-notification-templates [post] // @Security JWT func (h *SystemNotificationTemplateHandler) CreateSystemNotificationTemplate(w http.ResponseWriter, r *http.Request) { From b3083dd4c121873d51354e4b05e5b8c7515ade6a Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 25 Mar 2024 18:53:04 +0900 Subject: [PATCH 187/502] feature. add delete API for system-notification --- api/swagger/docs.go | 116 ++++++++++++++++++ api/swagger/swagger.json | 116 ++++++++++++++++++ api/swagger/swagger.yaml | 80 ++++++++++++ internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 ++ .../delivery/http/system-notification-rule.go | 45 ++++--- .../http/system-notification-template.go | 48 +++++++- internal/delivery/http/system-notification.go | 12 +- internal/model/system-notification-rule.go | 4 +- .../model/system-notification-template.go | 10 +- internal/model/system-notification.go | 14 +-- internal/route/route.go | 2 + internal/usecase/system-notification-rule.go | 22 +++- .../usecase/system-notification-template.go | 58 ++++++--- pkg/httpErrors/errorCode.go | 1 + 15 files changed, 482 insertions(+), 55 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 3ce6bb87..b740494e 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1366,6 +1366,13 @@ const docTemplate = `{ ], "summary": "Update SystemNotificationTemplate", "parameters": [ + { + "type": "string", + "description": "systemNotificationTemplateId", + "name": "systemNotificationTemplateId", + "in": "path", + "required": true + }, { "description": "Update alert template request", "name": "body", @@ -1381,6 +1388,38 @@ const docTemplate = `{ "description": "OK" } } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete SystemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Delete SystemNotificationTemplate", + "parameters": [ + { + "type": "string", + "description": "systemNotificationTemplateId", + "name": "systemNotificationTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } } }, "/app-groups": { @@ -6419,6 +6458,13 @@ const docTemplate = `{ ], "summary": "Get SystemNotificationRules", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -6481,6 +6527,13 @@ const docTemplate = `{ ], "summary": "Create SystemNotificationRule", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "create stack template request", "name": "body", @@ -6526,6 +6579,13 @@ const docTemplate = `{ "name": "name", "in": "path", "required": true + }, + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true } ], "responses": { @@ -6557,6 +6617,13 @@ const docTemplate = `{ ], "summary": "Get SystemNotificationRule", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "systemNotificationRuleId", @@ -6592,6 +6659,20 @@ const docTemplate = `{ ], "summary": "Update SystemNotificationRule", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", + "in": "path", + "required": true + }, { "description": "Update systemNotificationRule request", "name": "body", @@ -6626,6 +6707,13 @@ const docTemplate = `{ ], "summary": "Delete SystemNotificationRule", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "systemNotificationRuleId", @@ -6722,6 +6810,13 @@ const docTemplate = `{ ], "summary": "Remove organization systemNotificationTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "Remove organization systemNotification templates request", "name": "body", @@ -6756,6 +6851,13 @@ const docTemplate = `{ ], "summary": "Add organization systemNotificationTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "Add organization systemNotification templates request", "name": "body", @@ -6912,6 +7014,13 @@ const docTemplate = `{ "in": "path", "required": true }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + }, { "description": "Update cloud setting request", "name": "body", @@ -6993,6 +7102,13 @@ const docTemplate = `{ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true } ], "responses": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 2da9eb49..24ffd1b0 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1360,6 +1360,13 @@ ], "summary": "Update SystemNotificationTemplate", "parameters": [ + { + "type": "string", + "description": "systemNotificationTemplateId", + "name": "systemNotificationTemplateId", + "in": "path", + "required": true + }, { "description": "Update alert template request", "name": "body", @@ -1375,6 +1382,38 @@ "description": "OK" } } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete SystemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Delete SystemNotificationTemplate", + "parameters": [ + { + "type": "string", + "description": "systemNotificationTemplateId", + "name": "systemNotificationTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } } }, "/app-groups": { @@ -6413,6 +6452,13 @@ ], "summary": "Get SystemNotificationRules", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -6475,6 +6521,13 @@ ], "summary": "Create SystemNotificationRule", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "create stack template request", "name": "body", @@ -6520,6 +6573,13 @@ "name": "name", "in": "path", "required": true + }, + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true } ], "responses": { @@ -6551,6 +6611,13 @@ ], "summary": "Get SystemNotificationRule", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "systemNotificationRuleId", @@ -6586,6 +6653,20 @@ ], "summary": "Update SystemNotificationRule", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", + "in": "path", + "required": true + }, { "description": "Update systemNotificationRule request", "name": "body", @@ -6620,6 +6701,13 @@ ], "summary": "Delete SystemNotificationRule", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "systemNotificationRuleId", @@ -6716,6 +6804,13 @@ ], "summary": "Remove organization systemNotificationTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "Remove organization systemNotification templates request", "name": "body", @@ -6750,6 +6845,13 @@ ], "summary": "Add organization systemNotificationTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "Add organization systemNotification templates request", "name": "body", @@ -6906,6 +7008,13 @@ "in": "path", "required": true }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + }, { "description": "Update cloud setting request", "name": "body", @@ -6987,6 +7096,13 @@ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true } ], "responses": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 527db22c..012d0b28 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -4154,6 +4154,26 @@ paths: tags: - SystemNotificationTemplates /admin/system-notification-templates/{systemNotificationTemplateId}: + delete: + consumes: + - application/json + description: Delete SystemNotificationTemplate + parameters: + - description: systemNotificationTemplateId + in: path + name: systemNotificationTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Delete SystemNotificationTemplate + tags: + - SystemNotificationTemplates get: consumes: - application/json @@ -4181,6 +4201,11 @@ paths: - application/json description: Update SystemNotificationTemplate parameters: + - description: systemNotificationTemplateId + in: path + name: systemNotificationTemplateId + required: true + type: string - description: Update alert template request in: body name: body @@ -7400,6 +7425,11 @@ paths: - application/json description: Get SystemNotificationRules parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: pageSize in: query name: limit @@ -7440,6 +7470,11 @@ paths: - application/json description: Create SystemNotificationRule parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: create stack template request in: body name: body @@ -7464,6 +7499,11 @@ paths: - application/json description: Delete SystemNotificationRule parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: systemNotificationRuleId in: path name: systemNotificationRuleId @@ -7484,6 +7524,11 @@ paths: - application/json description: Get SystemNotificationRule parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: systemNotificationRuleId in: path name: systemNotificationRuleId @@ -7506,6 +7551,16 @@ paths: - application/json description: Update SystemNotificationRule parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: systemNotificationRuleId + in: path + name: systemNotificationRuleId + required: true + type: string - description: Update systemNotificationRule request in: body name: body @@ -7533,6 +7588,11 @@ paths: name: name required: true type: string + - description: organizationId + in: path + name: organizationId + required: true + type: string produces: - application/json responses: @@ -7591,6 +7651,11 @@ paths: - application/json description: Add organization systemNotificationTemplates parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: Add organization systemNotification templates request in: body name: body @@ -7612,6 +7677,11 @@ paths: - application/json description: Remove organization systemNotificationTemplates parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: Remove organization systemNotification templates request in: body name: body @@ -7737,6 +7807,11 @@ paths: name: organizationId required: true type: string + - description: systemNotificationId + in: path + name: systemNotificationId + required: true + type: string - description: Update cloud setting request in: body name: body @@ -7764,6 +7839,11 @@ paths: name: organizationId required: true type: string + - description: systemNotificationId + in: path + name: systemNotificationId + required: true + type: string produces: - application/json responses: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index df9fe7da..97db8fbe 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -120,6 +120,7 @@ const ( // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate Admin_UpdateSystemNotificationTemplate + Admin_DeleteSystemNotificationTemplate Admin_GetSystemNotificationTemplates Admin_GetSystemNotificationTemplate GetOrganizationSystemNotificationTemplates diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 88eb4d7e..2b966ca4 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -359,6 +359,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_UpdateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, + Admin_DeleteSystemNotificationTemplate: { + Name: "Admin_DeleteSystemNotificationTemplate", + Group: "SystemNotificationTemplate", + }, Admin_GetSystemNotificationTemplates: { Name: "Admin_GetSystemNotificationTemplates", Group: "SystemNotificationTemplate", @@ -988,6 +992,8 @@ func (e Endpoint) String() string { return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: return "Admin_UpdateSystemNotificationTemplate" + case Admin_DeleteSystemNotificationTemplate: + return "Admin_DeleteSystemNotificationTemplate" case Admin_GetSystemNotificationTemplates: return "Admin_GetSystemNotificationTemplates" case Admin_GetSystemNotificationTemplate: @@ -1396,6 +1402,8 @@ func GetEndpoint(name string) Endpoint { return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": return Admin_UpdateSystemNotificationTemplate + case "Admin_DeleteSystemNotificationTemplate": + return Admin_DeleteSystemNotificationTemplate case "Admin_GetSystemNotificationTemplates": return Admin_GetSystemNotificationTemplates case "Admin_GetSystemNotificationTemplate": diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 2c27207c..81319ed4 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -34,8 +34,9 @@ func NewSystemNotificationRuleHandler(h usecase.Usecase) *SystemNotificationRule // @Description Create SystemNotificationRule // @Accept json // @Produce json -// @Param body body domain.CreateSystemNotificationRuleRequest true "create stack template request" -// @Success 200 {object} domain.CreateSystemNotificationRuleResponse +// @Param organizationId path string true "organizationId" +// @Param body body domain.CreateSystemNotificationRuleRequest true "create stack template request" +// @Success 200 {object} domain.CreateSystemNotificationRuleResponse // @Router /organizations/{organizationId}/system-notification-rules [post] // @Security JWT func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.ResponseWriter, r *http.Request) { @@ -85,12 +86,13 @@ func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.Resp // @Description Get SystemNotificationRules // @Accept json // @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetSystemNotificationRulesResponse +// @Param organizationId path string true "organizationId" +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetSystemNotificationRulesResponse // @Router /organizations/{organizationId}/system-notification-rules [get] // @Security JWT func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.ResponseWriter, r *http.Request) { @@ -150,6 +152,7 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.Respon // @Description Get SystemNotificationRule // @Accept json // @Produce json +// @Param organizationId path string true "organizationId" // @Param systemNotificationRuleId path string true "systemNotificationRuleId" // @Success 200 {object} domain.GetSystemNotificationRuleResponse // @Router /organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId} [get] @@ -201,8 +204,10 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons // @Description Update SystemNotificationRule // @Accept json // @Produce json -// @Param body body domain.UpdateSystemNotificationRuleRequest true "Update systemNotificationRule request" -// @Success 200 {object} nil +// @Param organizationId path string true "organizationId" +// @Param systemNotificationRuleId path string true "systemNotificationRuleId" +// @Param body body domain.UpdateSystemNotificationRuleRequest true "Update systemNotificationRule request" +// @Success 200 {object} nil // @Router /organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId} [put] // @Security JWT func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.ResponseWriter, r *http.Request) { @@ -260,19 +265,30 @@ func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.Resp // @Description Delete SystemNotificationRule // @Accept json // @Produce json +// @Param organizationId path string true "organizationId" // @Param systemNotificationRuleId path string true "systemNotificationRuleId" // @Success 200 {object} nil // @Router /organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId} [delete] // @Security JWT func (h *SystemNotificationRuleHandler) DeleteSystemNotificationRule(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - _, ok := vars["systemNotificationRuleId"] + strId, ok := vars["systemNotificationRuleId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) return } + systemNotificationRuleId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } - ErrorJSON(w, r, fmt.Errorf("need implementation")) + err = h.usecase.Delete(r.Context(), systemNotificationRuleId) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) } // CheckSystemNotificationRuleName godoc @@ -282,8 +298,9 @@ func (h *SystemNotificationRuleHandler) DeleteSystemNotificationRule(w http.Resp // @Description Check name for systemNotificationRule // @Accept json // @Produce json -// @Param name path string true "name" -// @Success 200 {object} domain.CheckSystemNotificationRuleNameResponse +// @Param name path string true "name" +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.CheckSystemNotificationRuleNameResponse // @Router /organizations/{organizationId}/system-notification-rules/name/{name}/existence [GET] // @Security JWT func (h *SystemNotificationRuleHandler) CheckSystemNotificationRuleName(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index e4b11b01..ce4aefa0 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -175,8 +175,9 @@ func (h *SystemNotificationTemplateHandler) GetSystemNotificationTemplate(w http // @Description Update SystemNotificationTemplate // @Accept json // @Produce json -// @Param body body domain.UpdateSystemNotificationTemplateRequest true "Update alert template request" -// @Success 200 {object} nil +// @Param systemNotificationTemplateId path string true "systemNotificationTemplateId" +// @Param body body domain.UpdateSystemNotificationTemplateRequest true "Update alert template request" +// @Success 200 {object} nil // @Router /admin/system-notification-templates/{systemNotificationTemplateId} [put] // @Security JWT func (h *SystemNotificationTemplateHandler) UpdateSystemNotificationTemplate(w http.ResponseWriter, r *http.Request) { @@ -220,6 +221,39 @@ func (h *SystemNotificationTemplateHandler) UpdateSystemNotificationTemplate(w h ResponseJSON(w, r, http.StatusOK, nil) } +// DeleteSystemNotificationTemplate godoc +// +// @Tags SystemNotificationTemplates +// @Summary Delete SystemNotificationTemplate +// @Description Delete SystemNotificationTemplate +// @Accept json +// @Produce json +// @Param systemNotificationTemplateId path string true "systemNotificationTemplateId" +// @Success 200 {object} nil +// @Router /admin/system-notification-templates/{systemNotificationTemplateId} [delete] +// @Security JWT +func (h *SystemNotificationTemplateHandler) DeleteSystemNotificationTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["systemNotificationTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationTemplateId"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + systemNotificationTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + + err = h.usecase.Delete(r.Context(), systemNotificationTemplateId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + // GetOrganizationSystemNotificationTemplates godoc // // @Tags SystemNotificationTemplates @@ -280,8 +314,9 @@ func (h *SystemNotificationTemplateHandler) GetOrganizationSystemNotificationTem // @Description Add organization systemNotificationTemplates // @Accept json // @Produce json -// @Param body body domain.AddOrganizationSystemNotificationTemplatesRequest true "Add organization systemNotification templates request" -// @Success 200 {object} nil +// @Param organizationId path string true "organizationId" +// @Param body body domain.AddOrganizationSystemNotificationTemplatesRequest true "Add organization systemNotification templates request" +// @Success 200 {object} nil // @Router /organizations/{organizationId}/system-notification-templates [post] // @Security JWT func (h *SystemNotificationTemplateHandler) AddOrganizationSystemNotificationTemplates(w http.ResponseWriter, r *http.Request) { @@ -314,8 +349,9 @@ func (h *SystemNotificationTemplateHandler) AddOrganizationSystemNotificationTem // @Description Remove organization systemNotificationTemplates // @Accept json // @Produce json -// @Param body body domain.RemoveOrganizationSystemNotificationTemplatesRequest true "Remove organization systemNotification templates request" -// @Success 200 {object} nil +// @Param organizationId path string true "organizationId" +// @Param body body domain.RemoveOrganizationSystemNotificationTemplatesRequest true "Remove organization systemNotification templates request" +// @Success 200 {object} nil // @Router /organizations/{organizationId}/system-notification-templates [put] // @Security JWT func (h *SystemNotificationTemplateHandler) RemoveOrganizationSystemNotificationTemplates(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/system-notification.go b/internal/delivery/http/system-notification.go index 9f056bcb..49322289 100644 --- a/internal/delivery/http/system-notification.go +++ b/internal/delivery/http/system-notification.go @@ -204,9 +204,10 @@ func (h *SystemNotificationHandler) GetSystemNotification(w http.ResponseWriter, // @Description Update SystemNotification // @Accept json // @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body domain.UpdateSystemNotificationRequest true "Update cloud setting request" -// @Success 200 {object} nil +// @Param organizationId path string true "organizationId" +// @Param systemNotificationId path string true "systemNotificationId" +// @Param body body domain.UpdateSystemNotificationRequest true "Update cloud setting request" +// @Success 200 {object} nil // @Router /organizations/{organizationId}/system-notifications/{systemNotificationId} [put] // @Security JWT func (h *SystemNotificationHandler) UpdateSystemNotification(w http.ResponseWriter, r *http.Request) { @@ -246,8 +247,9 @@ func (h *SystemNotificationHandler) SystemNotificationTest(w http.ResponseWriter // @Description Create systemNotification action // @Accept json // @Produce json -// @Param organizationId path string true "organizationId" -// @Success 200 {object} nil +// @Param organizationId path string true "organizationId" +// @Param systemNotificationId path string true "systemNotificationId" +// @Success 200 {object} nil // @Router /organizations/{organizationId}/system-notifications/{systemNotificationId}/actions [post] // @Security JWT func (h *SystemNotificationHandler) CreateSystemNotificationAction(w http.ResponseWriter, r *http.Request) { diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index 9ab63c37..e1fc06eb 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -30,8 +30,8 @@ type SystemNotificationRule struct { Organization Organization `gorm:"foreignKey:OrganizationId"` SystemNotificationTemplate SystemNotificationTemplate `gorm:"foreignKey:SystemNotificationTemplateId"` SystemNotificationTemplateId string - SystemNotificationConditions []SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId"` - TargetUsers []User `gorm:"many2many:system_notification_rule_users"` + SystemNotificationConditions []SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` + TargetUsers []User `gorm:"many2many:system_notification_rule_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` TargetUserIds []string `gorm:"-:all"` MessageTitle string MessageContent string diff --git a/internal/model/system-notification-template.go b/internal/model/system-notification-template.go index 3c07964e..4c8ba603 100644 --- a/internal/model/system-notification-template.go +++ b/internal/model/system-notification-template.go @@ -7,8 +7,10 @@ import ( // Models type MetricParameter struct { - SystemNotificationTemplateId uuid.UUID `gorm:"primarykey"` - Order int `gorm:"primarykey"` + gorm.Model + + SystemNotificationTemplateId uuid.UUID + Order int Key string Value string } @@ -18,11 +20,11 @@ type SystemNotificationTemplate struct { ID uuid.UUID `gorm:"primarykey"` Name string `gorm:"index:idx_name,unique"` - Organizations []Organization `gorm:"many2many:system_notification_template_organizations"` + Organizations []Organization `gorm:"many2many:system_notification_template_organizations;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` OrganizationIds []string `gorm:"-:all"` Description string MetricQuery string - MetricParameters []MetricParameter `gorm:"foreignKey:SystemNotificationTemplateId;references:ID"` + MetricParameters []MetricParameter `gorm:"foreignKey:SystemNotificationTemplateId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` CreatorId *uuid.UUID Creator User `gorm:"foreignKey:CreatorId"` UpdatorId *uuid.UUID diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go index aea8cbb0..3c5678cc 100644 --- a/internal/model/system-notification.go +++ b/internal/model/system-notification.go @@ -26,13 +26,13 @@ type SystemNotification struct { Node string CheckPoint string GrafanaUrl string - FiredAt *time.Time `gorm:"-:all"` - TakedAt *time.Time `gorm:"-:all"` - ClosedAt *time.Time `gorm:"-:all"` - TakedSec int `gorm:"-:all"` - ProcessingSec int `gorm:"-:all"` - LastTaker User `gorm:"-:all"` - SystemNotificationActions []SystemNotificationAction + FiredAt *time.Time `gorm:"-:all"` + TakedAt *time.Time `gorm:"-:all"` + ClosedAt *time.Time `gorm:"-:all"` + TakedSec int `gorm:"-:all"` + ProcessingSec int `gorm:"-:all"` + LastTaker User `gorm:"-:all"` + SystemNotificationActions []SystemNotificationAction `gorm:"foreignKey:SystemNotificationId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` Summary string RawData datatypes.JSON Status domain.SystemNotificationActionStatus `gorm:"index"` diff --git a/internal/route/route.go b/internal/route/route.go index bb922dea..048ea4fc 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -222,6 +222,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates", customMiddleware.Handle(internalApi.Admin_GetSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetSystemNotificationTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_GetSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.GetSystemNotificationTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.UpdateSystemNotificationTemplate))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.DeleteSystemNotificationTemplate))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.GetOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetOrganizationSystemNotificationTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.AddOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.AddOrganizationSystemNotificationTemplates))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.RemoveOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.RemoveOrganizationSystemNotificationTemplates))).Methods(http.MethodPut) @@ -231,6 +232,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.DeleteSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.DeleteSystemNotificationRule))).Methods(http.MethodDelete) stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index d69c5c15..096e552f 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -20,7 +20,7 @@ type ISystemNotificationRuleUsecase interface { Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotificationRule, error) Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRule uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationRule) error - Delete(ctx context.Context, dto model.SystemNotificationRule) error + Delete(ctx context.Context, systemNotificationRuleId uuid.UUID) error GetByName(ctx context.Context, name string) (model.SystemNotificationRule, error) } @@ -141,6 +141,22 @@ func (u *SystemNotificationRuleUsecase) Fetch(ctx context.Context, organizationI return res, nil } -func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { - return nil +func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, systemNotificationRuleId uuid.UUID) (err error) { + systemNotificationRule, err := u.repo.Get(ctx, systemNotificationRuleId) + if err != nil { + return err + } + + user, ok := request.UserFrom(ctx) + if !ok { + return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + } + userId := user.GetUserId() + systemNotificationRule.UpdatorId = &userId + + err = u.repo.Delete(ctx, systemNotificationRule) + if err != nil { + return err + } + return } diff --git a/internal/usecase/system-notification-template.go b/internal/usecase/system-notification-template.go index 6516eb77..ebfd6cd7 100644 --- a/internal/usecase/system-notification-template.go +++ b/internal/usecase/system-notification-template.go @@ -22,24 +22,26 @@ type ISystemNotificationTemplateUsecase interface { FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotificationTemplate, error) Create(ctx context.Context, dto model.SystemNotificationTemplate) (systemNotificationTemplate uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationTemplate) error - Delete(ctx context.Context, dto model.SystemNotificationTemplate) error + Delete(ctx context.Context, systemNotificationTemplateId uuid.UUID) error AddOrganizationSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplateIds []string) error RemoveOrganizationSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplateIds []string) error } type SystemNotificationTemplateUsecase struct { - repo repository.ISystemNotificationTemplateRepository - clusterRepo repository.IClusterRepository - organizationRepo repository.IOrganizationRepository - appGroupRepo repository.IAppGroupRepository + repo repository.ISystemNotificationTemplateRepository + clusterRepo repository.IClusterRepository + organizationRepo repository.IOrganizationRepository + appGroupRepo repository.IAppGroupRepository + systemNotificationRuleRepo repository.ISystemNotificationRuleRepository } func NewSystemNotificationTemplateUsecase(r repository.Repository) ISystemNotificationTemplateUsecase { return &SystemNotificationTemplateUsecase{ - repo: r.SystemNotificationTemplate, - clusterRepo: r.Cluster, - appGroupRepo: r.AppGroup, - organizationRepo: r.Organization, + repo: r.SystemNotificationTemplate, + clusterRepo: r.Cluster, + appGroupRepo: r.AppGroup, + organizationRepo: r.Organization, + systemNotificationRuleRepo: r.SystemNotificationRule, } } @@ -89,10 +91,10 @@ func (u *SystemNotificationTemplateUsecase) Update(ctx context.Context, dto mode return nil } -func (u *SystemNotificationTemplateUsecase) Get(ctx context.Context, systemNotificationTemplate uuid.UUID) (alert model.SystemNotificationTemplate, err error) { - alert, err = u.repo.Get(ctx, systemNotificationTemplate) +func (u *SystemNotificationTemplateUsecase) Get(ctx context.Context, systemNotificationTemplateId uuid.UUID) (systemNotificationTemplate model.SystemNotificationTemplate, err error) { + systemNotificationTemplate, err = u.repo.Get(ctx, systemNotificationTemplateId) if err != nil { - return alert, err + return systemNotificationTemplate, err } return } @@ -125,8 +127,36 @@ func (u *SystemNotificationTemplateUsecase) FetchWithOrganization(ctx context.Co return res, nil } -func (u *SystemNotificationTemplateUsecase) Delete(ctx context.Context, dto model.SystemNotificationTemplate) (err error) { - return nil +func (u *SystemNotificationTemplateUsecase) Delete(ctx context.Context, systemNotificationTemplateId uuid.UUID) (err error) { + systemNotificationTemplate, err := u.repo.Get(ctx, systemNotificationTemplateId) + if err != nil { + return err + } + + user, ok := request.UserFrom(ctx) + if !ok { + return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + } + userId := user.GetUserId() + systemNotificationTemplate.UpdatorId = &userId + + // check if used + // system_notification_rules + pg := pagination.NewPaginationWithFilter("system_notification_template_id", "", "$eq", []string{systemNotificationTemplateId.String()}) + res, err := u.systemNotificationRuleRepo.Fetch(ctx, pg) + if err != nil { + return err + } + if len(res) > 0 { + return httpErrors.NewBadRequestError(fmt.Errorf("Failed to delete systemNotificationTemplate %s", systemNotificationTemplateId.String()), "SNT_FAILED_DELETE_EXIST_RULES", "") + } + + err = u.repo.Delete(ctx, systemNotificationTemplate) + if err != nil { + return err + } + + return } func (u *SystemNotificationTemplateUsecase) UpdateOrganizations(ctx context.Context, dto model.SystemNotificationTemplate) error { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 2db07ce1..179002d1 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -86,6 +86,7 @@ var errorMap = map[ErrorCode]string{ "SNT_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿을 가져오는데 실패했습니다.", "SNT_FAILED_UPDATE_ORGANIZATION": "알림템플릿에 조직을 설정하는데 실패했습니다.", "SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.", + "SNT_FAILED_DELETE_EXIST_RULES": "알림템플릿을 사용하고 있는 알림 설정이 있습니다. 알림 설정을 삭제하세요.", // SystemNotificationRule "SNR_CREATE_ALREADY_EXISTED_NAME": "알림 설정에 이미 존재하는 이름입니다.", From 274a4e72609189f838e19104006e2c5f92025c8c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 27 Mar 2024 10:08:31 +0900 Subject: [PATCH 188/502] feature. add delete api --- internal/delivery/http/stack-template.go | 15 +++++++-- .../delivery/http/system-notification-rule.go | 8 ++--- internal/usecase/stack-template.go | 33 +++++++++++++++++-- pkg/httpErrors/errorCode.go | 2 ++ 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index ba1d7935..fdbcd4b9 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -220,13 +220,24 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt // @Security JWT func (h *StackTemplateHandler) DeleteStackTemplate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - _, ok := vars["stackTemplateId"] + strId, ok := vars["stackTemplateId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) return } - ErrorJSON(w, r, fmt.Errorf("need implementation")) + stackTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + + err = h.usecase.Delete(r.Context(), stackTemplateId) + if err != nil { + ErrorJSON(w, r, err) + return + } + ResponseJSON(w, r, http.StatusOK, nil) } // GetStackTemplateServices godoc diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 81319ed4..ee245d95 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -161,13 +161,13 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons vars := mux.Vars(r) strId, ok := vars["systemNotificationRuleId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_SYSTEM_NOTIFICATION_RULE_ID", "")) return } systemNotificationRuleId, err := uuid.Parse(strId) if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_SYSTEM_NOTIFICATION_RULE_ID", "")) return } @@ -274,12 +274,12 @@ func (h *SystemNotificationRuleHandler) DeleteSystemNotificationRule(w http.Resp vars := mux.Vars(r) strId, ok := vars["systemNotificationRuleId"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_SYSTEM_NOTIFICATION_RULE_ID", "")) return } systemNotificationRuleId, err := uuid.Parse(strId) if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_SYSTEM_NOTIFICATION_RULE_ID", "")) return } diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 2b56f9e1..b397e01f 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -22,7 +22,7 @@ type IStackTemplateUsecase interface { FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.StackTemplate, error) Create(ctx context.Context, dto model.StackTemplate) (stackTemplate uuid.UUID, err error) Update(ctx context.Context, dto model.StackTemplate) error - Delete(ctx context.Context, dto model.StackTemplate) error + Delete(ctx context.Context, stackTemplateId uuid.UUID) error UpdateOrganizations(ctx context.Context, dto model.StackTemplate) error GetByName(ctx context.Context, name string) (model.StackTemplate, error) AddOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error @@ -32,12 +32,14 @@ type IStackTemplateUsecase interface { type StackTemplateUsecase struct { repo repository.IStackTemplateRepository organizationRepo repository.IOrganizationRepository + clusterRepo repository.IClusterRepository } func NewStackTemplateUsecase(r repository.Repository) IStackTemplateUsecase { return &StackTemplateUsecase{ repo: r.StackTemplate, organizationRepo: r.Organization, + clusterRepo: r.Cluster, } } @@ -130,7 +132,34 @@ func (u *StackTemplateUsecase) FetchWithOrganization(ctx context.Context, organi return res, nil } -func (u *StackTemplateUsecase) Delete(ctx context.Context, dto model.StackTemplate) (err error) { +func (u *StackTemplateUsecase) Delete(ctx context.Context, stackTemplateId uuid.UUID) (err error) { + stackTemplate, err := u.repo.Get(ctx, stackTemplateId) + if err != nil { + return err + } + + user, ok := request.UserFrom(ctx) + if !ok { + return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + } + userId := user.GetUserId() + stackTemplate.UpdatorId = &userId + + // check if used + pg := pagination.NewPaginationWithFilter("stack_template_id", "", "$eq", []string{stackTemplateId.String()}) + res, err := u.clusterRepo.Fetch(ctx, pg) + if err != nil { + return err + } + if len(res) > 0 { + return httpErrors.NewBadRequestError(fmt.Errorf("Failed to delete stackTemplate %s", stackTemplateId.String()), "ST_FAILED_DELETE_EXIST_CLUSTERS", "") + } + + err = u.repo.Delete(ctx, stackTemplate) + if err != nil { + return err + } + return nil } diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 179002d1..fb3d2302 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -14,6 +14,7 @@ var errorMap = map[ErrorCode]string{ "C_INVALID_CLOUD_ACCOUNT_ID": "유효하지 않은 클라우드어카운트 아이디입니다. 클라우드어카운트 아이디를 확인하세요.", "C_INVALID_STACK_TEMPLATE_ID": "유효하지 않은 스택템플릿 아이디입니다. 스택템플릿 아이디를 확인하세요.", "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID": "유효하지 않은 알림템플릿 아이디입니다. 알림템플릿 아이디를 확인하세요.", + "C_INVALID_SYSTEM_NOTIFICATION_RULE_ID": "유효하지 않은 알림설정 아이디입니다. 알림설정 아이디를 확인하세요.", "C_INVALID_ASA_ID": "유효하지 않은 앱서빙앱 아이디입니다. 앱서빙앱 아이디를 확인하세요.", "C_INVALID_ASA_TASK_ID": "유효하지 않은 테스크 아이디입니다. 테스크 아이디를 확인하세요.", "C_INVALID_CLOUD_SERVICE": "유효하지 않은 클라우드서비스입니다.", @@ -110,6 +111,7 @@ var errorMap = map[ErrorCode]string{ "ST_FAILED_REMOVE_ORGANIZATION_STACK_TEMPLATE": "조직에서 스택템플릿을 삭제하는데 실패하였습니다.", "ST_FAILED_ADD_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE": "조직에 시스템알람템플릿을 추가하는데 실패하였습니다.", "ST_FAILED_REMOVE_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE": "조직에서 시스템알람템플릿을 삭제하는데 실패하였습니다.", + "ST_FAILED_DELETE_EXIST_CLUSTERS": "스택템플릿을 사용하고 있는 스택이 있습니다. 스택을 삭제하세요.", // PolicyTemplate "PT_CREATE_ALREADY_EXISTED_NAME": "정첵 템플릿에 이미 존재하는 이름입니다.", From 1e9ab5aa5135f214f754280a44f38e793c5bc046 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 27 Mar 2024 15:13:02 +0900 Subject: [PATCH 189/502] trivial. change model name to system-notification-metric-parameters --- api/swagger/docs.go | 85 +++++-------------- api/swagger/swagger.json | 84 +++++------------- api/swagger/swagger.yaml | 34 ++++---- internal/database/database.go | 2 +- .../http/system-notification-template.go | 6 +- .../model/system-notification-template.go | 4 +- pkg/domain/system-notification-template.go | 42 ++++----- 7 files changed, 87 insertions(+), 170 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 1a5cdb39..c4ae64b6 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -9739,7 +9739,7 @@ const docTemplate = `{ "metricParameters": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" } }, "metricQuery": { @@ -9748,7 +9748,6 @@ const docTemplate = `{ "name": { "type": "string" }, - "organizationIds": { "type": "array", "items": { @@ -11039,65 +11038,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { - "type": "object", - "properties": { - "children": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - } - }, - "is_allowed": { - "type": "boolean" - }, - "key": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse": { - "type": "object", - "properties": { - "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { - "type": "object", - "required": [ - "key", - "order", - "value" - ], - "properties": { - "key": { - "type": "string" - }, - "order": { - "type": "integer" - }, - "value": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { @@ -12331,6 +12271,25 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse": { + "type": "object", + "required": [ + "key", + "order", + "value" + ], + "properties": { + "key": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter": { "type": "object", "properties": { @@ -12490,7 +12449,7 @@ const docTemplate = `{ "metricParameters": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" } }, "metricQuery": { @@ -13053,7 +13012,7 @@ const docTemplate = `{ "metricParameters": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" } }, "metricQuery": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index c4fd3f12..4629849a 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -9733,7 +9733,7 @@ "metricParameters": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" } }, "metricQuery": { @@ -11032,65 +11032,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { - "type": "object", - "properties": { - "children": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - } - }, - "is_allowed": { - "type": "boolean" - }, - "key": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse": { - "type": "object", - "properties": { - "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse": { - "type": "object", - "required": [ - "key", - "order", - "value" - ], - "properties": { - "key": { - "type": "string" - }, - "order": { - "type": "integer" - }, - "value": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { @@ -12324,6 +12265,25 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse": { + "type": "object", + "required": [ + "key", + "order", + "value" + ], + "properties": { + "key": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter": { "type": "object", "properties": { @@ -12483,7 +12443,7 @@ "metricParameters": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" } }, "metricQuery": { @@ -13046,7 +13006,7 @@ "metricParameters": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" } }, "metricQuery": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 17dd7af9..f23f3c40 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1152,7 +1152,7 @@ definitions: type: string metricParameters: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse' type: array metricQuery: type: string @@ -1320,8 +1320,6 @@ definitions: name: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse: - type: object github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: column: @@ -2006,19 +2004,6 @@ definitions: stack: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' type: object - github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse: - properties: - key: - type: string - order: - type: integer - value: - type: string - required: - - key - - order - - value - type: object github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse: properties: admin: @@ -2841,6 +2826,19 @@ definitions: severity: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse: + properties: + key: + type: string + order: + type: integer + value: + type: string + required: + - key + - order + - value + type: object github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter: properties: operator: @@ -2944,7 +2942,7 @@ definitions: type: string metricParameters: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse' type: array metricQuery: type: string @@ -3317,7 +3315,7 @@ definitions: type: string metricParameters: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MetricParameterResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse' type: array metricQuery: type: string diff --git a/internal/database/database.go b/internal/database/database.go index 4a480a4e..1a3f9fc2 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -122,7 +122,7 @@ func migrateSchema(db *gorm.DB) error { } // SystemNotificationTemplate - if err := db.AutoMigrate(&model.MetricParameter{}); err != nil { + if err := db.AutoMigrate(&model.SystemNotificationMetricParameter{}); err != nil { return err } if err := db.AutoMigrate(&model.SystemNotificationTemplate{}); err != nil { diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index ce4aefa0..7ce845ad 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -48,7 +48,7 @@ func (h *SystemNotificationTemplateHandler) CreateSystemNotificationTemplate(w h if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } - dto.MetricParameters = make([]model.MetricParameter, len(input.MetricParameters)) + dto.MetricParameters = make([]model.SystemNotificationMetricParameter, len(input.MetricParameters)) for i, metricParameter := range input.MetricParameters { if err := serializer.Map(r.Context(), metricParameter, &dto.MetricParameters[i]); err != nil { log.Info(r.Context(), err) @@ -157,7 +157,7 @@ func (h *SystemNotificationTemplateHandler) GetSystemNotificationTemplate(w http } } - out.SystemNotificationTemplate.MetricParameters = make([]domain.MetricParameterResponse, len(systemNotificationTemplate.MetricParameters)) + out.SystemNotificationTemplate.MetricParameters = make([]domain.SystemNotificationMetricParameterResponse, len(systemNotificationTemplate.MetricParameters)) for i, metricParameters := range systemNotificationTemplate.MetricParameters { if err := serializer.Map(r.Context(), metricParameters, &out.SystemNotificationTemplate.MetricParameters[i]); err != nil { log.Info(r.Context(), err) @@ -204,7 +204,7 @@ func (h *SystemNotificationTemplateHandler) UpdateSystemNotificationTemplate(w h log.Info(r.Context(), err) } dto.ID = systemNotificationTemplateId - dto.MetricParameters = make([]model.MetricParameter, len(input.MetricParameters)) + dto.MetricParameters = make([]model.SystemNotificationMetricParameter, len(input.MetricParameters)) for i, metricParameter := range input.MetricParameters { if err := serializer.Map(r.Context(), metricParameter, &dto.MetricParameters[i]); err != nil { log.Info(r.Context(), err) diff --git a/internal/model/system-notification-template.go b/internal/model/system-notification-template.go index 4c8ba603..eabf2dd5 100644 --- a/internal/model/system-notification-template.go +++ b/internal/model/system-notification-template.go @@ -6,7 +6,7 @@ import ( ) // Models -type MetricParameter struct { +type SystemNotificationMetricParameter struct { gorm.Model SystemNotificationTemplateId uuid.UUID @@ -24,7 +24,7 @@ type SystemNotificationTemplate struct { OrganizationIds []string `gorm:"-:all"` Description string MetricQuery string - MetricParameters []MetricParameter `gorm:"foreignKey:SystemNotificationTemplateId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` + MetricParameters []SystemNotificationMetricParameter `gorm:"foreignKey:SystemNotificationTemplateId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` CreatorId *uuid.UUID Creator User `gorm:"foreignKey:CreatorId"` UpdatorId *uuid.UUID diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index 8b242289..7889a615 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -5,16 +5,16 @@ import ( ) type SystemNotificationTemplateResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - MetricQuery string `json:"metricQuery" validate:"required"` - MetricParameters []MetricParameterResponse `json:"metricParameters,omitempty"` - Organizations []SimpleOrganizationResponse `json:"organizations,omitempty"` - Creator SimpleUserResponse `json:"creator"` - Updator SimpleUserResponse `json:"updator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + MetricQuery string `json:"metricQuery" validate:"required"` + MetricParameters []SystemNotificationMetricParameterResponse `json:"metricParameters,omitempty"` + Organizations []SimpleOrganizationResponse `json:"organizations,omitempty"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type SimpleSystemNotificationTemplateResponse struct { @@ -25,18 +25,18 @@ type SimpleSystemNotificationTemplateResponse struct { UpdatedAt time.Time `json:"updatedAt"` } -type MetricParameterResponse struct { +type SystemNotificationMetricParameterResponse struct { Order int `json:"order" validate:"required"` Key string `json:"key" validate:"required,name"` Value string `json:"value" validate:"required"` } type CreateSystemNotificationTemplateRequest struct { - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` - OrganizationIds []string `json:"organizationIds" validate:"required"` - MetricQuery string `json:"metricQuery" validate:"required"` - MetricParameters []MetricParameterResponse `json:"metricParameters"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + OrganizationIds []string `json:"organizationIds" validate:"required"` + MetricQuery string `json:"metricQuery" validate:"required"` + MetricParameters []SystemNotificationMetricParameterResponse `json:"metricParameters"` } type CreateSystemNotificationTemplateResponse struct { @@ -44,11 +44,11 @@ type CreateSystemNotificationTemplateResponse struct { } type UpdateSystemNotificationTemplateRequest struct { - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` - OrganizationIds []string `json:"organizationIds" validate:"required"` - MetricQuery string `json:"metricQuery" validate:"required"` - MetricParameters []MetricParameterResponse `json:"metricParameters"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + OrganizationIds []string `json:"organizationIds" validate:"required"` + MetricQuery string `json:"metricQuery" validate:"required"` + MetricParameters []SystemNotificationMetricParameterResponse `json:"metricParameters"` } type GetSystemNotificationTemplatesResponse struct { From fb8e4865a4b2a0e0bbc72584f0d75e7b2760ed2f Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 27 Mar 2024 15:43:23 +0900 Subject: [PATCH 190/502] tirivial. code beautify --- internal/database/database.go | 152 +++++++--------------------------- 1 file changed, 31 insertions(+), 121 deletions(-) diff --git a/internal/database/database.go b/internal/database/database.go index 1a3f9fc2..3f26ca8b 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -60,127 +60,37 @@ func InitDB() (*gorm.DB, error) { } func migrateSchema(db *gorm.DB) error { - // Auth - if err := db.AutoMigrate(&model.CacheEmailCode{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.ExpiredTokenTime{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.User{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.Role{}); err != nil { - return err - } - - // Organization - if err := db.AutoMigrate(&model.Organization{}); err != nil { - return err - } - - // CloudAccount - if err := db.AutoMigrate(&model.CloudAccount{}); err != nil { - return err - } - - // StackTemplate - if err := db.AutoMigrate(&model.StackTemplate{}); err != nil { - return err - } - - // Cluster - if err := db.AutoMigrate(&model.Cluster{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.ClusterFavorite{}); err != nil { - return err - } - - // Services - if err := db.AutoMigrate(&model.AppGroup{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.Application{}); err != nil { - return err - } - - // AppServe - if err := db.AutoMigrate(&model.AppServeApp{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.AppServeAppTask{}); err != nil { - return err - } - - // SystemNotification - if err := db.AutoMigrate(&model.SystemNotification{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.SystemNotificationAction{}); err != nil { - return err - } - - // SystemNotificationTemplate - if err := db.AutoMigrate(&model.SystemNotificationMetricParameter{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.SystemNotificationTemplate{}); err != nil { - return err - } - - // SystemNotificationRule - if err := db.AutoMigrate(&model.SystemNotificationCondition{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.SystemNotificationRule{}); err != nil { - return err - } - - // Role - if err := db.AutoMigrate(&model.Role{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.Permission{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.Endpoint{}); err != nil { - return err - } - - // Project - if err := db.AutoMigrate(&model.Project{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.ProjectMember{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.ProjectNamespace{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.ProjectRole{}); err != nil { - return err - } - - // Audit - if err := db.AutoMigrate(&model.Audit{}); err != nil { - return err - } - - // PolicyTemplate - if err := db.AutoMigrate(&model.PolicyTemplateSupportedVersion{}); err != nil { - return err - } - - if err := db.AutoMigrate(&model.PolicyTemplate{}); err != nil { - return err - } - - if err := db.AutoMigrate(&model.Policy{}); err != nil { - return err - } - - if err := db.AutoMigrate(&model.Dashboard{}); err != nil { + if err := db.AutoMigrate(&model.CacheEmailCode{}, + &model.ExpiredTokenTime{}, + &model.User{}, + &model.Role{}, + &model.Organization{}, + &model.CloudAccount{}, + &model.StackTemplate{}, + &model.Cluster{}, + &model.ClusterFavorite{}, + &model.AppGroup{}, + &model.Application{}, + &model.AppServeApp{}, + &model.AppServeAppTask{}, + &model.SystemNotification{}, + &model.SystemNotificationAction{}, + &model.SystemNotificationMetricParameter{}, + &model.SystemNotificationTemplate{}, + &model.SystemNotificationCondition{}, + &model.SystemNotificationRule{}, + &model.Permission{}, + &model.Endpoint{}, + &model.Project{}, + &model.ProjectMember{}, + &model.ProjectNamespace{}, + &model.ProjectRole{}, + &model.Audit{}, + &model.PolicyTemplateSupportedVersion{}, + &model.PolicyTemplate{}, + &model.Policy{}, + &model.Dashboard{}, + ); err != nil { return err } From 011501df130380897b82f8aa045201e295d5f6c9 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 28 Mar 2024 01:39:31 +0900 Subject: [PATCH 191/502] =?UTF-8?q?Organization=20Template=20API=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 +- internal/delivery/api/endpoint.go | 26 +- .../delivery/api/generated_endpoints.go.go | 156 ++-- internal/delivery/http/policy-template.go | 813 ++++++++++++++++-- internal/delivery/http/policy.go | 3 +- internal/delivery/http/role.go | 2 +- internal/model/permission.go | 26 +- internal/model/policy-template.go | 29 +- internal/repository/policy-template.go | 94 +- internal/route/route.go | 13 + internal/usecase/policy-template.go | 266 ++++-- internal/usecase/policy.go | 26 +- pkg/domain/admin/policy-template.go | 179 ++++ pkg/domain/policy-template.go | 143 +-- pkg/domain/policy.go | 1 - pkg/httpErrors/errorCode.go | 23 +- 16 files changed, 1425 insertions(+), 377 deletions(-) create mode 100644 pkg/domain/admin/policy-template.go diff --git a/go.mod b/go.mod index 92db160f..92a6c021 100644 --- a/go.mod +++ b/go.mod @@ -48,6 +48,7 @@ require ( gorm.io/gorm v1.25.7 goyave.dev/goyave/v4 v4.4.11 k8s.io/api v0.26.1 + k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.4 k8s.io/client-go v0.26.1 k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 @@ -138,7 +139,6 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gorm.io/driver/mysql v1.5.0 // indirect - k8s.io/apiextensions-apiserver v0.26.1 // indirect k8s.io/component-base v0.26.1 // indirect k8s.io/klog/v2 v2.80.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index b69a561d..6c04b1f9 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -243,19 +243,19 @@ const ( ExistsPolicyName // OrganizationPolicyTemplate - ListOrganizationPolicyTemplate - CreateOrganizationPolicyTemplate - DeleteOrganizationPolicyTemplate - GetOrganizationPolicyTemplate - UpdateOrganizationPolicyTemplate - GetOrganizationPolicyTemplateDeploy - ListOrganizationPolicyTemplateStatistics - ListOrganizationPolicyTemplateVersions - CreateOrganizationPolicyTemplateVersion - DeleteOrganizationPolicyTemplateVersion - GetOrganizationPolicyTemplateVersion - ExistsOrganizationPolicyTemplateKind - ExistsOrganizationPolicyTemplateName + ListPolicyTemplate + CreatePolicyTemplate + DeletePolicyTemplate + GetPolicyTemplate + UpdatePolicyTemplate + GetPolicyTemplateDeploy + ListPolicyTemplateStatistics + ListPolicyTemplateVersions + CreatePolicyTemplateVersion + DeletePolicyTemplateVersion + GetPolicyTemplateVersion + ExistsPolicyTemplateKind + ExistsPolicyTemplateName // PolicyTemplateExample ListPolicyTemplateExample diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 1af52d51..03298848 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -739,56 +739,56 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "ExistsPolicyName", Group: "Policy", }, - ListOrganizationPolicyTemplate: { - Name: "ListOrganizationPolicyTemplate", + ListPolicyTemplate: { + Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - CreateOrganizationPolicyTemplate: { - Name: "CreateOrganizationPolicyTemplate", + CreatePolicyTemplate: { + Name: "CreatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - DeleteOrganizationPolicyTemplate: { - Name: "DeleteOrganizationPolicyTemplate", + DeletePolicyTemplate: { + Name: "DeletePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetOrganizationPolicyTemplate: { - Name: "GetOrganizationPolicyTemplate", + GetPolicyTemplate: { + Name: "GetPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - UpdateOrganizationPolicyTemplate: { - Name: "UpdateOrganizationPolicyTemplate", + UpdatePolicyTemplate: { + Name: "UpdatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetOrganizationPolicyTemplateDeploy: { - Name: "GetOrganizationPolicyTemplateDeploy", + GetPolicyTemplateDeploy: { + Name: "GetPolicyTemplateDeploy", Group: "OrganizationPolicyTemplate", }, - ListOrganizationPolicyTemplateStatistics: { - Name: "ListOrganizationPolicyTemplateStatistics", + ListPolicyTemplateStatistics: { + Name: "ListPolicyTemplateStatistics", Group: "OrganizationPolicyTemplate", }, - ListOrganizationPolicyTemplateVersions: { - Name: "ListOrganizationPolicyTemplateVersions", + ListPolicyTemplateVersions: { + Name: "ListPolicyTemplateVersions", Group: "OrganizationPolicyTemplate", }, - CreateOrganizationPolicyTemplateVersion: { - Name: "CreateOrganizationPolicyTemplateVersion", + CreatePolicyTemplateVersion: { + Name: "CreatePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - DeleteOrganizationPolicyTemplateVersion: { - Name: "DeleteOrganizationPolicyTemplateVersion", + DeletePolicyTemplateVersion: { + Name: "DeletePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - GetOrganizationPolicyTemplateVersion: { - Name: "GetOrganizationPolicyTemplateVersion", + GetPolicyTemplateVersion: { + Name: "GetPolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - ExistsOrganizationPolicyTemplateKind: { - Name: "ExistsOrganizationPolicyTemplateKind", + ExistsPolicyTemplateKind: { + Name: "ExistsPolicyTemplateKind", Group: "OrganizationPolicyTemplate", }, - ExistsOrganizationPolicyTemplateName: { - Name: "ExistsOrganizationPolicyTemplateName", + ExistsPolicyTemplateName: { + Name: "ExistsPolicyTemplateName", Group: "OrganizationPolicyTemplate", }, ListPolicyTemplateExample: { @@ -1182,32 +1182,32 @@ func (e Endpoint) String() string { return "UpdatePolicyTargetClusters" case ExistsPolicyName: return "ExistsPolicyName" - case ListOrganizationPolicyTemplate: - return "ListOrganizationPolicyTemplate" - case CreateOrganizationPolicyTemplate: - return "CreateOrganizationPolicyTemplate" - case DeleteOrganizationPolicyTemplate: - return "DeleteOrganizationPolicyTemplate" - case GetOrganizationPolicyTemplate: - return "GetOrganizationPolicyTemplate" - case UpdateOrganizationPolicyTemplate: - return "UpdateOrganizationPolicyTemplate" - case GetOrganizationPolicyTemplateDeploy: - return "GetOrganizationPolicyTemplateDeploy" - case ListOrganizationPolicyTemplateStatistics: - return "ListOrganizationPolicyTemplateStatistics" - case ListOrganizationPolicyTemplateVersions: - return "ListOrganizationPolicyTemplateVersions" - case CreateOrganizationPolicyTemplateVersion: - return "CreateOrganizationPolicyTemplateVersion" - case DeleteOrganizationPolicyTemplateVersion: - return "DeleteOrganizationPolicyTemplateVersion" - case GetOrganizationPolicyTemplateVersion: - return "GetOrganizationPolicyTemplateVersion" - case ExistsOrganizationPolicyTemplateKind: - return "ExistsOrganizationPolicyTemplateKind" - case ExistsOrganizationPolicyTemplateName: - return "ExistsOrganizationPolicyTemplateName" + case ListPolicyTemplate: + return "ListPolicyTemplate" + case CreatePolicyTemplate: + return "CreatePolicyTemplate" + case DeletePolicyTemplate: + return "DeletePolicyTemplate" + case GetPolicyTemplate: + return "GetPolicyTemplate" + case UpdatePolicyTemplate: + return "UpdatePolicyTemplate" + case GetPolicyTemplateDeploy: + return "GetPolicyTemplateDeploy" + case ListPolicyTemplateStatistics: + return "ListPolicyTemplateStatistics" + case ListPolicyTemplateVersions: + return "ListPolicyTemplateVersions" + case CreatePolicyTemplateVersion: + return "CreatePolicyTemplateVersion" + case DeletePolicyTemplateVersion: + return "DeletePolicyTemplateVersion" + case GetPolicyTemplateVersion: + return "GetPolicyTemplateVersion" + case ExistsPolicyTemplateKind: + return "ExistsPolicyTemplateKind" + case ExistsPolicyTemplateName: + return "ExistsPolicyTemplateName" case ListPolicyTemplateExample: return "ListPolicyTemplateExample" case GetPolicyTemplateExample: @@ -1592,32 +1592,32 @@ func GetEndpoint(name string) Endpoint { return UpdatePolicyTargetClusters case "ExistsPolicyName": return ExistsPolicyName - case "ListOrganizationPolicyTemplate": - return ListOrganizationPolicyTemplate - case "CreateOrganizationPolicyTemplate": - return CreateOrganizationPolicyTemplate - case "DeleteOrganizationPolicyTemplate": - return DeleteOrganizationPolicyTemplate - case "GetOrganizationPolicyTemplate": - return GetOrganizationPolicyTemplate - case "UpdateOrganizationPolicyTemplate": - return UpdateOrganizationPolicyTemplate - case "GetOrganizationPolicyTemplateDeploy": - return GetOrganizationPolicyTemplateDeploy - case "ListOrganizationPolicyTemplateStatistics": - return ListOrganizationPolicyTemplateStatistics - case "ListOrganizationPolicyTemplateVersions": - return ListOrganizationPolicyTemplateVersions - case "CreateOrganizationPolicyTemplateVersion": - return CreateOrganizationPolicyTemplateVersion - case "DeleteOrganizationPolicyTemplateVersion": - return DeleteOrganizationPolicyTemplateVersion - case "GetOrganizationPolicyTemplateVersion": - return GetOrganizationPolicyTemplateVersion - case "ExistsOrganizationPolicyTemplateKind": - return ExistsOrganizationPolicyTemplateKind - case "ExistsOrganizationPolicyTemplateName": - return ExistsOrganizationPolicyTemplateName + case "ListPolicyTemplate": + return ListPolicyTemplate + case "CreatePolicyTemplate": + return CreatePolicyTemplate + case "DeletePolicyTemplate": + return DeletePolicyTemplate + case "GetPolicyTemplate": + return GetPolicyTemplate + case "UpdatePolicyTemplate": + return UpdatePolicyTemplate + case "GetPolicyTemplateDeploy": + return GetPolicyTemplateDeploy + case "ListPolicyTemplateStatistics": + return ListPolicyTemplateStatistics + case "ListPolicyTemplateVersions": + return ListPolicyTemplateVersions + case "CreatePolicyTemplateVersion": + return CreatePolicyTemplateVersion + case "DeletePolicyTemplateVersion": + return DeletePolicyTemplateVersion + case "GetPolicyTemplateVersion": + return GetPolicyTemplateVersion + case "ExistsPolicyTemplateKind": + return ExistsPolicyTemplateKind + case "ExistsPolicyTemplateName": + return ExistsPolicyTemplateName case "ListPolicyTemplateExample": return ListPolicyTemplateExample case "GetPolicyTemplateExample": diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index bc66d83b..c2ad3479 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -6,13 +6,15 @@ import ( "strconv" "strings" + "github.com/openinfradev/tks-api/pkg/domain" + admin_domain "github.com/openinfradev/tks-api/pkg/domain/admin" + "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" - "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" @@ -37,6 +39,21 @@ type IPolicyTemplateHandler interface { Admin_GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) Admin_DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) Admin_ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) + + CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) + UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) + DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) + GetPolicyTemplate(w http.ResponseWriter, r *http.Request) + ListPolicyTemplate(w http.ResponseWriter, r *http.Request) + ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) + ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) + ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) + GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) + CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) + ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) + RegoCompile(w http.ResponseWriter, r *http.Request) } @@ -49,16 +66,16 @@ func NewPolicyTemplateHandler(u usecase.Usecase) IPolicyTemplateHandler { // Admin_CreatePolicyTemplate godoc // // @Tags PolicyTemplate -// @Summary [CreatePolicyTemplate] 정책 템플릿 신규 생성 +// @Summary [Admin_CreatePolicyTemplate] 정책 템플릿 신규 생성 // @Description 정책 템플릿을 신규 생성(v1.0.0을 생성)한다. // @Accept json // @Produce json -// @Param body body domain.CreatePolicyTemplateRequest true "create policy template request" -// @Success 200 {object} domain.CreatePolicyTemplateReponse +// @Param body body admin_domain.CreatePolicyTemplateRequest true "create policy template request" +// @Success 200 {object} admin_domain.CreatePolicyTemplateReponse // @Router /admin/policy-templates [post] // @Security JWT func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) { - input := domain.CreatePolicyTemplateRequest{} + input := admin_domain.CreatePolicyTemplateRequest{} err := UnmarshalRequestInput(r, &input) @@ -72,13 +89,15 @@ func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplate(w http.ResponseWriter log.Info(r.Context(), err) } + dto.Type = "tks" + policyTemplateId, err := h.usecase.Create(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) return } - var out domain.CreatePolicyTemplateReponse + var out admin_domain.CreatePolicyTemplateReponse out.ID = policyTemplateId.String() ResponseJSON(w, r, http.StatusOK, out) @@ -87,12 +106,12 @@ func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplate(w http.ResponseWriter // Admin_UpdatePolicyTemplate godoc // // @Tags PolicyTemplate -// @Summary [UpdatePolicyTemplate] 정책 템플릿 업데이트 +// @Summary [Admin_UpdatePolicyTemplate] 정책 템플릿 업데이트 // @Description 정책 템플릿의 업데이트 가능한 필드들을 업데이트한다. // @Accept json // @Produce json -// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" -// @Param body body domain.UpdatePolicyTemplateRequest true "update policy template request" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param body body admin_domain.UpdatePolicyTemplateRequest true "update policy template request" // @Success 200 {object} nil // @Router /admin/policy-templates/{policyTemplateId} [patch] // @Security JWT @@ -111,7 +130,7 @@ func (h *PolicyTemplateHandler) Admin_UpdatePolicyTemplate(w http.ResponseWriter return } - input := domain.UpdatePolicyTemplateRequest{} + input := admin_domain.UpdatePolicyTemplateRequest{} err = UnmarshalRequestInput(r, &input) @@ -121,7 +140,7 @@ func (h *PolicyTemplateHandler) Admin_UpdatePolicyTemplate(w http.ResponseWriter return } - err = h.usecase.Update(r.Context(), id, input.TemplateName, input.Description, input.Severity, input.Deprecated, input.PermittedOrganizationIds) + err = h.usecase.Update(r.Context(), nil, id, input.TemplateName, input.Description, input.Severity, input.Deprecated, input.PermittedOrganizationIds) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -140,7 +159,7 @@ func (h *PolicyTemplateHandler) Admin_UpdatePolicyTemplate(w http.ResponseWriter // Admin_DeletePolicyTemplate godoc // // @Tags PolicyTemplate -// @Summary [DeletePolicyTemplate] 정책 템플릿 삭제 +// @Summary [Admin_DeletePolicyTemplate] 정책 템플릿 삭제 // @Description 정책 템플릿을 삭제한다. // @Accept json // @Produce json @@ -168,7 +187,7 @@ func (h *PolicyTemplateHandler) Admin_DeletePolicyTemplate(w http.ResponseWriter return } - err = h.usecase.Delete(r.Context(), id) + err = h.usecase.Delete(r.Context(), nil, id) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -187,12 +206,12 @@ func (h *PolicyTemplateHandler) Admin_DeletePolicyTemplate(w http.ResponseWriter // Admin_GetPolicyTemplate godoc // // @Tags PolicyTemplate -// @Summary [GetPolicyTemplate] 정책 템플릿 조회(최신 버전) +// @Summary [Admin_GetPolicyTemplate] 정책 템플릿 조회(최신 버전) // @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. // @Accept json // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" -// @Success 200 {object} domain.GetPolicyTemplateResponse +// @Success 200 {object} admin_domain.GetPolicyTemplateResponse // @Router /admin/policy-templates/{policyTemplateId} [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_GetPolicyTemplate(w http.ResponseWriter, r *http.Request) { @@ -215,7 +234,7 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplate(w http.ResponseWriter, r return } - policyTemplate, err := h.usecase.Get(r.Context(), id) + policyTemplate, err := h.usecase.Get(r.Context(), nil, id) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -232,7 +251,7 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplate(w http.ResponseWriter, r return } - var out domain.GetPolicyTemplateResponse + var out admin_domain.GetPolicyTemplateResponse if err = serializer.Map(r.Context(), *policyTemplate, &out.PolicyTemplate); err != nil { log.Error(r.Context(), err) } @@ -247,16 +266,16 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplate(w http.ResponseWriter, r // Admin_ListPolicyTemplate godoc // // @Tags PolicyTemplate -// @Summary [ListPolicyTemplate] 정책 템플릿 목록 조회 +// @Summary [Admin_ListPolicyTemplate] 정책 템플릿 목록 조회 // @Description 정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다. // @Accept json // @Produce json // @Param limit query string false "pageSize" // @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" +// @Param sortColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} domain.ListPolicyTemplateResponse +// @Success 200 {object} admin_domain.ListPolicyTemplateResponse // @Router /admin/policy-templates [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_ListPolicyTemplate(w http.ResponseWriter, r *http.Request) { @@ -264,14 +283,14 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplate(w http.ResponseWriter, pg := pagination.NewPagination(&urlParams) - policyTemplates, err := h.usecase.Fetch(r.Context(), pg) + policyTemplates, err := h.usecase.Fetch(r.Context(), nil, pg) if err != nil { ErrorJSON(w, r, err) return } - var out domain.ListPolicyTemplateResponse - out.PolicyTemplates = make([]domain.PolicyTemplateResponse, len(policyTemplates)) + var out admin_domain.ListPolicyTemplateResponse + out.PolicyTemplates = make([]admin_domain.PolicyTemplateResponse, len(policyTemplates)) for i, policyTemplate := range policyTemplates { if err := serializer.Map(r.Context(), policyTemplate, &out.PolicyTemplates[i]); err != nil { log.Info(r.Context(), err) @@ -293,12 +312,12 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplate(w http.ResponseWriter, // Admin_ListPolicyTemplateVersions godoc // // @Tags PolicyTemplate -// @Summary [ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회 +// @Summary [Admin_ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회 // @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. // @Accept json // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" -// @Success 200 {object} domain.ListPolicyTemplateVersionsResponse +// @Success 200 {object} admin_domain.ListPolicyTemplateVersionsResponse // @Router /admin/policy-templates/{policyTemplateId}/versions [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) { @@ -317,7 +336,7 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateVersions(w http.Response return } - policyTemplateVersions, err := h.usecase.ListPolicyTemplateVersions(r.Context(), id) + policyTemplateVersions, err := h.usecase.ListPolicyTemplateVersions(r.Context(), nil, id) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -330,7 +349,7 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateVersions(w http.Response return } - var out domain.ListPolicyTemplateVersionsResponse + var out admin_domain.ListPolicyTemplateVersionsResponse if err = serializer.Map(r.Context(), *policyTemplateVersions, &out); err != nil { log.Error(r.Context(), err) } @@ -341,17 +360,17 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateVersions(w http.Response // Admin_ListPolicyTemplateStatistics godoc // // @Tags PolicyTemplate -// @Summary [ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회 +// @Summary [Admin_ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회 // @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다. // @Accept json // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" -// @Success 200 {object} domain.ListPolicyTemplateStatisticsResponse +// @Success 200 {object} admin_domain.ListPolicyTemplateStatisticsResponse // @Router /admin/policy-templates/{policyTemplateId}/statistics [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { - // result := domain.ListPolicyTemplateStatisticsResponse{ - // PolicyTemplateStatistics: []domain.PolicyTemplateStatistics{ + // result := admin_domain.ListPolicyTemplateStatisticsResponse{ + // PolicyTemplateStatistics: []admin_domain.PolicyTemplateStatistics{ // { // OrganizationId: util.UUIDGen(), // OrganizationName: "개발팀", @@ -370,12 +389,12 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateStatistics(w http.Respon // Admin_GetPolicyTemplateDeploy godoc // // @Tags PolicyTemplate -// @Summary [GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회 +// @Summary [Admin_GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회 // @Description 해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다. // @Accept json // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" -// @Success 200 {object} domain.GetPolicyTemplateDeployResponse +// @Success 200 {object} admin_domain.GetPolicyTemplateDeployResponse // @Router /admin/policy-templates/{policyTemplateId}/deploy [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { @@ -383,7 +402,7 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateDeploy(w http.ResponseWri // c2 := util.UUIDGen() // c3 := util.UUIDGen() - // result := domain.GetPolicyTemplateDeployResponse{ + // result := admin_domain.GetPolicyTemplateDeployResponse{ // DeployVersion: map[string]string{ // c1: "v1.0.1", // c2: "v1.1.0", @@ -396,17 +415,24 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateDeploy(w http.ResponseWri // Admin_GetPolicyTemplateVersion godoc // // @Tags PolicyTemplate -// @Summary [GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회 +// @Summary [Admin_GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회 // @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다. // @Accept json // @Produce json // @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" // @Param version path string true "조회할 버전(v0.0.0 형식)" -// @Success 200 {object} domain.GetPolicyTemplateVersionResponse +// @Success 200 {object} admin_domain.GetPolicyTemplateVersionResponse // @Router /admin/policy-templates/{policyTemplateId}/versions/{version} [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + policyTemplateId, ok := vars["policyTemplateId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) @@ -425,7 +451,7 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateVersion(w http.ResponseWr return } - policyTemplate, err := h.usecase.GetPolicyTemplateVersion(r.Context(), id, version) + policyTemplate, err := h.usecase.GetPolicyTemplateVersion(r.Context(), &organizationId, id, version) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) @@ -438,7 +464,7 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateVersion(w http.ResponseWr return } - var out domain.GetPolicyTemplateVersionResponse + var out admin_domain.GetPolicyTemplateVersionResponse if err = serializer.Map(r.Context(), *policyTemplate, &out.PolicyTemplate); err != nil { log.Error(r.Context(), err) } @@ -453,13 +479,13 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateVersion(w http.ResponseWr // Admin_CreatePolicyTemplateVersion godoc // // @Tags PolicyTemplate -// @Summary [CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장 +// @Summary [Admin_CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장 // @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다. // @Accept json // @Produce json -// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" -// @Param body body domain.CreatePolicyTemplateVersionRequest true "create policy template version request" -// @Success 200 {object} domain.CreatePolicyTemplateVersionResponse +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param body body admin_domain.CreatePolicyTemplateVersionRequest true "create policy template version request" +// @Success 200 {object} admin_domain.CreatePolicyTemplateVersionResponse // @Router /admin/policy-templates/{policyTemplateId}/versions [post] // @Security JWT func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { @@ -476,7 +502,7 @@ func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplateVersion(w http.Respons return } - input := domain.CreatePolicyTemplateVersionRequest{} + input := admin_domain.CreatePolicyTemplateVersionRequest{} err = UnmarshalRequestInput(r, &input) @@ -513,14 +539,14 @@ func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplateVersion(w http.Respons input.ExpectedVersion, expectedVersion))) } - createdVersion, err := h.usecase.CreatePolicyTemplateVersion(r.Context(), id, expectedVersion, input.ParametersSchema, input.Rego, input.Libs) + createdVersion, err := h.usecase.CreatePolicyTemplateVersion(r.Context(), nil, id, expectedVersion, input.ParametersSchema, input.Rego, input.Libs) if err != nil { ErrorJSON(w, r, err) return } - var out domain.CreatePolicyTemplateVersionResponse + var out admin_domain.CreatePolicyTemplateVersionResponse out.Version = createdVersion ResponseJSON(w, r, http.StatusOK, out) @@ -529,7 +555,7 @@ func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplateVersion(w http.Respons // Admin_DeletePolicyTemplateVersion godoc // // @Tags PolicyTemplate -// @Summary [DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제 +// @Summary [Admin_DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제 // @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다. // @Accept json // @Produce json @@ -559,7 +585,7 @@ func (h *PolicyTemplateHandler) Admin_DeletePolicyTemplateVersion(w http.Respons return } - err = h.usecase.DeletePolicyTemplateVersion(r.Context(), id, version) + err = h.usecase.DeletePolicyTemplateVersion(r.Context(), nil, id, version) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -578,12 +604,12 @@ func (h *PolicyTemplateHandler) Admin_DeletePolicyTemplateVersion(w http.Respons // Admin_ExistsPolicyTemplateName godoc // // @Tags PolicyTemplate -// @Summary [ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인 +// @Summary [Admin_ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인 // @Description 해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다. // @Accept json // @Produce json // @Param policyTemplateName path string true "정책 템플릿 이름" -// @Success 200 {object} domain.CheckExistedResponse +// @Success 200 {object} admin_domain.ExistsPolicyTemplateNameResponse // @Router /admin/policy-templates/name/{policyTemplateName}/existence [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) { @@ -595,13 +621,13 @@ func (h *PolicyTemplateHandler) Admin_ExistsPolicyTemplateName(w http.ResponseWr return } - exist, err := h.usecase.IsPolicyTemplateNameExist(r.Context(), policyTemplateName) + exist, err := h.usecase.IsPolicyTemplateNameExist(r.Context(), nil, policyTemplateName) if err != nil { ErrorJSON(w, r, err) return } - var out domain.CheckExistedResponse + var out admin_domain.ExistsPolicyTemplateNameResponse out.Existed = exist ResponseJSON(w, r, http.StatusOK, out) @@ -610,12 +636,12 @@ func (h *PolicyTemplateHandler) Admin_ExistsPolicyTemplateName(w http.ResponseWr // Admin_ExistsPolicyTemplateKind godoc // // @Tags PolicyTemplate -// @Summary [ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인 +// @Summary [Admin_ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인 // @Description 해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다. // @Accept json // @Produce json // @Param policyTemplateKind path string true "정책 템플릿 이름" -// @Success 200 {object} domain.CheckExistedResponse +// @Success 200 {object} admin_domain.ExistsPolicyTemplateKindResponse // @Router /admin/policy-templates/kind/{policyTemplateKind}/existence [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) { @@ -627,13 +653,13 @@ func (h *PolicyTemplateHandler) Admin_ExistsPolicyTemplateKind(w http.ResponseWr return } - exist, err := h.usecase.IsPolicyTemplateKindExist(r.Context(), policyTemplateKind) + exist, err := h.usecase.IsPolicyTemplateKindExist(r.Context(), nil, policyTemplateKind) if err != nil { ErrorJSON(w, r, err) return } - var out domain.CheckExistedResponse + var out admin_domain.ExistsPolicyTemplateKindResponse out.Existed = exist ResponseJSON(w, r, http.StatusOK, out) @@ -685,3 +711,680 @@ func (h *PolicyTemplateHandler) RegoCompile(w http.ResponseWriter, r *http.Reque ResponseJSON(w, r, http.StatusCreated, response) } + +// CreatePolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [CreatePolicyTemplate] 정책 템플릿 신규 생성 +// @Description 정책 템플릿을 신규 생성(v1.0.0을 생성)한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param body body domain.CreatePolicyTemplateRequest true "create policy template request" +// @Success 200 {object} domain.CreatePolicyTemplateReponse +// @Router /organizations/{organizationId}/policy-templates [post] +// @Security JWT +func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.CreatePolicyTemplateRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto model.PolicyTemplate + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + + dto.Type = "organization" + dto.OrganizationId = &organizationId + + policyTemplateId, err := h.usecase.Create(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CreatePolicyTemplateReponse + out.ID = policyTemplateId.String() + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdatePolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [UpdatePolicyTemplate] 정책 템플릿 업데이트 +// @Description 정책 템플릿의 업데이트 가능한 필드들을 업데이트한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param body body domain.UpdatePolicyTemplateRequest true "update policy template request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId} [patch] +// @Security JWT +func (h *PolicyTemplateHandler) UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + input := domain.UpdatePolicyTemplateRequest{} + + err = UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + // Organization 템플릿은 PermittedOrganizations가 없음 + err = h.usecase.Update(r.Context(), &organizationId, id, input.TemplateName, input.Description, input.Severity, input.Deprecated, nil) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +// DeletePolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [DeletePolicyTemplate] 정책 템플릿 삭제 +// @Description 정책 템플릿을 삭제한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId} [delete] +// @Security JWT +func (h *PolicyTemplateHandler) DeletePolicyTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + err = h.usecase.Delete(r.Context(), &organizationId, id) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, "") +} + +// GetPolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [GetPolicyTemplate] 정책 템플릿 조회(최신 버전) +// @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.GetPolicyTemplateResponse +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId} [get] +// @Security JWT +func (h *PolicyTemplateHandler) GetPolicyTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + policyTemplate, err := h.usecase.Get(r.Context(), &organizationId, id) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + if policyTemplate == nil { + ResponseJSON(w, r, http.StatusNotFound, nil) + return + } + + var out domain.GetPolicyTemplateResponse + if err = serializer.Map(r.Context(), *policyTemplate, &out.PolicyTemplate); err != nil { + log.Error(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ListPolicyTemplate godoc +// +// @Tags PolicyTemplate +// @Summary [ListPolicyTemplate] 정책 템플릿 목록 조회 +// @Description 정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다. +// @Accept json +// @Produce json +// @Param limit query string false "pageSize" +// @Param page query string false "pageNumber" +// @Param sortColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Success 200 {object} domain.ListPolicyTemplateResponse +// @Router /organizations/{organizationId}/policy-templates [get] +// @Security JWT +func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *http.Request) { + urlParams := r.URL.Query() + + pg := pagination.NewPagination(&urlParams) + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplates, err := h.usecase.Fetch(r.Context(), &organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ListPolicyTemplateResponse + out.PolicyTemplates = make([]domain.PolicyTemplateResponse, len(policyTemplates)) + for i, policyTemplate := range policyTemplates { + if err := serializer.Map(r.Context(), policyTemplate, &out.PolicyTemplates[i]); err != nil { + log.Info(r.Context(), err) + continue + } + } + + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ListPolicyTemplateVersions godoc +// +// @Tags PolicyTemplate +// @Summary [ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회 +// @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.ListPolicyTemplateVersionsResponse +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/versions [get] +// @Security JWT +func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + policyTemplateVersions, err := h.usecase.ListPolicyTemplateVersions(r.Context(), &organizationId, id) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + var out domain.ListPolicyTemplateVersionsResponse + if err = serializer.Map(r.Context(), *policyTemplateVersions, &out); err != nil { + log.Error(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ListPolicyTemplateStatistics godoc +// +// @Tags PolicyTemplate +// @Summary [ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회 +// @Description 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.ListPolicyTemplateStatisticsResponse +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/statistics [get] +// @Security JWT +func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { + // result := domain.ListPolicyTemplateStatisticsResponse{ + // PolicyTemplateStatistics: []domain.PolicyTemplateStatistics{ + // { + // OrganizationId: util.UUIDGen(), + // OrganizationName: "개발팀", + // UsageCount: 10, + // }, + // { + // OrganizationId: util.UUIDGen(), + // OrganizationName: "운영팀", + // UsageCount: 5, + // }, + // }, + // } + // util.JsonResponse(w, result) +} + +// GetPolicyTemplateDeploy godoc +// +// @Tags PolicyTemplate +// @Summary [GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회 +// @Description 해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.GetPolicyTemplateDeployResponse +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/deploy [get] +// @Security JWT +func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { + // c1 := util.UUIDGen() + // c2 := util.UUIDGen() + // c3 := util.UUIDGen() + + // result := domain.GetPolicyTemplateDeployResponse{ + // DeployVersion: map[string]string{ + // c1: "v1.0.1", + // c2: "v1.1.0", + // c3: "v1.1.0", + // }, + // } + // util.JsonResponse(w, result) +} + +// GetPolicyTemplateVersion godoc +// +// @Tags PolicyTemplate +// @Summary [GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회 +// @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param version path string true "조회할 버전(v0.0.0 형식)" +// @Success 200 {object} domain.GetPolicyTemplateVersionResponse +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version} [get] +// @Security JWT +func (h *PolicyTemplateHandler) GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + version, ok := vars["version"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid version"), "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + policyTemplate, err := h.usecase.GetPolicyTemplateVersion(r.Context(), &organizationId, id, version) + if err != nil { + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) + return + } + } + + if policyTemplate == nil { + ResponseJSON(w, r, http.StatusNotFound, nil) + return + } + + var out domain.GetPolicyTemplateVersionResponse + if err = serializer.Map(r.Context(), *policyTemplate, &out.PolicyTemplate); err != nil { + log.Error(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// CreatePolicyTemplateVersion godoc +// +// @Tags PolicyTemplate +// @Summary [CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장 +// @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param body body domain.CreatePolicyTemplateVersionRequest true "create policy template version request" +// @Success 200 {object} domain.CreatePolicyTemplateVersionResponse +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/versions [post] +// @Security JWT +func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + input := domain.CreatePolicyTemplateVersionRequest{} + + err = UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + currentVer, err := semver.NewVersion(input.CurrentVersion) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid currentVersion"), "PT_INVALID_POLICY_TEMPLATE_VERSION", fmt.Sprintf("invalid version format '%s'", input.CurrentVersion))) + return + } + + versionUpType := strings.ToLower(input.VersionUpType) + + var expectedVersion string + + switch versionUpType { + case "major": + newVersion := currentVer.IncMajor() + expectedVersion = newVersion.Original() + case "minor": + newVersion := currentVer.IncMinor() + expectedVersion = newVersion.Original() + case "patch": + newVersion := currentVer.IncPatch() + expectedVersion = newVersion.Original() + } + + if expectedVersion != input.ExpectedVersion { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid expectedVersion"), "PT_INVALID_POLICY_TEMPLATE_VERSION", fmt.Sprintf("expected version mismatch '%s' != '%s'", + input.ExpectedVersion, expectedVersion))) + } + + createdVersion, err := h.usecase.CreatePolicyTemplateVersion(r.Context(), &organizationId, id, expectedVersion, input.ParametersSchema, input.Rego, input.Libs) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CreatePolicyTemplateVersionResponse + out.Version = createdVersion + + ResponseJSON(w, r, http.StatusOK, out) +} + +// DeletePolicyTemplateVersion godoc +// +// @Tags PolicyTemplate +// @Summary [DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제 +// @Description 해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param version path string true "삭제할 버전(v0.0.0 형식)" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version} [delete] +// @Security JWT +func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + version, ok := vars["version"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid version"), "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) + return + } + + err = h.usecase.DeletePolicyTemplateVersion(r.Context(), &organizationId, id, version) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, "") +} + +// ExistsPolicyTemplateName godoc +// +// @Tags PolicyTemplate +// @Summary [ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인 +// @Description 해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateName path string true "정책 템플릿 이름" +// @Success 200 {object} domain.ExistsPolicyTemplateNameResponse +// @Router /organizations/{organizationId}/policy-templates/name/{policyTemplateName}/existence [get] +// @Security JWT +func (h *PolicyTemplateHandler) ExistsPolicyTemplateName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateName, ok := vars["policyTemplateName"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyTemplateName not found in path"), + "PT_INVALID_POLICY_TEMPLATE_NAME", "")) + return + } + + exist, err := h.usecase.IsPolicyTemplateNameExist(r.Context(), &organizationId, policyTemplateName) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ExistsPolicyTemplateNameResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} + +// ExistsPolicyTemplateKind godoc +// +// @Tags PolicyTemplate +// @Summary [ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인 +// @Description 해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateKind path string true "정책 템플릿 이름" +// @Success 200 {object} domain.ExistsPolicyTemplateKindResponse +// @Router /organizations/{organizationId}/policy-templates/kind/{policyTemplateKind}/existence [get] +// @Security JWT +func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateKind, ok := vars["policyTemplateKind"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyTemplateKind not found in path"), + "PT_INVALID_POLICY_TEMPLATE_KIND", "")) + return + } + + exist, err := h.usecase.IsPolicyTemplateKindExist(r.Context(), &organizationId, policyTemplateKind) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ExistsPolicyTemplateKindResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 972648c8..24b7e59c 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -139,7 +139,6 @@ func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { return } templateId = &tuuid - } err = h.usecase.Update(r.Context(), organizationId, id, @@ -284,7 +283,7 @@ func (h *PolicyHandler) GetPolicy(w http.ResponseWriter, r *http.Request) { // @Param organizationId path string true "조직 식별자(o로 시작)" // @Param limit query string false "pageSize" // @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" +// @Param sortColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" // @Success 200 {object} domain.ListPolicyResponse diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 21658fd9..5ac474f3 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -341,7 +341,7 @@ func convertModelToPermissionResponse(ctx context.Context, permission *model.Per return &permissionResponse } -func convertModelToEndpointResponse(ctx context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { +func convertModelToEndpointResponse(_ context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { var endpointResponse domain.EndpointResponse endpointResponse.Name = endpoint.Name diff --git a/internal/model/permission.go b/internal/model/permission.go index 7fafc931..b81ec8a4 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -296,14 +296,14 @@ func newPolicy() *Permission { api.ExistsPolicyName, // OrganizationPolicyTemplate - api.ListOrganizationPolicyTemplate, - api.GetOrganizationPolicyTemplate, - api.GetOrganizationPolicyTemplateDeploy, - api.ListOrganizationPolicyTemplateStatistics, - api.ListOrganizationPolicyTemplateVersions, - api.GetOrganizationPolicyTemplateVersion, - api.ExistsOrganizationPolicyTemplateKind, - api.ExistsOrganizationPolicyTemplateName, + api.ListPolicyTemplate, + api.GetPolicyTemplate, + api.GetPolicyTemplateDeploy, + api.ListPolicyTemplateStatistics, + api.ListPolicyTemplateVersions, + api.GetPolicyTemplateVersion, + api.ExistsPolicyTemplateKind, + api.ExistsPolicyTemplateName, // PolicyTemplateExample api.ListPolicyTemplateExample, @@ -325,8 +325,8 @@ func newPolicy() *Permission { api.CreatePolicy, // OrganizationPolicyTemplate - api.CreateOrganizationPolicyTemplate, - api.CreateOrganizationPolicyTemplateVersion, + api.CreatePolicyTemplate, + api.CreatePolicyTemplateVersion, ), }, { @@ -346,7 +346,7 @@ func newPolicy() *Permission { api.UpdatePolicyTargetClusters, // OrganizationPolicyTemplate - api.UpdateOrganizationPolicyTemplate, + api.UpdatePolicyTemplate, // PolicyTemplateExample api.UpdatePolicyTemplateExample, @@ -366,8 +366,8 @@ func newPolicy() *Permission { api.DeletePolicy, // OrganizationPolicyTemplate - api.DeleteOrganizationPolicyTemplate, - api.DeleteOrganizationPolicyTemplateVersion, + api.DeletePolicyTemplate, + api.DeletePolicyTemplateVersion, // PolicyTemplateExample api.DeletePolicyTemplateExample, diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index c5e2f433..2a197376 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "slices" "strings" "github.com/google/uuid" @@ -32,12 +33,14 @@ type PolicyTemplate struct { Type string // Org or Tks Version string `gorm:"-:all"` // 삭제 예정 SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` + OrganizationId *string // Org 인 경우에만 설정 + Organization Organization `gorm:"foreignKey:OrganizationId"` Description string Kind string Deprecated bool Mandatory bool // Tks 인 경우에는 무시 Severity string - PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organiations"` + PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organizations"` ParametersSchema []domain.ParameterDef `gorm:"-:all"` Rego string `gorm:"-:all"` Libs []string `gorm:"-:all"` @@ -48,6 +51,28 @@ type PolicyTemplate struct { Updator User `gorm:"foreignKey:UpdatorId"` } +func (pt *PolicyTemplate) IsTksTemplate() bool { + return strings.ToLower(pt.Type) == "tks" +} + +func (pt *PolicyTemplate) IsOrganizationTemplate() bool { + return !pt.IsTksTemplate() +} + +func (pt *PolicyTemplate) IsPermittedToOrganization(organizationId *string) bool { + // tks Admin은 organizationId가 nil + if organizationId == nil { + return true + } + + if pt.IsTksTemplate() { + return len(pt.PermittedOrganizationIds) == 0 || + slices.Contains(pt.PermittedOrganizationIds, *organizationId) + } + + return pt.OrganizationId != nil && *organizationId == *pt.OrganizationId +} + func (pt *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { pt.ID = uuid.New() @@ -79,7 +104,7 @@ func (pt *PolicyTemplate) AfterFind(tx *gorm.DB) (err error) { supportedVersion := pt.SupportedVersions[0] pt.Version = supportedVersion.Version pt.Rego = supportedVersion.Rego - pt.Libs = strings.Split(supportedVersion.ParameterSchema, FILE_DELIMETER) + pt.Libs = strings.Split(supportedVersion.Libs, FILE_DELIMETER) // 마찬가지로 에러 무시 _ = json.Unmarshal([]byte(supportedVersion.ParameterSchema), &pt.ParametersSchema) diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 18cf0841..a7ecac85 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -19,12 +19,15 @@ type IPolicyTemplateRepository interface { Create(ctx context.Context, policyTemplate model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) Update(ctx context.Context, policyTemplateId uuid.UUID, updateMap map[string]interface{}, permittedOrganizations *[]model.Organization) (err error) Fetch(ctx context.Context, pg *pagination.Pagination) (out []model.PolicyTemplate, err error) + FetchForOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.PolicyTemplate, err error) GetByName(ctx context.Context, policyTemplateName string) (out *model.PolicyTemplate, err error) GetByKind(ctx context.Context, policyTemplateKind string) (out *model.PolicyTemplate, err error) GetByID(ctx context.Context, policyTemplateId uuid.UUID) (out *model.PolicyTemplate, err error) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) ExistByName(ctx context.Context, policyTemplateName string) (exist bool, err error) ExistByKind(ctx context.Context, policyTemplateKind string) (exist bool, err error) + ExistByNameInOrganization(ctx context.Context, organizationId string, policyTemplateName string) (exist bool, err error) + ExistByKindInOrganization(ctx context.Context, organizationId string, policyTemplateKind string) (exist bool, err error) ExistByID(ctx context.Context, policyTemplateId uuid.UUID) (exist bool, err error) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) @@ -70,7 +73,7 @@ func (r *PolicyTemplateRepository) Update(ctx context.Context, policyTemplateId if len(updateMap) > 0 { err = r.db.WithContext(ctx).Model(&policyTemplate).Limit(1). - Where("id = ? and type = 'tks'", policyTemplateId). + Where("id = ?", policyTemplateId).Where("type = ?", "tks"). Updates(updateMap).Error if err != nil { @@ -104,6 +107,58 @@ func (r *PolicyTemplateRepository) Fetch(ctx context.Context, pg *pagination.Pag return policyTemplates, nil } +func (r *PolicyTemplateRepository) FetchForOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.PolicyTemplate, err error) { + var policyTemplates []model.PolicyTemplate + if pg == nil { + pg = pagination.NewPagination(nil) + } + + // 다음과 같은 쿼리를 생성해서 tks 템플릿에 대해선 PermittedOrganizations가 비거나, PermittedOrganizations에 해당 organizations이 속하는 템플릿을 찾음 + // organization 템플릿은 organizationId가 매칭되는 것을 찾음, 이를 통해 해당 사용자가 사용할 수 있는 모든 템플릿을 fetch + // select id from policy_templates where + // ( + // type = 'tks' + // and ( + // id not in (select policy_template_id from policy_template_permitted_organizations) -- PermitedOrganizations이 빈 경우, 모두에게 허용 + // or id in (select policy_template_id from policy_template_permitted_organizations organization where organization_id = 'orgid') -- PermitedOrganizations 허용된 경우 + // ) + // ) + // or (type = 'organization' and organization_id='orgid') + subQueryAloowedAll := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id") + subQueryMatchId := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id"). + Where("organization_id = ?", organizationId) + + _, res := pg.Fetch(r.db.WithContext(ctx). + Preload("SupportedVersions", func(db *gorm.DB) *gorm.DB { + // 최신 버전만 + return db.Order("policy_template_supported_versions.version DESC") + }). + Preload("Creator").Preload("Updator"). // organization을 기준으로 조회할 때에는 PermittedOrganizations는 로딩하지 않아도 됨 + Model(&model.PolicyTemplate{}). + Where( + // tks 템플릿인 경우 + r.db.Where("type = ?", "tks"). + Where( + // permitted_organizations이 비어있거나 + r.db.Where("id not in (?)", subQueryAloowedAll). + Or("id in (?)", subQueryMatchId), + // permitted_organization에 매칭되는 템플릿 아이디가 있거나 + ), + ). + Or( + // organization 타입 템플릿이면서 organization_id가 매칭 + r.db.Where("type = ?", "organization"). + Where("organization_id = ?", organizationId), + ), + &policyTemplates) + + if res.Error != nil { + return nil, res.Error + } + + return policyTemplates, nil +} + func (r *PolicyTemplateRepository) ExistsBy(ctx context.Context, key string, value interface{}) (exists bool, err error) { query := fmt.Sprintf("%s = ?", key) @@ -132,6 +187,39 @@ func (r *PolicyTemplateRepository) ExistByKind(ctx context.Context, policyTempla return r.ExistsBy(ctx, "kind", policyTemplateKind) } +func (r *PolicyTemplateRepository) ExistsByInOrganization(ctx context.Context, organizationId string, key string, value interface{}) (exists bool, err error) { + + var policyTemplate model.PolicyTemplate + // query := fmt.Sprintf("%s = ? and (type = 'tks' or organization_id = ?)", key) + // res := r.db.WithContext(ctx).Where(query, value, organizationId). + // First(&policyTemplate) + + res := r.db.WithContext(ctx).Where(fmt.Sprintf("%s = ?", key), value). + Where( + r.db.Where("type = ?", "tks").Or("organization_id = ?", organizationId), + ).First(&policyTemplate) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Infof(ctx, "Not found policyTemplate %s='%v'", key, value) + return false, nil + } else { + log.Error(ctx, res.Error) + return false, res.Error + } + } + + return true, nil +} + +func (r *PolicyTemplateRepository) ExistByNameInOrganization(ctx context.Context, organizationId string, policyTemplateName string) (exist bool, err error) { + return r.ExistsByInOrganization(ctx, organizationId, "template_name", policyTemplateName) +} + +func (r *PolicyTemplateRepository) ExistByKindInOrganization(ctx context.Context, organizationId string, policyTemplateKind string) (exist bool, err error) { + return r.ExistsByInOrganization(ctx, organizationId, "kind", policyTemplateKind) +} + func (r *PolicyTemplateRepository) ExistByID(ctx context.Context, policyTemplateId uuid.UUID) (exist bool, err error) { return r.ExistsBy(ctx, "id", policyTemplateId) } @@ -268,7 +356,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(ctx context.Conte } // relaton을 unscoped로 삭제하지 않으면 동일한 키로 다시 생성할 때 키가 같은 레코드가 deleted 상태로 존재하므로 unscoped delete - res = r.db.WithContext(ctx).Unscoped().Where("policy_template_id = ? and version = ?", policyTemplateId, version). + res = r.db.WithContext(ctx).Unscoped().Where("policy_template_id = ?", policyTemplateId).Where("version = ?", version). Delete(&policyTemplateVersion) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { @@ -287,7 +375,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(ctx context.Conte func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db.WithContext(ctx).Limit(1). - Where("policy_template_id = ? and version = ?", policyTemplateId, version). + Where("policy_template_id = ?", policyTemplateId).Where("version = ?", version). First(&policyTemplateVersion) if res.Error == nil { diff --git a/internal/route/route.go b/internal/route/route.go index a209a15f..e1199f5d 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -313,6 +313,19 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.Admin_ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.Admin_ExistsPolicyTemplateKind))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.Admin_ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.Admin_ExistsPolicyTemplateName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/policy-templates/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(policyTemplateHandler.RegoCompile))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates", customMiddleware.Handle(internalApi.CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplate))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.DeletePolicyTemplate, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplate))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetPolicyTemplate, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.UpdatePolicyTemplate))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/deploy ", customMiddleware.Handle(internalApi.GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateDeploy))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/statistics", customMiddleware.Handle(internalApi.ListPolicyTemplateStatistics, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateStatistics))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.ListPolicyTemplateVersions, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateVersions))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplateVersion))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.DeletePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplateVersion))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateVersion))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateKind))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateName))).Methods(http.MethodGet) policyHandler := delivery.NewPolicyHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/mandatory-policies", customMiddleware.Handle(internalApi.GetMandatoryPolicies, http.HandlerFunc(policyHandler.GetMandatoryPolicies))).Methods(http.MethodGet) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 1294f157..1bf59fef 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + admin_domain "github.com/openinfradev/tks-api/pkg/domain/admin" + mapset "github.com/deckarep/golang-set/v2" "github.com/google/uuid" "github.com/open-policy-agent/opa/ast" @@ -18,24 +20,24 @@ import ( type IPolicyTemplateUsecase interface { Create(ctx context.Context, policyTemplate model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) - Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) - Update(ctx context.Context, policyTemplateId uuid.UUID, templateName *string, description *string, + Fetch(ctx context.Context, organizationId *string, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) + Update(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, templateName *string, description *string, severity *string, deorecated *bool, permittedOrganizationIds *[]string) (err error) - Get(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) - Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) - IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) - IsPolicyTemplateKindExist(ctx context.Context, policyTemplateKind string) (bool, error) - GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) - ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) - DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) - CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) + Get(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) + Delete(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (err error) + IsPolicyTemplateNameExist(ctx context.Context, organizationId *string, policyTemplateName string) (bool, error) + IsPolicyTemplateKindExist(ctx context.Context, organizationId *string, policyTemplateKind string) (bool, error) + GetPolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) + ListPolicyTemplateVersions(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) + DeletePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string) (err error) + CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) FillPermittedOrganizations(ctx context.Context, - policyTemplate *model.PolicyTemplate, out *domain.PolicyTemplateResponse) error + policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) error FillPermittedOrganizationsForList(ctx context.Context, - policyTemplates *[]model.PolicyTemplate, outs *[]domain.PolicyTemplateResponse) error + policyTemplates *[]model.PolicyTemplate, outs *[]admin_domain.PolicyTemplateResponse) error } type PolicyTemplateUsecase struct { @@ -58,33 +60,49 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } - exists, err := u.repo.ExistByName(ctx, dto.TemplateName) - if err == nil && exists { - return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") - } + if dto.IsTksTemplate() { + exists, err := u.repo.ExistByName(ctx, dto.TemplateName) + if err == nil && exists { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") + } + + exists, err = u.repo.ExistByKind(ctx, dto.Kind) + if err == nil && exists { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_KIND", "policy template kind already exists") + } + } else { + exists, err := u.repo.ExistByNameInOrganization(ctx, *dto.OrganizationId, dto.TemplateName) + if err == nil && exists { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") + } - exists, err = u.repo.ExistByKind(ctx, dto.Kind) - if err == nil && exists { - return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_KIND", "policy template kind already exists") + exists, err = u.repo.ExistByKindInOrganization(ctx, *dto.OrganizationId, dto.Kind) + if err == nil && exists { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_KIND", "policy template kind already exists") + } } - dto.PermittedOrganizations = make([]model.Organization, len(dto.PermittedOrganizationIds)) - for i, organizationId := range dto.PermittedOrganizationIds { + if dto.IsTksTemplate() { + // TKS 템블릿이면 + dto.Mandatory = false + dto.OrganizationId = nil + + dto.PermittedOrganizations = make([]model.Organization, len(dto.PermittedOrganizationIds)) + for i, organizationId := range dto.PermittedOrganizationIds { - organization, err := u.organizationRepo.Get(ctx, organizationId) - if err != nil { - return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + organization, err := u.organizationRepo.Get(ctx, organizationId) + if err != nil { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + dto.PermittedOrganizations[i] = organization } - dto.PermittedOrganizations[i] = organization + } else { + dto.PermittedOrganizations = make([]model.Organization, 0) } userId := user.GetUserId() dto.CreatorId = &userId - // 시스템 템플릿 속성 설정 - dto.Type = "tks" - dto.Mandatory = false - id, err := u.repo.Create(ctx, dto) if err != nil { @@ -94,31 +112,29 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp return id, nil } -func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) { - policyTemplates, err = u.repo.Fetch(ctx, pg) - - if err != nil { - return nil, err +func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, organizationId *string, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) { + if organizationId == nil { + return u.repo.Fetch(ctx, pg) } - return policyTemplates, nil + return u.repo.FetchForOrganization(ctx, *organizationId, pg) } func (u *PolicyTemplateUsecase) FillPermittedOrganizations(ctx context.Context, - policyTemplate *model.PolicyTemplate, out *domain.PolicyTemplateResponse) error { + policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) error { organizations, err := u.organizationRepo.Fetch(ctx, nil) if err != nil { return err } - u.updatePermittedOrganizations(ctx, organizations, policyTemplate, out) + u.fillPermittedOrganizations(ctx, organizations, policyTemplate, out) return nil } func (u *PolicyTemplateUsecase) FillPermittedOrganizationsForList(ctx context.Context, - policyTemplates *[]model.PolicyTemplate, outs *[]domain.PolicyTemplateResponse) error { + policyTemplates *[]model.PolicyTemplate, outs *[]admin_domain.PolicyTemplateResponse) error { organizations, err := u.organizationRepo.Fetch(ctx, nil) @@ -129,14 +145,14 @@ func (u *PolicyTemplateUsecase) FillPermittedOrganizationsForList(ctx context.Co results := *outs for i, policyTemplate := range *policyTemplates { - u.updatePermittedOrganizations(ctx, organizations, &policyTemplate, &results[i]) + u.fillPermittedOrganizations(ctx, organizations, &policyTemplate, &results[i]) } return nil } // 모든 조직 목록에 대해 허용 여부 업데이트 -func (u *PolicyTemplateUsecase) updatePermittedOrganizations(ctx context.Context, organizations *[]model.Organization, policyTemplate *model.PolicyTemplate, out *domain.PolicyTemplateResponse) { +func (u *PolicyTemplateUsecase) fillPermittedOrganizations(_ context.Context, organizations *[]model.Organization, policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) { if policyTemplate == nil || organizations == nil || out == nil { return } @@ -147,12 +163,12 @@ func (u *PolicyTemplateUsecase) updatePermittedOrganizations(ctx context.Context // 허용된 조직 포함 여부를 효율적으로 처리하기 위해 ID 리스트를 셋으로 변환 permittedOrganizationIdSet := mapset.NewSet(policyTemplate.PermittedOrganizationIds...) - out.PermittedOrganizations = make([]domain.PermittedOrganization, len(*organizations)) + out.PermittedOrganizations = make([]admin_domain.PermittedOrganization, len(*organizations)) for i, organization := range *organizations { permitted := allPermitted || permittedOrganizationIdSet.ContainsOne(organization.ID) - out.PermittedOrganizations[i] = domain.PermittedOrganization{ + out.PermittedOrganizations[i] = admin_domain.PermittedOrganization{ OrganizationId: organization.ID, OrganizationName: organization.Name, Permitted: permitted, @@ -160,35 +176,68 @@ func (u *PolicyTemplateUsecase) updatePermittedOrganizations(ctx context.Context } } -func (u *PolicyTemplateUsecase) Get(ctx context.Context, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) Get(ctx context.Context, organizationId *string, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetByID(ctx, policyTemplateID) if err != nil { return nil, err } + if !policyTemplate.IsPermittedToOrganization(organizationId) { + return nil, httpErrors.NewNotFoundError(fmt.Errorf( + "policy template not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + return policyTemplate, nil } -func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uuid.UUID, templateName *string, description *string, severity *string, deprecated *bool, permittedOrganizationIds *[]string) (err error) { +func (u *PolicyTemplateUsecase) Update(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, templateName *string, description *string, severity *string, deprecated *bool, permittedOrganizationIds *[]string) (err error) { user, ok := request.UserFrom(ctx) if !ok { return httpErrors.NewBadRequestError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } - _, err = u.repo.GetByID(ctx, policyTemplateId) + policyTemplate, err := u.repo.GetByID(ctx, policyTemplateId) if err != nil { return httpErrors.NewNotFoundError(err, "PT_FAILED_FETCH_POLICY_TEMPLATE", "") } + if policyTemplate == nil { + return httpErrors.NewBadRequestError(fmt.Errorf( + "failed to fetch policy template"), + "PT_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + if !policyTemplate.IsPermittedToOrganization(organizationId) { + // 다른 Organization의 템플릿을 조작하려고 함, 보안을 위해서 해당 식별자 존재 자체를 알려주면 안되므로 not found + if *organizationId != *policyTemplate.OrganizationId { + return httpErrors.NewNotFoundError(fmt.Errorf( + "policy template not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + + return httpErrors.NewForbiddenError(fmt.Errorf( + "cannot update policy template"), + "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE", "") + } + updateMap := make(map[string]interface{}) if templateName != nil { - exists, err := u.repo.ExistByName(ctx, *templateName) - if err == nil && exists { - return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") + if policyTemplate.IsTksTemplate() { + exists, err := u.repo.ExistByName(ctx, *templateName) + if err == nil && exists { + return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") + } + } else { + exists, err := u.repo.ExistByNameInOrganization(ctx, *organizationId, *templateName) + if err == nil && exists { + return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_TEMPLATE_NAME", "policy template name already exists") + } } - updateMap["name"] = templateName + + updateMap["template_name"] = templateName } if description != nil { @@ -233,37 +282,138 @@ func (u *PolicyTemplateUsecase) Update(ctx context.Context, policyTemplateId uui return nil } -func (u *PolicyTemplateUsecase) Delete(ctx context.Context, policyTemplateId uuid.UUID) (err error) { +func (u *PolicyTemplateUsecase) Delete(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (err error) { + policyTemplate, err := u.repo.GetByID(ctx, policyTemplateId) + + if err != nil { + return err + } + + if policyTemplate == nil { + return httpErrors.NewBadRequestError(fmt.Errorf( + "failed to fetch policy template"), + "PT_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + if !policyTemplate.IsPermittedToOrganization(organizationId) { + // 다른 Organization의 템플릿을 조작하려고 함, 보안을 위해서 해당 식별자 존재 자체를 알려주면 안되므로 not found + if *organizationId != *policyTemplate.OrganizationId { + return httpErrors.NewNotFoundError(fmt.Errorf( + "policy template not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + + return httpErrors.NewForbiddenError(fmt.Errorf( + "cannot delete tks policy template"), + "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE", "") + } + return u.repo.Delete(ctx, policyTemplateId) } -func (u *PolicyTemplateUsecase) IsPolicyTemplateNameExist(ctx context.Context, policyTemplateName string) (bool, error) { - return u.repo.ExistByName(ctx, policyTemplateName) +func (u *PolicyTemplateUsecase) IsPolicyTemplateNameExist(ctx context.Context, organizationId *string, policyTemplateName string) (bool, error) { + if organizationId == nil { + return u.repo.ExistByName(ctx, policyTemplateName) + } + + return u.repo.ExistByNameInOrganization(ctx, *organizationId, policyTemplateName) } -func (u *PolicyTemplateUsecase) IsPolicyTemplateKindExist(ctx context.Context, policyTemplateKind string) (bool, error) { - return u.repo.ExistByKind(ctx, policyTemplateKind) +func (u *PolicyTemplateUsecase) IsPolicyTemplateKindExist(ctx context.Context, organizationId *string, policyTemplateKind string) (bool, error) { + if organizationId == nil { + return u.repo.ExistByKind(ctx, policyTemplateKind) + } + + return u.repo.ExistByKindInOrganization(ctx, *organizationId, policyTemplateKind) } -func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { +func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetPolicyTemplateVersion(ctx, policyTemplateId, version) if err != nil { return nil, err } + if !policyTemplate.IsPermittedToOrganization(organizationId) { + return nil, httpErrors.NewNotFoundError(fmt.Errorf( + "policy template not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + return policyTemplate, nil } -func (u *PolicyTemplateUsecase) ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { +func (u *PolicyTemplateUsecase) ListPolicyTemplateVersions(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) { + policyTemplate, err := u.repo.GetByID(ctx, policyTemplateId) + + if err != nil { + return nil, err + } + + if !policyTemplate.IsPermittedToOrganization(organizationId) { + return nil, httpErrors.NewNotFoundError(fmt.Errorf( + "policy template not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + return u.repo.ListPolicyTemplateVersions(ctx, policyTemplateId) } -func (u *PolicyTemplateUsecase) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) { +func (u *PolicyTemplateUsecase) DeletePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string) (err error) { + policyTemplate, err := u.repo.GetPolicyTemplateVersion(ctx, policyTemplateId, version) + + if err != nil { + return err + } + + if policyTemplate == nil { + return httpErrors.NewBadRequestError(fmt.Errorf( + "failed to fetch policy template"), + "PT_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + if !policyTemplate.IsPermittedToOrganization(organizationId) { + // 다른 Organization의 템플릿을 조작하려고 함, 보안을 위해서 해당 식별자 존재 자체를 알려주면 안되므로 not found + if *organizationId != *policyTemplate.OrganizationId { + return httpErrors.NewNotFoundError(fmt.Errorf( + "policy template version not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + + return httpErrors.NewForbiddenError(fmt.Errorf( + "cannot delete tks policy template version"), + "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE", "") + } + return u.repo.DeletePolicyTemplateVersion(ctx, policyTemplateId, version) } -func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { +func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { + policyTemplate, err := u.repo.GetByID(ctx, policyTemplateId) + + if err != nil { + return "", err + } + + if policyTemplate == nil { + return "", httpErrors.NewBadRequestError(fmt.Errorf( + "failed to fetch policy template"), + "PT_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + if !policyTemplate.IsPermittedToOrganization(organizationId) { + // 다른 Organization의 템플릿을 조작하려고 함, 보안을 위해서 해당 식별자 존재 자체를 알려주면 안되므로 not found + if *organizationId != *policyTemplate.OrganizationId { + return "", httpErrors.NewNotFoundError(fmt.Errorf( + "policy template version not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + + return "", httpErrors.NewForbiddenError(fmt.Errorf( + "cannot crate tks policy template version"), + "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE", "") + } + return u.repo.CreatePolicyTemplateVersion(ctx, policyTemplateId, newVersion, schema, rego, libs) } diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 4f7da889..aac394e3 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -59,7 +59,7 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m } if exists { - return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_CREATE_ALREADY_EXISTED_NAME", "policy template name already exists") + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_CREATE_ALREADY_EXISTED_NAME", "policy name already exists") } dto.TargetClusters = make([]model.Cluster, len(dto.TargetClusterIds)) @@ -72,6 +72,18 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m dto.TargetClusters[i] = cluster } + policyTemplate, err := u.templateRepo.GetByID(ctx, dto.TemplateId) + + if err != nil { + return uuid.Nil, err + } + + if !policyTemplate.IsPermittedToOrganization(&organizationId) { + return uuid.Nil, httpErrors.NewNotFoundError(fmt.Errorf( + "policy template not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + userId := user.GetUserId() dto.CreatorId = &userId @@ -117,6 +129,18 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic } if templateId != nil { + policyTemplate, err := u.templateRepo.GetByID(ctx, *templateId) + + if err != nil { + return err + } + + if !policyTemplate.IsPermittedToOrganization(&organizationId) { + return httpErrors.NewNotFoundError(fmt.Errorf( + "policy template not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + updateMap["template_id"] = templateId } diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go new file mode 100644 index 00000000..9c56af9c --- /dev/null +++ b/pkg/domain/admin/policy-template.go @@ -0,0 +1,179 @@ +package admin + +import ( + "time" + + "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" +) + +type PermittedOrganization struct { + OrganizationId string `json:"organizationId"` + OrganizationName string `json:"organizationName"` + Permitted bool `json:"permitted"` +} + +type PolicyTemplateResponse struct { + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + Type string `json:"type" enums:"tks,organization" example:"tks"` + Creator domain.SimpleUserResponse `json:"creator"` + Updator domain.SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Kind string `json:"kind" example:"K8sRequiredLabels"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Version string `json:"version,omitempty" example:"v1.0.1"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []domain.ParameterDef `json:"parametersSchema,omitempty"` + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` + + PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` +} + +type SimplePolicyTemplateResponse struct { + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + Type string `json:"type" enums:"tks,organization" example:"tks"` + Name string `json:"templateName" example:"필수 Label 검사"` + Version string `json:"version,omitempty" example:"v1.0.1"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` +} + +type CreatePolicyTemplateRequest struct { + TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []domain.ParameterDef `json:"parametersSchema,omitempty"` + // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" + + Rego string `json:"rego" example:"rego 코드" validate:"required"` + Libs []string `json:"libs" example:"rego 코드"` + + PermittedOrganizationIds []string `json:"permittedOrganizationIds"` +} + +type CreatePolicyTemplateReponse struct { + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` +} + +type CreateOrganizationPolicyTemplateReponse struct { + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` +} + +type UpdateCommmonPolicyTemplateRequest struct { + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Description string `json:"description,omitempty"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + // Tags []string `json:"tags,omitempty"` +} + +type UpdatePolicyTemplateUpdate struct { + ID uuid.UUID + Type string + UpdatorId uuid.UUID + TemplateName *string + Description *string + Severity *string + Deprecated *bool + PermittedOrganizationIds *[]string +} + +func (dto *UpdatePolicyTemplateUpdate) IsNothingToUpdate() bool { + return dto.TemplateName == nil && + dto.Description == nil && + dto.Severity == nil && + dto.Deprecated == nil && + dto.PermittedOrganizationIds == nil +} + +type UpdatePolicyTemplateRequest struct { + TemplateName *string `json:"templateName,omitempty" example:"필수 Label 검사"` + Description *string `json:"description,omitempty"` + Severity *string `json:"severity,omitempty" enums:"low,medium,high" example:"medium"` + Deprecated *bool `json:"deprecated,omitempty" example:"false"` + PermittedOrganizationIds *[]string `json:"permittedOrganizationIds,omitempty"` +} + +type UpdateOrganizationPolicyTemplateRequest struct { + UpdateCommmonPolicyTemplateRequest + Mandatory bool `json:"mandatory"` +} + +type GetPolicyTemplateDeployResponse struct { + DeployVersion map[string]string `json:"deployVersion"` +} + +type GetOrganizationPolicyTemplateDeployResponse struct { + DeployVersion map[string]string `json:"deployVersion"` +} + +type ListPolicyTemplateVersionsResponse struct { + Versions []string `json:"versions" example:"v1.1.0,v1.0.1,v1.0.0"` +} + +type ListOrganizationPolicyTemplateVersionsResponse struct { + Versions []string `json:"versions" example:"v1.1.0,v1.0.1,v1.0.0"` +} + +type GetPolicyTemplateVersionResponse struct { + PolicyTemplate PolicyTemplateResponse `json:"policyTemplate"` +} + +type CreatePolicyTemplateVersionRequest struct { + VersionUpType string `json:"versionUpType" enums:"major,minor,patch" example:"minor" validate:"required"` + CurrentVersion string `json:"currentVersion" example:"v1.0.0" validate:"required"` + ExpectedVersion string `json:"expectedVersion" example:"v1.1.0" validate:"required"` + + ParametersSchema []domain.ParameterDef `json:"parametersSchema,omitempty"` + // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" + + Rego string `json:"rego" example:"rego 코드" validate:"required"` + Libs []string `json:"libs" example:"rego 코드"` +} + +type CreatePolicyTemplateVersionResponse struct { + Version string `json:"version" example:"v1.1.1"` +} + +type GetPolicyTemplateResponse struct { + PolicyTemplate PolicyTemplateResponse `json:"policyTemplate"` +} + +type ListPolicyTemplateResponse struct { + PolicyTemplates []PolicyTemplateResponse `json:"policyTemplates"` + Pagination domain.PaginationResponse `json:"pagination"` +} + +type PolicyTemplateStatistics struct { + OrganizationId string `json:"organizationId"` + OrganizationName string `json:"organizationName"` + UsageCount int `json:"usageCount"` +} + +type ListPolicyTemplateStatisticsResponse struct { + PolicyTemplateStatistics []PolicyTemplateStatistics `json:"policyTemplateStatistics"` +} + +type ExistsPolicyTemplateNameResponse struct { + Existed bool `json:"existed"` +} + +type ExistsPolicyTemplateKindResponse struct { + Existed bool `json:"existed"` +} + +type RegoCompileRequest struct { + Rego string `json:"rego" example:"Rego 코드" validate:"required"` + Libs []string `json:"libs,omitempty"` +} + +type RegoCompileResponse struct { + ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` + Errors []domain.RegoCompieError `json:"errors,omitempty"` +} diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index ea9998ba..e57fd772 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -6,41 +6,6 @@ import ( "github.com/google/uuid" ) -type CommonPolicyTemplate struct { - ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - Type string `json:"type" enums:"tks,organization" example:"tks"` - Creator SimpleUserResponse `json:"creator,omitempty"` - Updator SimpleUserResponse `json:"updator,omitempty"` - CreatedAt time.Time `json:"createdAt" format:"date-time"` - UpdatedAt time.Time `json:"updatedAt" format:"date-time"` - - TemplateName string `json:"templateName" example:"필수 Label 검사"` - Kind string `json:"kind" example:"K8sRequiredLabels"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` - Deprecated bool `json:"deprecated" example:"false"` - Version string `json:"version,omitempty" example:"v1.0.1"` - Description string `json:"description,omitempty" example:"이 정책은 ..."` - ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` - // Target string `json:"target,omitempty" example:"admission.k8s.gatekeeper.sh"` - // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - - Rego string `json:"rego" example:"rego 코드"` - Libs []string `json:"libs" example:"rego 코드"` - - // Tags []string `json:"tags,omitempty" example:"k8s,label"` -} - -type OrganizationPolicyTemplate struct { - Mandatory bool `json:"mandatory"` - CommonPolicyTemplate -} - -type PermittedOrganization struct { - OrganizationId string `json:"organizationId"` - OrganizationName string `json:"organizationName"` - Permitted bool `json:"permitted"` -} - type PolicyTemplateResponse struct { ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` Type string `json:"type" enums:"tks,organization" example:"tks"` @@ -58,8 +23,6 @@ type PolicyTemplateResponse struct { ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` Rego string `json:"rego" example:"rego 코드"` Libs []string `json:"libs" example:"rego 코드"` - - PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` } type SimplePolicyTemplateResponse struct { @@ -70,48 +33,6 @@ type SimplePolicyTemplateResponse struct { Description string `json:"description,omitempty" example:"이 정책은 ..."` } -/* -type PolicyTemplate struct { - ID PolicyTemplateId - Type string - CreatorId *uuid.UUID - Creator User - UpdatorId *uuid.UUID - Updator User - CreatedAt time.Time - UpdatedAt time.Time - - TemplateName string - Kind string - Severity string - Deprecated bool - Version string - Description string - ParametersSchema []ParameterDef - - Rego string - Libs []string - - PermittedOrganizationIds []string // 생성 시에만 사용 - PermittedOrganizations []PermittedOrganization -} -*/ - -type CreateCommonPolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` - Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` - Deprecated bool `json:"deprecated" example:"false"` - Description string `json:"description,omitempty" example:"이 정책은 ..."` - ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` - // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - - Rego string `json:"rego" example:"rego 코드" validate:"required"` - Libs []string `json:"libs" example:"rego 코드"` - - // Tags []string `json:"tags,omitempty" example:"k8s,label"` -} - type CreatePolicyTemplateRequest struct { TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` @@ -127,19 +48,10 @@ type CreatePolicyTemplateRequest struct { PermittedOrganizationIds []string `json:"permittedOrganizationIds"` } -type CreateOrganizationPolicyTemplateRequest struct { - CreateCommonPolicyTemplateRequest - Mandatory bool `json:"mandatory"` -} - type CreatePolicyTemplateReponse struct { ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` } -type CreateOrganizationPolicyTemplateReponse struct { - ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` -} - type UpdateCommmonPolicyTemplateRequest struct { TemplateName string `json:"templateName" example:"필수 Label 검사"` Description string `json:"description,omitempty"` @@ -175,38 +87,18 @@ type UpdatePolicyTemplateRequest struct { PermittedOrganizationIds *[]string `json:"permittedOrganizationIds,omitempty"` } -type UpdateOrganizationPolicyTemplateRequest struct { - UpdateCommmonPolicyTemplateRequest - Mandatory bool `json:"mandatory"` -} - -// type GetPolicyTemplateVersionResponse struct { -// PolicyTemplate PolicyTemplate `json:"policyTemplate"` -// } type GetPolicyTemplateDeployResponse struct { DeployVersion map[string]string `json:"deployVersion"` } -type GetOrganizationPolicyTemplateDeployResponse struct { - DeployVersion map[string]string `json:"deployVersion"` -} - type ListPolicyTemplateVersionsResponse struct { Versions []string `json:"versions" example:"v1.1.0,v1.0.1,v1.0.0"` } -type ListOrganizationPolicyTemplateVersionsResponse struct { - Versions []string `json:"versions" example:"v1.1.0,v1.0.1,v1.0.0"` -} - type GetPolicyTemplateVersionResponse struct { PolicyTemplate PolicyTemplateResponse `json:"policyTemplate"` } -type GetOrganizationPolicyTemplateVersionResponse struct { - PolicyTemplate OrganizationPolicyTemplate `json:"policyTemplate"` -} - type CreatePolicyTemplateVersionRequest struct { VersionUpType string `json:"versionUpType" enums:"major,minor,patch" example:"minor" validate:"required"` CurrentVersion string `json:"currentVersion" example:"v1.0.0" validate:"required"` @@ -219,68 +111,43 @@ type CreatePolicyTemplateVersionRequest struct { Libs []string `json:"libs" example:"rego 코드"` } -type CreateOrganizationPolicyTemplateVersionRequest struct { - CreatePolicyTemplateVersionRequest -} - type CreatePolicyTemplateVersionResponse struct { Version string `json:"version" example:"v1.1.1"` } -type CreateOrganizationPolicyTemplateVersionResponse struct { - Version string `json:"version" example:"v1.1.1"` -} - type GetPolicyTemplateResponse struct { PolicyTemplate PolicyTemplateResponse `json:"policyTemplate"` } -type GetOrganizationPolicyTemplateResponse struct { - PolicyTemplate OrganizationPolicyTemplate `json:"policyTemplate"` -} - type ListPolicyTemplateResponse struct { PolicyTemplates []PolicyTemplateResponse `json:"policyTemplates"` Pagination PaginationResponse `json:"pagination"` } -type ListOrganizationPolicyTemplateResponse struct { - PolicyTemplates []OrganizationPolicyTemplate `json:"policyTemplates"` - Pagination PaginationResponse `json:"pagination"` -} - type PolicyTemplateStatistics struct { OrganizationId string `json:"organizationId"` OrganizationName string `json:"organizationName"` UsageCount int `json:"usageCount"` } -type OrganizationPolicyTemplateStatistics struct { - OrganizationId string `json:"organizationId"` - OrganizationName string `json:"organizationName"` - UsageCount int `json:"usageCount"` -} - type ListPolicyTemplateStatisticsResponse struct { PolicyTemplateStatistics []PolicyTemplateStatistics `json:"policyTemplateStatistics"` } -type ListOrganizationPolicyTemplateStatisticsResponse struct { - PolicyTemplateStatistics []OrganizationPolicyTemplateStatistics `json:"policyTemplateStatistics"` -} - type ExistsPolicyTemplateNameResponse struct { + Existed bool `json:"existed"` } type ExistsPolicyTemplateKindResponse struct { + Existed bool `json:"existed"` } type ParameterDef struct { - Key string `json:"key"` - Type string `json:"type"` + Key string `json:"key" exmaples:"repos"` + Type string `json:"type" examples:"string[]"` DefaultValue string `json:"defaultValue"` Children []*ParameterDef `json:"children"` - IsArray bool `json:"isArray"` + IsArray bool `json:"isArray" examples:"true"` } type RegoCompileRequest struct { diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index e2ccf0e0..ddb45490 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -53,7 +53,6 @@ type CreatePolicyRequest struct { PolicyName string `json:"policyName" example:"label 정책"` Description string `json:"description"` TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - TemplateName string `json:"templateName" example:"필수 Label 검사"` EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun"` Parameters string `json:"parameters" example:"\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\""` Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 9f0e39f0..06444f8d 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -115,17 +115,18 @@ var errorMap = map[ErrorCode]string{ "ST_FAILED_DELETE_EXIST_CLUSTERS": "스택템플릿을 사용하고 있는 스택이 있습니다. 스택을 삭제하세요.", // PolicyTemplate - "PT_CREATE_ALREADY_EXISTED_NAME": "정첵 템플릿에 이미 존재하는 이름입니다.", - "PT_CREATE_ALREADY_EXISTED_KIND": "정책 템플릿에 이미 존재하는 유형입니다.", - "PT_NOT_FOUND_POLICY_TEMPLATE": "정책 템플릿이 존재하지 않습니다.", - "PT_INVALID_KIND": "유효하지 않은 정책 템플릿 유형입니다. 정책 템플릿 유형을 확인하세요.", - "PT_FAILED_FETCH_POLICY_TEMPLATE": "정책 템플릿 ID에 해당하는 정책 템플릿을 가져오는데 실패했습니다.", - "PT_INVALID_REGO_SYNTAX": "Rego 문법 오류입니다.", - "PT_INVALID_POLICY_TEMPLATE_VERSION": "유효하지 않은 정책 템플릿 버전닙니다. 정책 템플릿 버전을 확인하세요.", - "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION": "정책 템플릿 버전이 존재하지 않습니다.", - "PT_INVALID_POLICY_TEMPLATE_NAME": "유효하지 않은 정책 템플릿 이름입니다. 정책 템플릿 이름을 확인하세요.", - "PT_INVALID_POLICY_TEMPLATE_KIND": "유효하지 않은 정책 템플릿 유형입니다. 정책 템플릿 유형을 확인하세요.", - "PT_INVALID_REGO_PARSEPARAMETER": "유효하지 않은 Rego 파싱 설정입니다. Rego 파싱 설정을 확인하세요.", + "PT_CREATE_ALREADY_EXISTED_NAME": "정첵 템플릿에 이미 존재하는 이름입니다.", + "PT_CREATE_ALREADY_EXISTED_KIND": "정책 템플릿에 이미 존재하는 유형입니다.", + "PT_NOT_FOUND_POLICY_TEMPLATE": "정책 템플릿이 존재하지 않습니다.", + "PT_INVALID_KIND": "유효하지 않은 정책 템플릿 유형입니다. 정책 템플릿 유형을 확인하세요.", + "PT_FAILED_FETCH_POLICY_TEMPLATE": "정책 템플릿 ID에 해당하는 정책 템플릿을 가져오는데 실패했습니다.", + "PT_INVALID_REGO_SYNTAX": "Rego 문법 오류입니다.", + "PT_INVALID_POLICY_TEMPLATE_VERSION": "유효하지 않은 정책 템플릿 버전닙니다. 정책 템플릿 버전을 확인하세요.", + "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION": "정책 템플릿 버전이 존재하지 않습니다.", + "PT_INVALID_POLICY_TEMPLATE_NAME": "유효하지 않은 정책 템플릿 이름입니다. 정책 템플릿 이름을 확인하세요.", + "PT_INVALID_POLICY_TEMPLATE_KIND": "유효하지 않은 정책 템플릿 유형입니다. 정책 템플릿 유형을 확인하세요.", + "PT_INVALID_REGO_PARSEPARAMETER": "유효하지 않은 Rego 파싱 설정입니다. Rego 파싱 설정을 확인하세요.", + "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE": "tks 템플릿에 대해 해당 동작을 수행할 수 없습니다.", // Policy "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", From f0afdc1b2cd5f601f93d4a63bed2efce13b0b5b1 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 28 Mar 2024 10:22:06 +0900 Subject: [PATCH 192/502] trivial. swagger parameter fixes --- api/swagger/docs.go | 64 +++++++++---------- api/swagger/swagger.json | 64 +++++++++---------- api/swagger/swagger.yaml | 64 +++++++++---------- internal/database/database.go | 5 +- internal/delivery/http/app-group.go | 4 +- internal/delivery/http/app-serve-app.go | 8 +-- internal/delivery/http/audit.go | 4 +- internal/delivery/http/cloud-account.go | 4 +- internal/delivery/http/cluster.go | 4 +- internal/delivery/http/organization.go | 4 +- internal/delivery/http/policy-template.go | 4 +- internal/delivery/http/policy.go | 4 +- internal/delivery/http/stack-template.go | 8 +-- .../delivery/http/system-notification-rule.go | 4 +- .../http/system-notification-template.go | 8 +-- internal/delivery/http/system-notification.go | 4 +- internal/delivery/http/user.go | 4 +- 17 files changed, 130 insertions(+), 131 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index c4ae64b6..61cffa4b 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -44,13 +44,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -416,13 +416,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -939,13 +939,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -1244,13 +1244,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -1450,13 +1450,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -1925,13 +1925,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -2296,13 +2296,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -2557,13 +2557,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -3569,13 +3569,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -4284,13 +4284,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -4951,13 +4951,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -6267,13 +6267,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -6886,13 +6886,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -7169,13 +7169,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -7322,13 +7322,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -7565,13 +7565,13 @@ const docTemplate = `{ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 4629849a..880944d0 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -38,13 +38,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -410,13 +410,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -933,13 +933,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -1238,13 +1238,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -1444,13 +1444,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -1919,13 +1919,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -2290,13 +2290,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -2551,13 +2551,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -3563,13 +3563,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -4278,13 +4278,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -4945,13 +4945,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -6261,13 +6261,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -6880,13 +6880,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -7163,13 +7163,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -7316,13 +7316,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { @@ -7559,13 +7559,13 @@ { "type": "string", "description": "pageSize", - "name": "limit", + "name": "pageSize", "in": "query" }, { "type": "string", "description": "pageNumber", - "name": "page", + "name": "pageNumber", "in": "query" }, { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index f23f3c40..6a4a557a 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -3544,11 +3544,11 @@ paths: parameters: - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -3783,11 +3783,11 @@ paths: parameters: - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -4113,11 +4113,11 @@ paths: parameters: - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -4303,11 +4303,11 @@ paths: parameters: - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -4454,11 +4454,11 @@ paths: type: string - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -4743,11 +4743,11 @@ paths: type: string - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -4974,11 +4974,11 @@ paths: parameters: - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -5118,11 +5118,11 @@ paths: type: string - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -5761,11 +5761,11 @@ paths: type: string - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -6133,11 +6133,11 @@ paths: type: boolean - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -6500,11 +6500,11 @@ paths: type: string - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -7506,11 +7506,11 @@ paths: parameters: - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -7900,11 +7900,11 @@ paths: type: string - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -8081,11 +8081,11 @@ paths: parameters: - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -8179,11 +8179,11 @@ paths: type: string - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query @@ -8335,11 +8335,11 @@ paths: type: string - description: pageSize in: query - name: limit + name: pageSize type: string - description: pageNumber in: query - name: page + name: pageNumber type: string - description: sortColumn in: query diff --git a/internal/database/database.go b/internal/database/database.go index 3f26ca8b..9fcb1a37 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -62,11 +62,11 @@ func InitDB() (*gorm.DB, error) { func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&model.CacheEmailCode{}, &model.ExpiredTokenTime{}, - &model.User{}, &model.Role{}, - &model.Organization{}, &model.CloudAccount{}, &model.StackTemplate{}, + &model.Organization{}, + &model.User{}, &model.Cluster{}, &model.ClusterFavorite{}, &model.AppGroup{}, @@ -93,7 +93,6 @@ func migrateSchema(db *gorm.DB) error { ); err != nil { return err } - return nil } diff --git a/internal/delivery/http/app-group.go b/internal/delivery/http/app-group.go index 0a497091..02361c39 100644 --- a/internal/delivery/http/app-group.go +++ b/internal/delivery/http/app-group.go @@ -69,8 +69,8 @@ func (h *AppGroupHandler) CreateAppGroup(w http.ResponseWriter, r *http.Request) // @Accept json // @Produce json // @Param clusterId query string false "clusterId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 2430d0e9..04fd8e95 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -227,8 +227,8 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Param showAll query boolean false "Show all apps including deleted apps" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" @@ -443,8 +443,8 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. // @Produce json // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param sortColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index e95ae959..520521c1 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -47,8 +47,8 @@ func (h *AuditHandler) CreateAudit(w http.ResponseWriter, r *http.Request) { // @Description Get Audits // @Accept json // @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filter query []string false "filters" diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 53295041..25e144c3 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -80,8 +80,8 @@ func (h *CloudAccountHandler) CreateCloudAccount(w http.ResponseWriter, r *http. // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index b67042e4..7f9d878e 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -32,8 +32,8 @@ func NewClusterHandler(h usecase.Usecase) *ClusterHandler { // @Accept json // @Produce json // @Param organizationId query string false "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 6fc3e896..f1a1bba1 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -143,8 +143,8 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r // @Description Get organization list // @Accept json // @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index bc66d83b..145a9533 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -251,8 +251,8 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplate(w http.ResponseWriter, r // @Description 정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다. // @Accept json // @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 972648c8..87648524 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -282,8 +282,8 @@ func (h *PolicyHandler) GetPolicy(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param organizationId path string true "조직 식별자(o로 시작)" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index fdbcd4b9..23815272 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -71,8 +71,8 @@ func (h *StackTemplateHandler) CreateStackTemplate(w http.ResponseWriter, r *htt // @Description Get StackTemplates // @Accept json // @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" @@ -320,8 +320,8 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW // @Description Get Organization StackTemplates // @Accept json // @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index ee245d95..8e6706b2 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -87,8 +87,8 @@ func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.Resp // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index 7ce845ad..1a92122c 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -74,8 +74,8 @@ func (h *SystemNotificationTemplateHandler) CreateSystemNotificationTemplate(w h // @Description Get SystemNotificationTemplates // @Accept json // @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" @@ -261,8 +261,8 @@ func (h *SystemNotificationTemplateHandler) DeleteSystemNotificationTemplate(w h // @Description Get Organization SystemNotificationTemplates // @Accept json // @Produce json -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/system-notification.go b/internal/delivery/http/system-notification.go index 49322289..48deeea8 100644 --- a/internal/delivery/http/system-notification.go +++ b/internal/delivery/http/system-notification.go @@ -81,8 +81,8 @@ func (h *SystemNotificationHandler) CreateSystemNotification(w http.ResponseWrit // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index f9764f05..4a0b7e36 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -187,8 +187,8 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" From 6075ed7f1b2fd074b61c8d75cb6ca281543a5834 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 28 Mar 2024 11:00:31 +0900 Subject: [PATCH 193/502] feature. add API for checking name resource on system-notifications --- api/swagger/docs.go | 45 +++++++++++++++++++ api/swagger/swagger.json | 45 +++++++++++++++++++ api/swagger/swagger.yaml | 28 ++++++++++++ internal/delivery/api/endpoint.go | 2 + .../delivery/api/generated_endpoints.go.go | 16 +++++++ .../http/system-notification-template.go | 36 +++++++++++++++ internal/route/route.go | 2 + pkg/domain/system-notification-template.go | 4 ++ 8 files changed, 178 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 61cffa4b..e9424fce 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1312,6 +1312,43 @@ const docTemplate = `{ } } }, + "/admin/system-notification-templates/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for systemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Check name for systemNotificationTemplate", + "parameters": [ + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificaionTemplateNameResponse" + } + } + } + } + }, "/admin/system-notification-templates/{systemNotificationTemplateId}": { "get": { "security": [ @@ -8707,6 +8744,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificaionTemplateNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 880944d0..59752e0b 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1306,6 +1306,43 @@ } } }, + "/admin/system-notification-templates/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for systemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Check name for systemNotificationTemplate", + "parameters": [ + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificaionTemplateNameResponse" + } + } + } + } + }, "/admin/system-notification-templates/{systemNotificationTemplateId}": { "get": { "security": [ @@ -8701,6 +8738,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificaionTemplateNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 6a4a557a..12574cdc 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -456,6 +456,11 @@ definitions: existed: type: boolean type: object + github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificaionTemplateNameResponse: + properties: + existed: + type: boolean + type: object github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse: properties: existed: @@ -4421,6 +4426,29 @@ paths: summary: Update SystemNotificationTemplate tags: - SystemNotificationTemplates + /admin/system-notification-templates/name/{name}/existence: + get: + consumes: + - application/json + description: Check name for systemNotificationTemplate + parameters: + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificaionTemplateNameResponse' + security: + - JWT: [] + summary: Check name for systemNotificationTemplate + tags: + - SystemNotificationTemplates /app-groups: delete: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index b69a561d..967ff83c 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -123,6 +123,7 @@ const ( Admin_DeleteSystemNotificationTemplate Admin_GetSystemNotificationTemplates Admin_GetSystemNotificationTemplate + Admin_CheckSystemNotificationTemplateName GetOrganizationSystemNotificationTemplates AddOrganizationSystemNotificationTemplates RemoveOrganizationSystemNotificationTemplates @@ -131,6 +132,7 @@ const ( CreateSystemNotificationRule GetSystemNotificationRules GetSystemNotificationRule + CheckSystemNotificationRuleName DeleteSystemNotificationRule UpdateSystemNotificationRule diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 1af52d51..7a77dd9e 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -371,6 +371,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_GetSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, + Admin_CheckSystemNotificationTemplateName: { + Name: "Admin_CheckSystemNotificationTemplateName", + Group: "SystemNotificationTemplate", + }, GetOrganizationSystemNotificationTemplates: { Name: "GetOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", @@ -395,6 +399,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetSystemNotificationRule", Group: "SystemNotificationRule", }, + CheckSystemNotificationRuleName: { + Name: "CheckSystemNotificationRuleName", + Group: "SystemNotificationRule", + }, DeleteSystemNotificationRule: { Name: "DeleteSystemNotificationRule", Group: "SystemNotificationRule", @@ -998,6 +1006,8 @@ func (e Endpoint) String() string { return "Admin_GetSystemNotificationTemplates" case Admin_GetSystemNotificationTemplate: return "Admin_GetSystemNotificationTemplate" + case Admin_CheckSystemNotificationTemplateName: + return "Admin_CheckSystemNotificationTemplateName" case GetOrganizationSystemNotificationTemplates: return "GetOrganizationSystemNotificationTemplates" case AddOrganizationSystemNotificationTemplates: @@ -1010,6 +1020,8 @@ func (e Endpoint) String() string { return "GetSystemNotificationRules" case GetSystemNotificationRule: return "GetSystemNotificationRule" + case CheckSystemNotificationRuleName: + return "CheckSystemNotificationRuleName" case DeleteSystemNotificationRule: return "DeleteSystemNotificationRule" case UpdateSystemNotificationRule: @@ -1408,6 +1420,8 @@ func GetEndpoint(name string) Endpoint { return Admin_GetSystemNotificationTemplates case "Admin_GetSystemNotificationTemplate": return Admin_GetSystemNotificationTemplate + case "Admin_CheckSystemNotificationTemplateName": + return Admin_CheckSystemNotificationTemplateName case "GetOrganizationSystemNotificationTemplates": return GetOrganizationSystemNotificationTemplates case "AddOrganizationSystemNotificationTemplates": @@ -1420,6 +1434,8 @@ func GetEndpoint(name string) Endpoint { return GetSystemNotificationRules case "GetSystemNotificationRule": return GetSystemNotificationRule + case "CheckSystemNotificationRuleName": + return CheckSystemNotificationRuleName case "DeleteSystemNotificationRule": return DeleteSystemNotificationRule case "UpdateSystemNotificationRule": diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index 1a92122c..0bc64a60 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -376,3 +376,39 @@ func (h *SystemNotificationTemplateHandler) RemoveOrganizationSystemNotification } ResponseJSON(w, r, http.StatusOK, nil) } + +// CheckSystemNotificationTemplateName godoc +// +// @Tags SystemNotificationTemplates +// @Summary Check name for systemNotificationTemplate +// @Description Check name for systemNotificationTemplate +// @Accept json +// @Produce json +// @Param name path string true "name" +// @Success 200 {object} domain.CheckSystemNotificaionTemplateNameResponse +// @Router /admin/system-notification-templates/name/{name}/existence [GET] +// @Security JWT +func (h *SystemNotificationTemplateHandler) CheckSystemNotificationTemplateName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name, ok := vars["name"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid name"), "ST_INVALID_SYSTEM_NOTIFICATION_TEMAPLTE_NAME", "")) + return + } + + exist := true + _, err := h.usecase.GetByName(r.Context(), name) + if err != nil { + if _, code := httpErrors.ErrorResponse(err); code == http.StatusNotFound { + exist = false + } else { + ErrorJSON(w, r, err) + return + } + } + + var out domain.CheckSystemNotificaionTemplateNameResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/route/route.go b/internal/route/route.go index a209a15f..e4b7913a 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -225,6 +225,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_GetSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.GetSystemNotificationTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.UpdateSystemNotificationTemplate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.DeleteSystemNotificationTemplate))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/name/{name}/existence", customMiddleware.Handle(internalApi.Admin_CheckSystemNotificationTemplateName, http.HandlerFunc(systemNotificationTemplateHandler.CheckSystemNotificationTemplateName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.GetOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetOrganizationSystemNotificationTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.AddOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.AddOrganizationSystemNotificationTemplates))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.RemoveOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.RemoveOrganizationSystemNotificationTemplates))).Methods(http.MethodPut) @@ -232,6 +233,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa systemNotificationRuleHandler := delivery.NewSystemNotificationRuleHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/name/{name}/existence", customMiddleware.Handle(internalApi.CheckSystemNotificationRuleName, http.HandlerFunc(systemNotificationRuleHandler.CheckSystemNotificationRuleName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.DeleteSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.DeleteSystemNotificationRule))).Methods(http.MethodDelete) diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index 7889a615..00d9b0c0 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -67,3 +67,7 @@ type AddOrganizationSystemNotificationTemplatesRequest struct { type RemoveOrganizationSystemNotificationTemplatesRequest struct { SystemNotificationTemplateIds []string `json:"systemNotificationTemplateIds" validate:"required"` } + +type CheckSystemNotificaionTemplateNameResponse struct { + Existed bool `json:"existed"` +} From e4b4541b4c9dae0cb8c9cf44ff3ec495659b152b Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 28 Mar 2024 11:06:38 +0900 Subject: [PATCH 194/502] minor fix. Reform response data of Permission APIs --- internal/delivery/http/permission.go | 14 +++--- internal/delivery/http/role.go | 19 ++++---- internal/delivery/http/user.go | 18 ++++--- pkg/domain/permission.go | 72 +++++++++++++++------------- 4 files changed, 64 insertions(+), 59 deletions(-) diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index f298a394..2dcaf3ce 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -39,14 +39,14 @@ func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http permissionSet := model.NewDefaultPermissionSet() var out domain.GetPermissionTemplatesResponse - out.Permissions = new(domain.PermissionTemplateResponse) + out.Permissions = make([]*domain.TemplateResponse, 0) - out.Permissions.Dashboard = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Dashboard) - out.Permissions.Stack = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Stack) - out.Permissions.Policy = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Policy) - out.Permissions.ProjectManagement = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.ProjectManagement) - out.Permissions.Notification = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Notification) - out.Permissions.Configuration = convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Configuration) + out.Permissions = append(out.Permissions, convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Dashboard)) + out.Permissions = append(out.Permissions, convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Stack)) + out.Permissions = append(out.Permissions, convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Policy)) + out.Permissions = append(out.Permissions, convertModelToPermissionTemplateResponse(r.Context(), permissionSet.ProjectManagement)) + out.Permissions = append(out.Permissions, convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Notification)) + out.Permissions = append(out.Permissions, convertModelToPermissionTemplateResponse(r.Context(), permissionSet.Configuration)) ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 21658fd9..f3a69004 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -306,16 +306,15 @@ func (h RoleHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Reque return } - var permissionSetResponse domain.PermissionSetResponse - permissionSetResponse.Dashboard = convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard) - permissionSetResponse.Stack = convertModelToPermissionResponse(r.Context(), permissionSet.Stack) - permissionSetResponse.Policy = convertModelToPermissionResponse(r.Context(), permissionSet.Policy) - permissionSetResponse.ProjectManagement = convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement) - permissionSetResponse.Notification = convertModelToPermissionResponse(r.Context(), permissionSet.Notification) - permissionSetResponse.Configuration = convertModelToPermissionResponse(r.Context(), permissionSet.Configuration) - var out domain.GetPermissionsByRoleIdResponse - out.Permissions = &permissionSetResponse + out.Permissions = make([]*domain.PermissionResponse, 0) + + out.Permissions = append(out.Permissions, convertModelToPermissionResponse(r.Context(), permissionSet.Dashboard)) + out.Permissions = append(out.Permissions, convertModelToPermissionResponse(r.Context(), permissionSet.Stack)) + out.Permissions = append(out.Permissions, convertModelToPermissionResponse(r.Context(), permissionSet.Policy)) + out.Permissions = append(out.Permissions, convertModelToPermissionResponse(r.Context(), permissionSet.ProjectManagement)) + out.Permissions = append(out.Permissions, convertModelToPermissionResponse(r.Context(), permissionSet.Notification)) + out.Permissions = append(out.Permissions, convertModelToPermissionResponse(r.Context(), permissionSet.Configuration)) ResponseJSON(w, r, http.StatusOK, out) } @@ -323,11 +322,11 @@ func (h RoleHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Reque func convertModelToPermissionResponse(ctx context.Context, permission *model.Permission) *domain.PermissionResponse { var permissionResponse domain.PermissionResponse - permissionResponse.ID = permission.ID permissionResponse.Key = permission.Key permissionResponse.Name = permission.Name if permission.IsAllowed != nil { permissionResponse.IsAllowed = permission.IsAllowed + permissionResponse.ID = &permission.ID } for _, endpoint := range permission.Endpoints { diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 4a0b7e36..9a7748a9 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -720,18 +720,16 @@ func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Re mergedPermissionSet := u.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) - var permissions domain.MergedPermissionSetResponse - permissions.Dashboard = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard) - permissions.Stack = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack) - permissions.Policy = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy) - permissions.ProjectManagement = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement) - permissions.Notification = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification) - permissions.Configuration = convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration) - var out domain.GetUsersPermissionsResponse - out.Permissions = &permissions - ResponseJSON(w, r, http.StatusOK, out) + out.Permissions = make([]*domain.MergePermissionResponse, 0) + out.Permissions = append(out.Permissions, convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Dashboard)) + out.Permissions = append(out.Permissions, convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Stack)) + out.Permissions = append(out.Permissions, convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Policy)) + out.Permissions = append(out.Permissions, convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.ProjectManagement)) + out.Permissions = append(out.Permissions, convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Notification)) + out.Permissions = append(out.Permissions, convertModelToMergedPermissionSetResponse(r.Context(), mergedPermissionSet.Configuration)) + ResponseJSON(w, r, http.StatusOK, out) } func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index d9e83240..3ae4805c 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -5,66 +5,74 @@ import ( ) type GetPermissionTemplatesResponse struct { - Permissions *PermissionTemplateResponse `json:"permissions"` + //Permissions *PermissionTemplateResponse `json:"permissions"` + Permissions []*TemplateResponse `json:"permissions"` } -type PermissionTemplateResponse struct { - Dashboard *TemplateResponse `json:"dashboard,omitempty"` - Stack *TemplateResponse `json:"stack,omitempty"` - Policy *TemplateResponse `json:"policy,omitempty"` - ProjectManagement *TemplateResponse `json:"project_management,omitempty"` - Notification *TemplateResponse `json:"notification,omitempty"` - Configuration *TemplateResponse `json:"configuration,omitempty"` -} +//type PermissionTemplateResponse struct { +// Dashboard *TemplateResponse `json:"dashboard,omitempty"` +// Stack *TemplateResponse `json:"stack,omitempty"` +// Policy *TemplateResponse `json:"policy,omitempty"` +// ProjectManagement *TemplateResponse `json:"project_management,omitempty"` +// Notification *TemplateResponse `json:"notification,omitempty"` +// Configuration *TemplateResponse `json:"configuration,omitempty"` +//} type TemplateResponse struct { Name string `json:"name"` Key string `json:"key"` - IsAllowed *bool `json:"is_allowed,omitempty"` + IsAllowed *bool `json:"isAllowed,omitempty"` Children []*TemplateResponse `json:"children,omitempty"` } type GetPermissionsByRoleIdResponse struct { - Permissions *PermissionSetResponse `json:"permissions"` + //Permissions *PermissionSetResponse `json:"permissions"` + Permissions []*PermissionResponse `json:"permissions"` } -type PermissionSetResponse struct { - Dashboard *PermissionResponse `json:"dashboard,omitempty"` - Stack *PermissionResponse `json:"stack,omitempty"` - Policy *PermissionResponse `json:"policy,omitempty"` - ProjectManagement *PermissionResponse `json:"project_management,omitempty"` - Notification *PermissionResponse `json:"notification,omitempty"` - Configuration *PermissionResponse `json:"configuration,omitempty"` -} +//type PermissionSetResponse struct { +// Dashboard *PermissionResponse `json:"dashboard,omitempty"` +// Stack *PermissionResponse `json:"stack,omitempty"` +// Policy *PermissionResponse `json:"policy,omitempty"` +// ProjectManagement *PermissionResponse `json:"project_management,omitempty"` +// Notification *PermissionResponse `json:"notification,omitempty"` +// Configuration *PermissionResponse `json:"configuration,omitempty"` +//} type PermissionResponse struct { - ID uuid.UUID `json:"ID"` + ID *uuid.UUID `json:"ID,omitempty"` Name string `json:"name"` Key string `json:"key"` - IsAllowed *bool `json:"is_allowed,omitempty"` + IsAllowed *bool `json:"isAllowed,omitempty"` Endpoints []*EndpointResponse `json:"endpoints,omitempty"` Children []*PermissionResponse `json:"children,omitempty"` } +type UpdatePermissionUpdateRequest struct { + ID uuid.UUID `json:"ID" validate:"required"` + IsAllowed *bool `json:"isAllowed" validate:"required,oneof=true false"` +} + type UpdatePermissionsByRoleIdRequest struct { - Permissions []*PermissionResponse `json:"permissions"` + Permissions []*UpdatePermissionUpdateRequest `json:"permissions"` } type GetUsersPermissionsResponse struct { - Permissions *MergedPermissionSetResponse `json:"permissions"` + //Permissions *MergedPermissionSetResponse `json:"permissions"` + Permissions []*MergePermissionResponse `json:"permissions"` } -type MergedPermissionSetResponse struct { - Dashboard *MergePermissionResponse `json:"dashboard,omitempty"` - Stack *MergePermissionResponse `json:"stack,omitempty"` - Policy *MergePermissionResponse `json:"policy,omitempty"` - ProjectManagement *MergePermissionResponse `json:"project_management,omitempty"` - Notification *MergePermissionResponse `json:"notification,omitempty"` - Configuration *MergePermissionResponse `json:"configuration,omitempty"` -} +//type MergedPermissionSetResponse struct { +// Dashboard *MergePermissionResponse `json:"dashboard,omitempty"` +// Stack *MergePermissionResponse `json:"stack,omitempty"` +// Policy *MergePermissionResponse `json:"policy,omitempty"` +// ProjectManagement *MergePermissionResponse `json:"project_management,omitempty"` +// Notification *MergePermissionResponse `json:"notification,omitempty"` +// Configuration *MergePermissionResponse `json:"configuration,omitempty"` +//} type MergePermissionResponse struct { Key string `json:"key"` - IsAllowed *bool `json:"is_allowed,omitempty"` + IsAllowed *bool `json:"isAllowed,omitempty"` Children []*MergePermissionResponse `json:"children,omitempty"` } From b5c61d7bfb2ae751b24be30cebfd3e4b80781f13 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 28 Mar 2024 11:26:04 +0900 Subject: [PATCH 195/502] minor fix. fix swag error --- api/swagger/docs.go | 125 ++++++++++++++++----------- api/swagger/swagger.json | 125 ++++++++++++++++----------- api/swagger/swagger.yaml | 87 +++++++++++-------- internal/delivery/http/permission.go | 2 +- internal/delivery/http/role.go | 2 +- 5 files changed, 199 insertions(+), 142 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 61cffa4b..c81d7dac 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -6191,7 +6191,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse" } } } @@ -7974,7 +7974,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse" } } } @@ -10329,6 +10329,30 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse": { + "type": "object", + "properties": { + "permissions": { + "description": "Permissions *PermissionTemplateResponse ` + "`" + `json:\"permissions\"` + "`" + `", + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse": { + "type": "object", + "properties": { + "permissions": { + "description": "Permissions *PermissionSetResponse ` + "`" + `json:\"permissions\"` + "`" + `", + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse": { "type": "object", "properties": { @@ -10703,7 +10727,11 @@ const docTemplate = `{ "type": "object", "properties": { "permissions": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse" + "description": "Permissions *MergedPermissionSetResponse ` + "`" + `json:\"permissions\"` + "`" + `", + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } } } }, @@ -11007,7 +11035,7 @@ const docTemplate = `{ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" } }, - "is_allowed": { + "isAllowed": { "type": "boolean" }, "key": { @@ -11015,29 +11043,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse": { - "type": "object", - "properties": { - "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { @@ -11161,7 +11166,7 @@ const docTemplate = `{ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse" } }, - "is_allowed": { + "isAllowed": { "type": "boolean" }, "key": { @@ -11172,29 +11177,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse": { - "type": "object", - "properties": { - "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization": { "type": "object", "properties": { @@ -12472,6 +12454,26 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.TemplateResponse": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateResponse" + } + }, + "isAllowed": { + "type": "boolean" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.Unit": { "type": "object", "properties": { @@ -12691,13 +12693,32 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest": { + "type": "object", + "required": [ + "ID", + "isAllowed" + ], + "properties": { + "ID": { + "type": "string" + }, + "isAllowed": { + "type": "boolean", + "enum": [ + true, + false + ] + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { "type": "object", "properties": { "permissions": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest" } } } diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 880944d0..e67b2342 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -6185,7 +6185,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse" } } } @@ -7968,7 +7968,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse" } } } @@ -10323,6 +10323,30 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse": { + "type": "object", + "properties": { + "permissions": { + "description": "Permissions *PermissionTemplateResponse `json:\"permissions\"`", + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateResponse" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse": { + "type": "object", + "properties": { + "permissions": { + "description": "Permissions *PermissionSetResponse `json:\"permissions\"`", + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse": { "type": "object", "properties": { @@ -10697,7 +10721,11 @@ "type": "object", "properties": { "permissions": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse" + "description": "Permissions *MergedPermissionSetResponse `json:\"permissions\"`", + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" + } } } }, @@ -11001,7 +11029,7 @@ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" } }, - "is_allowed": { + "isAllowed": { "type": "boolean" }, "key": { @@ -11009,29 +11037,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse": { - "type": "object", - "properties": { - "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - }, - "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse": { "type": "object", "properties": { @@ -11155,7 +11160,7 @@ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse" } }, - "is_allowed": { + "isAllowed": { "type": "boolean" }, "key": { @@ -11166,29 +11171,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse": { - "type": "object", - "properties": { - "configuration": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "dashboard": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "notification": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "policy": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "project_management": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - }, - "stack": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization": { "type": "object", "properties": { @@ -12466,6 +12448,26 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.TemplateResponse": { + "type": "object", + "properties": { + "children": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateResponse" + } + }, + "isAllowed": { + "type": "boolean" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.Unit": { "type": "object", "properties": { @@ -12685,13 +12687,32 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest": { + "type": "object", + "required": [ + "ID", + "isAllowed" + ], + "properties": { + "ID": { + "type": "string" + }, + "isAllowed": { + "type": "boolean", + "enum": [ + true, + false + ] + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { "type": "object", "properties": { "permissions": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest" } } } diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 6a4a557a..f430024b 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1544,6 +1544,22 @@ definitions: organization: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse: + properties: + permissions: + description: Permissions *PermissionTemplateResponse `json:"permissions"` + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateResponse' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse: + properties: + permissions: + description: Permissions *PermissionSetResponse `json:"permissions"` + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse: properties: policy: @@ -1783,7 +1799,10 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse: properties: permissions: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse' + description: Permissions *MergedPermissionSetResponse `json:"permissions"` + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' + type: array type: object github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest: properties: @@ -1984,26 +2003,11 @@ definitions: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' type: array - is_allowed: + isAllowed: type: boolean key: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.MergedPermissionSetResponse: - properties: - configuration: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' - dashboard: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' - notification: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' - policy: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' - project_management: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' - stack: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse' - type: object github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse: properties: admin: @@ -2085,28 +2089,13 @@ definitions: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.EndpointResponse' type: array - is_allowed: + isAllowed: type: boolean key: type: string name: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse: - properties: - configuration: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - dashboard: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - notification: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - policy: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - project_management: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - stack: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' - type: object github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization: properties: organizationId: @@ -2959,6 +2948,19 @@ definitions: required: - metricQuery type: object + github_com_openinfradev_tks-api_pkg_domain.TemplateResponse: + properties: + children: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateResponse' + type: array + isAllowed: + type: boolean + key: + type: string + name: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.Unit: properties: data: @@ -3105,11 +3107,24 @@ definitions: - newPassword - originPassword type: object + github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest: + properties: + ID: + type: string + isAllowed: + enum: + - true + - false + type: boolean + required: + - ID + - isAllowed + type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest: properties: permissions: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest' type: array type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest: @@ -7461,7 +7476,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse' security: - JWT: [] summary: Get Permissions By Role ID @@ -8621,7 +8636,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionSetResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse' security: - JWT: [] summary: Get Permission Templates diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 2dcaf3ce..3ad7798f 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -32,7 +32,7 @@ func NewPermissionHandler(usecase usecase.Usecase) IPermissionHandler { // @Description Get Permission Templates // @Accept json // @Produce json -// @Success 200 {object} domain.PermissionSetResponse +// @Success 200 {object} domain.GetPermissionTemplatesResponse // @Router /permissions/templates [get] // @Security JWT func (h PermissionHandler) GetPermissionTemplates(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index f3a69004..b96f4792 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -285,7 +285,7 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "Organization ID" // @Param roleId path string true "Role ID" -// @Success 200 {object} domain.PermissionSetResponse +// @Success 200 {object} domain.GetPermissionsByRoleIdResponse // @Router /organizations/{organizationId}/roles/{roleId}/permissions [get] // @Security JWT func (h RoleHandler) GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) { From f32df573a2c5a383edf614c7092fa53f7a7c0c2e Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 28 Mar 2024 16:21:04 +0900 Subject: [PATCH 196/502] trivial. add metric parameters to systemNotificationTemplates --- api/swagger/docs.go | 4232 ++++++++++------- api/swagger/swagger.json | 4232 ++++++++++------- api/swagger/swagger.yaml | 718 ++- .../http/system-notification-template.go | 8 + 4 files changed, 5870 insertions(+), 3320 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index d2461874..35264f49 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -411,7 +411,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", + "summary": "[Admin_ListPolicyTemplate] 정책 템플릿 목록 조회", "parameters": [ { "type": "string", @@ -428,7 +428,7 @@ const docTemplate = `{ { "type": "string", "description": "sortColumn", - "name": "soertColumn", + "name": "sortColumn", "in": "query" }, { @@ -452,7 +452,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse" } } } @@ -473,7 +473,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", + "summary": "[Admin_CreatePolicyTemplate] 정책 템플릿 신규 생성", "parameters": [ { "description": "create policy template request", @@ -481,7 +481,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateRequest" } } ], @@ -489,7 +489,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse" } } } @@ -512,7 +512,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", + "summary": "[Admin_ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", "parameters": [ { "type": "string", @@ -526,7 +526,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse" } } } @@ -549,7 +549,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "summary": "[Admin_ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", "parameters": [ { "type": "string", @@ -563,7 +563,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateNameResponse" } } } @@ -586,7 +586,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", + "summary": "[Admin_GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", "parameters": [ { "type": "string", @@ -600,7 +600,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateResponse" } } } @@ -621,7 +621,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", + "summary": "[Admin_DeletePolicyTemplate] 정책 템플릿 삭제", "parameters": [ { "type": "string", @@ -653,7 +653,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", + "summary": "[Admin_UpdatePolicyTemplate] 정책 템플릿 업데이트", "parameters": [ { "type": "string", @@ -668,7 +668,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest" } } ], @@ -696,7 +696,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", + "summary": "[Admin_GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", "parameters": [ { "type": "string", @@ -710,7 +710,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse" } } } @@ -733,7 +733,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", + "summary": "[Admin_ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", "parameters": [ { "type": "string", @@ -747,7 +747,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateStatisticsResponse" } } } @@ -770,7 +770,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", + "summary": "[Admin_ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", "parameters": [ { "type": "string", @@ -784,7 +784,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateVersionsResponse" } } } @@ -805,7 +805,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", + "summary": "[Admin_CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", "parameters": [ { "type": "string", @@ -820,7 +820,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest" } } ], @@ -828,7 +828,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionResponse" } } } @@ -851,7 +851,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", + "summary": "[Admin_GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", "parameters": [ { "type": "string", @@ -872,7 +872,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateVersionResponse" } } } @@ -893,7 +893,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", + "summary": "[Admin_DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", "parameters": [ { "type": "string", @@ -3618,7 +3618,7 @@ const docTemplate = `{ { "type": "string", "description": "sortColumn", - "name": "soertColumn", + "name": "sortColumn", "in": "query" }, { @@ -3917,14 +3917,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/primary-cluster": { - "patch": { + "/organizations/{organizationId}/policy-templates": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update primary cluster", + "description": "정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다.", "consumes": [ "application/json" ], @@ -3932,72 +3932,57 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Organizations" + "PolicyTemplate" ], - "summary": "Update primary cluster", + "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "description": "pageSize", + "name": "limit", + "in": "query" }, { - "description": "update primary cluster request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/projects": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get projects", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Projects" - ], - "summary": "Get projects", - "parameters": [ + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, { "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true + "description": "sortColumn", + "name": "sortColumn", + "in": "query" }, { "type": "string", - "description": "(all | only)", - "name": "query", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", "in": "query" + }, + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" } } } @@ -4008,7 +3993,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Create new project", + "description": "정책 템플릿을 신규 생성(v1.0.0을 생성)한다.", "consumes": [ "application/json" ], @@ -4016,24 +4001,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Create new project", + "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { - "description": "Request body to create project", - "name": "request", + "description": "create policy template request", + "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" } } ], @@ -4041,20 +4026,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" } } } } }, - "/organizations/{organizationId}/projects/existence": { + "/organizations/{organizationId}/policy-templates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Check project name exist", + "description": "해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다.", "consumes": [ "application/json" ], @@ -4062,28 +4047,22 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Check project name exist", + "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "type (name)", - "name": "type", - "in": "query" - }, - { - "type": "string", - "description": "value (project name)", - "name": "value", - "in": "query", + "description": "정책 템플릿 이름", + "name": "policyTemplateKind", + "in": "path", "required": true } ], @@ -4091,20 +4070,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" } } } } }, - "/organizations/{organizationId}/projects/project-roles": { + "/organizations/{organizationId}/policy-templates/name/{policyTemplateName}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project roles by giving params", + "description": "해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다.", "consumes": [ "application/json" ], @@ -4112,42 +4091,43 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Get project roles", + "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "project role search by query (query=all), (query=leader), (query=member), (query=viewer)", - "name": "query", - "in": "query" + "description": "정책 템플릿 이름", + "name": "policyTemplateName", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateNameResponse" } } } } }, - "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "/organizations/{organizationId}/policy-templates/{policyTemplateId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project role by id", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", "consumes": [ "application/json" ], @@ -4155,21 +4135,21 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Get project role", + "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project Role ID", - "name": "projectRoleId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true } @@ -4178,20 +4158,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get projects", + "description": "정책 템플릿을 삭제한다.", "consumes": [ "application/json" ], @@ -4199,41 +4177,38 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Get projects", + "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse" - } + "description": "OK" } } }, - "put": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Update project", + "description": "정책 템플릿의 업데이트 가능한 필드들을 업데이트한다.", "consumes": [ "application/json" ], @@ -4241,52 +4216,49 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Update project", + "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true }, { - "description": "Request body to update project", - "name": "request", + "description": "update policy template request", + "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" - } + "description": "OK" } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/deploy": { "get": { "security": [ { "JWT": [] } ], - "description": "Get appServeApp list by giving params", + "description": "해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다.", "consumes": [ "application/json" ], @@ -4294,84 +4266,43 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Get appServeApp list", + "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true - }, - { - "type": "boolean", - "description": "Show all apps including deleted apps", - "name": "showAll", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/statistics": { + "get": { "security": [ { "JWT": [] } ], - "description": "Install appServeApp", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다.", "consumes": [ "application/json" ], @@ -4379,52 +4310,43 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Install appServeApp", + "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true - }, - { - "description": "Request body to create app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions": { "get": { "security": [ { "JWT": [] } ], - "description": "Get number of apps on given stack", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", "consumes": [ "application/json" ], @@ -4432,50 +4354,41 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Get number of apps on given stack", + "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true - }, - { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "query", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "type": "integer" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Check duplicate appServeAppName by giving params", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다.", "consumes": [ "application/json" ], @@ -4483,50 +4396,52 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Check duplicate appServeAppName", + "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true }, { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true + "description": "create policy template version request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "boolean" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get appServeApp by giving params", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다.", "consumes": [ "application/json" ], @@ -4534,28 +4449,28 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Get appServeApp", + "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true }, { "type": "string", - "description": "App ID", - "name": "appId", + "description": "조회할 버전(v0.0.0 형식)", + "name": "version", "in": "path", "required": true } @@ -4564,18 +4479,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" } } } }, - "put": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Update appServeApp", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다.", "consumes": [ "application/json" ], @@ -4583,57 +4498,47 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Update appServeApp", + "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true }, { "type": "string", - "description": "App ID", - "name": "appId", + "description": "삭제할 버전(v0.0.0 형식)", + "name": "version", "in": "path", "required": true - }, - { - "description": "Request body to update app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest" - } } ], "responses": { "200": { - "description": "OK", - "schema": { - "type": "string" - } + "description": "OK" } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/primary-cluster": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Uninstall appServeApp", + "description": "Update primary cluster", "consumes": [ "application/json" ], @@ -4641,50 +4546,42 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "Organizations" ], - "summary": "Uninstall appServeApp", + "summary": "Update primary cluster", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true }, { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true + "description": "update primary cluster request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest" + } } ], "responses": { "200": { - "description": "OK", - "schema": { - "type": "string" - } + "description": "OK" } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { - "patch": { + "/organizations/{organizationId}/projects": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update app endpoint", + "description": "Get projects", "consumes": [ "application/json" ], @@ -4692,9 +4589,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Update app endpoint", + "summary": "Get projects", "parameters": [ { "type": "string", @@ -4705,46 +4602,27 @@ const docTemplate = `{ }, { "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "appId", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app endpoint", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest" - } + "description": "(all | only)", + "name": "query", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get appServeApp by giving params", + "description": "Create new project", "consumes": [ "application/json" ], @@ -4752,9 +4630,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Get appServeApp", + "summary": "Create new project", "parameters": [ { "type": "string", @@ -4764,31 +4642,33 @@ const docTemplate = `{ "required": true }, { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true + "description": "Request body to create project", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "boolean" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "/organizations/{organizationId}/projects/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get latest task from appServeApp", + "description": "Check project name exist", "consumes": [ "application/json" ], @@ -4796,9 +4676,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Get latest task from appServeApp", + "summary": "Check project name exist", "parameters": [ { "type": "string", @@ -4809,16 +4689,15 @@ const docTemplate = `{ }, { "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true + "description": "type (name)", + "name": "type", + "in": "query" }, { "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", + "description": "value (project name)", + "name": "value", + "in": "query", "required": true } ], @@ -4826,20 +4705,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { - "post": { + "/organizations/{organizationId}/projects/project-roles": { + "get": { "security": [ { "JWT": [] } ], - "description": "Rollback appServeApp", + "description": "Get project roles by giving params", "consumes": [ "application/json" ], @@ -4847,9 +4726,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Rollback appServeApp", + "summary": "Get project roles", "parameters": [ { "type": "string", @@ -4860,46 +4739,73 @@ const docTemplate = `{ }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "project role search by query (query=all), (query=leader), (query=member), (query=viewer)", + "name": "query", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project role by id", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "App ID", - "name": "appId", + "description": "Project Role ID", + "name": "projectRoleId", "in": "path", "required": true - }, - { - "description": "Request body to rollback app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { - "patch": { + "/organizations/{organizationId}/projects/{projectId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update app status", + "description": "Get projects", "consumes": [ "application/json" ], @@ -4907,9 +4813,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Update app status", + "summary": "Get projects", "parameters": [ { "type": "string", @@ -4924,21 +4830,56 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true }, { "type": "string", - "description": "App ID", - "name": "appId", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true }, { - "description": "Request body to update app status", - "name": "body", + "description": "Request body to update project", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest" } } ], @@ -4946,20 +4887,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { "get": { "security": [ { "JWT": [] } ], - "description": "Get appServeAppTask list by giving params", + "description": "Get appServeApp list by giving params", "consumes": [ "application/json" ], @@ -4969,7 +4910,7 @@ const docTemplate = `{ "tags": [ "AppServeApps" ], - "summary": "Get appServeAppTask list", + "summary": "Get appServeApp list", "parameters": [ { "type": "string", @@ -4985,6 +4926,12 @@ const docTemplate = `{ "in": "path", "required": true }, + { + "type": "boolean", + "description": "Show all apps including deleted apps", + "name": "showAll", + "in": "query" + }, { "type": "string", "description": "pageSize", @@ -5000,7 +4947,7 @@ const docTemplate = `{ { "type": "string", "description": "sortColumn", - "name": "sortColumn", + "name": "soertColumn", "in": "query" }, { @@ -5031,16 +4978,14 @@ const docTemplate = `{ } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get task detail from appServeApp", + "description": "Install appServeApp", "consumes": [ "application/json" ], @@ -5050,7 +4995,7 @@ const docTemplate = `{ "tags": [ "AppServeApps" ], - "summary": "Get task detail from appServeApp", + "summary": "Install appServeApp", "parameters": [ { "type": "string", @@ -5067,38 +5012,33 @@ const docTemplate = `{ "required": true }, { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Task ID", - "name": "taskId", - "in": "path", - "required": true + "description": "Request body to create app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" + "type": "string" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project kubeconfig", + "description": "Get number of apps on given stack", "consumes": [ "application/json" ], @@ -5106,9 +5046,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project kubeconfig", + "summary": "Get number of apps on given stack", "parameters": [ { "type": "string", @@ -5123,26 +5063,33 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse" + "type": "integer" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/members": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project members", + "description": "Check duplicate appServeAppName by giving params", "consumes": [ "application/json" ], @@ -5150,9 +5097,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project members", + "summary": "Check duplicate appServeAppName", "parameters": [ { "type": "string", @@ -5170,27 +5117,30 @@ const docTemplate = `{ }, { "type": "string", - "description": "project member search by query (query=all), (query=leader), (query=member), (query=viewer)", - "name": "query", - "in": "query" + "description": "name", + "name": "name", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse" + "type": "boolean" } } } - }, - "put": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update project member Role", + "description": "Get appServeApp by giving params", "consumes": [ "application/json" ], @@ -5198,9 +5148,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Update project member Role", + "summary": "Get appServeApp", "parameters": [ { "type": "string", @@ -5217,31 +5167,29 @@ const docTemplate = `{ "required": true }, { - "description": "Request body to update project member role", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest" - } - } + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse" } } } }, - "post": { + "put": { "security": [ { "JWT": [] } ], - "description": "Add project member to project", + "description": "Update appServeApp", "consumes": [ "application/json" ], @@ -5249,9 +5197,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Add project member to project", + "summary": "Update appServeApp", "parameters": [ { "type": "string", @@ -5268,12 +5216,19 @@ const docTemplate = `{ "required": true }, { - "description": "Request body to add project member", - "name": "request", + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app", + "name": "object", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest" } } ], @@ -5281,7 +5236,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "type": "string" } } } @@ -5292,7 +5247,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Remove project members to project", + "description": "Uninstall appServeApp", "consumes": [ "application/json" ], @@ -5300,9 +5255,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Remove project members to project", + "summary": "Uninstall appServeApp", "parameters": [ { "type": "string", @@ -5319,33 +5274,31 @@ const docTemplate = `{ "required": true }, { - "description": "Request body to remove project member", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest" - } + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "type": "string" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/members/count": { - "get": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Get project member count group by project role", + "description": "Update app endpoint", "consumes": [ "application/json" ], @@ -5353,9 +5306,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project member count group by project role", + "summary": "Update app endpoint", "parameters": [ { "type": "string", @@ -5370,26 +5323,42 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "appId", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app endpoint", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse" + "type": "string" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project member", + "description": "Get appServeApp by giving params", "consumes": [ "application/json" ], @@ -5397,9 +5366,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project member", + "summary": "Get appServeApp", "parameters": [ { "type": "string", @@ -5414,31 +5383,26 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true - }, - { - "type": "string", - "description": "Project Member ID", - "name": "projectMemberId", - "in": "path", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse" + "type": "boolean" } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "get": { "security": [ { "JWT": [] } ], - "description": "Remove project members to project", + "description": "Get latest task from appServeApp", "consumes": [ "application/json" ], @@ -5446,9 +5410,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Remove project members to project", + "summary": "Get latest task from appServeApp", "parameters": [ { "type": "string", @@ -5466,8 +5430,8 @@ const docTemplate = `{ }, { "type": "string", - "description": "Project Member ID", - "name": "projectMemberId", + "description": "App ID", + "name": "appId", "in": "path", "required": true } @@ -5476,20 +5440,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { - "put": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { + "post": { "security": [ { "JWT": [] } ], - "description": "Update project member Role", + "description": "Rollback appServeApp", "consumes": [ "application/json" ], @@ -5497,9 +5461,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Update project member Role", + "summary": "Rollback appServeApp", "parameters": [ { "type": "string", @@ -5517,18 +5481,18 @@ const docTemplate = `{ }, { "type": "string", - "description": "Project Member ID", - "name": "projectMemberId", + "description": "App ID", + "name": "appId", "in": "path", "required": true }, { - "description": "Request body to update project member role", - "name": "request", + "description": "Request body to rollback app", + "name": "object", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest" } } ], @@ -5536,20 +5500,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "type": "string" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces": { - "get": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Get project namespaces", + "description": "Update app status", "consumes": [ "application/json" ], @@ -5557,9 +5521,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project namespaces", + "summary": "Update app status", "parameters": [ { "type": "string", @@ -5574,24 +5538,42 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app status", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse" + "type": "string" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create project namespace", + "description": "Get appServeAppTask list by giving params", "consumes": [ "application/json" ], @@ -5599,9 +5581,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Create project namespace", + "summary": "Get appServeAppTask list", "parameters": [ { "type": "string", @@ -5618,33 +5600,61 @@ const docTemplate = `{ "required": true }, { - "description": "Request body to create project namespace", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest" - } + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" + } } } } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project namespace", + "description": "Get task detail from appServeApp", "consumes": [ "application/json" ], @@ -5652,9 +5662,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project namespace", + "summary": "Get task detail from appServeApp", "parameters": [ { "type": "string", @@ -5672,15 +5682,15 @@ const docTemplate = `{ }, { "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", + "description": "App ID", + "name": "appId", "in": "path", "required": true }, { "type": "string", - "description": "Project Stack ID", - "name": "stackId", + "description": "Task ID", + "name": "taskId", "in": "path", "required": true } @@ -5689,18 +5699,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" } } } - }, - "put": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update project namespace", + "description": "Get project kubeconfig", "consumes": [ "application/json" ], @@ -5710,7 +5722,7 @@ const docTemplate = `{ "tags": [ "Projects" ], - "summary": "Update project namespace", + "summary": "Get project kubeconfig", "parameters": [ { "type": "string", @@ -5725,47 +5737,26 @@ const docTemplate = `{ "name": "projectId", "in": "path", "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "description": "Request body to update project namespace", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse" } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/members": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete project namespace", + "description": "Get project members", "consumes": [ "application/json" ], @@ -5775,7 +5766,7 @@ const docTemplate = `{ "tags": [ "Projects" ], - "summary": "Delete project namespace", + "summary": "Get project members", "parameters": [ { "type": "string", @@ -5793,37 +5784,27 @@ const docTemplate = `{ }, { "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true + "description": "project member search by query (query=all), (query=leader), (query=member), (query=viewer)", + "name": "query", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Check project namespace exist", + "description": "Update project member Role", "consumes": [ "application/json" ], @@ -5833,7 +5814,7 @@ const docTemplate = `{ "tags": [ "Projects" ], - "summary": "Check project namespace exist", + "summary": "Update project member Role", "parameters": [ { "type": "string", @@ -5850,38 +5831,31 @@ const docTemplate = `{ "required": true }, { - "type": "string", - "description": "Project Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true + "description": "Request body to update project member role", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get k8s resources for project namespace", + "description": "Add project member to project", "consumes": [ "application/json" ], @@ -5891,7 +5865,7 @@ const docTemplate = `{ "tags": [ "Projects" ], - "summary": "Get k8s resources for project namespace", + "summary": "Add project member to project", "parameters": [ { "type": "string", @@ -5908,38 +5882,31 @@ const docTemplate = `{ "required": true }, { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true + "description": "Request body to add project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get resources usage for project namespace", + "description": "Remove project members to project", "consumes": [ "application/json" ], @@ -5949,7 +5916,7 @@ const docTemplate = `{ "tags": [ "Projects" ], - "summary": "Get resources usage for project namespace", + "summary": "Remove project members to project", "parameters": [ { "type": "string", @@ -5966,45 +5933,43 @@ const docTemplate = `{ "required": true }, { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true + "description": "Request body to remove project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } } }, - "/organizations/{organizationId}/roles": { + "/organizations/{organizationId}/projects/{projectId}/members/count": { "get": { "security": [ { "JWT": [] } ], - "description": "List Tks Roles", + "description": "Get project member count group by project role", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "List Tks Roles", + "summary": "Get project member count group by project role", "parameters": [ { "type": "string", @@ -6012,24 +5977,33 @@ const docTemplate = `{ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create Tks Role", + "description": "Get project member", "consumes": [ "application/json" ], @@ -6037,9 +6011,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Create Tks Role", + "summary": "Get project member", "parameters": [ { "type": "string", @@ -6049,40 +6023,46 @@ const docTemplate = `{ "required": true }, { - "description": "Create Tks Role Request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest" - } + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse" } } } - } - }, - "/organizations/{organizationId}/roles/{roleId}": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get Tks Role", + "description": "Remove project members to project", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Get Tks Role", + "summary": "Remove project members to project", "parameters": [ { "type": "string", @@ -6093,8 +6073,15 @@ const docTemplate = `{ }, { "type": "string", - "description": "Role ID", - "name": "roleId", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", "in": "path", "required": true } @@ -6103,18 +6090,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } - }, + } + }, + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { "put": { "security": [ { "JWT": [] } ], - "description": "Update Tks Role", + "description": "Update project member Role", "consumes": [ "application/json" ], @@ -6122,9 +6111,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Update Tks Role", + "summary": "Update project member Role", "parameters": [ { "type": "string", @@ -6135,79 +6124,56 @@ const docTemplate = `{ }, { "type": "string", - "description": "Role ID", - "name": "roleId", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true }, { - "description": "Update Tks Role Request", - "name": "body", + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project member role", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/namespaces": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete Tks Role", - "produces": [ + "description": "Get project namespaces", + "consumes": [ "application/json" ], - "tags": [ - "Roles" - ], - "summary": "Delete Tks Role", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Role ID", - "name": "roleId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/roles/{roleId}/permissions": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Permissions By Role ID", "produces": [ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Get Permissions By Role ID", + "summary": "Get project namespaces", "parameters": [ { "type": "string", @@ -6218,8 +6184,8 @@ const docTemplate = `{ }, { "type": "string", - "description": "Role ID", - "name": "roleId", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true } @@ -6228,18 +6194,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse" } } } }, - "put": { + "post": { "security": [ { "JWT": [] } ], - "description": "Update Permissions By Role ID", + "description": "Create project namespace", "consumes": [ "application/json" ], @@ -6247,9 +6213,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Update Permissions By Role ID", + "summary": "Create project namespace", "parameters": [ { "type": "string", @@ -6260,36 +6226,39 @@ const docTemplate = `{ }, { "type": "string", - "description": "Role ID", - "name": "roleId", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true }, { - "description": "Update Permissions By Role ID Request", - "name": "body", + "description": "Request body to create project namespace", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + } } } } }, - "/organizations/{organizationId}/stack-templates": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplates", + "description": "Get project namespace", "consumes": [ "application/json" ], @@ -6297,50 +6266,44 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "Projects" ], - "summary": "Get Organization StackTemplates", + "summary": "Get project namespace", "parameters": [ { "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true }, { "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true }, { "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true }, { "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse" } } } @@ -6351,7 +6314,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Remove organization stackTemplates", + "description": "Update project namespace", "consumes": [ "application/json" ], @@ -6359,33 +6322,64 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "Projects" ], - "summary": "Remove organization stackTemplates", + "summary": "Update project namespace", "parameters": [ { - "description": "Remove organization stack templates request", - "name": "body", + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project namespace", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + } } } }, - "post": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Add organization stackTemplates", + "description": "Delete project namespace", "consumes": [ "application/json" ], @@ -6393,35 +6387,57 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "Projects" ], - "summary": "Add organization stackTemplates", + "summary": "Delete project namespace", "parameters": [ { - "description": "Add organization stack templates request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" - } + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + } } } } }, - "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplate", + "description": "Check project namespace exist", "consumes": [ "application/json" ], @@ -6429,27 +6445,57 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "Projects" + ], + "summary": "Check project namespace exist", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + } ], - "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", + "description": "Get k8s resources for project namespace", "consumes": [ "application/json" ], @@ -6457,104 +6503,57 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "Projects" ], - "summary": "Get Stacks", + "summary": "Get k8s resources for project namespace", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true }, { "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true }, { "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Create Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", + "description": "Project Namespace", + "name": "projectNamespace", "in": "path", "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse" } } } } }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { "get": { "security": [ { "JWT": [] } ], - "description": "Check name for stack", + "description": "Get resources usage for project namespace", "consumes": [ "application/json" ], @@ -6562,89 +6561,89 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "Projects" ], - "summary": "Check name for stack", + "summary": "Get resources usage for project namespace", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", "name": "stackId", "in": "path", "required": true }, { "type": "string", - "description": "name", - "name": "name", + "description": "Project Namespace", + "name": "projectNamespace", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse" + } } } } }, - "/organizations/{organizationId}/stacks/{stackId}": { + "/organizations/{organizationId}/roles": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stack", - "consumes": [ - "application/json" - ], + "description": "List Tks Roles", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Get Stack", + "summary": "List Tks Roles", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" } } } }, - "put": { + "post": { "security": [ { "JWT": [] } ], - "description": "Update Stack", + "description": "Create Tks Role", "consumes": [ "application/json" ], @@ -6652,88 +6651,84 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Update Stack", + "summary": "Create Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", + "description": "Create Tks Role Request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse" + } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/roles/{roleId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete Stack", - "consumes": [ - "application/json" - ], + "description": "Get Tks Role", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Delete Stack", + "summary": "Get Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } } } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/favorite": { - "post": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Set favorite stack", + "description": "Update Tks Role", "consumes": [ "application/json" ], @@ -6741,23 +6736,32 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Set favorite stack", + "summary": "Update Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true + }, + { + "description": "Update Tks Role Request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest" + } } ], "responses": { @@ -6772,29 +6776,26 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Delete favorite stack", - "consumes": [ - "application/json" - ], + "description": "Delete Tks Role", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Delete favorite stack", + "summary": "Delete Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true } @@ -6806,36 +6807,33 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "/organizations/{organizationId}/roles/{roleId}/permissions": { "get": { "security": [ { "JWT": [] } ], - "description": "Get KubeConfig by stack", - "consumes": [ - "application/json" - ], + "description": "Get Permissions By Role ID", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Get KubeConfig by stack", + "summary": "Get Permissions By Role ID", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "organizationId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true } @@ -6844,20 +6842,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse" } } } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Get Stack Status", + "description": "Update Permissions By Role ID", "consumes": [ "application/json" ], @@ -6865,43 +6861,49 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Get Stack Status", + "summary": "Update Permissions By Role ID", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK", + }, + { + "description": "Update Permissions By Role ID Request", + "name": "body", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" } } + ], + "responses": { + "200": { + "description": "OK" + } } } }, - "/organizations/{organizationId}/system-notification-rules": { + "/organizations/{organizationId}/stack-templates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotificationRules", + "description": "Get Organization StackTemplates", "consumes": [ "application/json" ], @@ -6909,17 +6911,10 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationRules" + "StackTemplates" ], - "summary": "Get SystemNotificationRules", + "summary": "Get Organization StackTemplates", "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, { "type": "string", "description": "pageSize", @@ -6959,18 +6954,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" } } } }, - "post": { + "put": { "security": [ { "JWT": [] } ], - "description": "Create SystemNotificationRule", + "description": "Remove organization stackTemplates", "consumes": [ "application/json" ], @@ -6978,45 +6973,33 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationRules" + "StackTemplates" ], - "summary": "Create SystemNotificationRule", + "summary": "Remove organization stackTemplates", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create stack template request", + "description": "Remove organization stack templates request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse" - } + "description": "OK" } } - } - }, - "/organizations/{organizationId}/system-notification-rules/name/{name}/existence": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Check name for systemNotificationRule", + "description": "Add organization stackTemplates", "consumes": [ "application/json" ], @@ -7024,43 +7007,63 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationRules" + "StackTemplates" ], - "summary": "Check name for systemNotificationRule", + "summary": "Add organization stackTemplates", "parameters": [ { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - }, + "description": "Add organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "get": { + "security": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "JWT": [] } ], + "description": "Get Organization StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" } } } } }, - "/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}": { + "/organizations/{organizationId}/stacks": { "get": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotificationRule", + "description": "Get Stacks", "consumes": [ "application/json" ], @@ -7068,9 +7071,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationRules" + "Stacks" ], - "summary": "Get SystemNotificationRule", + "summary": "Get Stacks", "parameters": [ { "type": "string", @@ -7081,28 +7084,45 @@ const docTemplate = `{ }, { "type": "string", - "description": "systemNotificationRuleId", - "name": "systemNotificationRuleId", - "in": "path", - "required": true + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" } } } }, - "put": { + "post": { "security": [ { "JWT": [] } ], - "description": "Update SystemNotificationRule", + "description": "Create Stack", "consumes": [ "application/json" ], @@ -7110,9 +7130,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationRules" + "Stacks" ], - "summary": "Update SystemNotificationRule", + "summary": "Create Stack", "parameters": [ { "type": "string", @@ -7122,35 +7142,33 @@ const docTemplate = `{ "required": true }, { - "type": "string", - "description": "systemNotificationRuleId", - "name": "systemNotificationRuleId", - "in": "path", - "required": true - }, - { - "description": "Update systemNotificationRule request", + "description": "create cloud setting request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/stacks/name/{name}/existence": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete SystemNotificationRule", + "description": "Check name for stack", "consumes": [ "application/json" ], @@ -7158,9 +7176,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationRules" + "Stacks" ], - "summary": "Delete SystemNotificationRule", + "summary": "Check name for stack", "parameters": [ { "type": "string", @@ -7171,8 +7189,15 @@ const docTemplate = `{ }, { "type": "string", - "description": "systemNotificationRuleId", - "name": "systemNotificationRuleId", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", "in": "path", "required": true } @@ -7184,14 +7209,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/system-notification-templates": { + "/organizations/{organizationId}/stacks/{stackId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization SystemNotificationTemplates", + "description": "Get Stack", "consumes": [ "application/json" ], @@ -7199,50 +7224,30 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationTemplates" + "Stacks" ], - "summary": "Get Organization SystemNotificationTemplates", + "summary": "Get Stack", "parameters": [ { "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true }, { "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" } } } @@ -7253,7 +7258,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Remove organization systemNotificationTemplates", + "description": "Update Stack", "consumes": [ "application/json" ], @@ -7261,9 +7266,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationTemplates" + "Stacks" ], - "summary": "Remove organization systemNotificationTemplates", + "summary": "Update Stack", "parameters": [ { "type": "string", @@ -7273,12 +7278,19 @@ const docTemplate = `{ "required": true }, { - "description": "Remove organization systemNotification templates request", + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest" } } ], @@ -7288,13 +7300,13 @@ const docTemplate = `{ } } }, - "post": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Add organization systemNotificationTemplates", + "description": "Delete Stack", "consumes": [ "application/json" ], @@ -7302,9 +7314,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationTemplates" + "Stacks" ], - "summary": "Add organization systemNotificationTemplates", + "summary": "Delete Stack", "parameters": [ { "type": "string", @@ -7313,102 +7325,29 @@ const docTemplate = `{ "in": "path", "required": true }, - { - "description": "Add organization systemNotification templates request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/system-notifications": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get SystemNotifications", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "SystemNotifications" - ], - "summary": "Get SystemNotifications", - "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", + "description": "stackId", + "name": "stackId", "in": "path", "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" - } + "description": "OK" } } } }, - "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { - "get": { + "/organizations/{organizationId}/stacks/{stackId}/favorite": { + "post": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotification", + "description": "Set favorite stack", "consumes": [ "application/json" ], @@ -7416,9 +7355,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "Stacks" ], - "summary": "Get SystemNotification", + "summary": "Set favorite stack", "parameters": [ { "type": "string", @@ -7429,28 +7368,25 @@ const docTemplate = `{ }, { "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "stackId", + "name": "stackId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" - } + "description": "OK" } } }, - "put": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Update SystemNotification", + "description": "Delete favorite stack", "consumes": [ "application/json" ], @@ -7458,9 +7394,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "Stacks" ], - "summary": "Update SystemNotification", + "summary": "Delete favorite stack", "parameters": [ { "type": "string", @@ -7471,19 +7407,10 @@ const docTemplate = `{ }, { "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "stackId", + "name": "stackId", "in": "path", "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" - } } ], "responses": { @@ -7491,14 +7418,16 @@ const docTemplate = `{ "description": "OK" } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete SystemNotification", + "description": "Get KubeConfig by stack", "consumes": [ "application/json" ], @@ -7506,9 +7435,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "Stacks" ], - "summary": "Delete SystemNotification", + "summary": "Get KubeConfig by stack", "parameters": [ { "type": "string", @@ -7519,27 +7448,30 @@ const docTemplate = `{ }, { "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "organizationId", + "name": "stackId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse" + } } } } }, - "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { - "post": { + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create systemNotification action", + "description": "Get Stack Status", "consumes": [ "application/json" ], @@ -7547,9 +7479,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotifications" + "Stacks" ], - "summary": "Create systemNotification action", + "summary": "Get Stack Status", "parameters": [ { "type": "string", @@ -7560,27 +7492,30 @@ const docTemplate = `{ }, { "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "stackId", + "name": "stackId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + } } } } }, - "/organizations/{organizationId}/users": { + "/organizations/{organizationId}/system-notification-rules": { "get": { "security": [ { "JWT": [] } ], - "description": "Get user list", + "description": "Get SystemNotificationRules", "consumes": [ "application/json" ], @@ -7588,9 +7523,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Get user list", + "summary": "Get SystemNotificationRules", "parameters": [ { "type": "string", @@ -7638,10 +7573,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListUserBody" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse" } } } @@ -7652,7 +7584,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Create user", + "description": "Create SystemNotificationRule", "consumes": [ "application/json" ], @@ -7660,9 +7592,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Create user", + "summary": "Create SystemNotificationRule", "parameters": [ { "type": "string", @@ -7672,52 +7604,55 @@ const docTemplate = `{ "required": true }, { - "description": "create user request", + "description": "create stack template request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest" } } ], "responses": { "200": { - "description": "create user response", + "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse" } } } } }, - "/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "/organizations/{organizationId}/system-notification-rules/name/{name}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "return true when accountId exists", + "description": "Check name for systemNotificationRule", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Get user id existence", + "summary": "Check name for systemNotificationRule", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", + "description": "name", + "name": "name", "in": "path", "required": true }, { "type": "string", - "description": "accountId", - "name": "accountId", + "description": "organizationId", + "name": "organizationId", "in": "path", "required": true } @@ -7726,27 +7661,30 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse" } } } } }, - "/organizations/{organizationId}/users/email/{email}/existence": { + "/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}": { "get": { "security": [ { "JWT": [] } ], - "description": "return true when email exists", + "description": "Get SystemNotificationRule", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Get user email existence", + "summary": "Get SystemNotificationRule", "parameters": [ { "type": "string", @@ -7757,8 +7695,8 @@ const docTemplate = `{ }, { "type": "string", - "description": "email", - "name": "accountId", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", "in": "path", "required": true } @@ -7767,20 +7705,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse" } } } - } - }, - "/organizations/{organizationId}/users/{accountId}": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Get user detail", + "description": "Update SystemNotificationRule", "consumes": [ "application/json" ], @@ -7788,9 +7724,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Get user detail", + "summary": "Update SystemNotificationRule", "parameters": [ { "type": "string", @@ -7801,28 +7737,34 @@ const docTemplate = `{ }, { "type": "string", - "description": "accountId", - "name": "accountId", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUserResponse" + }, + { + "description": "Update systemNotificationRule request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest" } } + ], + "responses": { + "200": { + "description": "OK" + } } }, - "put": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Update user", + "description": "Delete SystemNotificationRule", "consumes": [ "application/json" ], @@ -7830,9 +7772,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Update user", + "summary": "Delete SystemNotificationRule", "parameters": [ { "type": "string", @@ -7843,37 +7785,27 @@ const docTemplate = `{ }, { "type": "string", - "description": "accountId", - "name": "accountId", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", "in": "path", "required": true - }, - { - "description": "input", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest" - } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse" - } + "description": "OK" } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/system-notification-templates": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete user", + "description": "Get Organization SystemNotificationTemplates", "consumes": [ "application/json" ], @@ -7881,81 +7813,102 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Users" + "SystemNotificationTemplates" ], - "summary": "Delete user", + "summary": "Get Organization SystemNotificationTemplates", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "description": "pageSize", + "name": "pageSize", + "in": "query" }, { "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse" + } } } - } - }, - "/organizations/{organizationId}/users/{accountId}/permissions": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Get Permissions By Account ID", + "description": "Remove organization systemNotificationTemplates", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Users" + "SystemNotificationTemplates" ], - "summary": "Get Permissions By Account ID", + "summary": "Remove organization systemNotificationTemplates", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true }, { - "type": "string", - "description": "Account ID", - "name": "accountId", - "in": "path", - "required": true + "description": "Remove organization systemNotification templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest" + } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse" - } + "description": "OK" } } - } - }, - "/organizations/{organizationId}/users/{accountId}/reset-password": { - "put": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Reset user's password as temporary password by admin and send email to user", + "description": "Add organization systemNotificationTemplates", "consumes": [ "application/json" ], @@ -7963,9 +7916,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Users" + "SystemNotificationTemplates" ], - "summary": "Reset user's password as temporary password by admin", + "summary": "Add organization systemNotificationTemplates", "parameters": [ { "type": "string", @@ -7975,11 +7928,13 @@ const docTemplate = `{ "required": true }, { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true + "description": "Add organization systemNotification templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest" + } } ], "responses": { @@ -7989,14 +7944,14 @@ const docTemplate = `{ } } }, - "/permissions/templates": { + "/organizations/{organizationId}/system-notifications": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Permission Templates", + "description": "Get SystemNotifications", "consumes": [ "application/json" ], @@ -8004,27 +7959,70 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Permission" + "SystemNotifications" + ], + "summary": "Get SystemNotifications", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } ], - "summary": "Get Permission Templates", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" } } } } }, - "/policy-templates/rego-compile": { - "post": { + "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", + "description": "Get SystemNotification", "consumes": [ "application/json" ], @@ -8032,45 +8030,41 @@ const docTemplate = `{ "application/json" ], "tags": [ - "PolicyTemplate" + "SystemNotifications" ], - "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", + "summary": "Get SystemNotification", "parameters": [ { - "type": "boolean", - "description": "파라미터 파싱 여부", - "name": "parseParameter", - "in": "query", + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", "required": true }, { - "description": "Rego 코드", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" - } + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" } } } - } - }, - "/system-api/organizations/{organizationId}/system-notifications": { - "post": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Create systemNotification. ADMIN ONLY", + "description": "Update SystemNotification", "consumes": [ "application/json" ], @@ -8080,7 +8074,7 @@ const docTemplate = `{ "tags": [ "SystemNotifications" ], - "summary": "Create systemNotification. ADMIN ONLY", + "summary": "Update SystemNotification", "parameters": [ { "type": "string", @@ -8088,16 +8082,636 @@ const docTemplate = `{ "name": "organizationId", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - } - }, + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Delete SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create systemNotification action", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Create systemNotification action", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/users": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user list", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListUserBody" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create user request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "create user response", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "return true when accountId exists", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user id existence", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/email/{email}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "return true when email exists", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user email existence", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "email", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUserResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}/permissions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permissions By Account ID", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get Permissions By Account ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}/reset-password": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Reset user's password as temporary password by admin and send email to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Reset user's password as temporary password by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/permissions/templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permission Templates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Get Permission Templates", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse" + } + } + } + } + }, + "/policy-templates/rego-compile": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", + "parameters": [ + { + "type": "boolean", + "description": "파라미터 파싱 여부", + "name": "parseParameter", + "in": "query", + "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" + } + } + } + } + }, + "/system-api/organizations/{organizationId}/system-notifications": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create systemNotification. ADMIN ONLY", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Create systemNotification. ADMIN ONLY", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, "definitions": { "github_com_openinfradev_tks-api_internal_model.AppServeApp": { "type": "object", @@ -9375,10 +9989,6 @@ const docTemplate = `{ "templateId": { "type": "string", "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" - }, - "templateName": { - "type": "string", - "example": "필수 Label 검사" } } }, @@ -10028,6 +10638,22 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -11222,20 +11848,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization": { - "type": "object", - "properties": { - "organizationId": { - "type": "string" - }, - "organizationName": { - "type": "string" - }, - "permitted": { - "type": "boolean" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.PodCount": { "type": "object", "properties": { @@ -11354,12 +11966,6 @@ const docTemplate = `{ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" } }, - "permittedOrganizations": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization" - } - }, "rego": { "type": "string", "example": "rego 코드" @@ -12757,385 +13363,670 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest": { + "type": "object", + "properties": { + "currentTargetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "newTargetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "enforcementAction": { + "type": "string" + }, + "mandatory": { + "type": "boolean" + }, + "match": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "refer": "match.Match" + } + }, + "parameters": { + "type": "string", + "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + }, + "policyName": { + "type": "string", + "example": "label 정책" + }, + "targetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "templateId": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { + "type": "object", + "properties": { + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string" + }, + "permittedOrganizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { + "type": "object", + "properties": { + "primaryClusterId": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest": { + "type": "object", + "properties": { + "projectRoleId": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectMemberId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + } + } + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "projectLeaderId": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest": { "type": "object", + "required": [ + "organizationIds" + ], "properties": { - "permissions": { + "organizationIds": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest" + "type": "string" } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { "type": "object", + "required": [ + "serviceIds" + ], "properties": { - "currentTargetClusterIds": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "83bf8081-f0c5-4b31-826d-23f6f366ec90" - ] + "cloudService": { + "type": "string" }, - "newTargetClusterIds": { + "description": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "serviceIds": { "type": "array", "items": { "type": "string" - }, - "example": [ - "83bf8081-f0c5-4b31-826d-23f6f366ec90", - "83bf8081-f0c5-4b31-826d-23f6f366ec90" - ] + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "version": { + "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", + "required": [ + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" + ], "properties": { "description": { "type": "string" }, - "enforcementAction": { + "messageActionProposal": { "type": "string" }, - "mandatory": { - "type": "boolean" + "messageCondition": { + "type": "string" }, - "match": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "refer": "match.Match" - } + "messageContent": { + "type": "string" }, - "parameters": { - "type": "string", - "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + "messageTitle": { + "type": "string" }, - "policyName": { - "type": "string", - "example": "label 정책" + "name": { + "type": "string" }, - "targetClusterIds": { + "systemNotificationConditions": { "type": "array", "items": { - "type": "string" - }, - "example": [ - "83bf8081-f0c5-4b31-826d-23f6f366ec90", - "83bf8081-f0c5-4b31-826d-23f6f366ec90" - ] + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } }, - "templateId": { - "type": "string", - "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest": { "type": "object", + "required": [ + "metricQuery", + "name", + "organizationIds" + ], "properties": { - "deprecated": { - "type": "boolean", - "example": false - }, "description": { "type": "string" }, - "permittedOrganizationIds": { + "metricParameters": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" } }, - "severity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ], - "example": "medium" + "metricQuery": { + "type": "string" }, - "templateName": { - "type": "string", - "example": "필수 Label 검사" + "name": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { "type": "object", "properties": { - "primaryClusterId": { - "type": "string" + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest": { "type": "object", "properties": { - "projectRoleId": { + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { "type": "string" + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "role": { + "type": "string", + "enum": [ + "admin", + "user" + ] } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse": { "type": "object", "properties": { - "projectMembers": { - "type": "array", - "items": { - "type": "object", - "properties": { - "projectMemberId": { - "type": "string" - }, - "projectRoleId": { - "type": "string" - } + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + }, + "updatedAt": { + "type": "string" } } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ - "name" + "email", + "organizationId", + "userName" ], "properties": { - "description": { + "email": { "type": "string" }, - "name": { + "organizationId": { "type": "string" }, - "projectLeaderId": { + "userName": { "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse": { "type": "object", "properties": { - "description": { + "validityPeriod": { "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest": { - "type": "object", - "required": [ - "organizationIds" - ], - "properties": { - "organizationIds": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest": { "type": "object", "required": [ - "serviceIds" + "accountId", + "email", + "organizationId", + "userName" ], "properties": { - "cloudService": { + "accountId": { "type": "string" }, - "description": { + "email": { "type": "string" }, - "kubeType": { + "organizationId": { "type": "string" }, - "kubeVersion": { + "userName": { "type": "string" - }, - "platform": { + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse": { + "type": "object", + "properties": { + "validityPeriod": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.WidgetResponse": { + "type": "object", + "properties": { + "key": { "type": "string" }, - "serviceIds": { - "type": "array", - "items": { - "type": "string" - } + "sizeX": { + "type": "integer" }, - "template": { - "type": "string" + "sizeY": { + "type": "integer" }, - "templateType": { - "type": "string" + "startX": { + "type": "integer" }, - "version": { - "type": "string" + "startY": { + "type": "integer" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse": { "type": "object", "properties": { - "description": { - "type": "string" + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateRequest": { "type": "object", "required": [ - "messageCondition", - "messageContent", - "messageTitle", - "name", - "systemNotificationTemplateId" + "kind", + "rego" ], "properties": { - "description": { - "type": "string" - }, - "messageActionProposal": { - "type": "string" - }, - "messageCondition": { - "type": "string" + "deprecated": { + "type": "boolean", + "example": false }, - "messageContent": { - "type": "string" + "description": { + "type": "string", + "example": "이 정책은 ..." }, - "messageTitle": { - "type": "string" + "kind": { + "type": "string", + "example": "K8sRequiredLabels" }, - "name": { - "type": "string" + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] }, - "systemNotificationConditions": { + "parametersSchema": { "type": "array", "items": { - "type": "object", - "properties": { - "duration": { - "type": "integer" - }, - "enableEmail": { - "type": "boolean" - }, - "enablePortal": { - "type": "boolean" - }, - "order": { - "type": "integer" - }, - "parameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" - } - }, - "severity": { - "type": "string" - } - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" } }, - "systemNotificationTemplateId": { - "type": "string" - }, - "targetUserIds": { + "permittedOrganizationIds": { "type": "array", "items": { "type": "string" } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest": { "type": "object", "required": [ - "metricQuery", - "name", - "organizationIds" + "currentVersion", + "expectedVersion", + "rego", + "versionUpType" ], "properties": { - "description": { - "type": "string" + "currentVersion": { + "type": "string", + "example": "v1.0.0" }, - "metricParameters": { + "expectedVersion": { + "type": "string", + "example": "v1.1.0" + }, + "libs": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" - } - }, - "metricQuery": { - "type": "string" - }, - "name": { - "type": "string" + "type": "string" + }, + "example": [ + "rego 코드" + ] }, - "organizationIds": { + "parametersSchema": { "type": "array", "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "versionUpType": { + "type": "string", + "enum": [ + "major", + "minor", + "patch" + ], + "example": "minor" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionResponse": { + "type": "object", + "properties": { + "version": { + "type": "string", + "example": "v1.1.1" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse": { + "type": "object", + "properties": { + "deployVersion": { + "type": "object", + "additionalProperties": { "type": "string" } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateResponse": { "type": "object", "properties": { - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 + "policyTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateVersionResponse": { "type": "object", "properties": { - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] + "policyTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { "type": "object", "properties": { "user": { @@ -13147,6 +14038,9 @@ const docTemplate = `{ "createdAt": { "type": "string" }, + "creator": { + "type": "string" + }, "department": { "type": "string" }, @@ -13175,124 +14069,186 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse": { "type": "object", - "required": [ - "email", - "organizationId", - "userName" - ], "properties": { - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, - "userName": { - "type": "string" + "policyTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse" + } } } }, - "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateStatisticsResponse": { "type": "object", "properties": { - "validityPeriod": { - "type": "string" + "policyTemplateStatistics": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateStatistics" + } } } }, - "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateVersionsResponse": { + "type": "object", + "properties": { + "versions": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "v1.1.0", + "v1.0.1", + "v1.0.0" + ] + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization": { "type": "object", - "required": [ - "accountId", - "email", - "organizationId", - "userName" - ], "properties": { - "accountId": { - "type": "string" - }, - "email": { - "type": "string" - }, "organizationId": { "type": "string" }, - "userName": { + "organizationName": { "type": "string" + }, + "permitted": { + "type": "boolean" } } }, - "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse": { "type": "object", "properties": { - "validityPeriod": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "kind": { + "type": "string", + "example": "K8sRequiredLabels" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "permittedOrganizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "type": { + "type": "string", + "enum": [ + "tks", + "organization" + ], + "example": "tks" + }, + "updatedAt": { "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "version": { + "type": "string", + "example": "v1.0.1" } } }, - "github_com_openinfradev_tks-api_pkg_domain.WidgetResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateStatistics": { "type": "object", "properties": { - "key": { + "organizationId": { "type": "string" }, - "sizeX": { - "type": "integer" - }, - "sizeY": { - "type": "integer" - }, - "startX": { - "type": "integer" + "organizationName": { + "type": "string" }, - "startY": { + "usageCount": { "type": "integer" } } }, - "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest": { "type": "object", "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "updatedAt": { - "type": "string" - } + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string" + }, + "permittedOrganizationIds": { + "type": "array", + "items": { + "type": "string" } + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 27c2281a..8a8f1e1e 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -405,7 +405,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", + "summary": "[Admin_ListPolicyTemplate] 정책 템플릿 목록 조회", "parameters": [ { "type": "string", @@ -422,7 +422,7 @@ { "type": "string", "description": "sortColumn", - "name": "soertColumn", + "name": "sortColumn", "in": "query" }, { @@ -446,7 +446,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse" } } } @@ -467,7 +467,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", + "summary": "[Admin_CreatePolicyTemplate] 정책 템플릿 신규 생성", "parameters": [ { "description": "create policy template request", @@ -475,7 +475,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateRequest" } } ], @@ -483,7 +483,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse" } } } @@ -506,7 +506,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", + "summary": "[Admin_ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", "parameters": [ { "type": "string", @@ -520,7 +520,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse" } } } @@ -543,7 +543,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "summary": "[Admin_ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", "parameters": [ { "type": "string", @@ -557,7 +557,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateNameResponse" } } } @@ -580,7 +580,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", + "summary": "[Admin_GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", "parameters": [ { "type": "string", @@ -594,7 +594,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateResponse" } } } @@ -615,7 +615,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", + "summary": "[Admin_DeletePolicyTemplate] 정책 템플릿 삭제", "parameters": [ { "type": "string", @@ -647,7 +647,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", + "summary": "[Admin_UpdatePolicyTemplate] 정책 템플릿 업데이트", "parameters": [ { "type": "string", @@ -662,7 +662,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest" } } ], @@ -690,7 +690,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", + "summary": "[Admin_GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", "parameters": [ { "type": "string", @@ -704,7 +704,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse" } } } @@ -727,7 +727,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", + "summary": "[Admin_ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", "parameters": [ { "type": "string", @@ -741,7 +741,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateStatisticsResponse" } } } @@ -764,7 +764,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", + "summary": "[Admin_ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", "parameters": [ { "type": "string", @@ -778,7 +778,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateVersionsResponse" } } } @@ -799,7 +799,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", + "summary": "[Admin_CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", "parameters": [ { "type": "string", @@ -814,7 +814,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest" } } ], @@ -822,7 +822,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionResponse" } } } @@ -845,7 +845,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", + "summary": "[Admin_GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", "parameters": [ { "type": "string", @@ -866,7 +866,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateVersionResponse" } } } @@ -887,7 +887,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", + "summary": "[Admin_DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", "parameters": [ { "type": "string", @@ -3612,7 +3612,7 @@ { "type": "string", "description": "sortColumn", - "name": "soertColumn", + "name": "sortColumn", "in": "query" }, { @@ -3911,14 +3911,14 @@ } } }, - "/organizations/{organizationId}/primary-cluster": { - "patch": { + "/organizations/{organizationId}/policy-templates": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update primary cluster", + "description": "정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다.", "consumes": [ "application/json" ], @@ -3926,72 +3926,57 @@ "application/json" ], "tags": [ - "Organizations" + "PolicyTemplate" ], - "summary": "Update primary cluster", + "summary": "[ListPolicyTemplate] 정책 템플릿 목록 조회", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "description": "pageSize", + "name": "limit", + "in": "query" }, { - "description": "update primary cluster request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/projects": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get projects", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Projects" - ], - "summary": "Get projects", - "parameters": [ + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, { "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true + "description": "sortColumn", + "name": "sortColumn", + "in": "query" }, { "type": "string", - "description": "(all | only)", - "name": "query", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", "in": "query" + }, + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse" } } } @@ -4002,7 +3987,7 @@ "JWT": [] } ], - "description": "Create new project", + "description": "정책 템플릿을 신규 생성(v1.0.0을 생성)한다.", "consumes": [ "application/json" ], @@ -4010,24 +3995,24 @@ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Create new project", + "summary": "[CreatePolicyTemplate] 정책 템플릿 신규 생성", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { - "description": "Request body to create project", - "name": "request", + "description": "create policy template request", + "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest" } } ], @@ -4035,20 +4020,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse" } } } } }, - "/organizations/{organizationId}/projects/existence": { + "/organizations/{organizationId}/policy-templates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Check project name exist", + "description": "해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다.", "consumes": [ "application/json" ], @@ -4056,28 +4041,22 @@ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Check project name exist", + "summary": "[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "type (name)", - "name": "type", - "in": "query" - }, - { - "type": "string", - "description": "value (project name)", - "name": "value", - "in": "query", + "description": "정책 템플릿 이름", + "name": "policyTemplateKind", + "in": "path", "required": true } ], @@ -4085,20 +4064,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse" } } } } }, - "/organizations/{organizationId}/projects/project-roles": { + "/organizations/{organizationId}/policy-templates/name/{policyTemplateName}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project roles by giving params", + "description": "해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다.", "consumes": [ "application/json" ], @@ -4106,42 +4085,43 @@ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Get project roles", + "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "project role search by query (query=all), (query=leader), (query=member), (query=viewer)", - "name": "query", - "in": "query" + "description": "정책 템플릿 이름", + "name": "policyTemplateName", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateNameResponse" } } } } }, - "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "/organizations/{organizationId}/policy-templates/{policyTemplateId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project role by id", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", "consumes": [ "application/json" ], @@ -4149,21 +4129,21 @@ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Get project role", + "summary": "[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project Role ID", - "name": "projectRoleId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true } @@ -4172,20 +4152,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get projects", + "description": "정책 템플릿을 삭제한다.", "consumes": [ "application/json" ], @@ -4193,41 +4171,38 @@ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Get projects", + "summary": "[DeletePolicyTemplate] 정책 템플릿 삭제", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse" - } + "description": "OK" } } }, - "put": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Update project", + "description": "정책 템플릿의 업데이트 가능한 필드들을 업데이트한다.", "consumes": [ "application/json" ], @@ -4235,52 +4210,49 @@ "application/json" ], "tags": [ - "Projects" + "PolicyTemplate" ], - "summary": "Update project", + "summary": "[UpdatePolicyTemplate] 정책 템플릿 업데이트", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true }, { - "description": "Request body to update project", - "name": "request", + "description": "update policy template request", + "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest" } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" - } + "description": "OK" } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/deploy": { "get": { "security": [ { "JWT": [] } ], - "description": "Get appServeApp list by giving params", + "description": "해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다.", "consumes": [ "application/json" ], @@ -4288,84 +4260,43 @@ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Get appServeApp list", + "summary": "[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true - }, - { - "type": "boolean", - "description": "Show all apps including deleted apps", - "name": "showAll", - "in": "query" - }, - { - "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/statistics": { + "get": { "security": [ { "JWT": [] } ], - "description": "Install appServeApp", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 tks로 설정한다.", "consumes": [ "application/json" ], @@ -4373,52 +4304,43 @@ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Install appServeApp", + "summary": "[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true - }, - { - "description": "Request body to create app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions": { "get": { "security": [ { "JWT": [] } ], - "description": "Get number of apps on given stack", + "description": "해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다.", "consumes": [ "application/json" ], @@ -4426,50 +4348,41 @@ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Get number of apps on given stack", + "summary": "[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true - }, - { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "query", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "type": "integer" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Check duplicate appServeAppName by giving params", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다.", "consumes": [ "application/json" ], @@ -4477,50 +4390,52 @@ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Check duplicate appServeAppName", + "summary": "[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true }, { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true + "description": "create policy template version request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "boolean" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get appServeApp by giving params", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다.", "consumes": [ "application/json" ], @@ -4528,28 +4443,28 @@ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Get appServeApp", + "summary": "[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true }, { "type": "string", - "description": "App ID", - "name": "appId", + "description": "조회할 버전(v0.0.0 형식)", + "name": "version", "in": "path", "required": true } @@ -4558,18 +4473,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse" } } } }, - "put": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Update appServeApp", + "description": "해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다.", "consumes": [ "application/json" ], @@ -4577,57 +4492,47 @@ "application/json" ], "tags": [ - "AppServeApps" + "PolicyTemplate" ], - "summary": "Update appServeApp", + "summary": "[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", "in": "path", "required": true }, { "type": "string", - "description": "App ID", - "name": "appId", + "description": "삭제할 버전(v0.0.0 형식)", + "name": "version", "in": "path", "required": true - }, - { - "description": "Request body to update app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest" - } } ], "responses": { "200": { - "description": "OK", - "schema": { - "type": "string" - } + "description": "OK" } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/primary-cluster": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Uninstall appServeApp", + "description": "Update primary cluster", "consumes": [ "application/json" ], @@ -4635,50 +4540,42 @@ "application/json" ], "tags": [ - "AppServeApps" + "Organizations" ], - "summary": "Uninstall appServeApp", + "summary": "Update primary cluster", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true }, { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true + "description": "update primary cluster request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest" + } } ], "responses": { "200": { - "description": "OK", - "schema": { - "type": "string" - } + "description": "OK" } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { - "patch": { + "/organizations/{organizationId}/projects": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update app endpoint", + "description": "Get projects", "consumes": [ "application/json" ], @@ -4686,9 +4583,9 @@ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Update app endpoint", + "summary": "Get projects", "parameters": [ { "type": "string", @@ -4699,46 +4596,27 @@ }, { "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "appId", - "name": "appId", - "in": "path", - "required": true - }, - { - "description": "Request body to update app endpoint", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest" - } + "description": "(all | only)", + "name": "query", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectsResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get appServeApp by giving params", + "description": "Create new project", "consumes": [ "application/json" ], @@ -4746,9 +4624,9 @@ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Get appServeApp", + "summary": "Create new project", "parameters": [ { "type": "string", @@ -4758,31 +4636,33 @@ "required": true }, { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true + "description": "Request body to create project", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "boolean" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "/organizations/{organizationId}/projects/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get latest task from appServeApp", + "description": "Check project name exist", "consumes": [ "application/json" ], @@ -4790,9 +4670,9 @@ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Get latest task from appServeApp", + "summary": "Check project name exist", "parameters": [ { "type": "string", @@ -4803,16 +4683,15 @@ }, { "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true + "description": "type (name)", + "name": "type", + "in": "query" }, { "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", + "description": "value (project name)", + "name": "value", + "in": "query", "required": true } ], @@ -4820,20 +4699,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { - "post": { + "/organizations/{organizationId}/projects/project-roles": { + "get": { "security": [ { "JWT": [] } ], - "description": "Rollback appServeApp", + "description": "Get project roles by giving params", "consumes": [ "application/json" ], @@ -4841,9 +4720,9 @@ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Rollback appServeApp", + "summary": "Get project roles", "parameters": [ { "type": "string", @@ -4854,46 +4733,73 @@ }, { "type": "string", - "description": "Project ID", - "name": "projectId", + "description": "project role search by query (query=all), (query=leader), (query=member), (query=viewer)", + "name": "query", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRolesResponse" + } + } + } + } + }, + "/organizations/{organizationId}/projects/project-roles/{projectRoleId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project role by id", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project role", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "App ID", - "name": "appId", + "description": "Project Role ID", + "name": "projectRoleId", "in": "path", "required": true - }, - { - "description": "Request body to rollback app", - "name": "object", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectRoleResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { - "patch": { + "/organizations/{organizationId}/projects/{projectId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update app status", + "description": "Get projects", "consumes": [ "application/json" ], @@ -4901,9 +4807,9 @@ "application/json" ], "tags": [ - "AppServeApps" + "Projects" ], - "summary": "Update app status", + "summary": "Get projects", "parameters": [ { "type": "string", @@ -4918,21 +4824,56 @@ "name": "projectId", "in": "path", "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update project", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Update project", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true }, { "type": "string", - "description": "App ID", - "name": "appId", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true }, { - "description": "Request body to update app status", - "name": "body", + "description": "Request body to update project", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest" } } ], @@ -4940,20 +4881,20 @@ "200": { "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps": { "get": { "security": [ { "JWT": [] } ], - "description": "Get appServeAppTask list by giving params", + "description": "Get appServeApp list by giving params", "consumes": [ "application/json" ], @@ -4963,7 +4904,7 @@ "tags": [ "AppServeApps" ], - "summary": "Get appServeAppTask list", + "summary": "Get appServeApp list", "parameters": [ { "type": "string", @@ -4979,6 +4920,12 @@ "in": "path", "required": true }, + { + "type": "boolean", + "description": "Show all apps including deleted apps", + "name": "showAll", + "in": "query" + }, { "type": "string", "description": "pageSize", @@ -4994,7 +4941,7 @@ { "type": "string", "description": "sortColumn", - "name": "sortColumn", + "name": "soertColumn", "in": "query" }, { @@ -5025,16 +4972,14 @@ } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get task detail from appServeApp", + "description": "Install appServeApp", "consumes": [ "application/json" ], @@ -5044,7 +4989,7 @@ "tags": [ "AppServeApps" ], - "summary": "Get task detail from appServeApp", + "summary": "Install appServeApp", "parameters": [ { "type": "string", @@ -5061,38 +5006,33 @@ "required": true }, { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Task ID", - "name": "taskId", - "in": "path", - "required": true + "description": "Request body to create app", + "name": "object", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateAppServeAppRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" + "type": "string" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project kubeconfig", + "description": "Get number of apps on given stack", "consumes": [ "application/json" ], @@ -5100,9 +5040,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project kubeconfig", + "summary": "Get number of apps on given stack", "parameters": [ { "type": "string", @@ -5117,26 +5057,33 @@ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse" + "type": "integer" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/members": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project members", + "description": "Check duplicate appServeAppName by giving params", "consumes": [ "application/json" ], @@ -5144,9 +5091,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project members", + "summary": "Check duplicate appServeAppName", "parameters": [ { "type": "string", @@ -5164,27 +5111,30 @@ }, { "type": "string", - "description": "project member search by query (query=all), (query=leader), (query=member), (query=viewer)", - "name": "query", - "in": "query" + "description": "name", + "name": "name", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse" + "type": "boolean" } } } - }, - "put": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update project member Role", + "description": "Get appServeApp by giving params", "consumes": [ "application/json" ], @@ -5192,9 +5142,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Update project member Role", + "summary": "Get appServeApp", "parameters": [ { "type": "string", @@ -5211,31 +5161,29 @@ "required": true }, { - "description": "Request body to update project member role", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest" - } - } + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse" } } } }, - "post": { + "put": { "security": [ { "JWT": [] } ], - "description": "Add project member to project", + "description": "Update appServeApp", "consumes": [ "application/json" ], @@ -5243,9 +5191,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Add project member to project", + "summary": "Update appServeApp", "parameters": [ { "type": "string", @@ -5262,12 +5210,19 @@ "required": true }, { - "description": "Request body to add project member", - "name": "request", + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app", + "name": "object", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppRequest" } } ], @@ -5275,7 +5230,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "type": "string" } } } @@ -5286,7 +5241,7 @@ "JWT": [] } ], - "description": "Remove project members to project", + "description": "Uninstall appServeApp", "consumes": [ "application/json" ], @@ -5294,9 +5249,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Remove project members to project", + "summary": "Uninstall appServeApp", "parameters": [ { "type": "string", @@ -5313,33 +5268,31 @@ "required": true }, { - "description": "Request body to remove project member", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest" - } + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "type": "string" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/members/count": { - "get": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/endpoint": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Get project member count group by project role", + "description": "Update app endpoint", "consumes": [ "application/json" ], @@ -5347,9 +5300,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project member count group by project role", + "summary": "Update app endpoint", "parameters": [ { "type": "string", @@ -5364,26 +5317,42 @@ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "appId", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app endpoint", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse" + "type": "string" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project member", + "description": "Get appServeApp by giving params", "consumes": [ "application/json" ], @@ -5391,9 +5360,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project member", + "summary": "Get appServeApp", "parameters": [ { "type": "string", @@ -5408,31 +5377,26 @@ "name": "projectId", "in": "path", "required": true - }, - { - "type": "string", - "description": "Project Member ID", - "name": "projectMemberId", - "in": "path", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse" + "type": "boolean" } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task": { + "get": { "security": [ { "JWT": [] } ], - "description": "Remove project members to project", + "description": "Get latest task from appServeApp", "consumes": [ "application/json" ], @@ -5440,9 +5404,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Remove project members to project", + "summary": "Get latest task from appServeApp", "parameters": [ { "type": "string", @@ -5460,8 +5424,8 @@ }, { "type": "string", - "description": "Project Member ID", - "name": "projectMemberId", + "description": "App ID", + "name": "appId", "in": "path", "required": true } @@ -5470,20 +5434,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { - "put": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { + "post": { "security": [ { "JWT": [] } ], - "description": "Update project member Role", + "description": "Rollback appServeApp", "consumes": [ "application/json" ], @@ -5491,9 +5455,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Update project member Role", + "summary": "Rollback appServeApp", "parameters": [ { "type": "string", @@ -5511,18 +5475,18 @@ }, { "type": "string", - "description": "Project Member ID", - "name": "projectMemberId", + "description": "App ID", + "name": "appId", "in": "path", "required": true }, { - "description": "Request body to update project member role", - "name": "request", + "description": "Request body to rollback app", + "name": "object", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest" } } ], @@ -5530,20 +5494,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "type": "string" } } } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces": { - "get": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/status": { + "patch": { "security": [ { "JWT": [] } ], - "description": "Get project namespaces", + "description": "Update app status", "consumes": [ "application/json" ], @@ -5551,9 +5515,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project namespaces", + "summary": "Update app status", "parameters": [ { "type": "string", @@ -5568,24 +5532,42 @@ "name": "projectId", "in": "path", "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + }, + { + "description": "Request body to update app status", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppStatusRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse" + "type": "string" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create project namespace", + "description": "Get appServeAppTask list by giving params", "consumes": [ "application/json" ], @@ -5593,9 +5575,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Create project namespace", + "summary": "Get appServeAppTask list", "parameters": [ { "type": "string", @@ -5612,33 +5594,61 @@ "required": true }, { - "description": "Request body to create project namespace", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest" - } + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeApp" + } } } } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get project namespace", + "description": "Get task detail from appServeApp", "consumes": [ "application/json" ], @@ -5646,9 +5656,9 @@ "application/json" ], "tags": [ - "Projects" + "AppServeApps" ], - "summary": "Get project namespace", + "summary": "Get task detail from appServeApp", "parameters": [ { "type": "string", @@ -5666,15 +5676,15 @@ }, { "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", + "description": "App ID", + "name": "appId", "in": "path", "required": true }, { "type": "string", - "description": "Project Stack ID", - "name": "stackId", + "description": "Task ID", + "name": "taskId", "in": "path", "required": true } @@ -5683,18 +5693,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse" } } } - }, - "put": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update project namespace", + "description": "Get project kubeconfig", "consumes": [ "application/json" ], @@ -5704,7 +5716,7 @@ "tags": [ "Projects" ], - "summary": "Update project namespace", + "summary": "Get project kubeconfig", "parameters": [ { "type": "string", @@ -5719,47 +5731,26 @@ "name": "projectId", "in": "path", "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "description": "Request body to update project namespace", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectKubeconfigResponse" } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/members": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete project namespace", + "description": "Get project members", "consumes": [ "application/json" ], @@ -5769,7 +5760,7 @@ "tags": [ "Projects" ], - "summary": "Delete project namespace", + "summary": "Get project members", "parameters": [ { "type": "string", @@ -5787,37 +5778,27 @@ }, { "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true + "description": "project member search by query (query=all), (query=leader), (query=member), (query=viewer)", + "name": "query", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMembersResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Check project namespace exist", + "description": "Update project member Role", "consumes": [ "application/json" ], @@ -5827,7 +5808,7 @@ "tags": [ "Projects" ], - "summary": "Check project namespace exist", + "summary": "Update project member Role", "parameters": [ { "type": "string", @@ -5844,38 +5825,31 @@ "required": true }, { - "type": "string", - "description": "Project Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true + "description": "Request body to update project member role", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get k8s resources for project namespace", + "description": "Add project member to project", "consumes": [ "application/json" ], @@ -5885,7 +5859,7 @@ "tags": [ "Projects" ], - "summary": "Get k8s resources for project namespace", + "summary": "Add project member to project", "parameters": [ { "type": "string", @@ -5902,38 +5876,31 @@ "required": true }, { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true + "description": "Request body to add project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } - } - }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get resources usage for project namespace", + "description": "Remove project members to project", "consumes": [ "application/json" ], @@ -5943,7 +5910,7 @@ "tags": [ "Projects" ], - "summary": "Get resources usage for project namespace", + "summary": "Remove project members to project", "parameters": [ { "type": "string", @@ -5960,45 +5927,43 @@ "required": true }, { - "type": "string", - "description": "Stack ID", - "name": "stackId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project Namespace", - "name": "projectNamespace", - "in": "path", - "required": true + "description": "Request body to remove project member", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveProjectMemberRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } } }, - "/organizations/{organizationId}/roles": { + "/organizations/{organizationId}/projects/{projectId}/members/count": { "get": { "security": [ { "JWT": [] } ], - "description": "List Tks Roles", + "description": "Get project member count group by project role", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "List Tks Roles", + "summary": "Get project member count group by project role", "parameters": [ { "type": "string", @@ -6006,24 +5971,33 @@ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberCountResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create Tks Role", + "description": "Get project member", "consumes": [ "application/json" ], @@ -6031,9 +6005,9 @@ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Create Tks Role", + "summary": "Get project member", "parameters": [ { "type": "string", @@ -6043,40 +6017,46 @@ "required": true }, { - "description": "Create Tks Role Request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest" - } + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectMemberResponse" } } } - } - }, - "/organizations/{organizationId}/roles/{roleId}": { - "get": { + }, + "delete": { "security": [ { "JWT": [] } ], - "description": "Get Tks Role", + "description": "Remove project members to project", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Get Tks Role", + "summary": "Remove project members to project", "parameters": [ { "type": "string", @@ -6087,8 +6067,15 @@ }, { "type": "string", - "description": "Role ID", - "name": "roleId", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", "in": "path", "required": true } @@ -6097,18 +6084,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" } } } - }, + } + }, + "/organizations/{organizationId}/projects/{projectId}/members/{projectMemberId}/role": { "put": { "security": [ { "JWT": [] } ], - "description": "Update Tks Role", + "description": "Update project member Role", "consumes": [ "application/json" ], @@ -6116,9 +6105,9 @@ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Update Tks Role", + "summary": "Update project member Role", "parameters": [ { "type": "string", @@ -6129,79 +6118,56 @@ }, { "type": "string", - "description": "Role ID", - "name": "roleId", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true }, { - "description": "Update Tks Role Request", - "name": "body", + "type": "string", + "description": "Project Member ID", + "name": "projectMemberId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project member role", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/projects/{projectId}/namespaces": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete Tks Role", - "produces": [ + "description": "Get project namespaces", + "consumes": [ "application/json" ], - "tags": [ - "Roles" - ], - "summary": "Delete Tks Role", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Role ID", - "name": "roleId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/roles/{roleId}/permissions": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get Permissions By Role ID", "produces": [ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Get Permissions By Role ID", + "summary": "Get project namespaces", "parameters": [ { "type": "string", @@ -6212,8 +6178,8 @@ }, { "type": "string", - "description": "Role ID", - "name": "roleId", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true } @@ -6222,18 +6188,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespacesResponse" } } } }, - "put": { + "post": { "security": [ { "JWT": [] } ], - "description": "Update Permissions By Role ID", + "description": "Create project namespace", "consumes": [ "application/json" ], @@ -6241,9 +6207,9 @@ "application/json" ], "tags": [ - "Roles" + "Projects" ], - "summary": "Update Permissions By Role ID", + "summary": "Create project namespace", "parameters": [ { "type": "string", @@ -6254,36 +6220,39 @@ }, { "type": "string", - "description": "Role ID", - "name": "roleId", + "description": "Project ID", + "name": "projectId", "in": "path", "required": true }, { - "description": "Update Permissions By Role ID Request", - "name": "body", + "description": "Request body to create project namespace", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateProjectNamespaceRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + } } } } }, - "/organizations/{organizationId}/stack-templates": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplates", + "description": "Get project namespace", "consumes": [ "application/json" ], @@ -6291,50 +6260,44 @@ "application/json" ], "tags": [ - "StackTemplates" + "Projects" ], - "summary": "Get Organization StackTemplates", + "summary": "Get project namespace", "parameters": [ { "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true }, { "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true }, { "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true }, { "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResponse" } } } @@ -6345,7 +6308,7 @@ "JWT": [] } ], - "description": "Remove organization stackTemplates", + "description": "Update project namespace", "consumes": [ "application/json" ], @@ -6353,33 +6316,64 @@ "application/json" ], "tags": [ - "StackTemplates" + "Projects" ], - "summary": "Remove organization stackTemplates", + "summary": "Update project namespace", "parameters": [ { - "description": "Remove organization stack templates request", - "name": "body", + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Request body to update project namespace", + "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + } } } }, - "post": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Add organization stackTemplates", + "description": "Delete project namespace", "consumes": [ "application/json" ], @@ -6387,35 +6381,57 @@ "application/json" ], "tags": [ - "StackTemplates" + "Projects" ], - "summary": "Add organization stackTemplates", + "summary": "Delete project namespace", "parameters": [ { - "description": "Add organization stack templates request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" - } + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonProjectResponse" + } } } } }, - "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplate", + "description": "Check project namespace exist", "consumes": [ "application/json" ], @@ -6423,27 +6439,57 @@ "application/json" ], "tags": [ - "StackTemplates" + "Projects" + ], + "summary": "Check project namespace exist", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + } ], - "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" } } } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/k8s-resources": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", + "description": "Get k8s resources for project namespace", "consumes": [ "application/json" ], @@ -6451,104 +6497,57 @@ "application/json" ], "tags": [ - "Stacks" + "Projects" ], - "summary": "Get Stacks", + "summary": "Get k8s resources for project namespace", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "pageSize", - "name": "limit", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "page", - "in": "query" + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true }, { "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true }, { "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" - } - } - } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create Stack", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Stacks" - ], - "summary": "Create Stack", - "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", + "description": "Project Namespace", + "name": "projectNamespace", "in": "path", "required": true - }, - { - "description": "create cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceK8sResourcesResponse" } } } } }, - "/organizations/{organizationId}/stacks/name/{name}/existence": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { "get": { "security": [ { "JWT": [] } ], - "description": "Check name for stack", + "description": "Get resources usage for project namespace", "consumes": [ "application/json" ], @@ -6556,89 +6555,89 @@ "application/json" ], "tags": [ - "Stacks" + "Projects" ], - "summary": "Check name for stack", + "summary": "Get resources usage for project namespace", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", "name": "stackId", "in": "path", "required": true }, { "type": "string", - "description": "name", - "name": "name", + "description": "Project Namespace", + "name": "projectNamespace", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse" + } } } } }, - "/organizations/{organizationId}/stacks/{stackId}": { + "/organizations/{organizationId}/roles": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stack", - "consumes": [ - "application/json" - ], + "description": "List Tks Roles", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Get Stack", + "summary": "List Tks Roles", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true - }, - { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse" } } } }, - "put": { + "post": { "security": [ { "JWT": [] } ], - "description": "Update Stack", + "description": "Create Tks Role", "consumes": [ "application/json" ], @@ -6646,88 +6645,84 @@ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Update Stack", + "summary": "Create Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { - "type": "string", - "description": "stackId", - "name": "stackId", - "in": "path", - "required": true - }, - { - "description": "Update cloud setting request", + "description": "Create Tks Role Request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateTksRoleResponse" + } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/roles/{roleId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete Stack", - "consumes": [ - "application/json" - ], + "description": "Get Tks Role", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Delete Stack", + "summary": "Get Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse" + } } } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/favorite": { - "post": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Set favorite stack", + "description": "Update Tks Role", "consumes": [ "application/json" ], @@ -6735,23 +6730,32 @@ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Set favorite stack", + "summary": "Update Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true + }, + { + "description": "Update Tks Role Request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest" + } } ], "responses": { @@ -6766,29 +6770,26 @@ "JWT": [] } ], - "description": "Delete favorite stack", - "consumes": [ - "application/json" - ], + "description": "Delete Tks Role", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Delete favorite stack", + "summary": "Delete Tks Role", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true } @@ -6800,36 +6801,33 @@ } } }, - "/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "/organizations/{organizationId}/roles/{roleId}/permissions": { "get": { "security": [ { "JWT": [] } ], - "description": "Get KubeConfig by stack", - "consumes": [ - "application/json" - ], + "description": "Get Permissions By Role ID", "produces": [ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Get KubeConfig by stack", + "summary": "Get Permissions By Role ID", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "organizationId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true } @@ -6838,20 +6836,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionsByRoleIdResponse" } } } - } - }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Get Stack Status", + "description": "Update Permissions By Role ID", "consumes": [ "application/json" ], @@ -6859,43 +6855,49 @@ "application/json" ], "tags": [ - "Stacks" + "Roles" ], - "summary": "Get Stack Status", + "summary": "Update Permissions By Role ID", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", - "name": "stackId", + "description": "Role ID", + "name": "roleId", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK", + }, + { + "description": "Update Permissions By Role ID Request", + "name": "body", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest" } } + ], + "responses": { + "200": { + "description": "OK" + } } } }, - "/organizations/{organizationId}/system-notification-rules": { + "/organizations/{organizationId}/stack-templates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotificationRules", + "description": "Get Organization StackTemplates", "consumes": [ "application/json" ], @@ -6903,17 +6905,10 @@ "application/json" ], "tags": [ - "SystemNotificationRules" + "StackTemplates" ], - "summary": "Get SystemNotificationRules", + "summary": "Get Organization StackTemplates", "parameters": [ - { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, { "type": "string", "description": "pageSize", @@ -6953,18 +6948,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" } } } }, - "post": { + "put": { "security": [ { "JWT": [] } ], - "description": "Create SystemNotificationRule", + "description": "Remove organization stackTemplates", "consumes": [ "application/json" ], @@ -6972,45 +6967,33 @@ "application/json" ], "tags": [ - "SystemNotificationRules" + "StackTemplates" ], - "summary": "Create SystemNotificationRule", + "summary": "Remove organization stackTemplates", "parameters": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "create stack template request", + "description": "Remove organization stack templates request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse" - } + "description": "OK" } } - } - }, - "/organizations/{organizationId}/system-notification-rules/name/{name}/existence": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Check name for systemNotificationRule", + "description": "Add organization stackTemplates", "consumes": [ "application/json" ], @@ -7018,43 +7001,63 @@ "application/json" ], "tags": [ - "SystemNotificationRules" + "StackTemplates" ], - "summary": "Check name for systemNotificationRule", + "summary": "Add organization stackTemplates", "parameters": [ { - "type": "string", - "description": "name", - "name": "name", - "in": "path", - "required": true - }, + "description": "Add organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "get": { + "security": [ { - "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "JWT": [] } ], + "description": "Get Organization StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" } } } } }, - "/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}": { + "/organizations/{organizationId}/stacks": { "get": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotificationRule", + "description": "Get Stacks", "consumes": [ "application/json" ], @@ -7062,9 +7065,9 @@ "application/json" ], "tags": [ - "SystemNotificationRules" + "Stacks" ], - "summary": "Get SystemNotificationRule", + "summary": "Get Stacks", "parameters": [ { "type": "string", @@ -7075,28 +7078,45 @@ }, { "type": "string", - "description": "systemNotificationRuleId", - "name": "systemNotificationRuleId", - "in": "path", - "required": true + "description": "pageSize", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStacksResponse" } } } }, - "put": { + "post": { "security": [ { "JWT": [] } ], - "description": "Update SystemNotificationRule", + "description": "Create Stack", "consumes": [ "application/json" ], @@ -7104,9 +7124,9 @@ "application/json" ], "tags": [ - "SystemNotificationRules" + "Stacks" ], - "summary": "Update SystemNotificationRule", + "summary": "Create Stack", "parameters": [ { "type": "string", @@ -7116,35 +7136,33 @@ "required": true }, { - "type": "string", - "description": "systemNotificationRuleId", - "name": "systemNotificationRuleId", - "in": "path", - "required": true - }, - { - "description": "Update systemNotificationRule request", + "description": "create cloud setting request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackRequest" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateStackResponse" + } } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/stacks/name/{name}/existence": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete SystemNotificationRule", + "description": "Check name for stack", "consumes": [ "application/json" ], @@ -7152,9 +7170,9 @@ "application/json" ], "tags": [ - "SystemNotificationRules" + "Stacks" ], - "summary": "Delete SystemNotificationRule", + "summary": "Check name for stack", "parameters": [ { "type": "string", @@ -7165,8 +7183,15 @@ }, { "type": "string", - "description": "systemNotificationRuleId", - "name": "systemNotificationRuleId", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name", + "name": "name", "in": "path", "required": true } @@ -7178,14 +7203,14 @@ } } }, - "/organizations/{organizationId}/system-notification-templates": { + "/organizations/{organizationId}/stacks/{stackId}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization SystemNotificationTemplates", + "description": "Get Stack", "consumes": [ "application/json" ], @@ -7193,50 +7218,30 @@ "application/json" ], "tags": [ - "SystemNotificationTemplates" + "Stacks" ], - "summary": "Get Organization SystemNotificationTemplates", + "summary": "Get Stack", "parameters": [ { "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true }, { "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackResponse" } } } @@ -7247,7 +7252,7 @@ "JWT": [] } ], - "description": "Remove organization systemNotificationTemplates", + "description": "Update Stack", "consumes": [ "application/json" ], @@ -7255,9 +7260,9 @@ "application/json" ], "tags": [ - "SystemNotificationTemplates" + "Stacks" ], - "summary": "Remove organization systemNotificationTemplates", + "summary": "Update Stack", "parameters": [ { "type": "string", @@ -7267,12 +7272,19 @@ "required": true }, { - "description": "Remove organization systemNotification templates request", + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest" } } ], @@ -7282,13 +7294,13 @@ } } }, - "post": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Add organization systemNotificationTemplates", + "description": "Delete Stack", "consumes": [ "application/json" ], @@ -7296,9 +7308,9 @@ "application/json" ], "tags": [ - "SystemNotificationTemplates" + "Stacks" ], - "summary": "Add organization systemNotificationTemplates", + "summary": "Delete Stack", "parameters": [ { "type": "string", @@ -7307,102 +7319,29 @@ "in": "path", "required": true }, - { - "description": "Add organization systemNotification templates request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/organizations/{organizationId}/system-notifications": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get SystemNotifications", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "SystemNotifications" - ], - "summary": "Get SystemNotifications", - "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", + "description": "stackId", + "name": "stackId", "in": "path", "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "soertColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" - } + "description": "OK" } } } }, - "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { - "get": { + "/organizations/{organizationId}/stacks/{stackId}/favorite": { + "post": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotification", + "description": "Set favorite stack", "consumes": [ "application/json" ], @@ -7410,9 +7349,9 @@ "application/json" ], "tags": [ - "SystemNotifications" + "Stacks" ], - "summary": "Get SystemNotification", + "summary": "Set favorite stack", "parameters": [ { "type": "string", @@ -7423,28 +7362,25 @@ }, { "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "stackId", + "name": "stackId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" - } + "description": "OK" } } }, - "put": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Update SystemNotification", + "description": "Delete favorite stack", "consumes": [ "application/json" ], @@ -7452,9 +7388,9 @@ "application/json" ], "tags": [ - "SystemNotifications" + "Stacks" ], - "summary": "Update SystemNotification", + "summary": "Delete favorite stack", "parameters": [ { "type": "string", @@ -7465,19 +7401,10 @@ }, { "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "stackId", + "name": "stackId", "in": "path", "required": true - }, - { - "description": "Update cloud setting request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" - } } ], "responses": { @@ -7485,14 +7412,16 @@ "description": "OK" } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/stacks/{stackId}/kube-config": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete SystemNotification", + "description": "Get KubeConfig by stack", "consumes": [ "application/json" ], @@ -7500,9 +7429,9 @@ "application/json" ], "tags": [ - "SystemNotifications" + "Stacks" ], - "summary": "Delete SystemNotification", + "summary": "Get KubeConfig by stack", "parameters": [ { "type": "string", @@ -7513,27 +7442,30 @@ }, { "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "organizationId", + "name": "stackId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse" + } } } } }, - "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { - "post": { + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create systemNotification action", + "description": "Get Stack Status", "consumes": [ "application/json" ], @@ -7541,9 +7473,9 @@ "application/json" ], "tags": [ - "SystemNotifications" + "Stacks" ], - "summary": "Create systemNotification action", + "summary": "Get Stack Status", "parameters": [ { "type": "string", @@ -7554,27 +7486,30 @@ }, { "type": "string", - "description": "systemNotificationId", - "name": "systemNotificationId", + "description": "stackId", + "name": "stackId", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + } } } } }, - "/organizations/{organizationId}/users": { + "/organizations/{organizationId}/system-notification-rules": { "get": { "security": [ { "JWT": [] } ], - "description": "Get user list", + "description": "Get SystemNotificationRules", "consumes": [ "application/json" ], @@ -7582,9 +7517,9 @@ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Get user list", + "summary": "Get SystemNotificationRules", "parameters": [ { "type": "string", @@ -7632,10 +7567,7 @@ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListUserBody" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRulesResponse" } } } @@ -7646,7 +7578,7 @@ "JWT": [] } ], - "description": "Create user", + "description": "Create SystemNotificationRule", "consumes": [ "application/json" ], @@ -7654,9 +7586,9 @@ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Create user", + "summary": "Create SystemNotificationRule", "parameters": [ { "type": "string", @@ -7666,52 +7598,55 @@ "required": true }, { - "description": "create user request", + "description": "create stack template request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest" } } ], "responses": { "200": { - "description": "create user response", + "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse" } } } } }, - "/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "/organizations/{organizationId}/system-notification-rules/name/{name}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "return true when accountId exists", + "description": "Check name for systemNotificationRule", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Get user id existence", + "summary": "Check name for systemNotificationRule", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", + "description": "name", + "name": "name", "in": "path", "required": true }, { "type": "string", - "description": "accountId", - "name": "accountId", + "description": "organizationId", + "name": "organizationId", "in": "path", "required": true } @@ -7720,27 +7655,30 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckSystemNotificationRuleNameResponse" } } } } }, - "/organizations/{organizationId}/users/email/{email}/existence": { + "/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}": { "get": { "security": [ { "JWT": [] } ], - "description": "return true when email exists", + "description": "Get SystemNotificationRule", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Get user email existence", + "summary": "Get SystemNotificationRule", "parameters": [ { "type": "string", @@ -7751,8 +7689,8 @@ }, { "type": "string", - "description": "email", - "name": "accountId", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", "in": "path", "required": true } @@ -7761,20 +7699,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationRuleResponse" } } } - } - }, - "/organizations/{organizationId}/users/{accountId}": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Get user detail", + "description": "Update SystemNotificationRule", "consumes": [ "application/json" ], @@ -7782,9 +7718,9 @@ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Get user detail", + "summary": "Update SystemNotificationRule", "parameters": [ { "type": "string", @@ -7795,28 +7731,34 @@ }, { "type": "string", - "description": "accountId", - "name": "accountId", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUserResponse" + }, + { + "description": "Update systemNotificationRule request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest" } } + ], + "responses": { + "200": { + "description": "OK" + } } }, - "put": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Update user", + "description": "Delete SystemNotificationRule", "consumes": [ "application/json" ], @@ -7824,9 +7766,9 @@ "application/json" ], "tags": [ - "Users" + "SystemNotificationRules" ], - "summary": "Update user", + "summary": "Delete SystemNotificationRule", "parameters": [ { "type": "string", @@ -7837,37 +7779,27 @@ }, { "type": "string", - "description": "accountId", - "name": "accountId", + "description": "systemNotificationRuleId", + "name": "systemNotificationRuleId", "in": "path", "required": true - }, - { - "description": "input", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest" - } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse" - } + "description": "OK" } } - }, - "delete": { + } + }, + "/organizations/{organizationId}/system-notification-templates": { + "get": { "security": [ { "JWT": [] } ], - "description": "Delete user", + "description": "Get Organization SystemNotificationTemplates", "consumes": [ "application/json" ], @@ -7875,81 +7807,102 @@ "application/json" ], "tags": [ - "Users" + "SystemNotificationTemplates" ], - "summary": "Delete user", + "summary": "Get Organization SystemNotificationTemplates", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "description": "pageSize", + "name": "pageSize", + "in": "query" }, { "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplatesResponse" + } } } - } - }, - "/organizations/{organizationId}/users/{accountId}/permissions": { - "get": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Get Permissions By Account ID", + "description": "Remove organization systemNotificationTemplates", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "Users" + "SystemNotificationTemplates" ], - "summary": "Get Permissions By Account ID", + "summary": "Remove organization systemNotificationTemplates", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true }, { - "type": "string", - "description": "Account ID", - "name": "accountId", - "in": "path", - "required": true + "description": "Remove organization systemNotification templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationSystemNotificationTemplatesRequest" + } } ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse" - } + "description": "OK" } } - } - }, - "/organizations/{organizationId}/users/{accountId}/reset-password": { - "put": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Reset user's password as temporary password by admin and send email to user", + "description": "Add organization systemNotificationTemplates", "consumes": [ "application/json" ], @@ -7957,9 +7910,9 @@ "application/json" ], "tags": [ - "Users" + "SystemNotificationTemplates" ], - "summary": "Reset user's password as temporary password by admin", + "summary": "Add organization systemNotificationTemplates", "parameters": [ { "type": "string", @@ -7969,11 +7922,13 @@ "required": true }, { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true + "description": "Add organization systemNotification templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationSystemNotificationTemplatesRequest" + } } ], "responses": { @@ -7983,14 +7938,14 @@ } } }, - "/permissions/templates": { + "/organizations/{organizationId}/system-notifications": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Permission Templates", + "description": "Get SystemNotifications", "consumes": [ "application/json" ], @@ -7998,27 +7953,70 @@ "application/json" ], "tags": [ - "Permission" + "SystemNotifications" + ], + "summary": "Get SystemNotifications", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } ], - "summary": "Get Permission Templates", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationsResponse" } } } } }, - "/policy-templates/rego-compile": { - "post": { + "/organizations/{organizationId}/system-notifications/{systemNotificationId}": { + "get": { "security": [ { "JWT": [] } ], - "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", + "description": "Get SystemNotification", "consumes": [ "application/json" ], @@ -8026,45 +8024,41 @@ "application/json" ], "tags": [ - "PolicyTemplate" + "SystemNotifications" ], - "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", + "summary": "Get SystemNotification", "parameters": [ { - "type": "boolean", - "description": "파라미터 파싱 여부", - "name": "parseParameter", - "in": "query", + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", "required": true }, { - "description": "Rego 코드", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" - } + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationResponse" } } } - } - }, - "/system-api/organizations/{organizationId}/system-notifications": { - "post": { + }, + "put": { "security": [ { "JWT": [] } ], - "description": "Create systemNotification. ADMIN ONLY", + "description": "Update SystemNotification", "consumes": [ "application/json" ], @@ -8074,7 +8068,7 @@ "tags": [ "SystemNotifications" ], - "summary": "Create systemNotification. ADMIN ONLY", + "summary": "Update SystemNotification", "parameters": [ { "type": "string", @@ -8082,16 +8076,636 @@ "name": "organizationId", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - } - }, + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + }, + { + "description": "Update cloud setting request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete SystemNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Delete SystemNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create systemNotification action", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Create systemNotification action", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "systemNotificationId", + "name": "systemNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/users": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user list", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user list", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListUserBody" + } + } + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "create user request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "create user response", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/account-id/{accountId}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "return true when accountId exists", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user id existence", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/email/{email}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "return true when email exists", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user email existence", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "email", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get user detail", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user detail", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUserResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete user", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}/permissions": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permissions By Account ID", + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get Permissions By Account ID", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Account ID", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/users/{accountId}/reset-password": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Reset user's password as temporary password by admin and send email to user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Reset user's password as temporary password by admin", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/permissions/templates": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Permission Templates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Permission" + ], + "summary": "Get Permission Templates", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPermissionTemplatesResponse" + } + } + } + } + }, + "/policy-templates/rego-compile": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Rego 코드 컴파일 및 파라미터 파싱을 수행한다. 파라미터 파싱을 위해서는 먼저 컴파일이 성공해야 하며, parseParameter를 false로 하면 컴파일만 수행할 수 있다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[CompileRego] Rego 코드 컴파일 및 파라미터 파싱", + "parameters": [ + { + "type": "boolean", + "description": "파라미터 파싱 여부", + "name": "parseParameter", + "in": "query", + "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompileResponse" + } + } + } + } + }, + "/system-api/organizations/{organizationId}/system-notifications": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create systemNotification. ADMIN ONLY", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotifications" + ], + "summary": "Create systemNotification. ADMIN ONLY", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, "definitions": { "github_com_openinfradev_tks-api_internal_model.AppServeApp": { "type": "object", @@ -9369,10 +9983,6 @@ "templateId": { "type": "string", "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" - }, - "templateName": { - "type": "string", - "example": "필수 Label 검사" } } }, @@ -10022,6 +10632,22 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -11216,20 +11842,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization": { - "type": "object", - "properties": { - "organizationId": { - "type": "string" - }, - "organizationName": { - "type": "string" - }, - "permitted": { - "type": "boolean" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.PodCount": { "type": "object", "properties": { @@ -11348,12 +11960,6 @@ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" } }, - "permittedOrganizations": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization" - } - }, "rego": { "type": "string", "example": "rego 코드" @@ -12751,385 +13357,670 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionsByRoleIdRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest": { + "type": "object", + "properties": { + "currentTargetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "newTargetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "enforcementAction": { + "type": "string" + }, + "mandatory": { + "type": "boolean" + }, + "match": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "refer": "match.Match" + } + }, + "parameters": { + "type": "string", + "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + }, + "policyName": { + "type": "string", + "example": "label 정책" + }, + "targetClusterIds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "83bf8081-f0c5-4b31-826d-23f6f366ec90", + "83bf8081-f0c5-4b31-826d-23f6f366ec90" + ] + }, + "templateId": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { + "type": "object", + "properties": { + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string" + }, + "permittedOrganizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { + "type": "object", + "properties": { + "primaryClusterId": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest": { + "type": "object", + "properties": { + "projectRoleId": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest": { + "type": "object", + "properties": { + "projectMembers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "projectMemberId": { + "type": "string" + }, + "projectRoleId": { + "type": "string" + } + } + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "projectLeaderId": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest": { "type": "object", + "required": [ + "organizationIds" + ], "properties": { - "permissions": { + "organizationIds": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePermissionUpdateRequest" + "type": "string" } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyClustersRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { "type": "object", + "required": [ + "serviceIds" + ], "properties": { - "currentTargetClusterIds": { - "type": "array", - "items": { - "type": "string" - }, - "example": [ - "83bf8081-f0c5-4b31-826d-23f6f366ec90" - ] + "cloudService": { + "type": "string" }, - "newTargetClusterIds": { + "description": { + "type": "string" + }, + "kubeType": { + "type": "string" + }, + "kubeVersion": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "serviceIds": { "type": "array", "items": { "type": "string" - }, - "example": [ - "83bf8081-f0c5-4b31-826d-23f6f366ec90", - "83bf8081-f0c5-4b31-826d-23f6f366ec90" - ] + } + }, + "template": { + "type": "string" + }, + "templateType": { + "type": "string" + }, + "version": { + "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", + "required": [ + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" + ], "properties": { "description": { "type": "string" }, - "enforcementAction": { + "messageActionProposal": { "type": "string" }, - "mandatory": { - "type": "boolean" + "messageCondition": { + "type": "string" }, - "match": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "refer": "match.Match" - } + "messageContent": { + "type": "string" }, - "parameters": { - "type": "string", - "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + "messageTitle": { + "type": "string" }, - "policyName": { - "type": "string", - "example": "label 정책" + "name": { + "type": "string" }, - "targetClusterIds": { + "systemNotificationConditions": { "type": "array", "items": { - "type": "string" - }, - "example": [ - "83bf8081-f0c5-4b31-826d-23f6f366ec90", - "83bf8081-f0c5-4b31-826d-23f6f366ec90" - ] + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } }, - "templateId": { - "type": "string", - "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest": { "type": "object", + "required": [ + "metricQuery", + "name", + "organizationIds" + ], "properties": { - "deprecated": { - "type": "boolean", - "example": false - }, "description": { "type": "string" }, - "permittedOrganizationIds": { + "metricParameters": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" } }, - "severity": { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ], - "example": "medium" + "metricQuery": { + "type": "string" }, - "templateName": { - "type": "string", - "example": "필수 Label 검사" + "name": { + "type": "string" + }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { "type": "object", "properties": { - "primaryClusterId": { - "type": "string" + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMemberRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest": { "type": "object", "properties": { - "projectRoleId": { + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { "type": "string" + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "role": { + "type": "string", + "enum": [ + "admin", + "user" + ] } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectMembersRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse": { "type": "object", "properties": { - "projectMembers": { - "type": "array", - "items": { - "type": "object", - "properties": { - "projectMemberId": { - "type": "string" - }, - "projectRoleId": { - "type": "string" - } + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + }, + "role": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + }, + "updatedAt": { + "type": "string" } } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectNamespaceRequest": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateProjectRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ - "name" + "email", + "organizationId", + "userName" ], "properties": { - "description": { + "email": { "type": "string" }, - "name": { + "organizationId": { "type": "string" }, - "projectLeaderId": { + "userName": { "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse": { "type": "object", "properties": { - "description": { + "validityPeriod": { "type": "string" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateOrganizationsRequest": { - "type": "object", - "required": [ - "organizationIds" - ], - "properties": { - "organizationIds": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest": { "type": "object", "required": [ - "serviceIds" + "accountId", + "email", + "organizationId", + "userName" ], "properties": { - "cloudService": { + "accountId": { "type": "string" }, - "description": { + "email": { "type": "string" }, - "kubeType": { + "organizationId": { "type": "string" }, - "kubeVersion": { + "userName": { "type": "string" - }, - "platform": { + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse": { + "type": "object", + "properties": { + "validityPeriod": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.WidgetResponse": { + "type": "object", + "properties": { + "key": { "type": "string" }, - "serviceIds": { - "type": "array", - "items": { - "type": "string" - } + "sizeX": { + "type": "integer" }, - "template": { - "type": "string" + "sizeY": { + "type": "integer" }, - "templateType": { - "type": "string" + "startX": { + "type": "integer" }, - "version": { - "type": "string" + "startY": { + "type": "integer" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse": { "type": "object", "properties": { - "description": { - "type": "string" + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateRequest": { "type": "object", "required": [ - "messageCondition", - "messageContent", - "messageTitle", - "name", - "systemNotificationTemplateId" + "kind", + "rego" ], "properties": { - "description": { - "type": "string" - }, - "messageActionProposal": { - "type": "string" - }, - "messageCondition": { - "type": "string" + "deprecated": { + "type": "boolean", + "example": false }, - "messageContent": { - "type": "string" + "description": { + "type": "string", + "example": "이 정책은 ..." }, - "messageTitle": { - "type": "string" + "kind": { + "type": "string", + "example": "K8sRequiredLabels" }, - "name": { - "type": "string" + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] }, - "systemNotificationConditions": { + "parametersSchema": { "type": "array", "items": { - "type": "object", - "properties": { - "duration": { - "type": "integer" - }, - "enableEmail": { - "type": "boolean" - }, - "enablePortal": { - "type": "boolean" - }, - "order": { - "type": "integer" - }, - "parameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" - } - }, - "severity": { - "type": "string" - } - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" } }, - "systemNotificationTemplateId": { - "type": "string" - }, - "targetUserIds": { + "permittedOrganizationIds": { "type": "array", "items": { "type": "string" } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest": { "type": "object", "required": [ - "metricQuery", - "name", - "organizationIds" + "currentVersion", + "expectedVersion", + "rego", + "versionUpType" ], "properties": { - "description": { - "type": "string" + "currentVersion": { + "type": "string", + "example": "v1.0.0" }, - "metricParameters": { + "expectedVersion": { + "type": "string", + "example": "v1.1.0" + }, + "libs": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse" - } - }, - "metricQuery": { - "type": "string" - }, - "name": { - "type": "string" + "type": "string" + }, + "example": [ + "rego 코드" + ] }, - "organizationIds": { + "parametersSchema": { "type": "array", "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "versionUpType": { + "type": "string", + "enum": [ + "major", + "minor", + "patch" + ], + "example": "minor" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionResponse": { + "type": "object", + "properties": { + "version": { + "type": "string", + "example": "v1.1.1" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateNameResponse": { + "type": "object", + "properties": { + "existed": { + "type": "boolean" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse": { + "type": "object", + "properties": { + "deployVersion": { + "type": "object", + "additionalProperties": { "type": "string" } } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateTksRoleRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateResponse": { "type": "object", "properties": { - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 + "policyTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateVersionResponse": { "type": "object", "properties": { - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 - }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] + "policyTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse" } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { "type": "object", "properties": { "user": { @@ -13141,6 +14032,9 @@ "createdAt": { "type": "string" }, + "creator": { + "type": "string" + }, "department": { "type": "string" }, @@ -13169,124 +14063,186 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse": { "type": "object", - "required": [ - "email", - "organizationId", - "userName" - ], "properties": { - "email": { - "type": "string" - }, - "organizationId": { - "type": "string" + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" }, - "userName": { - "type": "string" + "policyTemplates": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse" + } } } }, - "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateStatisticsResponse": { "type": "object", "properties": { - "validityPeriod": { - "type": "string" + "policyTemplateStatistics": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateStatistics" + } } } }, - "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordRequest": { + "github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateVersionsResponse": { + "type": "object", + "properties": { + "versions": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "v1.1.0", + "v1.0.1", + "v1.0.0" + ] + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization": { "type": "object", - "required": [ - "accountId", - "email", - "organizationId", - "userName" - ], "properties": { - "accountId": { - "type": "string" - }, - "email": { - "type": "string" - }, "organizationId": { "type": "string" }, - "userName": { + "organizationName": { "type": "string" + }, + "permitted": { + "type": "boolean" } } }, - "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostPasswordResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse": { "type": "object", "properties": { - "validityPeriod": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "kind": { + "type": "string", + "example": "K8sRequiredLabels" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "permittedOrganizations": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "type": { + "type": "string", + "enum": [ + "tks", + "organization" + ], + "example": "tks" + }, + "updatedAt": { "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "version": { + "type": "string", + "example": "v1.0.1" } } }, - "github_com_openinfradev_tks-api_pkg_domain.WidgetResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateStatistics": { "type": "object", "properties": { - "key": { + "organizationId": { "type": "string" }, - "sizeX": { - "type": "integer" - }, - "sizeY": { - "type": "integer" - }, - "startX": { - "type": "integer" + "organizationName": { + "type": "string" }, - "startY": { + "usageCount": { "type": "integer" } } }, - "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { + "github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest": { "type": "object", "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "updatedAt": { - "type": "string" - } + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string" + }, + "permittedOrganizationIds": { + "type": "array", + "items": { + "type": "string" } + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 55a0706b..ab4e5738 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -881,9 +881,6 @@ definitions: templateId: example: d98ef5f1-4a68-4047-a446-2207787ce3ff type: string - templateName: - example: 필수 Label 검사 - type: string type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse: properties: @@ -1325,6 +1322,16 @@ definitions: name: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse: + properties: + existed: + type: boolean + type: object + github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateNameResponse: + properties: + existed: + type: boolean + type: object github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: column: @@ -2101,15 +2108,6 @@ definitions: name: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization: - properties: - organizationId: - type: string - organizationName: - type: string - permitted: - type: boolean - type: object github_com_openinfradev_tks-api_pkg_domain.PodCount: properties: day: @@ -2192,10 +2190,6 @@ definitions: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' type: array - permittedOrganizations: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermittedOrganization' - type: array rego: example: rego 코드 type: string @@ -3457,6 +3451,121 @@ definitions: startY: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse: + properties: + id: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateRequest: + properties: + deprecated: + example: false + type: boolean + description: + example: 이 정책은 ... + type: string + kind: + example: K8sRequiredLabels + type: string + libs: + example: + - rego 코드 + items: + type: string + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + permittedOrganizationIds: + items: + type: string + type: array + rego: + example: rego 코드 + type: string + severity: + enum: + - low + - medium + - high + example: medium + type: string + templateName: + example: 필수 Label 검사 + type: string + required: + - kind + - rego + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest: + properties: + currentVersion: + example: v1.0.0 + type: string + expectedVersion: + example: v1.1.0 + type: string + libs: + example: + - rego 코드 + items: + type: string + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + rego: + example: rego 코드 + type: string + versionUpType: + enum: + - major + - minor + - patch + example: minor + type: string + required: + - currentVersion + - expectedVersion + - rego + - versionUpType + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionResponse: + properties: + version: + example: v1.1.1 + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse: + properties: + existed: + type: boolean + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateNameResponse: + properties: + existed: + type: boolean + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse: + properties: + deployVersion: + additionalProperties: + type: string + type: object + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateResponse: + properties: + policyTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse' + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateVersionResponse: + properties: + policyTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse' + type: object github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse: properties: user: @@ -3485,6 +3594,132 @@ definitions: type: string type: object type: object + github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + policyTemplates: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateStatisticsResponse: + properties: + policyTemplateStatistics: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateStatistics' + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateVersionsResponse: + properties: + versions: + example: + - v1.1.0 + - v1.0.1 + - v1.0.0 + items: + type: string + type: array + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization: + properties: + organizationId: + type: string + organizationName: + type: string + permitted: + type: boolean + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse: + properties: + createdAt: + type: string + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + deprecated: + example: false + type: boolean + description: + example: 이 정책은 ... + type: string + id: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + kind: + example: K8sRequiredLabels + type: string + libs: + example: + - rego 코드 + items: + type: string + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + permittedOrganizations: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization' + type: array + rego: + example: rego 코드 + type: string + severity: + enum: + - low + - medium + - high + example: medium + type: string + templateName: + example: 필수 Label 검사 + type: string + type: + enum: + - tks + - organization + example: tks + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + version: + example: v1.0.1 + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateStatistics: + properties: + organizationId: + type: string + organizationName: + type: string + usageCount: + type: integer + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest: + properties: + deprecated: + example: false + type: boolean + description: + type: string + permittedOrganizationIds: + items: + type: string + type: array + severity: + enum: + - low + - medium + - high + example: medium + type: string + templateName: + example: 필수 Label 검사 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest: properties: adminPassword: @@ -3811,7 +4046,7 @@ paths: type: string - description: sortColumn in: query - name: soertColumn + name: sortColumn type: string - description: sortOrder in: query @@ -3830,10 +4065,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse' security: - JWT: [] - summary: '[ListPolicyTemplate] 정책 템플릿 목록 조회' + summary: '[Admin_ListPolicyTemplate] 정책 템플릿 목록 조회' tags: - PolicyTemplate post: @@ -3846,17 +4081,17 @@ paths: name: body required: true schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse' security: - JWT: [] - summary: '[CreatePolicyTemplate] 정책 템플릿 신규 생성' + summary: '[Admin_CreatePolicyTemplate] 정책 템플릿 신규 생성' tags: - PolicyTemplate /admin/policy-templates/{policyTemplateId}: @@ -3877,7 +4112,7 @@ paths: description: OK security: - JWT: [] - summary: '[DeletePolicyTemplate] 정책 템플릿 삭제' + summary: '[Admin_DeletePolicyTemplate] 정책 템플릿 삭제' tags: - PolicyTemplate get: @@ -3896,10 +4131,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateResponse' security: - JWT: [] - summary: '[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)' + summary: '[Admin_GetPolicyTemplate] 정책 템플릿 조회(최신 버전)' tags: - PolicyTemplate patch: @@ -3917,7 +4152,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest' produces: - application/json responses: @@ -3925,7 +4160,7 @@ paths: description: OK security: - JWT: [] - summary: '[UpdatePolicyTemplate] 정책 템플릿 업데이트' + summary: '[Admin_UpdatePolicyTemplate] 정책 템플릿 업데이트' tags: - PolicyTemplate /admin/policy-templates/{policyTemplateId}/deploy: @@ -3945,10 +4180,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse' security: - JWT: [] - summary: '[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회' + summary: '[Admin_GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회' tags: - PolicyTemplate /admin/policy-templates/{policyTemplateId}/statistics: @@ -3969,10 +4204,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateStatisticsResponse' security: - JWT: [] - summary: '[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회' + summary: '[Admin_ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회' tags: - PolicyTemplate /admin/policy-templates/{policyTemplateId}/versions: @@ -3992,10 +4227,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateVersionsResponse' security: - JWT: [] - summary: '[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회' + summary: '[Admin_ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회' tags: - PolicyTemplate post: @@ -4013,17 +4248,17 @@ paths: name: body required: true schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionResponse' security: - JWT: [] - summary: '[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장' + summary: '[Admin_CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장' tags: - PolicyTemplate /admin/policy-templates/{policyTemplateId}/versions/{version}: @@ -4049,7 +4284,7 @@ paths: description: OK security: - JWT: [] - summary: '[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제' + summary: '[Admin_DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제' tags: - PolicyTemplate get: @@ -4073,10 +4308,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateVersionResponse' security: - JWT: [] - summary: '[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' + summary: '[Admin_GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' tags: - PolicyTemplate /admin/policy-templates/kind/{policyTemplateKind}/existence: @@ -4096,10 +4331,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse' security: - JWT: [] - summary: '[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인' + summary: '[Admin_ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인' tags: - PolicyTemplate /admin/policy-templates/name/{policyTemplateName}/existence: @@ -4119,10 +4354,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateNameResponse' security: - JWT: [] - summary: '[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인' + summary: '[Admin_ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인' tags: - PolicyTemplate /admin/stack-templates: @@ -5812,7 +6047,7 @@ paths: type: string - description: sortColumn in: query - name: soertColumn + name: sortColumn type: string - description: sortOrder in: query @@ -6011,6 +6246,401 @@ paths: summary: '[ExistsPolicyName] 정책 아름 존재 여부 확인' tags: - Policy + /organizations/{organizationId}/policy-templates: + get: + consumes: + - application/json + description: 정책 템플릿 목록을 조회한다. 정책 템플릿 목록 조회 결과는 최신 템플릿 버전 목록만 조회된다. + parameters: + - description: pageSize + in: query + name: limit + type: string + - description: pageNumber + in: query + name: page + type: string + - description: sortColumn + in: query + name: sortColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateResponse' + security: + - JWT: [] + summary: '[ListPolicyTemplate] 정책 템플릿 목록 조회' + tags: + - PolicyTemplate + post: + consumes: + - application/json + description: 정책 템플릿을 신규 생성(v1.0.0을 생성)한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: create policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateReponse' + security: + - JWT: [] + summary: '[CreatePolicyTemplate] 정책 템플릿 신규 생성' + tags: + - PolicyTemplate + /organizations/{organizationId}/policy-templates/{policyTemplateId}: + delete: + consumes: + - application/json + description: 정책 템플릿을 삭제한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[DeletePolicyTemplate] 정책 템플릿 삭제' + tags: + - PolicyTemplate + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse' + security: + - JWT: [] + summary: '[GetPolicyTemplate] 정책 템플릿 조회(최신 버전)' + tags: + - PolicyTemplate + patch: + consumes: + - application/json + description: 정책 템플릿의 업데이트 가능한 필드들을 업데이트한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: update policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[UpdatePolicyTemplate] 정책 템플릿 업데이트' + tags: + - PolicyTemplate + /organizations/{organizationId}/policy-templates/{policyTemplateId}/deploy: + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 정책 템플릿 클러스터 별 설치 버전을 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateDeployResponse' + security: + - JWT: [] + summary: '[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회' + tags: + - PolicyTemplate + /organizations/{organizationId}/policy-templates/{policyTemplateId}/statistics: + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. 전체 조직의 통계를 조회하려면 organizationId를 + tks로 설정한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse' + security: + - JWT: [] + summary: '[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회' + tags: + - PolicyTemplate + /organizations/{organizationId}/policy-templates/{policyTemplateId}/versions: + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 최신 버전을 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateVersionsResponse' + security: + - JWT: [] + summary: '[ListPolicyTemplateVersions] 정책 템플릿 버전목록 조회' + tags: + - PolicyTemplate + post: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 특정 버전을 저장한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: create policy template version request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionResponse' + security: + - JWT: [] + summary: '[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장' + tags: + - PolicyTemplate + /organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}: + delete: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 특정 버전을 삭제한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: 삭제할 버전(v0.0.0 형식) + in: path + name: version + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[DeletePolicyTemplateVersion] 정책 템플릿 특정 버전 삭제' + tags: + - PolicyTemplate + get: + consumes: + - application/json + description: 해당 식별자를 가진 정책 템플릿의 특정 버전을 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: 조회할 버전(v0.0.0 형식) + in: path + name: version + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse' + security: + - JWT: [] + summary: '[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' + tags: + - PolicyTemplate + /organizations/{organizationId}/policy-templates/kind/{policyTemplateKind}/existence: + get: + consumes: + - application/json + description: 해당 유형을 가진 정책 템플릿이 이미 존재하는지 확인한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 이름 + in: path + name: policyTemplateKind + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateKindResponse' + security: + - JWT: [] + summary: '[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인' + tags: + - PolicyTemplate + /organizations/{organizationId}/policy-templates/name/{policyTemplateName}/existence: + get: + consumes: + - application/json + description: 해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 이름 + in: path + name: policyTemplateName + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateNameResponse' + security: + - JWT: [] + summary: '[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인' + tags: + - PolicyTemplate /organizations/{organizationId}/primary-cluster: patch: consumes: diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index 0bc64a60..d65aa67d 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -104,6 +104,14 @@ func (h *SystemNotificationTemplateHandler) GetSystemNotificationTemplates(w htt log.Info(r.Context(), err) } } + + out.SystemNotificationTemplates[i].MetricParameters = make([]domain.SystemNotificationMetricParameterResponse, len(systemNotificationTemplate.MetricParameters)) + for j, metricParameters := range systemNotificationTemplate.MetricParameters { + if err := serializer.Map(r.Context(), metricParameters, &out.SystemNotificationTemplates[i].MetricParameters[j]); err != nil { + log.Info(r.Context(), err) + } + } + } if out.Pagination, err = pg.Response(r.Context()); err != nil { From 5e9b2ef66c55da691641a38f9b607c8c90d9e8bc Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 28 Mar 2024 16:35:28 +0900 Subject: [PATCH 197/502] trivial. remove unused paramter. --- api/swagger/docs.go | 11 ----------- api/swagger/swagger.json | 11 ----------- api/swagger/swagger.yaml | 8 -------- internal/model/system-notification-rule.go | 1 - internal/repository/system-notification-rule.go | 1 - pkg/domain/system-notification-rule.go | 3 --- 6 files changed, 35 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 35264f49..56fa0c75 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -10307,7 +10307,6 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { "type": "object", "required": [ - "messageCondition", "messageContent", "messageTitle", "name", @@ -10320,9 +10319,6 @@ const docTemplate = `{ "messageActionProposal": { "type": "string" }, - "messageCondition": { - "type": "string" - }, "messageContent": { "type": "string" }, @@ -13026,9 +13022,6 @@ const docTemplate = `{ "messageActionProposal": { "type": "string" }, - "messageCondition": { - "type": "string" - }, "messageContent": { "type": "string" }, @@ -13605,7 +13598,6 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", "required": [ - "messageCondition", "messageContent", "messageTitle", "name", @@ -13618,9 +13610,6 @@ const docTemplate = `{ "messageActionProposal": { "type": "string" }, - "messageCondition": { - "type": "string" - }, "messageContent": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 8a8f1e1e..8a58e363 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -10301,7 +10301,6 @@ "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { "type": "object", "required": [ - "messageCondition", "messageContent", "messageTitle", "name", @@ -10314,9 +10313,6 @@ "messageActionProposal": { "type": "string" }, - "messageCondition": { - "type": "string" - }, "messageContent": { "type": "string" }, @@ -13020,9 +13016,6 @@ "messageActionProposal": { "type": "string" }, - "messageCondition": { - "type": "string" - }, "messageContent": { "type": "string" }, @@ -13599,7 +13592,6 @@ "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", "required": [ - "messageCondition", "messageContent", "messageTitle", "name", @@ -13612,9 +13604,6 @@ "messageActionProposal": { "type": "string" }, - "messageCondition": { - "type": "string" - }, "messageContent": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ab4e5738..23bff86e 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1103,8 +1103,6 @@ definitions: type: string messageActionProposal: type: string - messageCondition: - type: string messageContent: type: string messageTitle: @@ -1137,7 +1135,6 @@ definitions: type: string type: array required: - - messageCondition - messageContent - messageTitle - name @@ -2895,8 +2892,6 @@ definitions: type: string messageActionProposal: type: string - messageCondition: - type: string messageContent: type: string messageTitle: @@ -3283,8 +3278,6 @@ definitions: type: string messageActionProposal: type: string - messageCondition: - type: string messageContent: type: string messageTitle: @@ -3317,7 +3310,6 @@ definitions: type: string type: array required: - - messageCondition - messageContent - messageTitle - name diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index e1fc06eb..76a277ff 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -35,7 +35,6 @@ type SystemNotificationRule struct { TargetUserIds []string `gorm:"-:all"` MessageTitle string MessageContent string - MessageCondition datatypes.JSON MessageActionProposal string CreatorId *uuid.UUID `gorm:"type:uuid"` Creator *User `gorm:"foreignKey:CreatorId"` diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 84ed1063..44266e0d 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -99,7 +99,6 @@ func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model //m.SystemNotificationConditions = dto.SystemNotificationConditions m.MessageTitle = dto.MessageTitle m.MessageContent = dto.MessageContent - m.MessageCondition = dto.MessageCondition m.MessageActionProposal = dto.MessageActionProposal m.UpdatorId = dto.UpdatorId diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index d891799a..a9c8abc4 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -10,7 +10,6 @@ type SystemNotificationRuleResponse struct { Description string `json:"description"` MessageTitle string `json:"messageTitle"` MessageContent string `json:"messageContent"` - MessageCondition string `json:"messageCondition"` MessageActionProposal string `json:"messageActionProposal"` TargetUsers []SimpleUserResponse `json:"targetUsers"` SystemNotificationTemplate SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplate"` @@ -56,7 +55,6 @@ type CreateSystemNotificationRuleRequest struct { Description string `json:"description"` MessageTitle string `json:"messageTitle" validate:"required"` MessageContent string `json:"messageContent" validate:"required"` - MessageCondition string `json:"messageCondition" validate:"required"` MessageActionProposal string `json:"messageActionProposal"` TargetUserIds []string `json:"targetUserIds"` SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` @@ -79,7 +77,6 @@ type UpdateSystemNotificationRuleRequest struct { Description string `json:"description"` MessageTitle string `json:"messageTitle" validate:"required"` MessageContent string `json:"messageContent" validate:"required"` - MessageCondition string `json:"messageCondition" validate:"required"` MessageActionProposal string `json:"messageActionProposal"` TargetUserIds []string `json:"targetUserIds"` SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` From 62490293e05f66022e496ec7c6e64039d508650c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 1 Apr 2024 14:58:02 +0900 Subject: [PATCH 198/502] trivial. add attribute metricParameters to system-notification-templates --- internal/delivery/http/system-notification-rule.go | 1 - internal/delivery/http/system-notification-template.go | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 8e6706b2..5152381d 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -130,7 +130,6 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.Respon if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRules[i].SystemNotificationConditions[j]); err != nil { log.Info(r.Context(), err) } - log.Info(r.Context(), condition.Parameter) err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRules[i].SystemNotificationConditions[j].Parameters) if err != nil { log.Error(r.Context(), err) diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index d65aa67d..3663a605 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -306,6 +306,13 @@ func (h *SystemNotificationTemplateHandler) GetOrganizationSystemNotificationTem log.Info(r.Context(), err) } } + + out.SystemNotificationTemplates[i].MetricParameters = make([]domain.SystemNotificationMetricParameterResponse, len(systemNotificationTemplate.MetricParameters)) + for k, metricParameters := range systemNotificationTemplate.MetricParameters { + if err := serializer.Map(r.Context(), metricParameters, &out.SystemNotificationTemplates[i].MetricParameters[k]); err != nil { + log.Info(r.Context(), err) + } + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { From b47f010adea84ad2e3e135d93ec802928478e586 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 1 Apr 2024 15:05:03 +0900 Subject: [PATCH 199/502] minor fix. remove unused contents --- internal/delivery/http/auth.go | 15 --------------- pkg/domain/auth.go | 25 +++++++------------------ 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index eec9d560..14f35296 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -97,26 +97,11 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { } } - projects, err := h.projectUsecase.GetProjects(r.Context(), input.OrganizationId, user.ID.String(), true, nil) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } - var out domain.LoginResponse if err = serializer.Map(r.Context(), user, &out.User); err != nil { log.Error(r.Context(), err) } - for _, project := range projects { - var projectRole domain.ProjectIdProjectRoleResponse - projectRole.ID = project.ID - projectRole.ProjectRoleId = project.ProjectRoleId - projectRole.ProjectRoleName = project.ProjectRoleName - out.User.Projects = append(out.User.Projects, &projectRole) - } - ResponseJSON(w, r, http.StatusOK, out) } diff --git a/pkg/domain/auth.go b/pkg/domain/auth.go index 8d8983e3..ece8bcd0 100644 --- a/pkg/domain/auth.go +++ b/pkg/domain/auth.go @@ -8,14 +8,13 @@ type LoginRequest struct { type LoginResponse struct { User struct { - AccountId string `json:"accountId"` - Name string `json:"name"` - Token string `json:"token"` - Role RoleIdRoleNameResponse `json:"role"` - Projects []*ProjectIdProjectRoleResponse `json:"projects"` - Department string `json:"department"` - Organization OrganizationResponse `json:"organization"` - PasswordExpired bool `json:"passwordExpired"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Token string `json:"token"` + Role RoleIdRoleNameResponse `json:"role"` + Department string `json:"department"` + Organization OrganizationResponse `json:"organization"` + PasswordExpired bool `json:"passwordExpired"` } `json:"user"` } @@ -24,16 +23,6 @@ type RoleIdRoleNameResponse struct { Name string `json:"roleName"` } -type ProjectIdProjectRoleResponse struct { - ID string `json:"projectId"` - ProjectRoleId string `json:"projectRoleId"` - ProjectRoleName string `json:"projectRoleName"` -} - -type LogoutResponse struct { - SsoUrls map[string][]string `json:"ssoUrls"` -} - type VerifyIdentityForLostIdRequest struct { OrganizationId string `json:"organizationId" validate:"required"` Email string `json:"email" validate:"required,email"` From aa90681559bf5e2b9dbd7b2829737c7b62d398b1 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 1 Apr 2024 16:33:41 +0900 Subject: [PATCH 200/502] fix query project --- internal/delivery/http/project.go | 23 ++++++++++++++++++++--- internal/repository/project.go | 9 --------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index c5405eed..ee9dc2e8 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -289,6 +289,26 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { return } + var projectRoleId, projectRoleName string + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + ErrorJSON(w, r, fmt.Errorf("failed to retrieve user info from request")) + } + userProjectRole := requestUserInfo.GetRoleProjectMapping() + if userProjectRole != nil { + projectRoleName = userProjectRole[project.ID] + } + projectRoles, err := p.usecase.GetProjectRoles(r.Context(), usecase.ProjectAll) + if err != nil { + ErrorJSON(w, r, fmt.Errorf("failed to retrieve project role")) + } + for _, projectRole := range projectRoles { + if projectRoleName == projectRole.Name { + projectRoleId = projectRole.ID + break + } + } + //appCount, err := p.usecase.GetAppCount(organizationId, projectId) //if err != nil { // log.Error(r.Context(), "Failed to retrieve app count", err) @@ -303,14 +323,11 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { } var projectLeaderId, projectLeaderName, projectLeaderAccountId, projectLeaderDepartment string - var projectRoleId, projectRoleName string for _, pu := range project.ProjectMembers { projectLeaderId = pu.ProjectUser.ID.String() projectLeaderName = pu.ProjectUser.Name projectLeaderAccountId = pu.ProjectUser.AccountId projectLeaderDepartment = pu.ProjectUser.Department - projectRoleId = pu.ProjectRole.ID - projectRoleName = pu.ProjectRole.Name } var pdr domain.ProjectDetailResponse diff --git a/internal/repository/project.go b/internal/repository/project.go index 53c4041d..48a3091b 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -84,7 +84,6 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " left join projects as p on pn.project_id = p.id "+ " left join project_members as pm on pn.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId "+ " group by p.id) as pn on p.id = pn.project_id "+ " left join "+ " (select p.id as project_id, count(asa.id) as count "+ @@ -92,14 +91,12 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " left join projects as p on asa.project_id = p.id "+ " left join project_members as pm on asa.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId "+ " group by p.id) as asa on p.id = asa.project_id "+ " left join "+ " (select p.id as project_id, count(pm.id) as count "+ " from project_members as pm "+ " left join projects as p on pm.project_id = p.id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId "+ " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ " and p.organization_id = @organizationId "+ @@ -122,7 +119,6 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " left join projects as p on pn.project_id = p.id "+ " left join project_members as pm on pn.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id <> @userId "+ " group by p.id) as pn on p.id = pn.project_id "+ " left join "+ " (select p.id as project_id, count(asa.id) as count "+ @@ -130,14 +126,12 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " left join projects as p on asa.project_id = p.id "+ " left join project_members as pm on asa.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id <> @userId "+ " group by p.id) as asa on p.id = asa.project_id "+ " left join "+ " (select p.id as project_id, count(pm.id) as count "+ " from project_members as pm "+ " left join projects as p on pm.project_id = p.id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id <> @userId "+ " group by p.id) as pm_count on p.id = pm_count.project_id"+ " where p.id = pm.project_id "+ " and p.organization_id = @organizationId "+ @@ -175,7 +169,6 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio " left join projects as p on pn.project_id = p.id "+ " left join project_members as pm on pn.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId "+ " group by p.id) as pn on p.id = pn.project_id "+ " left join "+ " (select p.id as project_id, count(asa.id) as count "+ @@ -183,14 +176,12 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio " left join projects as p on asa.project_id = p.id "+ " left join project_members as pm on asa.project_id = pm.project_id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId "+ " group by p.id) as asa on p.id = asa.project_id "+ " left join "+ " (select p.id as project_id, count(pm.id) as count "+ " from project_members as pm "+ " left join projects as p on pm.project_id = p.id "+ " where p.organization_id = @organizationId "+ - " and pm.project_user_id = @userId "+ " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ " and p.organization_id = @organizationId", sql.Named("organizationId", organizationId), sql.Named("userId", userId)). From a3c97160c4aa66244e64ec541225038dbe1831d0 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 1 Apr 2024 17:43:27 +0900 Subject: [PATCH 201/502] minor fix. fix swag error --- api/swagger/docs.go | 43 +--------------------------------- api/swagger/swagger.json | 43 +--------------------------------- api/swagger/swagger.yaml | 28 +--------------------- internal/delivery/http/auth.go | 1 - 4 files changed, 3 insertions(+), 112 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 56fa0c75..42dfe176 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1924,14 +1924,7 @@ const docTemplate = `{ "Auth" ], "summary": "logout", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.LogoutResponse" - } - } - } + "responses": {} } }, "/clusters": { @@ -11605,12 +11598,6 @@ const docTemplate = `{ "passwordExpired": { "type": "boolean" }, - "projects": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse" - } - }, "role": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse" }, @@ -11621,20 +11608,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.LogoutResponse": { - "type": "object", - "properties": { - "ssoUrls": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo": { "type": "object", "properties": { @@ -12055,20 +12028,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse": { - "type": "object", - "properties": { - "projectId": { - "type": "string" - }, - "projectRoleId": { - "type": "string" - }, - "projectRoleName": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest": { "type": "object", "required": [ diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 8a58e363..e44189d6 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1918,14 +1918,7 @@ "Auth" ], "summary": "logout", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.LogoutResponse" - } - } - } + "responses": {} } }, "/clusters": { @@ -11599,12 +11592,6 @@ "passwordExpired": { "type": "boolean" }, - "projects": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse" - } - }, "role": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse" }, @@ -11615,20 +11602,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.LogoutResponse": { - "type": "object", - "properties": { - "ssoUrls": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo": { "type": "object", "properties": { @@ -12049,20 +12022,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse": { - "type": "object", - "properties": { - "projectId": { - "type": "string" - }, - "projectRoleId": { - "type": "string" - }, - "projectRoleName": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest": { "type": "object", "required": [ diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 23bff86e..70743dae 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1947,25 +1947,12 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' passwordExpired: type: boolean - projects: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse' - type: array role: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse' token: type: string type: object type: object - github_com_openinfradev_tks-api_pkg_domain.LogoutResponse: - properties: - ssoUrls: - additionalProperties: - items: - type: string - type: array - type: object - type: object github_com_openinfradev_tks-api_pkg_domain.MandatoryPolicyInfo: properties: description: @@ -2254,15 +2241,6 @@ definitions: updatedAt: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.ProjectIdProjectRoleResponse: - properties: - projectId: - type: string - projectRoleId: - type: string - projectRoleName: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest: properties: projectRoleId: @@ -4991,11 +4969,7 @@ paths: description: logout produces: - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.LogoutResponse' + responses: {} security: - JWT: [] summary: logout diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 14f35296..f3953183 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -112,7 +112,6 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { // @Description logout // @Accept json // @Produce json -// @Success 200 {object} domain.LogoutResponse // @Router /auth/logout [post] // @Security JWT func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { From f8fd48e93035108175a5cf1fe6754871c6c636ac Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 1 Apr 2024 18:21:24 +0900 Subject: [PATCH 202/502] Change workflow to use base branch's latest commit for builds --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e016dd67..1ce1986a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From 1cad1d9ba41b1f30082ab12f8cb87ca262d8aa24 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sun, 31 Mar 2024 23:24:22 +0900 Subject: [PATCH 203/502] =?UTF-8?q?k8s=20=EC=A0=95=EC=B1=85=20=EB=8F=99?= =?UTF-8?q?=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 + internal/delivery/http/policy-template.go | 185 +++++--- internal/delivery/http/policy.go | 231 ++++++++++ internal/model/policy-template.go | 18 +- internal/model/policy.go | 6 + internal/policy-template/paramdef-util.go | 114 +++++ internal/policy-template/policy-operator.go | 84 ++++ internal/policy-template/tkscluster.go | 94 ++++ internal/policy-template/tkspolicy.go | 212 +++++++++ internal/policy-template/tkspolicytemplate.go | 264 +++++++++++ internal/repository/policy-template.go | 15 + internal/repository/policy.go | 59 +++ internal/route/route.go | 9 +- internal/usecase/policy-template.go | 69 +++ internal/usecase/policy.go | 423 +++++++++++++++++- pkg/domain/policy-template.go | 22 +- pkg/domain/policy.go | 78 +++- pkg/httpErrors/errorCode.go | 4 + 19 files changed, 1809 insertions(+), 87 deletions(-) create mode 100644 internal/policy-template/policy-operator.go create mode 100644 internal/policy-template/tkscluster.go create mode 100644 internal/policy-template/tkspolicy.go create mode 100644 internal/policy-template/tkspolicytemplate.go diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 7f81e178..2ff26186 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -243,6 +243,7 @@ const ( UpdatePolicy UpdatePolicyTargetClusters ExistsPolicyName + GetPolicyEdit // OrganizationPolicyTemplate ListPolicyTemplate diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index ff819d0b..4037874e 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -747,6 +747,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "ExistsPolicyName", Group: "Policy", }, + GetPolicyEdit: { + Name: "GetPolicyEdit", + Group: "Policy", + }, ListPolicyTemplate: { Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", @@ -1194,6 +1198,8 @@ func (e Endpoint) String() string { return "UpdatePolicyTargetClusters" case ExistsPolicyName: return "ExistsPolicyName" + case GetPolicyEdit: + return "GetPolicyEdit" case ListPolicyTemplate: return "ListPolicyTemplate" case CreatePolicyTemplate: @@ -1608,6 +1614,8 @@ func GetEndpoint(name string) Endpoint { return UpdatePolicyTargetClusters case "ExistsPolicyName": return ExistsPolicyName + case "GetPolicyEdit": + return GetPolicyEdit case "ListPolicyTemplate": return ListPolicyTemplate case "CreatePolicyTemplate": diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 71caafa3..e396827b 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -369,21 +369,39 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateVersions(w http.Response // @Router /admin/policy-templates/{policyTemplateId}/statistics [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { - // result := admin_domain.ListPolicyTemplateStatisticsResponse{ - // PolicyTemplateStatistics: []admin_domain.PolicyTemplateStatistics{ - // { - // OrganizationId: util.UUIDGen(), - // OrganizationName: "개발팀", - // UsageCount: 10, - // }, - // { - // OrganizationId: util.UUIDGen(), - // OrganizationName: "운영팀", - // UsageCount: 5, - // }, - // }, - // } - // util.JsonResponse(w, result) + vars := mux.Vars(r) + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + usageCounts, err := h.usecase.ListPolicyTemplateStatistics(r.Context(), nil, id) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + var out admin_domain.ListPolicyTemplateStatisticsResponse + out.PolicyTemplateStatistics = make([]admin_domain.PolicyTemplateStatistics, len(usageCounts)) + for i, usageCount := range usageCounts { + if err := serializer.Map(r.Context(), usageCount, &out.PolicyTemplateStatistics[i]); err != nil { + log.Info(r.Context(), err) + continue + } + } + + ResponseJSON(w, r, http.StatusOK, out) } // Admin_GetPolicyTemplateDeploy godoc @@ -398,18 +416,31 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateStatistics(w http.Respon // @Router /admin/policy-templates/{policyTemplateId}/deploy [get] // @Security JWT func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { - // c1 := util.UUIDGen() - // c2 := util.UUIDGen() - // c3 := util.UUIDGen() - - // result := admin_domain.GetPolicyTemplateDeployResponse{ - // DeployVersion: map[string]string{ - // c1: "v1.0.1", - // c2: "v1.1.0", - // c3: "v1.1.0", - // }, - // } - // util.JsonResponse(w, result) + vars := mux.Vars(r) + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + out, err := h.usecase.GetPolicyTemplateDeploy(r.Context(), nil, id) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, out) } // Admin_GetPolicyTemplateVersion godoc @@ -748,6 +779,9 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplate(w http.ResponseWriter, r *h log.Info(r.Context(), err) } + // // no converter found for *[]domain.ParameterDef -> []*domain.ParameterDef + // dto.ParametersSchema = input.ParametersSchema + dto.Type = "organization" dto.OrganizationId = &organizationId @@ -1063,21 +1097,45 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateVersions(w http.ResponseWriter // @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/statistics [get] // @Security JWT func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWriter, r *http.Request) { - // result := domain.ListPolicyTemplateStatisticsResponse{ - // PolicyTemplateStatistics: []domain.PolicyTemplateStatistics{ - // { - // OrganizationId: util.UUIDGen(), - // OrganizationName: "개발팀", - // UsageCount: 10, - // }, - // { - // OrganizationId: util.UUIDGen(), - // OrganizationName: "운영팀", - // UsageCount: 5, - // }, - // }, - // } - // util.JsonResponse(w, result) + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + usageCounts, err := h.usecase.ListPolicyTemplateStatistics(r.Context(), &organizationId, id) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + var out domain.ListPolicyTemplateStatisticsResponse + out.PolicyTemplateStatistics = make([]domain.PolicyTemplateStatistics, len(usageCounts)) + for i, usageCount := range usageCounts { + if err := serializer.Map(r.Context(), usageCount, &out.PolicyTemplateStatistics[i]); err != nil { + log.Info(r.Context(), err) + continue + } + } + ResponseJSON(w, r, http.StatusOK, out) } // GetPolicyTemplateDeploy godoc @@ -1093,18 +1151,37 @@ func (h *PolicyTemplateHandler) ListPolicyTemplateStatistics(w http.ResponseWrit // @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/deploy [get] // @Security JWT func (h *PolicyTemplateHandler) GetPolicyTemplateDeploy(w http.ResponseWriter, r *http.Request) { - // c1 := util.UUIDGen() - // c2 := util.UUIDGen() - // c3 := util.UUIDGen() - - // result := domain.GetPolicyTemplateDeployResponse{ - // DeployVersion: map[string]string{ - // c1: "v1.0.1", - // c2: "v1.1.0", - // c3: "v1.1.0", - // }, - // } - // util.JsonResponse(w, result) + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + out, err := h.usecase.GetPolicyTemplateDeploy(r.Context(), &organizationId, id) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, out) } // GetPolicyTemplateVersion godoc diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 16fb0e85..1bcbccc1 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -8,6 +8,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + policytemplate "github.com/openinfradev/tks-api/internal/policy-template" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" @@ -29,6 +30,10 @@ type IPolicyHandler interface { GetMandatoryPolicies(w http.ResponseWriter, r *http.Request) SetMandatoryPolicies(w http.ResponseWriter, r *http.Request) ExistsPolicyName(w http.ResponseWriter, r *http.Request) + ListClusterPolicyStatus(w http.ResponseWriter, r *http.Request) + GetClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) + UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) + GetPolicyEdit(w http.ResponseWriter, r *http.Request) } func NewPolicyHandler(u usecase.Usecase) IPolicyHandler { @@ -447,6 +452,7 @@ func (h *PolicyHandler) SetMandatoryPolicies(w http.ResponseWriter, r *http.Requ "C_INVALID_ORGANIZATION_ID", "")) return } + input := domain.SetMandatoryPoliciesRequest{} err := UnmarshalRequestInput(r, &input) @@ -531,3 +537,228 @@ func (h *PolicyHandler) ExistsPolicyName(w http.ResponseWriter, r *http.Request) ResponseJSON(w, r, http.StatusOK, out) } + +// ListClusterPolicyStatus godoc +// +// @Tags ClusterPolicyStatus +// @Summary [ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회 +// @Description 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. +// @Accept json +// @Produce json +// @Param clusterId path string true "클러스터 식별자(uuid)" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" +// @Param sortColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.ListClusterPolicyStatusResponse +// @Router /clusters/{clusterId}/policy-status [get] +// @Security JWT +func (h *PolicyHandler) ListClusterPolicyStatus(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + clusterId, ok := vars["clusterId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), + "C_INVALID_CLUSTER_ID", "")) + return + } + + urlParams := r.URL.Query() + + pg := pagination.NewPagination(&urlParams) + + policyStatuses, err := h.usecase.ListClusterPolicyStatus(r.Context(), clusterId, pg) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + out := domain.ListClusterPolicyStatusResponse{ + Polices: policyStatuses, + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetClusterPolicyTemplateStatus godoc +// +// @Tags ClusterPolicyStatus +// @Summary [GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회 +// @Description 템플릿의 클러스터 버전 등 상태를 조회한다. +// @Accept json +// @Produce json +// @Param clusterId path string true "클러스터 식별자(uuid)" +// @Param templateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.GetClusterPolicyTemplateStatusResponse +// @Router /clusters/{clusterId}/policy-templates/{templateId} [get] +// @Security JWT +func (h *PolicyHandler) GetClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + clusterId, ok := vars["clusterId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), + "C_INVALID_CLUSTER_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + out, err := h.usecase.GetClusterPolicyTemplateStatus(r.Context(), clusterId, id) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// UpdateClusterPolicyTemplateStatus godoc +// +// @Tags ClusterPolicyStatus +// @Summary [UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트 +// @Description 해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다. +// @Accept json +// @Produce json +// @Param clusterId path string true "클러스터 식별자(uuid)" +// @Param templateId path string true "정책 템플릿 식별자(uuid)" +// @Param body body domain.UpdateClusterPolicyTemplateStatusRequest true "update cluster policy template status request" +// @Success 200 {object} nil +// @Router /clusters/{clusterId}/policy-templates/{templateId} [patch] +// @Security JWT +func (h *PolicyHandler) UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + clusterId, ok := vars["clusterId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), + "C_INVALID_CLUSTER_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + input := domain.UpdateClusterPolicyTemplateStatusRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + err = h.usecase.UpdateClusterPolicyTemplateStatus(r.Context(), clusterId, id, + input.TemplateCurrentVersion, input.TemplateTargetVerson) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +// GetPolicyEdit godoc +// +// @Tags Policy +// @Summary [GetPolicy] 정책 조회 +// @Description 정책 정보를 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyId path string true "정책 식별자(uuid)" +// @Success 200 {object} domain.GetPolicyResponse +// @Router /organizations/{organizationId}/policies/{policyId}/edit [get] +// @Security JWT +func (h *PolicyHandler) GetPolicyEdit(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyId, ok := vars["policyId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "")) + return + } + + id, err := uuid.Parse(policyId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_ID", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + policy, err := h.usecase.GetForEdit(r.Context(), organizationId, id) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "P_NOT_FOUND_POLICY", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + if policy == nil { + ResponseJSON(w, r, http.StatusNotFound, nil) + return + } + + var out domain.GetPolicyResponse + if err = serializer.Map(r.Context(), *policy, &out.Policy); err != nil { + log.Error(r.Context(), err) + } + + parameterSchema := policy.PolicyTemplate.ParametersSchema + parameters := policy.Parameters + + err = policytemplate.FillParamDefFromJsonStr(parameterSchema, parameters) + if err != nil { + log.Error(r.Context(), err) + } else { + out.Policy.FilledParameters = parameterSchema + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index 2a197376..a9db7a1e 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -40,15 +40,15 @@ type PolicyTemplate struct { Deprecated bool Mandatory bool // Tks 인 경우에는 무시 Severity string - PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organizations"` - ParametersSchema []domain.ParameterDef `gorm:"-:all"` - Rego string `gorm:"-:all"` - Libs []string `gorm:"-:all"` - PermittedOrganizationIds []string `gorm:"-:all"` - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` + PermittedOrganizations []Organization `gorm:"many2many:policy_template_permitted_organizations"` + ParametersSchema []*domain.ParameterDef `gorm:"-:all"` + Rego string `gorm:"-:all"` + Libs []string `gorm:"-:all"` + PermittedOrganizationIds []string `gorm:"-:all"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` } func (pt *PolicyTemplate) IsTksTemplate() bool { diff --git a/internal/model/policy.go b/internal/model/policy.go index 1a05c5ef..5d997d24 100644 --- a/internal/model/policy.go +++ b/internal/model/policy.go @@ -75,3 +75,9 @@ type PolicyTargetCluster struct { PolicyId uuid.UUID `gorm:"primarykey"` ClusterId domain.ClusterId `gorm:"primarykey"` } + +type UsageCount struct { + OrganizationId string + OrganizationName string + UsageCount int +} diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go index 04ca850c..cc735b1b 100644 --- a/internal/policy-template/paramdef-util.go +++ b/internal/policy-template/paramdef-util.go @@ -1,12 +1,86 @@ package policytemplate import ( + "encoding/json" + "errors" + "fmt" "strings" "github.com/openinfradev/tks-api/pkg/domain" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" ) +func GetNewParamDefs(paramdefs1 []*domain.ParameterDef, paramdefs2 []*domain.ParameterDef) (newParamdefs []*domain.ParameterDef, err error) { + result := []*domain.ParameterDef{} + + if len(paramdefs1) > len(paramdefs2) { + return nil, errors.New("not compatible, parameter number reduced") + } + + for _, paramdef2 := range paramdefs2 { + paramdef1 := findParamDefByName(paramdefs1, paramdef2.Key) + + if paramdef1 == nil { + // Not found, it's new parameter + result = append(result, paramdef2) + } + + if !CompareParamDef(paramdef2, paramdef1) { + return nil, fmt.Errorf("not compatible, parameter definition of '%s' is changed", paramdef2.Key) + } + } + + return result, nil +} + +func findParamDefByName(paramdefs []*domain.ParameterDef, name string) *domain.ParameterDef { + for _, paramdef := range paramdefs { + if paramdef.Key == name { + return paramdef + } + } + + return nil +} + +func CompareParamDef(paramdef1 *domain.ParameterDef, paramdef2 *domain.ParameterDef) bool { + if paramdef1 == nil || paramdef2 == nil { + return paramdef2 == paramdef1 + } + + if paramdef1.Key != paramdef2.Key { + return false + } + + if paramdef1.IsArray != paramdef2.IsArray { + return false + } + + if paramdef1.Type != paramdef2.Type { + return false + } + + if paramdef1.DefaultValue != paramdef2.DefaultValue { + return false + } + + if len(paramdef1.Children) != len(paramdef2.Children) { + return false + } + + for _, child := range paramdef1.Children { + child2 := paramdef2.GetChildrenByName(child.Key) + + equals := CompareParamDef(child, child2) + + if !equals { + return false + } + } + + return true +} + func ParamDefsToJSONSchemaProeprties(paramdefs []*domain.ParameterDef) *apiextensionsv1.JSONSchemaProps { if paramdefs == nil { return nil @@ -83,3 +157,43 @@ func convertToParameterDef(jsschema *apiextensionsv1.JSONSchemaProps) *domain.Pa return &domain.ParameterDef{Key: jsschema.ID, Type: jsschema.Type, DefaultValue: defaultValue, Children: []*domain.ParameterDef{}} } } + +func FillParamDefFromJsonStr(paramdefs []*domain.ParameterDef, parameters string) (err error) { + var parametersMap map[string]interface{} + + err = json.Unmarshal([]byte(parameters), ¶metersMap) + + if err != nil { + return err + } + + return FillParamDefFromJson(paramdefs, ¶metersMap) +} + +func FillParamDefFromJson(paramdefs []*domain.ParameterDef, parameters *map[string]interface{}) (err error) { + if len(paramdefs) == 0 || parameters == nil { + return nil + } + + for key, value := range *parameters { + paramdef := findParamDefByName(paramdefs, key) + + if nestedMap, ok := value.(map[string]interface{}); ok { + return FillParamDefFromJson(paramdef.Children, &nestedMap) + } else if nestedMapArray, ok := value.([]map[string]interface{}); ok { + jsonByte, err := json.Marshal(nestedMapArray) + + if err != nil { + paramdef.DefaultValue = string(jsonByte) + } + } else if value != nil { + jsonByte, err := json.Marshal(value) + + if err != nil { + paramdef.DefaultValue = string(jsonByte) + } + } + } + + return nil +} diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go new file mode 100644 index 00000000..d1072c21 --- /dev/null +++ b/internal/policy-template/policy-operator.go @@ -0,0 +1,84 @@ +package policytemplate + +import ( + "strings" + + "github.com/openinfradev/tks-api/internal/model" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { + if policy == nil { + return nil + } + + jsonParams := apiextensionsv1.JSON{Raw: []byte(policy.Parameters)} + + labels := map[string]string{} + labels["app.kubernetes.io/part-of"] = "tks-policy-operator" + + return &TKSPolicy{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "tkspolicy.openinfradev.github.io/v1", + Kind: "TKSPolicy", + }, + + ObjectMeta: metav1.ObjectMeta{ + Name: policy.PolicyName, + Labels: labels, + }, + + Spec: TKSPolicySpec{ + Clusters: policy.TargetClusterIds, + Template: policy.PolicyTemplate.Kind, + Match: policy.Match, + Params: &jsonParams, + }, + } +} + +func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) *TKSPolicyTemplate { + if policyTemplate == nil { + return nil + } + + labels := map[string]string{} + labels["app.kubernetes.io/part-of"] = "tks-policy-operator" + + return &TKSPolicyTemplate{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "tkspolicy.openinfradev.github.io/v1", + Kind: "TKSPolicyTemplate", + }, + + ObjectMeta: metav1.ObjectMeta{ + Name: strings.ToLower(policyTemplate.Kind), + Labels: labels, + }, + + Spec: TKSPolicyTemplateSpec{ + CRD: CRD{ + Spec: CRDSpec{ + Names: Names{ + Kind: policyTemplate.Kind, + }, + Validation: &Validation{ + OpenAPIV3Schema: ParamDefsToJSONSchemaProeprties(policyTemplate.ParametersSchema), + }, + }, + }, + Targets: []Target{{ + Target: "admission.k8s.gatekeeper.sh", + Rego: policyTemplate.Rego, + Libs: policyTemplate.Libs, + }}, + Version: policyTemplate.Version, + }, + } +} + +func syncToKubernetes() bool { + return true + // return os.Getenv("SYNC_POLICY_TO_K8S") != "" +} diff --git a/internal/policy-template/tkscluster.go b/internal/policy-template/tkscluster.go new file mode 100644 index 00000000..e4ce4a93 --- /dev/null +++ b/internal/policy-template/tkscluster.go @@ -0,0 +1,94 @@ +package policytemplate + +import ( + "context" + "encoding/json" + + "github.com/openinfradev/tks-api/internal/kubernetes" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var TKSClusterGVR = schema.GroupVersionResource{ + Group: "tkspolicy.openinfradev.github.io", Version: "v1", + Resource: "tksclusters", +} + +type TKSClusterSpec struct { + ClusterName string `json:"clusterName" validate:"required"` + Context string `json:"context" validate:"required"` + TemplatesRef TemplateReference `json:"templateref,omitempty"` +} + +type TKSProxy struct { + ControllerManager *DeploymentInfo `json:"controllerManager,omitempty"` + Audit *DeploymentInfo `json:"audit,omitempty"` +} + +type DeploymentInfo struct { + Image string `json:"image,omitempty"` + Args []string `json:"args,omitempty"` + TotalReplicas int `json:"totalReplicas,omitempty"` + NumReplicas int `json:"numReplicas,omitempty"` +} + +type TemplateReference struct { + Policies map[string]string `json:"polices,omitempty"` + Templates map[string]string `json:"templates,omitempty"` +} + +type TKSClusterStatus struct { + Status string `json:"status" enums:"running,deleting,error"` + Error string `json:"error,omitempty"` + TKSProxy TKSProxy `json:"tksproxy,omitempty"` + LastStatusCheckTime int64 `json:"laststatuschecktime,omitempty"` + Policies map[string]string `json:"polices,omitempty"` + Templates map[string]string `json:"templates,omitempty"` + LastUpdate string `json:"lastUpdate"` + UpdateQueue map[string]bool `json:"updateQueue,omitempty"` +} + +type TKSCluster struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TKSClusterSpec `json:"spec,omitempty"` + Status TKSClusterStatus `json:"status,omitempty"` +} + +type TKSClusterList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TKSCluster `json:"items"` +} + +func GetTksClusterCR(ctx context.Context, primaryClusterId string, name string) (*TKSCluster, error) { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return nil, err + } + + result, err := dynamicClient.Resource(TKSClusterGVR).Namespace(primaryClusterId). + Get(ctx, name, metav1.GetOptions{}) + + if err != nil { + return nil, err + } + + // Unstructured를 바로 TKSPolicyTemplate으로 컨버팅할 수 없기 때문에 json으로 변환 + jsonBytes, err := json.Marshal(result.Object) + + if err != nil { + return nil, err + } + + var tksCluster TKSCluster + err = json.Unmarshal(jsonBytes, &tksCluster) + + if err != nil { + return nil, err + } + + return &tksCluster, nil +} diff --git a/internal/policy-template/tkspolicy.go b/internal/policy-template/tkspolicy.go new file mode 100644 index 00000000..d0999720 --- /dev/null +++ b/internal/policy-template/tkspolicy.go @@ -0,0 +1,212 @@ +package policytemplate + +import ( + "context" + "encoding/json" + + "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/pkg/domain" + "gopkg.in/yaml.v3" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var TKSPolicyGVR = schema.GroupVersionResource{ + Group: "tkspolicy.openinfradev.github.io", Version: "v1", + Resource: "tkspolicies", +} + +type TKSPolicySpec struct { + Clusters []string `json:"clusters"` + Template string `json:"template" validate:"required"` + + // map[string]interface를 쓸 수 없어서 apiextensionsv1.JSON 사용 + Params *apiextensionsv1.JSON `json:"params,omitempty"` + Match *domain.Match `json:"match,omitempty"` +} + +type PolicyStatus struct { + ConstraintStatus string `json:"status" enums:"ready,applying,deleting,error"` + Reason string `json:"reason"` + LastUpdate string `json:"lastUpdate"` + TemplateVersion string `json:"templateVersion"` +} + +// TKSPolicyStatus defines the observed state of TKSPolicy +type TKSPolicyStatus struct { + Clusters map[string]PolicyStatus `json:"clusters"` + LastUpdate string `json:"lastUpdate"` + UpdateQueue map[string]bool `json:"updateQueue,omitempty"` +} + +type TKSPolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TKSPolicySpec `json:"spec,omitempty"` + Status TKSPolicyStatus `json:"status,omitempty"` +} + +func (tksPolicy *TKSPolicy) JSON() (string, error) { + result, err := json.MarshalIndent(tksPolicy, "", " ") + + if err != nil { + return "", err + } + + return string(result), nil +} + +func (tksPolicy *TKSPolicy) YAML() (string, error) { + target := map[string]interface{}{} + + jsonStr, err := tksPolicy.JSON() + + if err != nil { + return "", err + } + + err = json.Unmarshal([]byte(jsonStr), &target) + + if err != nil { + return "", err + } + + result, err := yaml.Marshal(&target) + + if err != nil { + return "", err + } + + return string(result), nil +} + +func (tksPolicy *TKSPolicy) ToUnstructured() (*unstructured.Unstructured, error) { + obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tksPolicy) + + if err != nil { + return nil, err + } + + tksPolicyUnstructured := &unstructured.Unstructured{ + Object: obj, + } + + return tksPolicyUnstructured, nil +} + +func ApplyTksPolicyCR(ctx context.Context, primaryClusterId string, tksPolicy *TKSPolicy) error { + if syncToKubernetes() { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return err + } + + policy, err := GetTksPolicyCR(ctx, primaryClusterId, tksPolicy.Name) + + if err != nil { + if errors.IsNotFound(err) { + tksPolicyUnstructured, err := tksPolicy.ToUnstructured() + + if err != nil { + return err + } + + _, err = dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). + Create(ctx, tksPolicyUnstructured, metav1.CreateOptions{}) + return err + } else { + return err + } + } + + policy.Spec = tksPolicy.Spec + tksPolicyUnstructured, err := policy.ToUnstructured() + + if err != nil { + return err + } + + _, err = dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). + Update(ctx, tksPolicyUnstructured, metav1.UpdateOptions{}) + + return err + } + return nil +} + +func DeleteTksPolicyCR(ctx context.Context, primaryClusterId string, name string) error { + if syncToKubernetes() { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return err + } + + err = dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). + Delete(ctx, name, metav1.DeleteOptions{}) + + return err + } + return nil +} + +func GetTksPolicyCR(ctx context.Context, primaryClusterId string, name string) (*TKSPolicy, error) { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return nil, err + } + + result, err := dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). + Get(ctx, name, metav1.GetOptions{}) + + if err != nil { + return nil, err + } + + // Unstructured를 바로 TKSPolicyTemplate으로 컨버팅할 수 없기 때문에 json으로 변환 + jsonBytes, err := json.Marshal(result.Object) + + if err != nil { + return nil, err + } + + var tksPolicy TKSPolicy + err = json.Unmarshal(jsonBytes, &tksPolicy) + + if err != nil { + return nil, err + } + + return &tksPolicy, nil +} + +func ExistsTksPolicyCR(ctx context.Context, primaryClusterId string, name string) (bool, error) { + if syncToKubernetes() { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return false, err + } + + result, err := dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). + Get(ctx, name, metav1.GetOptions{}) + + if err != nil { + if errors.IsNotFound(err) { + return false, nil + } else { + return false, err + } + } + + return result != nil, nil + } + return true, nil +} diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go new file mode 100644 index 00000000..ed22103f --- /dev/null +++ b/internal/policy-template/tkspolicytemplate.go @@ -0,0 +1,264 @@ +package policytemplate + +import ( + "context" + "encoding/json" + "strings" + + "github.com/openinfradev/tks-api/internal/kubernetes" + "gopkg.in/yaml.v3" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var TKSPolicyTemplateGVR = schema.GroupVersionResource{ + Group: "tkspolicy.openinfradev.github.io", Version: "v1", + Resource: "tkspolicytemplates", +} + +type Anything struct { + Value interface{} `json:"-"` +} + +type CRD struct { + Spec CRDSpec `json:"spec,omitempty"` +} + +type CRDSpec struct { + Names Names `json:"names,omitempty"` + Validation *Validation `json:"validation,omitempty"` +} + +type Names struct { + Kind string `json:"kind,omitempty"` + ShortNames []string `json:"shortNames,omitempty"` +} + +type Validation struct { + OpenAPIV3Schema *apiextensionsv1.JSONSchemaProps `json:"openAPIV3Schema,omitempty"` + LegacySchema *bool `json:"legacySchema,omitempty"` // *bool allows for "unset" state which we need to apply appropriate defaults +} + +type Target struct { + Target string `json:"target,omitempty"` + Rego string `json:"rego,omitempty"` + Libs []string `json:"libs,omitempty"` + Code []Code `json:"code,omitempty"` +} + +type Code struct { + Engine string `json:"engine"` + Source *Anything `json:"source"` +} + +type TKSPolicyTemplateSpec struct { + CRD CRD `json:"crd,omitempty"` + Targets []Target `json:"targets,omitempty"` + Clusters []string `json:"clusters,omitempty"` + ToLatest []string `json:"toLatest,omitempty"` + Version string `json:"version"` +} + +type TemplateStatus struct { + ConstraintTemplateStatus string `json:"status" enums:"ready,applying,deleting,error"` + Reason string `json:"reason"` + LastUpdate string `json:"lastUpdate"` + Version string `json:"version"` +} + +type TKSPolicyTemplateStatus struct { + TemplateStatus map[string]*TemplateStatus `json:"clusterStatus"` + LastUpdate string `json:"lastUpdate"` + UpdateQueue map[string]bool `json:"updateQueue,omitempty"` +} + +// TKSPolicyTemplate is the Schema for the tkspolicytemplates API +type TKSPolicyTemplate struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TKSPolicyTemplateSpec `json:"spec,omitempty"` + Status TKSPolicyTemplateStatus `json:"status,omitempty"` +} + +func (tksPolicyTemplate *TKSPolicyTemplate) JSON() (string, error) { + result, err := json.MarshalIndent(tksPolicyTemplate, "", " ") + + if err != nil { + return "", err + } + + return string(result), nil +} + +func (tksPolicyTemplate *TKSPolicyTemplate) YAML() (string, error) { + target := map[string]interface{}{} + + jsonStr, err := tksPolicyTemplate.JSON() + + if err != nil { + return "", err + } + + err = json.Unmarshal([]byte(jsonStr), &target) + + if err != nil { + return "", err + } + + result, err := yaml.Marshal(&target) + + if err != nil { + return "", err + } + + return string(result), nil +} + +func (tksPolicyTemplate *TKSPolicyTemplate) ToUnstructured() (*unstructured.Unstructured, error) { + obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tksPolicyTemplate) + + if err != nil { + return nil, err + } + + tksPolicyTemplateUnstructured := &unstructured.Unstructured{ + Object: obj, + } + + return tksPolicyTemplateUnstructured, nil +} + +func ApplyTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tksPolicyTemplate *TKSPolicyTemplate) error { + if syncToKubernetes() { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return err + } + + policyTemplate, err := GetTksPolicyTemplateCR(ctx, primaryClusterId, strings.ToLower(tksPolicyTemplate.Kind)) + + if err != nil { + if errors.IsNotFound(err) { + tksPolicyTemplateUnstructured, err := tksPolicyTemplate.ToUnstructured() + + if err != nil { + return err + } + + _, err = dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). + Create(ctx, tksPolicyTemplateUnstructured, metav1.CreateOptions{}) + return err + } else { + return err + } + } + + policyTemplate.Spec = tksPolicyTemplate.Spec + tksPolicyTemplateUnstructured, err := policyTemplate.ToUnstructured() + + if err != nil { + return err + } + + _, err = dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). + Update(ctx, tksPolicyTemplateUnstructured, metav1.UpdateOptions{}) + + return err + } + return nil +} + +func DeleteTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, name string) error { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return err + } + + err = dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). + Delete(ctx, name, metav1.DeleteOptions{}) + + return err +} + +func ExistsTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, name string) (bool, error) { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return false, err + } + + result, err := dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). + Get(ctx, name, metav1.GetOptions{}) + + if err != nil { + if errors.IsNotFound(err) { + return false, nil + } else { + return false, err + } + } + + return result != nil, nil +} + +func GetTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, name string) (*TKSPolicyTemplate, error) { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return nil, err + } + + result, err := dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). + Get(ctx, name, metav1.GetOptions{}) + + if err != nil { + return nil, err + } + + // Unstructured를 바로 TKSPolicyTemplate으로 컨버팅할 수 없기 때문에 json으로 변환 + jsonBytes, err := json.Marshal(result.Object) + + if err != nil { + return nil, err + } + + var tksPolicyTemplate TKSPolicyTemplate + err = json.Unmarshal(jsonBytes, &tksPolicyTemplate) + + if err != nil { + return nil, err + } + + return &tksPolicyTemplate, nil +} + +func UpdateTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tksPolicyTemplate *TKSPolicyTemplate) error { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return err + } + + obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tksPolicyTemplate) + + if err != nil { + return err + } + + tksPolicyUnstructured := &unstructured.Unstructured{ + Object: obj, + } + + _, err = dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). + Update(ctx, tksPolicyUnstructured, metav1.UpdateOptions{}) + + return err +} diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index a7ecac85..9127f8cd 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -33,6 +33,7 @@ type IPolicyTemplateRepository interface { GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) + GetLatestTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID) (version string, err error) } type PolicyTemplateRepository struct { @@ -420,3 +421,17 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Conte return newVersion, nil } + +func (r *PolicyTemplateRepository) GetLatestTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID) (version string, err error) { + var policyTemplateVersion model.PolicyTemplateSupportedVersion + + err = r.db.WithContext(ctx). + Where("policy_template_id = ?", policyTemplateId). + Order("created_at desc").First(&policyTemplateVersion).Error + + if err != nil { + return + } + + return policyTemplateVersion.Version, nil +} diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 9ceda1aa..8b336b1a 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -19,6 +19,8 @@ type IPolicyRepository interface { Update(ctx context.Context, organizationId string, policyId uuid.UUID, updateMap map[string]interface{}, TargetClusters *[]model.Cluster) (err error) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out *[]model.Policy, err error) + FetchByClusterId(ctx context.Context, clusterId string, pg *pagination.Pagination) (out *[]model.Policy, err error) + FetchByClusterIdAndTemplaeId(ctx context.Context, clusterId string, templateId uuid.UUID) (out *[]model.Policy, err error) ExistByName(ctx context.Context, organizationId string, policyName string) (exist bool, err error) ExistByID(ctx context.Context, organizationId string, policyId uuid.UUID) (exist bool, err error) GetByName(ctx context.Context, organizationId string, policyName string) (out *model.Policy, err error) @@ -26,6 +28,7 @@ type IPolicyRepository interface { Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusters []model.Cluster) (err error) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) + GetUsageCountByTemplateId(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (usageCounts []model.UsageCount, err error) } type PolicyRepository struct { @@ -93,6 +96,36 @@ func (r *PolicyRepository) Fetch(ctx context.Context, organizationId string, pg return } +func (r *PolicyRepository) FetchByClusterId(ctx context.Context, clusterId string, pg *pagination.Pagination) (out *[]model.Policy, err error) { + if pg == nil { + pg = pagination.NewPagination(nil) + } + + subQueryClusterId := r.db.Table("policy_target_clusters").Select("policy_id"). + Where("cluster_id = ?", clusterId) + + _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations). + Where("id in (?)", subQueryClusterId), &out) + + if res.Error != nil { + return nil, res.Error + } + return +} + +func (r *PolicyRepository) FetchByClusterIdAndTemplaeId(ctx context.Context, clusterId string, templateId uuid.UUID) (out *[]model.Policy, err error) { + subQueryClusterId := r.db.Table("policy_target_clusters").Select("policy_id"). + Where("cluster_id = ?", clusterId) + + res := r.db.WithContext(ctx).Preload(clause.Associations). + Where("template_id = ?").Where("id in (?)", subQueryClusterId).Find(&out) + + if res.Error != nil { + return nil, res.Error + } + return +} + func (r *PolicyRepository) ExistBy(ctx context.Context, organizationId string, key string, value interface{}) (exists bool, err error) { query := fmt.Sprintf("organization_id = ? and %s = ?", key) @@ -211,3 +244,29 @@ func (r *PolicyRepository) SetMandatoryPolicies(ctx context.Context, organizatio return nil }) } + +func (r *PolicyRepository) GetUsageCountByTemplateId(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (usageCounts []model.UsageCount, err error) { + // 다음과 같은 쿼리, organization_id 가 nil인 경우는 and organization_id = '...'를 조합하지 않음 + // select organizations.id, organizations.name, count(organizations.id) from policies join organizations + // on policies.organization_id = organizations.id + // where policies.template_id='7f8a9f78-1771-43d4-aa4a-c395b43ebdd6' + // and organization_id = 'ozvnzr3oz' + // group by organizations.id + + query := r.db.WithContext(ctx).Model(&model.Policy{}). + Select("organizations.id as organization_id", "organizations.name as organization_name", "count(organizations.id) as usage_count"). + Joins("join organizations on policies.organization_id = organizations.id"). + Where("template_id = ?", policyTemplateId) + + if organizationId != nil { + query = query.Where("organization_id = ?", organizationId) + } + + err = query.Group("organizations.id").Scan(&usageCounts).Error + + if err != nil { + return nil, err + } + + return +} diff --git a/internal/route/route.go b/internal/route/route.go index 59d58214..aabb8590 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -306,7 +306,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.Admin_DeletePolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_DeletePolicyTemplate))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.Admin_GetPolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_GetPolicyTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_UpdatePolicyTemplate))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/deploy ", customMiddleware.Handle(internalApi.Admin_GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.Admin_GetPolicyTemplateDeploy))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/deploy", customMiddleware.Handle(internalApi.Admin_GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.Admin_GetPolicyTemplateDeploy))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/statistics", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplateStatistics, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplateStatistics))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplateVersions, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplateVersions))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.Admin_CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.Admin_CreatePolicyTemplateVersion))).Methods(http.MethodPost) @@ -334,12 +334,17 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/mandatory-policies", customMiddleware.Handle(internalApi.SetMandatoryPolicies, http.HandlerFunc(policyHandler.SetMandatoryPolicies))).Methods(http.MethodPatch) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies", customMiddleware.Handle(internalApi.ListPolicy, http.HandlerFunc(policyHandler.ListPolicy))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies", customMiddleware.Handle(internalApi.CreatePolicy, http.HandlerFunc(policyHandler.CreatePolicy))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}/clusters", customMiddleware.Handle(internalApi.UpdatePolicyTargetClusters, http.HandlerFunc(policyHandler.UpdatePolicyTargetClusters))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}/edit", customMiddleware.Handle(internalApi.GetPolicyEdit, http.HandlerFunc(policyHandler.GetPolicyEdit))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.GetPolicy, http.HandlerFunc(policyHandler.GetPolicy))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.DeletePolicy, http.HandlerFunc(policyHandler.DeletePolicy))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.UpdatePolicy, http.HandlerFunc(policyHandler.UpdatePolicy))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}/clusters", customMiddleware.Handle(internalApi.UpdatePolicyTargetClusters, http.HandlerFunc(policyHandler.UpdatePolicyTargetClusters))).Methods(http.MethodPatch) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyName, http.HandlerFunc(policyHandler.ExistsPolicyName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-status", customMiddleware.Handle(internalApi.ListClusterPolicyStatus, http.HandlerFunc(policyHandler.ListClusterPolicyStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{templateId}", customMiddleware.Handle(internalApi.GetClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.GetClusterPolicyTemplateStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{templateId}", customMiddleware.Handle(internalApi.UpdateClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.UpdateClusterPolicyTemplateStatus))).Methods(http.MethodPatch) + // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) r.PathPrefix("/").Handler(httpSwagger.WrapHandler).Methods(http.MethodGet) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 1bf59fef..41c03b00 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -3,8 +3,10 @@ package usecase import ( "context" "fmt" + "strings" admin_domain "github.com/openinfradev/tks-api/pkg/domain/admin" + "github.com/openinfradev/tks-api/pkg/log" mapset "github.com/deckarep/golang-set/v2" "github.com/google/uuid" @@ -38,17 +40,22 @@ type IPolicyTemplateUsecase interface { policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) error FillPermittedOrganizationsForList(ctx context.Context, policyTemplates *[]model.PolicyTemplate, outs *[]admin_domain.PolicyTemplateResponse) error + + ListPolicyTemplateStatistics(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (statistics []model.UsageCount, err error) + GetPolicyTemplateDeploy(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (deployInfo domain.GetPolicyTemplateDeployResponse, err error) } type PolicyTemplateUsecase struct { organizationRepo repository.IOrganizationRepository clusterRepo repository.IClusterRepository + policyRepo repository.IPolicyRepository repo repository.IPolicyTemplateRepository } func NewPolicyTemplateUsecase(r repository.Repository) IPolicyTemplateUsecase { return &PolicyTemplateUsecase{ repo: r.PolicyTemplate, + policyRepo: r.Policy, organizationRepo: r.Organization, clusterRepo: r.Cluster, } @@ -451,3 +458,65 @@ func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, return response, nil } + +func (u *PolicyTemplateUsecase) ListPolicyTemplateStatistics(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (statistics []model.UsageCount, err error) { + return u.policyRepo.GetUsageCountByTemplateId(ctx, organizationId, policyTemplateId) +} + +func (u *PolicyTemplateUsecase) GetPolicyTemplateDeploy(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (deployVersions domain.GetPolicyTemplateDeployResponse, err error) { + policyTemplate, err := u.repo.GetByID(ctx, policyTemplateId) + + if err != nil { + return deployVersions, err + } + + if !policyTemplate.IsPermittedToOrganization(organizationId) { + return deployVersions, httpErrors.NewNotFoundError(fmt.Errorf( + "policy template not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + + if organizationId == nil { + organizations, err := u.organizationRepo.Fetch(ctx, nil) + if err != nil { + return deployVersions, err + } + + deployVersions.DeployVersion = map[string]string{} + for _, organization := range *organizations { + tksPolicyTemplate, err := policytemplate.GetTksPolicyTemplateCR(ctx, organization.PrimaryClusterId, strings.ToLower(policyTemplate.Kind)) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + continue + } + + for clusterId, status := range tksPolicyTemplate.Status.TemplateStatus { + if status != nil { + deployVersions.DeployVersion[clusterId] = status.Version + } + } + } + + return deployVersions, nil + } + + organization, err := u.organizationRepo.Get(ctx, *organizationId) + if err != nil { + return deployVersions, err + } + + tksPolicyTemplate, err := policytemplate.GetTksPolicyTemplateCR(ctx, organization.PrimaryClusterId, strings.ToLower(policyTemplate.Kind)) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return deployVersions, httpErrors.NewInternalServerError(err, "P_FAILED_TO_CALL_KUBERNETES", "") + } + + for clusterId, status := range tksPolicyTemplate.Status.TemplateStatus { + if status != nil { + deployVersions.DeployVersion[clusterId] = status.Version + } + } + + return deployVersions, nil +} diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index aac394e3..f76f7b54 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -2,16 +2,22 @@ package usecase import ( "context" + "encoding/json" "fmt" + "strings" mapset "github.com/deckarep/golang-set/v2" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + policytemplate "github.com/openinfradev/tks-api/internal/policy-template" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "k8s.io/utils/strings/slices" ) type IPolicyUsecase interface { @@ -21,12 +27,17 @@ type IPolicyUsecase interface { parameters *string, match *domain.Match, targetClusterIds *[]string) (err error) Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) Get(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) + GetForEdit(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.Policy, error) IsPolicyIdExist(ctx context.Context, organizationId string, policyId uuid.UUID) (exists bool, err error) IsPolicyNameExist(ctx context.Context, organizationId string, policyName string) (exists bool, err error) UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusterIds []string) (err error) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) GetMandatoryPolicies(ctx context.Context, organizationId string) (response *domain.GetMandatoryPoliciesResponse, err error) + ListClusterPolicyStatus(ctx context.Context, clusterId string, pg *pagination.Pagination) (policyStatuses []domain.ClusterPolicyStatusResponse, err error) + GetClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID) (clusterPolicyTemplateStatusResponse *domain.GetClusterPolicyTemplateStatusResponse, err error) + UpdateClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID, + currentVersion string, targetVerson string) (err error) } type PolicyUsecase struct { @@ -53,7 +64,7 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } - exists, err := u.repo.ExistByName(ctx, dto.OrganizationId, dto.TemplateName) + exists, err := u.repo.ExistByName(ctx, dto.OrganizationId, dto.PolicyName) if err != nil { return uuid.Nil, err } @@ -62,22 +73,27 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_CREATE_ALREADY_EXISTED_NAME", "policy name already exists") } + policyTemplate, err := u.templateRepo.GetByID(ctx, dto.TemplateId) + if err != nil { + return uuid.Nil, err + } + + if policyTemplate == nil { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_POlICY_TEMPLATE_NOT_FOUND", "policy template not found") + } + dto.TargetClusters = make([]model.Cluster, len(dto.TargetClusterIds)) for i, clusterId := range dto.TargetClusterIds { cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) if err != nil { - return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return uuid.Nil, httpErrors.NewBadRequestError(err, "P_FAILED_FETCH_CLUSTER", "") } dto.TargetClusters[i] = cluster } - policyTemplate, err := u.templateRepo.GetByID(ctx, dto.TemplateId) - - if err != nil { - return uuid.Nil, err - } - if !policyTemplate.IsPermittedToOrganization(&organizationId) { return uuid.Nil, httpErrors.NewNotFoundError(fmt.Errorf( "policy template not found"), @@ -86,6 +102,55 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m userId := user.GetUserId() dto.CreatorId = &userId + dto.TemplateId = policyTemplate.ID + + policyCR := policytemplate.PolicyToTksPolicyCR(&dto) + policyTemplateCR := policytemplate.PolicyTemplateToTksPolicyTemplateCR(policyTemplate) + + organization, err := u.organizationRepo.Get(ctx, organizationId) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + + exists, err = policytemplate.ExistsTksPolicyTemplateCR(ctx, organization.PrimaryClusterId, policyTemplateCR.Name) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return uuid.Nil, httpErrors.NewInternalServerError(err, "P_FAILED_TO_CALL_KUBERNETES", "") + } + + if !exists { + err = policytemplate.ApplyTksPolicyTemplateCR(ctx, organization.PrimaryClusterId, policyTemplateCR) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return uuid.Nil, httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") + } + } + + err = policytemplate.ApplyTksPolicyCR(ctx, organization.PrimaryClusterId, policyCR) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return uuid.Nil, httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") + } + + // policyYaml, _ := policyCR.YAML() + // policyTemplateYaml, _ := policyTemplateCR.YAML() + + // fmt.Println("-------------------- Policy --------------------") + // fmt.Printf("%+v\n", policyYaml) + // fmt.Println("------------------------------------------------") + // fmt.Println("--------------- Policy Template ----------------") + // fmt.Printf("%+v\n", policyTemplateYaml) + // fmt.Println("------------------------------------------------") + // fmt.Printf("%+v\n", policyTemplateCR.Spec.Targets[0].Rego) + // fmt.Println("------------------------------------------------") id, err := u.repo.Create(ctx, dto) @@ -107,7 +172,7 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic _, err = u.repo.GetByID(ctx, organizationId, policyId) if err != nil { - return httpErrors.NewNotFoundError(err, "P_FAILED_FETCH_POLICY_TEMPLATE", "") + return httpErrors.NewNotFoundError(err, "P_FAILED_FETCH_POLICY", "") } updateMap := make(map[string]interface{}) @@ -183,10 +248,72 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic return err } + if policyName != nil || templateId != nil || enforcementAction != nil || + parameters != nil || match != nil || targetClusterIds != nil { + + organization, err := u.organizationRepo.Get(ctx, organizationId) + + if err != nil { + return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + + if policyName != nil { + err = policytemplate.DeleteTksPolicyCR(ctx, organization.PrimaryClusterId, *policyName) + + if err != nil { + log.Errorf(ctx, "failed to delete TksPolicyCR: %v", err) + return httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") + + } + } + + policy, err := u.repo.GetByID(ctx, organizationId, policyId) + if err != nil { + return httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "") + } + + policyCR := policytemplate.PolicyToTksPolicyCR(policy) + + err = policytemplate.ApplyTksPolicyCR(ctx, organization.PrimaryClusterId, policyCR) + + if err != nil { + log.Errorf(ctx, "failed to apply TksPolicyCR: %v", err) + return err + } + + return err + } + return nil } func (u *PolicyUsecase) Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) { + policy, err := u.repo.GetByID(ctx, organizationId, policyId) + if err != nil { + return err + } + + organization, err := u.organizationRepo.Get(ctx, organizationId) + + if err != nil { + return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + + exists, err := policytemplate.ExistsTksPolicyCR(ctx, organization.PrimaryClusterId, policy.PolicyName) + if err != nil { + log.Errorf(ctx, "failed to check TksPolicyCR: %v", err) + return httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") + } + + if exists { + err = policytemplate.DeleteTksPolicyCR(ctx, organization.PrimaryClusterId, policy.PolicyName) + + if err != nil { + log.Errorf(ctx, "failed to delete TksPolicyCR: %v", err) + return httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") + } + } + return u.repo.Delete(ctx, organizationId, policyId) } @@ -194,6 +321,22 @@ func (u *PolicyUsecase) Get(ctx context.Context, organizationId string, policyId return u.repo.GetByID(ctx, organizationId, policyId) } +func (u *PolicyUsecase) GetForEdit(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) { + policy, err = u.repo.GetByID(ctx, organizationId, policyId) + + if err != nil { + return nil, err + } + + policyTemplate, err := u.templateRepo.GetByID(ctx, policy.TemplateId) + + if policyTemplate != nil { + policy.PolicyTemplate = *policyTemplate + } + + return policy, err +} + func (u *PolicyUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.Policy, error) { return u.repo.Fetch(ctx, organizationId, pg) } @@ -280,3 +423,265 @@ func (u *PolicyUsecase) GetMandatoryPolicies(ctx context.Context, organizationId return &out, nil } + +func (u *PolicyUsecase) ListClusterPolicyStatus(ctx context.Context, clusterId string, pg *pagination.Pagination) (policyStatuses []domain.ClusterPolicyStatusResponse, err error) { + policies, err := u.repo.FetchByClusterId(ctx, clusterId, pg) + + if err != nil { + return nil, err + } + + // policies가 빈 목록일 수도 있으므로 policy의 organization 정보는 못 가져올 수도 있음 + // 따라서 cluster의 Organization에서 primaryClusterId를 가져옴 + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) + if err != nil { + return nil, err + } + + primaryClusterId := cluster.Organization.PrimaryClusterId + + tksClusterCR, err := policytemplate.GetTksClusterCR(ctx, primaryClusterId, clusterId) + if err != nil { + return nil, err + } + + result := make([]domain.ClusterPolicyStatusResponse, len(*policies)) + + for i, policy := range *policies { + if err := serializer.Map(ctx, policy, &result[i]); err != nil { + continue + } + + result[i].PolicyId = policy.ID.String() + result[i].PolicyDescription = policy.Description + result[i].PolicyMandatory = policy.Mandatory + latestVersion, _ := u.templateRepo.GetLatestTemplateVersion(ctx, policy.TemplateId) + version, ok := tksClusterCR.Status.Templates[policy.PolicyTemplate.Kind] + + if ok { + result[i].TemplateCurrentVersion = version + } + + result[i].TemplateLatestVerson = latestVersion + result[i].TemplateDescription = policy.PolicyTemplate.Description + } + + return result, nil +} + +func (u *PolicyUsecase) UpdateClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID, + currentVersion string, targetVerson string) (err error) { + if currentVersion == targetVerson { + // 버전 동일, 할일 없음 + return nil + } + + latestTemplate, err := u.templateRepo.GetByID(ctx, policyTemplateId) + if err != nil { + return err + } + + if targetVerson != latestTemplate.Version { + return fmt.Errorf("targetVersion is not a latest version") + } + + currentTemplate, err := u.templateRepo.GetPolicyTemplateVersion(ctx, policyTemplateId, currentVersion) + if err != nil { + return err + } + + // 파라미터 호환성 검증, 파라미터 스키마가 동일하거나 추가된 필드만 있어야 하고 기존 필드는 이름, 타입이 유지되어야 함 + _, err = extractNewTemplateParameter(currentTemplate.ParametersSchema, latestTemplate.ParametersSchema) + if err != nil { + return err + } + + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) + if err != nil { + return err + } + + primaryClusterId := cluster.Organization.PrimaryClusterId + + resourceName := strings.ToLower(latestTemplate.Kind) + + tksPolicyTemplate, err := policytemplate.GetTksPolicyTemplateCR(ctx, primaryClusterId, resourceName) + + if err != nil { + return err + } + + if tksPolicyTemplate.Spec.ToLatest == nil { + tksPolicyTemplate.Spec.ToLatest = []string{} + } + + latestTemplateCR := policytemplate.PolicyTemplateToTksPolicyTemplateCR(latestTemplate) + tksPolicyTemplate.Spec = latestTemplateCR.Spec + + if !slices.Contains(tksPolicyTemplate.Spec.ToLatest, clusterId) { + tksPolicyTemplate.Spec.ToLatest = append(tksPolicyTemplate.Spec.ToLatest, clusterId) + } + + return policytemplate.UpdateTksPolicyTemplateCR(ctx, primaryClusterId, tksPolicyTemplate) +} + +func (u *PolicyUsecase) GetClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID) (clusterPolicyTemplateStatusResponse *domain.GetClusterPolicyTemplateStatusResponse, err error) { + policies, err := u.repo.FetchByClusterIdAndTemplaeId(ctx, clusterId, policyTemplateId) + + if err != nil { + return nil, err + } + + latestTemplate, err := u.templateRepo.GetByID(ctx, policyTemplateId) + if err != nil { + return nil, err + } + + // policies가 빈 목록일 수도 있으므로 policy의 organization 정보는 못 가져올 수도 있음 + // 따라서 cluster의 Organization에서 primaryClusterId를 가져옴 + cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) + if err != nil { + return nil, err + } + + primaryClusterId := cluster.Organization.PrimaryClusterId + + tksClusterCR, err := policytemplate.GetTksClusterCR(ctx, primaryClusterId, clusterId) + if err != nil { + return nil, err + } + + version, ok := tksClusterCR.Status.Templates[latestTemplate.Kind] + + if !ok { + return nil, fmt.Errorf("version not found in CR") + } + + currentTemplate, err := u.templateRepo.GetPolicyTemplateVersion(ctx, policyTemplateId, version) + if err != nil { + return nil, err + } + + updatedPolicyParameters, err := extractNewTemplateParameter(currentTemplate.ParametersSchema, latestTemplate.ParametersSchema) + + if err != nil { + return nil, err + } + + affectedPolicies := make([]domain.PolicyStatus, len(*policies)) + + for i, policy := range *policies { + affectedPolicies[i].PolicyId = policy.ID.String() + affectedPolicies[i].PolicyName = policy.PolicyName + + parsed, err := parseParameter(currentTemplate.ParametersSchema, latestTemplate.ParametersSchema, policy.Parameters) + + if err != nil { + return nil, err + } + affectedPolicies[i].PolicyParameters = parsed + } + + result := domain.GetClusterPolicyTemplateStatusResponse{ + TemplateName: currentTemplate.TemplateName, + TemplateId: policyTemplateId.String(), + TemplateDescription: currentTemplate.Description, + TemplateLatestVerson: latestTemplate.Version, + TemplateCurrentVersion: currentTemplate.Version, + TemplateLatestVersonReleaseDate: latestTemplate.CreatedAt, + AffectedPolicies: affectedPolicies, + UpdatedPolicyParameters: updatedPolicyParameters, + } + + return &result, nil +} + +func extractNewTemplateParameter(paramdefs []*domain.ParameterDef, newParamDefs []*domain.ParameterDef) (policyParameters []domain.UpdatedPolicyTemplateParameter, err error) { + diffParamDef, err := policytemplate.GetNewParamDefs(paramdefs, newParamDefs) + + if err != nil { + return nil, err + } + + results := []domain.UpdatedPolicyTemplateParameter{} + + // 새버전에 추가된 파라미터 + for _, paramdef := range diffParamDef { + result := domain.UpdatedPolicyTemplateParameter{ + Name: paramdef.Key, + Type: paramdef.Type, + Value: paramdef.DefaultValue, + } + + results = append(results, result) + } + + return results, nil +} + +func parseParameter(paramdefs []*domain.ParameterDef, newParamDefs []*domain.ParameterDef, parameter string) (policyParameters []domain.PolicyParameter, err error) { + diffParamDef, err := policytemplate.GetNewParamDefs(paramdefs, newParamDefs) + + if err != nil { + return nil, err + } + + paramMap, err := parameterToValueMap(parameter) + if err != nil { + return nil, err + } + + // 기존 파라미터 + results := []domain.PolicyParameter{} + for _, paramdef := range paramdefs { + result := domain.PolicyParameter{ + Name: paramdef.Key, + Type: paramdef.Type, + Value: paramdef.DefaultValue, + Updatable: false, + } + + if val, ok := paramMap[paramdef.Key]; ok { + result.Value = val + } + + results = append(results, result) + } + + // 새버전에 추가된 파라미터 + for _, paramdef := range diffParamDef { + result := domain.PolicyParameter{ + Name: paramdef.Key, + Type: paramdef.Type, + Value: paramdef.DefaultValue, + Updatable: true, + } + + results = append(results, result) + } + + return results, nil +} + +func parameterToValueMap(parameters string) (parameterMap map[string]string, err error) { + var obj map[string]interface{} + result := map[string]string{} + + err = json.Unmarshal([]byte(parameters), &obj) + + for k, v := range obj { + value, err := json.Marshal(v) + + if err != nil { + return nil, err + } + + result[k] = string(value) + } + + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index e57fd772..f4ea64e1 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -34,12 +34,12 @@ type SimplePolicyTemplateResponse struct { } type CreatePolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` - Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` - Deprecated bool `json:"deprecated" example:"false"` - Description string `json:"description,omitempty" example:"이 정책은 ..."` - ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` + TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" Rego string `json:"rego" example:"rego 코드" validate:"required"` @@ -150,6 +150,16 @@ type ParameterDef struct { IsArray bool `json:"isArray" examples:"true"` } +func (pd *ParameterDef) GetChildrenByName(name string) *ParameterDef { + for _, child := range pd.Children { + if child.Key == name { + return child + } + } + + return nil +} + type RegoCompileRequest struct { Rego string `json:"rego" example:"Rego 코드" validate:"required"` Libs []string `json:"libs,omitempty"` diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index ddb45490..65b13e63 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -36,13 +36,14 @@ type PolicyResponse struct { TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` Mandatory bool `json:"mandatory"` - PolicyName string `json:"policyName" example:"label 정책"` - Description string `json:"description"` - TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - TemplateName string `json:"templateName" example:"필수 Label 검사"` - EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun"` - Parameters string `json:"parameters" example:"\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\""` - Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` + PolicyName string `json:"policyName" example:"label 정책"` + Description string `json:"description"` + TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + TemplateName string `json:"templateName" example:"필수 Label 검사"` + EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun"` + Parameters string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"}"` + FilledParameters []*ParameterDef `json:"filledParameters"` + Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } @@ -117,3 +118,66 @@ type MandatoryPolicyPatchInfo struct { type SetMandatoryPoliciesRequest struct { Policies []MandatoryPolicyPatchInfo `json:"policies"` } + +type ClusterPolicyStatusResponse struct { + PolicyName string `json:"policyName" example:"org 레이블 요구"` + PolicyId string `json:"policyId" example:"0091fe9b-e44b-423d-9562-ac2b73089593"` + PolicyDescription string `json:"policyDescription" example:"org 레이블 설정 여부 검사"` + PolicyMandatory bool `json:"policyMandatory"` + TemplateName string `json:"templateName" example:"레이블 요구"` + TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` + TemplateDescription string `json:"templateDescription" example:"파라미터로 설정된 레이블 검사"` + TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` + TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` +} + +type ListClusterPolicyStatusResponse struct { + Polices []ClusterPolicyStatusResponse `json:"polices"` +} + +type GetClusterPolicyTemplateStatusResponse struct { + TemplateName string `json:"templateName" example:"레이블 요구"` + TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` + TemplateDescription string `json:"templateDescription" example:"파라미터로 설정된 레이블 검사"` + TemplateMandatory bool `json:"templateMandatory"` + TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` + TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` + TemplateLatestVersonReleaseDate time.Time `json:"templateLatestVersonReleaseDate" format:"date-time"` + UpdatedPolicyParameters []UpdatedPolicyTemplateParameter `json:"updatedPolicyParameters"` + AffectedPolicies []PolicyStatus `json:"affectedPolicies"` +} + +type PolicyStatus struct { + PolicyId string `json:"policyId" example:"0091fe9b-e44b-423d-9562-ac2b73089593"` + PolicyName string `json:"policyName"` + PolicyParameters []PolicyParameter `json:"policyPolicyParameters"` +} + +type UpdatedPolicyTemplateParameter struct { + Name string `json:"name"` + Type string `json:"type"` + Value string `json:"value"` +} + +type PolicyParameter struct { + Name string `json:"name"` + Type string `json:"type"` + Value string `json:"value"` + Updatable bool `json:"updatable"` +} + +type UpdatedPolicyParameters struct { + Name string `json:"name"` + Value string `json:"value"` +} + +type PolicyUpdate struct { + PolicyId string `json:"policyId" example:"0091fe9b-e44b-423d-9562-ac2b73089593"` + UpdatedPolicyParameters []UpdatedPolicyParameters `json:"updatedPolicyParameters"` +} + +type UpdateClusterPolicyTemplateStatusRequest struct { + TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` + TemplateTargetVerson string `json:"templateTargetVerson" example:"v1.0.3"` + // PolicyUpdate []PolicyUpdate `json:"policyUpdate"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 06444f8d..29ab66ad 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -132,6 +132,10 @@ var errorMap = map[ErrorCode]string{ "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", "P_NOT_FOUND_POLICY": "정책이 존재하지 않습니다.", "P_INVALID_POLICY_NAME": "유효하지 않은 정책 이름입니다. 정책 이름을 확인하세요.", + "P_FAILED_FETCH_POLICY": "정책 ID에 해당하는 정책을 가져오는데 실패했습니다.", + "P_FAILED_FETCH_CLUSTER": "정책의 클러스터 정보를 가져오는데 실패했습니다.", + "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", + "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", } func (m ErrorCode) GetText() string { From 4b1c08cd96a6b7630afb257a233e38c1d208bcf8 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 2 Apr 2024 11:10:55 +0900 Subject: [PATCH 204/502] trivial. fix constraint orgniazations and users --- api/swagger/docs.go | 372 ++++++++++++++++++++++++++++++- api/swagger/swagger.json | 372 ++++++++++++++++++++++++++++++- api/swagger/swagger.yaml | 247 +++++++++++++++++++- internal/model/organization.go | 2 +- internal/usecase/organization.go | 26 +++ 5 files changed, 1015 insertions(+), 4 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 42dfe176..d8548d1c 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -2267,6 +2267,169 @@ const docTemplate = `{ } } }, + "/clusters/{clusterId}/policy-status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ClusterPolicyStatus" + ], + "summary": "[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", + "parameters": [ + { + "type": "string", + "description": "클러스터 식별자(uuid)", + "name": "clusterId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse" + } + } + } + } + }, + "/clusters/{clusterId}/policy-templates/{templateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ClusterPolicyStatus" + ], + "summary": "[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", + "parameters": [ + { + "type": "string", + "description": "클러스터 식별자(uuid)", + "name": "clusterId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "templateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse" + } + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ClusterPolicyStatus" + ], + "summary": "[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트", + "parameters": [ + { + "type": "string", + "description": "클러스터 식별자(uuid)", + "name": "clusterId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "templateId", + "in": "path", + "required": true + }, + { + "description": "update cluster policy template status request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/clusters/{clusterId}/site-values": { "get": { "security": [ @@ -3910,6 +4073,50 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/policies/{policyId}/edit": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 정보를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[GetPolicy] 정책 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse" + } + } + } + } + }, "/organizations/{organizationId}/policy-templates": { "get": { "security": [ @@ -9489,6 +9696,46 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse": { + "type": "object", + "properties": { + "policyDescription": { + "type": "string", + "example": "org 레이블 설정 여부 검사" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyMandatory": { + "type": "boolean" + }, + "policyName": { + "type": "string", + "example": "org 레이블 요구" + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ClusterResponse": { "type": "object", "properties": { @@ -10859,6 +11106,50 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse": { + "type": "object", + "properties": { + "affectedPolicies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" + } + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateLatestVersonReleaseDate": { + "type": "string", + "format": "date-time" + }, + "templateMandatory": { + "type": "boolean" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + }, + "updatedPolicyParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { "type": "object", "properties": { @@ -11437,6 +11728,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse": { + "type": "object", + "properties": { + "polices": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -11828,6 +12130,23 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyParameter": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatable": { + "type": "boolean" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyResponse": { "type": "object", "properties": { @@ -11844,6 +12163,12 @@ const docTemplate = `{ "enforcementAction": { "type": "string" }, + "filledParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, "id": { "type": "string", "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" @@ -11862,7 +12187,7 @@ const docTemplate = `{ }, "parameters": { "type": "string", - "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"}" }, "policyName": { "type": "string", @@ -11895,6 +12220,24 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyStatus": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyName": { + "type": "string" + }, + "policyPolicyParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyParameter" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse": { "type": "object", "properties": { @@ -13180,6 +13523,19 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest": { + "type": "object", + "properties": { + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateTargetVerson": { + "type": "string", + "example": "v1.0.3" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest": { "type": "object", "properties": { @@ -13729,6 +14085,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index e44189d6..7b2293c4 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -2261,6 +2261,169 @@ } } }, + "/clusters/{clusterId}/policy-status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ClusterPolicyStatus" + ], + "summary": "[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", + "parameters": [ + { + "type": "string", + "description": "클러스터 식별자(uuid)", + "name": "clusterId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse" + } + } + } + } + }, + "/clusters/{clusterId}/policy-templates/{templateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ClusterPolicyStatus" + ], + "summary": "[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", + "parameters": [ + { + "type": "string", + "description": "클러스터 식별자(uuid)", + "name": "clusterId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "templateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse" + } + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ClusterPolicyStatus" + ], + "summary": "[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트", + "parameters": [ + { + "type": "string", + "description": "클러스터 식별자(uuid)", + "name": "clusterId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "templateId", + "in": "path", + "required": true + }, + { + "description": "update cluster policy template status request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/clusters/{clusterId}/site-values": { "get": { "security": [ @@ -3904,6 +4067,50 @@ } } }, + "/organizations/{organizationId}/policies/{policyId}/edit": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 정보를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[GetPolicy] 정책 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 식별자(uuid)", + "name": "policyId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse" + } + } + } + } + }, "/organizations/{organizationId}/policy-templates": { "get": { "security": [ @@ -9483,6 +9690,46 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse": { + "type": "object", + "properties": { + "policyDescription": { + "type": "string", + "example": "org 레이블 설정 여부 검사" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyMandatory": { + "type": "boolean" + }, + "policyName": { + "type": "string", + "example": "org 레이블 요구" + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ClusterResponse": { "type": "object", "properties": { @@ -10853,6 +11100,50 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse": { + "type": "object", + "properties": { + "affectedPolicies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" + } + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateLatestVersonReleaseDate": { + "type": "string", + "format": "date-time" + }, + "templateMandatory": { + "type": "boolean" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + }, + "updatedPolicyParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { "type": "object", "properties": { @@ -11431,6 +11722,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse": { + "type": "object", + "properties": { + "polices": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -11822,6 +12124,23 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyParameter": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatable": { + "type": "boolean" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyResponse": { "type": "object", "properties": { @@ -11838,6 +12157,12 @@ "enforcementAction": { "type": "string" }, + "filledParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, "id": { "type": "string", "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" @@ -11856,7 +12181,7 @@ }, "parameters": { "type": "string", - "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"}" }, "policyName": { "type": "string", @@ -11889,6 +12214,24 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyStatus": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyName": { + "type": "string" + }, + "policyPolicyParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyParameter" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse": { "type": "object", "properties": { @@ -13174,6 +13517,19 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest": { + "type": "object", + "properties": { + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateTargetVerson": { + "type": "string", + "example": "v1.0.3" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest": { "type": "object", "properties": { @@ -13723,6 +14079,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 70743dae..ac85f22d 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -546,6 +546,35 @@ definitions: validity: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse: + properties: + policyDescription: + example: org 레이블 설정 여부 검사 + type: string + policyId: + example: 0091fe9b-e44b-423d-9562-ac2b73089593 + type: string + policyMandatory: + type: boolean + policyName: + example: org 레이블 요구 + type: string + templateCurrentVersion: + example: v1.0.1 + type: string + templateDescription: + example: 파라미터로 설정된 레이블 검사 + type: string + templateId: + example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 + type: string + templateLatestVerson: + example: v1.0.3 + type: string + templateName: + example: 레이블 요구 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ClusterResponse: properties: byoClusterEndpointHost: @@ -1470,6 +1499,37 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse: + properties: + affectedPolicies: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus' + type: array + templateCurrentVersion: + example: v1.0.1 + type: string + templateDescription: + example: 파라미터로 설정된 레이블 검사 + type: string + templateId: + example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 + type: string + templateLatestVerson: + example: v1.0.3 + type: string + templateLatestVersonReleaseDate: + format: date-time + type: string + templateMandatory: + type: boolean + templateName: + example: 레이블 요구 + type: string + updatedPolicyParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse: properties: cluster: @@ -1841,6 +1901,13 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse: + properties: + polices: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse: properties: organizations: @@ -2099,6 +2166,17 @@ definitions: value: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyParameter: + properties: + name: + type: string + type: + type: string + updatable: + type: boolean + value: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.PolicyResponse: properties: createdAt: @@ -2110,6 +2188,10 @@ definitions: type: string enforcementAction: type: string + filledParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array id: example: d98ef5f1-4a68-4047-a446-2207787ce3ff type: string @@ -2122,7 +2204,7 @@ definitions: refer: match.Match type: object parameters: - example: '"labels":{"key":"owner","allowedRegex:^[a-zA-Z]+.agilebank.demo$}"' + example: '{"labels":{"key":"owner","allowedRegex:^[a-zA-Z]+.agilebank.demo$}"}' type: string policyName: example: label 정책 @@ -2146,6 +2228,18 @@ definitions: updator: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyStatus: + properties: + policyId: + example: 0091fe9b-e44b-423d-9562-ac2b73089593 + type: string + policyName: + type: string + policyPolicyParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyParameter' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse: properties: createdAt: @@ -3001,6 +3095,15 @@ definitions: description: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest: + properties: + templateCurrentVersion: + example: v1.0.1 + type: string + templateTargetVerson: + example: v1.0.3 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest: properties: groupName: @@ -3369,6 +3472,15 @@ definitions: type: string type: object type: object + github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter: + properties: + name: + type: string + type: + type: string + value: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest: properties: email: @@ -5163,6 +5275,111 @@ paths: summary: Get nodes information for BYOH tags: - Clusters + /clusters/{clusterId}/policy-status: + get: + consumes: + - application/json + description: 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. + parameters: + - description: 클러스터 식별자(uuid) + in: path + name: clusterId + required: true + type: string + - description: pageSize + in: query + name: pageSize + type: string + - description: pageNumber + in: query + name: pageNumber + type: string + - description: sortColumn + in: query + name: sortColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse' + security: + - JWT: [] + summary: '[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회' + tags: + - ClusterPolicyStatus + /clusters/{clusterId}/policy-templates/{templateId}: + get: + consumes: + - application/json + description: 템플릿의 클러스터 버전 등 상태를 조회한다. + parameters: + - description: 클러스터 식별자(uuid) + in: path + name: clusterId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: templateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse' + security: + - JWT: [] + summary: '[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회' + tags: + - ClusterPolicyStatus + patch: + consumes: + - application/json + description: 해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다. + parameters: + - description: 클러스터 식별자(uuid) + in: path + name: clusterId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: templateId + required: true + type: string + - description: update cluster policy template status request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트' + tags: + - ClusterPolicyStatus /clusters/{clusterId}/site-values: get: consumes: @@ -6184,6 +6401,34 @@ paths: summary: '[UpdatePolicyTargetClusters] 정책 적용 대상 클러스터 수정' tags: - Policy + /organizations/{organizationId}/policies/{policyId}/edit: + get: + consumes: + - application/json + description: 정책 정보를 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 식별자(uuid) + in: path + name: policyId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse' + security: + - JWT: [] + summary: '[GetPolicy] 정책 조회' + tags: + - Policy /organizations/{organizationId}/policies/name/{policyName}/existence: get: consumes: diff --git a/internal/model/organization.go b/internal/model/organization.go index 5f466a31..f912f774 100644 --- a/internal/model/organization.go +++ b/internal/model/organization.go @@ -27,5 +27,5 @@ type Organization struct { SystemNotificationTemplateIds []uuid.UUID `gorm:"-:all"` ClusterCount int `gorm:"-:all"` AdminId *uuid.UUID - Admin *User `gorm:"foreignKey:AdminId"` + Admin *User `gorm:"-:all"` } diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 9fa70a56..ea794543 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -32,6 +32,7 @@ type IOrganizationUsecase interface { type OrganizationUsecase struct { repo repository.IOrganizationRepository + userRepo repository.IUserRepository roleRepo repository.IRoleRepository clusterRepo repository.IClusterRepository stackTemplateRepo repository.IStackTemplateRepository @@ -43,6 +44,7 @@ type OrganizationUsecase struct { func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClient, kc keycloak.IKeycloak) IOrganizationUsecase { return &OrganizationUsecase{ repo: r.Organization, + userRepo: r.User, roleRepo: r.Role, clusterRepo: r.Cluster, stackTemplateRepo: r.StackTemplate, @@ -99,6 +101,22 @@ func (u *OrganizationUsecase) Fetch(ctx context.Context, pg *pagination.Paginati if err != nil { return nil, err } + + // Make Admin object + users, err := u.userRepo.List(ctx) + if err == nil { + for i, organization := range *organizations { + if organization.AdminId == nil { + continue + } + for _, user := range *users { + if user.ID == *organization.AdminId { + (*organizations)[i].Admin = &user + } + } + } + } + return organizations, nil } func (u *OrganizationUsecase) Get(ctx context.Context, organizationId string) (out model.Organization, err error) { @@ -107,6 +125,14 @@ func (u *OrganizationUsecase) Get(ctx context.Context, organizationId string) (o return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") } + // Make Admin object + if out.AdminId != nil { + admin, err := u.userRepo.GetByUuid(ctx, *out.AdminId) + if err == nil { + out.Admin = &admin + } + } + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, uuid.Nil, nil) if err != nil { log.Info(ctx, err) From 164fc5502df7108922f06b568e42ce245ec8c9a7 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 2 Apr 2024 11:27:53 +0900 Subject: [PATCH 205/502] trivial. add TargetUsers to GetSystemNotificationRule API --- api/swagger/docs.go | 6 ++++ api/swagger/swagger.json | 6 ++++ api/swagger/swagger.yaml | 4 +++ .../delivery/http/system-notification-rule.go | 7 ++++ pkg/domain/stack.go | 33 ++++++++++--------- 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index d8548d1c..61c697f6 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -10430,6 +10430,12 @@ const docTemplate = `{ "name": { "type": "string" }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, "stackTemplateId": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 7b2293c4..058f2406 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -10424,6 +10424,12 @@ "name": { "type": "string" }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, "stackTemplateId": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ac85f22d..7b9152ce 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1044,6 +1044,10 @@ definitions: type: string name: type: string + policyIds: + items: + type: string + type: array stackTemplateId: type: string tksCpNode: diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 5152381d..c7b354d2 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -181,6 +181,13 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons log.Info(r.Context(), err) } + out.SystemNotificationRule.TargetUsers = make([]domain.SimpleUserResponse, len(systemNotificationRule.TargetUsers)) + for i, targetUser := range systemNotificationRule.TargetUsers { + if err := serializer.Map(r.Context(), targetUser, &out.SystemNotificationRule.TargetUsers[i]); err != nil { + log.Info(r.Context(), err) + } + } + out.SystemNotificationRule.SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) for i, condition := range systemNotificationRule.SystemNotificationConditions { if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRule.SystemNotificationConditions[i]); err != nil { diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index c56abc48..82cb8e66 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -81,22 +81,23 @@ type StackStepStatus struct { } type CreateStackRequest struct { - Name string `json:"name" validate:"required,name,rfc1123"` - Description string `json:"description"` - ClusterId string `json:"clusterId"` - CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` - StackTemplateId string `json:"stackTemplateId" validate:"required"` - CloudAccountId string `json:"cloudAccountId"` - ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` - TksCpNode int `json:"tksCpNode"` - TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` - TksCpNodeType string `json:"tksCpNodeType,omitempty"` - TksInfraNode int `json:"tksInfraNode"` - TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` - TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` - TksUserNode int `json:"tksUserNode"` - TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` - TksUserNodeType string `json:"tksUserNodeType,omitempty"` + Name string `json:"name" validate:"required,name,rfc1123"` + Description string `json:"description"` + ClusterId string `json:"clusterId"` + CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + CloudAccountId string `json:"cloudAccountId"` + ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` + PolicyIds []string `json:"policyIds,omitempty"` + TksCpNode int `json:"tksCpNode"` + TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` + TksCpNodeType string `json:"tksCpNodeType,omitempty"` + TksInfraNode int `json:"tksInfraNode"` + TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` + TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` + TksUserNode int `json:"tksUserNode"` + TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` + TksUserNodeType string `json:"tksUserNodeType,omitempty"` } type CreateStackResponse struct { From 42ec7059750644f5d710c7ee2059bac4903c1310 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 2 Apr 2024 12:53:21 +0900 Subject: [PATCH 206/502] =?UTF-8?q?PolicyTemplate=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=82=A4=EB=A7=88=EA=B0=80=20=EC=82=AC=EB=9D=BC?= =?UTF-8?q?=EC=A7=80=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/domain/admin/policy-template.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index 9c56af9c..c3d9cf46 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -21,15 +21,15 @@ type PolicyTemplateResponse struct { CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - TemplateName string `json:"templateName" example:"필수 Label 검사"` - Kind string `json:"kind" example:"K8sRequiredLabels"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` - Deprecated bool `json:"deprecated" example:"false"` - Version string `json:"version,omitempty" example:"v1.0.1"` - Description string `json:"description,omitempty" example:"이 정책은 ..."` - ParametersSchema []domain.ParameterDef `json:"parametersSchema,omitempty"` - Rego string `json:"rego" example:"rego 코드"` - Libs []string `json:"libs" example:"rego 코드"` + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Kind string `json:"kind" example:"K8sRequiredLabels"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Version string `json:"version,omitempty" example:"v1.0.1"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` } From bc0476cb6f681a7f08b355f5907beb3d868f9e95 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 2 Apr 2024 15:49:58 +0900 Subject: [PATCH 207/502] =?UTF-8?q?match=EC=A0=88=EC=9D=84=20Raw=20YAML?= =?UTF-8?q?=EB=A1=9C=20=EC=84=A4=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/swagger/docs.go | 86 ++++++++++++++------- api/swagger/swagger.json | 86 ++++++++++++++------- api/swagger/swagger.yaml | 59 +++++++++----- internal/delivery/http/policy.go | 37 ++++++++- internal/model/policy.go | 1 + internal/policy-template/policy-operator.go | 12 +++ internal/usecase/policy.go | 10 ++- pkg/domain/policy.go | 27 ++++--- pkg/httpErrors/errorCode.go | 1 + 9 files changed, 232 insertions(+), 87 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 61c697f6..68d13e11 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -10194,23 +10194,22 @@ const docTemplate = `{ "type": "string" }, "enforcementAction": { - "type": "string" + "type": "string", + "example": "deny" }, "mandatory": { "type": "boolean" }, "match": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "refer": "match.Match" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" + }, + "matchYaml": { + "type": "string", + "example": "namespaces:\r\n- testns1" }, "parameters": { "type": "string", - "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" }, "policyName": { "type": "string", @@ -11734,6 +11733,23 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Kinds": { + "type": "object", + "properties": { + "apiGroups": { + "type": "array", + "items": { + "type": "string" + } + }, + "kinds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse": { "type": "object", "properties": { @@ -11974,6 +11990,29 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Match": { + "type": "object", + "properties": { + "excludedNamespaces": { + "type": "array", + "items": { + "type": "string" + } + }, + "kinds": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Kinds" + } + }, + "namespaces": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { "type": "object", "properties": { @@ -12167,7 +12206,8 @@ const docTemplate = `{ "type": "string" }, "enforcementAction": { - "type": "string" + "type": "string", + "example": "deny" }, "filledParameters": { "type": "array", @@ -12183,17 +12223,14 @@ const docTemplate = `{ "type": "boolean" }, "match": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "refer": "match.Match" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" + }, + "matchYaml": { + "type": "string" }, "parameters": { "type": "string", - "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"}" + "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" }, "policyName": { "type": "string", @@ -13725,17 +13762,14 @@ const docTemplate = `{ "type": "boolean" }, "match": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "refer": "match.Match" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" + }, + "matchYaml": { + "type": "string" }, "parameters": { "type": "string", - "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" }, "policyName": { "type": "string", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 058f2406..9fa4a0f9 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -10188,23 +10188,22 @@ "type": "string" }, "enforcementAction": { - "type": "string" + "type": "string", + "example": "deny" }, "mandatory": { "type": "boolean" }, "match": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "refer": "match.Match" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" + }, + "matchYaml": { + "type": "string", + "example": "namespaces:\r\n- testns1" }, "parameters": { "type": "string", - "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" }, "policyName": { "type": "string", @@ -11728,6 +11727,23 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Kinds": { + "type": "object", + "properties": { + "apiGroups": { + "type": "array", + "items": { + "type": "string" + } + }, + "kinds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse": { "type": "object", "properties": { @@ -11968,6 +11984,29 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Match": { + "type": "object", + "properties": { + "excludedNamespaces": { + "type": "array", + "items": { + "type": "string" + } + }, + "kinds": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Kinds" + } + }, + "namespaces": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { "type": "object", "properties": { @@ -12161,7 +12200,8 @@ "type": "string" }, "enforcementAction": { - "type": "string" + "type": "string", + "example": "deny" }, "filledParameters": { "type": "array", @@ -12177,17 +12217,14 @@ "type": "boolean" }, "match": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "refer": "match.Match" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" + }, + "matchYaml": { + "type": "string" }, "parameters": { "type": "string", - "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"}" + "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" }, "policyName": { "type": "string", @@ -13719,17 +13756,14 @@ "type": "boolean" }, "match": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "refer": "match.Match" - } + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" + }, + "matchYaml": { + "type": "string" }, "parameters": { "type": "string", - "example": "\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"" + "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" }, "policyName": { "type": "string", diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 7b9152ce..8656e906 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -885,17 +885,17 @@ definitions: description: type: string enforcementAction: + example: deny type: string mandatory: type: boolean match: - additionalProperties: - type: string - example: - refer: match.Match - type: object + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match' + matchYaml: + example: "namespaces:\r\n- testns1" + type: string parameters: - example: '"labels":{"key":"owner","allowedRegex:^[a-zA-Z]+.agilebank.demo$}"' + example: '{"labels":{"key":"owner","allowedRegex":"test*"}' type: string policyName: example: label 정책 @@ -1905,6 +1905,17 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.Kinds: + properties: + apiGroups: + items: + type: string + type: array + kinds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse: properties: polices: @@ -2064,6 +2075,21 @@ definitions: example: 레이블 요구 type: string type: object + github_com_openinfradev_tks-api_pkg_domain.Match: + properties: + excludedNamespaces: + items: + type: string + type: array + kinds: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Kinds' + type: array + namespaces: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse: properties: children: @@ -2191,6 +2217,7 @@ definitions: description: type: string enforcementAction: + example: deny type: string filledParameters: items: @@ -2202,13 +2229,11 @@ definitions: mandatory: type: boolean match: - additionalProperties: - type: string - example: - refer: match.Match - type: object + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match' + matchYaml: + type: string parameters: - example: '{"labels":{"key":"owner","allowedRegex:^[a-zA-Z]+.agilebank.demo$}"}' + example: '{"labels":{"key":"owner","allowedRegex":"test*"}' type: string policyName: example: label 정책 @@ -3231,13 +3256,11 @@ definitions: mandatory: type: boolean match: - additionalProperties: - type: string - example: - refer: match.Match - type: object + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match' + matchYaml: + type: string parameters: - example: '"labels":{"key":"owner","allowedRegex:^[a-zA-Z]+.agilebank.demo$}"' + example: '{"labels":{"key":"owner","allowedRegex":"test*"}' type: string policyName: example: label 정책 diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 1bcbccc1..30a58f5f 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -14,6 +14,7 @@ import ( "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" + "gopkg.in/yaml.v3" ) type PolicyHandler struct { @@ -72,6 +73,22 @@ func (h *PolicyHandler) CreatePolicy(w http.ResponseWriter, r *http.Request) { return } + if input.Match != nil && input.MatchYaml != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("both match and match yaml specified"), "P_INVALID_MATCH", "")) + return + } + + if input.MatchYaml != nil { + var match domain.Match + + err := yaml.Unmarshal([]byte(*input.MatchYaml), &match) + + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match yaml error: %s", err), "P_INVALID_MATCH", "")) + return + } + } + var dto model.Policy if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) @@ -134,6 +151,22 @@ func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { return } + if input.Match != nil && input.MatchYaml != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("both match and match yaml specified"), "P_INVALID_MATCH", "")) + return + } + + if input.MatchYaml != nil { + var match domain.Match + + err := yaml.Unmarshal([]byte(*input.MatchYaml), &match) + + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match yaml error: %s", err), "P_INVALID_MATCH", "")) + return + } + } + var templateId *uuid.UUID = nil if input.TemplateId != nil { @@ -147,8 +180,8 @@ func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { } err = h.usecase.Update(r.Context(), organizationId, id, - input.Mandatory, input.PolicyName, &input.Description, templateId, input.EnforcementAction, - input.Parameters, input.Match, input.TargetClusterIds) + input.Mandatory, input.PolicyName, input.Description, templateId, input.EnforcementAction, + input.Parameters, input.Match, input.MatchYaml, input.TargetClusterIds) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) diff --git a/internal/model/policy.go b/internal/model/policy.go index 5d997d24..48f1ce8a 100644 --- a/internal/model/policy.go +++ b/internal/model/policy.go @@ -25,6 +25,7 @@ type Policy struct { Parameters string `gorm:"type:text"` PolicyMatch string `gorm:"type:text"` + MatchYaml *string `gorm:"type:text"` Match *domain.Match `gorm:"-:all"` TemplateName string `gorm:"-:all"` diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index d1072c21..66fb30af 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -4,6 +4,8 @@ import ( "strings" "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/pkg/domain" + "gopkg.in/yaml.v3" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -18,6 +20,16 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { labels := map[string]string{} labels["app.kubernetes.io/part-of"] = "tks-policy-operator" + if policy.MatchYaml != nil { + var match domain.Match + + err := yaml.Unmarshal([]byte(*policy.MatchYaml), &match) + + if err != nil { + policy.Match = &match + } + } + return &TKSPolicy{ TypeMeta: metav1.TypeMeta{ APIVersion: "tkspolicy.openinfradev.github.io/v1", diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index f76f7b54..5e6f7cb2 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -24,7 +24,7 @@ type IPolicyUsecase interface { Create(ctx context.Context, organizationId string, dto model.Policy) (policyId uuid.UUID, err error) Update(ctx context.Context, organizationId string, policyId uuid.UUID, mandatory *bool, policyName *string, description *string, templateId *uuid.UUID, enforcementAction *string, - parameters *string, match *domain.Match, targetClusterIds *[]string) (err error) + parameters *string, match *domain.Match, matchYaml *string, targetClusterIds *[]string) (err error) Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) Get(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) GetForEdit(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) @@ -163,7 +163,7 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, policyId uuid.UUID, mandatory *bool, policyName *string, description *string, templateId *uuid.UUID, enforcementAction *string, - parameters *string, match *domain.Match, targetClusterIds *[]string) (err error) { + parameters *string, match *domain.Match, matchYaml *string, targetClusterIds *[]string) (err error) { user, ok := request.UserFrom(ctx) if !ok { @@ -217,8 +217,12 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic updateMap["parameters"] = parameters } - if parameters != nil { + if matchYaml != nil { + updateMap["match_yaml"] = matchYaml + updateMap["policy_match"] = nil + } else if match != nil { updateMap["policy_match"] = match.JSON() + updateMap["match_yaml"] = nil } var newTargetClusters *[]model.Cluster = nil diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index 65b13e63..8c647852 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -40,10 +40,11 @@ type PolicyResponse struct { Description string `json:"description"` TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` TemplateName string `json:"templateName" example:"필수 Label 검사"` - EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun"` - Parameters string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\"}"` + EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun" example:"deny"` + Parameters string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` FilledParameters []*ParameterDef `json:"filledParameters"` - Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` + Match *Match `json:"match,omitempty"` + MatchYaml *string `json:"matchYaml,omitempty" "namespaces:\r\n- testns1"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } @@ -51,12 +52,13 @@ type CreatePolicyRequest struct { TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` Mandatory bool `json:"mandatory"` - PolicyName string `json:"policyName" example:"label 정책"` - Description string `json:"description"` - TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun"` - Parameters string `json:"parameters" example:"\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\""` - Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` + PolicyName string `json:"policyName" example:"label 정책"` + Description string `json:"description"` + TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun" example:"deny"` + Parameters string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` + Match *Match `json:"match,omitempty"` + MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } @@ -69,11 +71,12 @@ type UpdatePolicyRequest struct { Mandatory *bool `json:"mandatory,omitempty"` PolicyName *string `json:"policyName,omitempty" example:"label 정책"` - Description string `json:"description"` + Description *string `json:"description"` TemplateId *string `json:"templateId,omitempty" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` EnforcementAction *string `json:"enforcementAction,omitempty" enum:"warn,deny,dryrun"` - Parameters *string `json:"parameters,omitempty" example:"\"labels\":{\"key\":\"owner\",\"allowedRegex:^[a-zA-Z]+.agilebank.demo$}\""` - Match *Match `json:"match,omitempty" swaggertype:"object,string" example:"refer:match.Match"` + Parameters *string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` + Match *Match `json:"match,omitempty"` + MatchYaml *string `json:"matchYaml,omitempty"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 29ab66ad..0adb6c9f 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -132,6 +132,7 @@ var errorMap = map[ErrorCode]string{ "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", "P_NOT_FOUND_POLICY": "정책이 존재하지 않습니다.", "P_INVALID_POLICY_NAME": "유효하지 않은 정책 이름입니다. 정책 이름을 확인하세요.", + "P_INVALID_MATCH": "유효하지 않은 match 설정입니다. match 설정을 확인하세요.", "P_FAILED_FETCH_POLICY": "정책 ID에 해당하는 정책을 가져오는데 실패했습니다.", "P_FAILED_FETCH_CLUSTER": "정책의 클러스터 정보를 가져오는데 실패했습니다.", "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", From 0ec7d86572b4184a23ba5aa7a9d9b26af9ed6222 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 2 Apr 2024 15:52:04 +0900 Subject: [PATCH 208/502] =?UTF-8?q?lint=20=EC=97=90=EB=9F=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/domain/policy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index 8c647852..2b965c77 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -44,7 +44,7 @@ type PolicyResponse struct { Parameters string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` FilledParameters []*ParameterDef `json:"filledParameters"` Match *Match `json:"match,omitempty"` - MatchYaml *string `json:"matchYaml,omitempty" "namespaces:\r\n- testns1"` + MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } From 7efff850290314b8d8484cc670dbbd37286ce555 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 2 Apr 2024 22:07:18 +0900 Subject: [PATCH 209/502] feature. move kubernetes pkg --- api/swagger/docs.go | 3 ++- api/swagger/swagger.json | 3 ++- api/swagger/swagger.yaml | 1 + internal/model/system-notification-rule.go | 1 + internal/policy-template/tkscluster.go | 2 +- internal/policy-template/tkspolicy.go | 2 +- internal/policy-template/tkspolicytemplate.go | 2 +- internal/usecase/app-serve-app.go | 2 +- internal/usecase/cloud-account.go | 2 +- internal/usecase/cluster.go | 2 +- internal/usecase/dashboard.go | 2 +- internal/usecase/project.go | 2 +- internal/usecase/stack.go | 2 +- pkg/domain/system-notification-rule.go | 25 +++++++++++++++++++ {internal => pkg}/kubernetes/kubernetes.go | 0 .../kubernetes/kubernetes_test.go | 5 ++-- 16 files changed, 43 insertions(+), 13 deletions(-) rename {internal => pkg}/kubernetes/kubernetes.go (100%) rename {internal => pkg}/kubernetes/kubernetes_test.go (99%) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 68d13e11..89f1284e 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -12226,7 +12226,8 @@ const docTemplate = `{ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" }, "matchYaml": { - "type": "string" + "type": "string", + "example": "namespaces:\r\n- testns1" }, "parameters": { "type": "string", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 9fa4a0f9..751a13e4 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -12220,7 +12220,8 @@ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" }, "matchYaml": { - "type": "string" + "type": "string", + "example": "namespaces:\r\n- testns1" }, "parameters": { "type": "string", diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 8656e906..d5ae8da5 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2231,6 +2231,7 @@ definitions: match: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match' matchYaml: + example: "namespaces:\r\n- testns1" type: string parameters: example: '{"labels":{"key":"owner","allowedRegex":"test*"}' diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index 76a277ff..cfdbe12d 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -36,6 +36,7 @@ type SystemNotificationRule struct { MessageTitle string MessageContent string MessageActionProposal string + Status domain.SystemNotificationRuleStatus CreatorId *uuid.UUID `gorm:"type:uuid"` Creator *User `gorm:"foreignKey:CreatorId"` UpdatorId *uuid.UUID `gorm:"type:uuid"` diff --git a/internal/policy-template/tkscluster.go b/internal/policy-template/tkscluster.go index e4ce4a93..0fb2fa7f 100644 --- a/internal/policy-template/tkscluster.go +++ b/internal/policy-template/tkscluster.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" - "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/pkg/kubernetes" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" ) diff --git a/internal/policy-template/tkspolicy.go b/internal/policy-template/tkspolicy.go index d0999720..9c32892f 100644 --- a/internal/policy-template/tkspolicy.go +++ b/internal/policy-template/tkspolicy.go @@ -4,8 +4,8 @@ import ( "context" "encoding/json" - "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/kubernetes" "gopkg.in/yaml.v3" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/errors" diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index ed22103f..a561fb32 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -5,7 +5,7 @@ import ( "encoding/json" "strings" - "github.com/openinfradev/tks-api/internal/kubernetes" + "github.com/openinfradev/tks-api/pkg/kubernetes" "gopkg.in/yaml.v3" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 4fb12686..28e76385 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -13,13 +13,13 @@ import ( "github.com/spf13/viper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" argowf "github.com/openinfradev/tks-api/pkg/argo-client" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/kubernetes" "github.com/openinfradev/tks-api/pkg/log" ) diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index 33c9ceae..9cf649f4 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -16,7 +16,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/servicequotas" "github.com/aws/aws-sdk-go-v2/service/sts" "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -24,6 +23,7 @@ import ( argowf "github.com/openinfradev/tks-api/pkg/argo-client" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/kubernetes" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gorm.io/gorm" diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index a2b04912..2300b8dc 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -10,7 +10,6 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -19,6 +18,7 @@ import ( argowf "github.com/openinfradev/tks-api/pkg/argo-client" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/kubernetes" "github.com/openinfradev/tks-api/pkg/log" gcache "github.com/patrickmn/go-cache" "github.com/pkg/errors" diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 82cf8c93..67337c0a 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -10,12 +10,12 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/kubernetes" "github.com/openinfradev/tks-api/pkg/log" thanos "github.com/openinfradev/tks-api/pkg/thanos-client" gcache "github.com/patrickmn/go-cache" diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 4fbc4382..51b0b524 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -8,13 +8,13 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/keycloak" - "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" argowf "github.com/openinfradev/tks-api/pkg/argo-client" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/kubernetes" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gopkg.in/yaml.v3" diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 00a2e6c9..7c9bd129 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -9,7 +9,6 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" - "github.com/openinfradev/tks-api/internal/kubernetes" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -18,6 +17,7 @@ import ( argowf "github.com/openinfradev/tks-api/pkg/argo-client" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/kubernetes" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "github.com/spf13/viper" diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index a9c8abc4..25380f6a 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -4,6 +4,31 @@ import ( "time" ) +// enum +type SystemNotificationRuleStatus int32 + +const ( + SystemNotificationRuleStatus_PENDING SystemNotificationRuleStatus = iota + SystemNotificationRuleStatus_APPLYED + SystemNotificationRuleStatus_ERROR +) + +var systemNotificationRuleStatus = [...]string{ + "PENDING", + "APPLYED", + "ERROR", +} + +func (m SystemNotificationRuleStatus) String() string { return systemNotificationRuleStatus[(m)] } +func (m SystemNotificationRuleStatus) FromString(s string) SystemNotificationRuleStatus { + for i, v := range systemNotificationRuleStatus { + if v == s { + return SystemNotificationRuleStatus(i) + } + } + return SystemNotificationRuleStatus_PENDING +} + type SystemNotificationRuleResponse struct { ID string `json:"id"` Name string `json:"name"` diff --git a/internal/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go similarity index 100% rename from internal/kubernetes/kubernetes.go rename to pkg/kubernetes/kubernetes.go diff --git a/internal/kubernetes/kubernetes_test.go b/pkg/kubernetes/kubernetes_test.go similarity index 99% rename from internal/kubernetes/kubernetes_test.go rename to pkg/kubernetes/kubernetes_test.go index 4a7d6bf8..647d57a1 100644 --- a/internal/kubernetes/kubernetes_test.go +++ b/pkg/kubernetes/kubernetes_test.go @@ -2,11 +2,12 @@ package kubernetes_test import ( "context" - "github.com/openinfradev/tks-api/internal/kubernetes" - "gopkg.in/yaml.v3" "os" "reflect" "testing" + + "github.com/openinfradev/tks-api/pkg/kubernetes" + "gopkg.in/yaml.v3" ) const path = "/Users/1113433/local_vm_kube/kubeconfig" From b47faef14522bb32e3e666c8b53f95967e66f5f2 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Wed, 3 Apr 2024 01:39:47 +0900 Subject: [PATCH 210/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20k8s=20resource=20name=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/swagger/docs.go | 15 +++++++-- api/swagger/swagger.json | 15 +++++++-- api/swagger/swagger.yaml | 11 ++++-- internal/delivery/http/policy.go | 10 ++++++ internal/model/policy.go | 7 ++-- internal/policy-template/policy-operator.go | 2 +- internal/repository/policy.go | 5 +++ internal/usecase/policy.go | 37 ++++++++++++++++++--- pkg/domain/policy.go | 34 ++++++++++--------- pkg/httpErrors/errorCode.go | 17 +++++----- 10 files changed, 113 insertions(+), 40 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 68d13e11..66b9323b 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -10209,12 +10209,16 @@ const docTemplate = `{ }, "parameters": { "type": "string", - "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" + "example": "{\"key\":\"value\"}" }, "policyName": { "type": "string", "example": "label 정책" }, + "policyResourceName": { + "type": "string", + "example": "labelpolicy" + }, "targetClusterIds": { "type": "array", "items": { @@ -12226,16 +12230,21 @@ const docTemplate = `{ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" }, "matchYaml": { - "type": "string" + "type": "string", + "example": "namespaces:\r\n- testns1" }, "parameters": { "type": "string", - "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" + "example": "{\"key\":\"value\"}" }, "policyName": { "type": "string", "example": "label 정책" }, + "policyResourceName": { + "type": "string", + "example": "labelpolicy" + }, "targetClusterIds": { "type": "array", "items": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 9fa4a0f9..84f0cf62 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -10203,12 +10203,16 @@ }, "parameters": { "type": "string", - "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" + "example": "{\"key\":\"value\"}" }, "policyName": { "type": "string", "example": "label 정책" }, + "policyResourceName": { + "type": "string", + "example": "labelpolicy" + }, "targetClusterIds": { "type": "array", "items": { @@ -12220,16 +12224,21 @@ "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" }, "matchYaml": { - "type": "string" + "type": "string", + "example": "namespaces:\r\n- testns1" }, "parameters": { "type": "string", - "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" + "example": "{\"key\":\"value\"}" }, "policyName": { "type": "string", "example": "label 정책" }, + "policyResourceName": { + "type": "string", + "example": "labelpolicy" + }, "targetClusterIds": { "type": "array", "items": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 8656e906..c8347de1 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -895,11 +895,14 @@ definitions: example: "namespaces:\r\n- testns1" type: string parameters: - example: '{"labels":{"key":"owner","allowedRegex":"test*"}' + example: '{"key":"value"}' type: string policyName: example: label 정책 type: string + policyResourceName: + example: labelpolicy + type: string targetClusterIds: example: - 83bf8081-f0c5-4b31-826d-23f6f366ec90 @@ -2231,13 +2234,17 @@ definitions: match: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match' matchYaml: + example: "namespaces:\r\n- testns1" type: string parameters: - example: '{"labels":{"key":"owner","allowedRegex":"test*"}' + example: '{"key":"value"}' type: string policyName: example: label 정책 type: string + policyResourceName: + example: labelpolicy + type: string targetClusterIds: example: - 83bf8081-f0c5-4b31-826d-23f6f366ec90 diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 30a58f5f..3c5ade9a 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -15,6 +15,7 @@ import ( "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" "gopkg.in/yaml.v3" + "k8s.io/apimachinery/pkg/util/validation" ) type PolicyHandler struct { @@ -89,6 +90,15 @@ func (h *PolicyHandler) CreatePolicy(w http.ResponseWriter, r *http.Request) { } } + if len(input.PolicyResourceName) > 0 { + errMsgs := validation.IsDNS1123Subdomain(input.PolicyResourceName) + + if len(errMsgs) > 0 { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid k8s resource name for policy: %v", errMsgs), "P_INVALID_RESURCE_NAME", "")) + return + } + } + var dto model.Policy if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) diff --git a/internal/model/policy.go b/internal/model/policy.go index 48f1ce8a..d86a9045 100644 --- a/internal/model/policy.go +++ b/internal/model/policy.go @@ -14,9 +14,10 @@ type Policy struct { ID uuid.UUID `gorm:"primarykey;type:varchar(36);not null"` OrganizationId string - PolicyName string - Mandatory bool - Description string + PolicyName string + PolicyResourceName string + Mandatory bool + Description string TargetClusterIds []string `gorm:"-:all"` TargetClusters []Cluster `gorm:"many2many:policy_target_clusters"` diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 66fb30af..6ad98fff 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -37,7 +37,7 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { }, ObjectMeta: metav1.ObjectMeta{ - Name: policy.PolicyName, + Name: policy.PolicyResourceName, Labels: labels, }, diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 8b336b1a..ac8cc8dd 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -22,6 +22,7 @@ type IPolicyRepository interface { FetchByClusterId(ctx context.Context, clusterId string, pg *pagination.Pagination) (out *[]model.Policy, err error) FetchByClusterIdAndTemplaeId(ctx context.Context, clusterId string, templateId uuid.UUID) (out *[]model.Policy, err error) ExistByName(ctx context.Context, organizationId string, policyName string) (exist bool, err error) + ExistByResourceName(ctx context.Context, organizationId string, policyName string) (exist bool, err error) ExistByID(ctx context.Context, organizationId string, policyId uuid.UUID) (exist bool, err error) GetByName(ctx context.Context, organizationId string, policyName string) (out *model.Policy, err error) GetByID(ctx context.Context, organizationId string, policyId uuid.UUID) (out *model.Policy, err error) @@ -150,6 +151,10 @@ func (r *PolicyRepository) ExistByName(ctx context.Context, organizationId strin return r.ExistBy(ctx, organizationId, "policy_name", policyName) } +func (r *PolicyRepository) ExistByResourceName(ctx context.Context, organizationId string, policyName string) (exist bool, err error) { + return r.ExistBy(ctx, organizationId, "policy_resource_name", policyName) +} + func (r *PolicyRepository) ExistByID(ctx context.Context, organizationId string, policyId uuid.UUID) (exist bool, err error) { return r.ExistBy(ctx, organizationId, "id", policyId) } diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 5e6f7cb2..3a2bbf9c 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -56,6 +56,12 @@ func NewPolicyUsecase(r repository.Repository) IPolicyUsecase { } } +func randomResouceName(kind string) string { + uuid := uuid.New().String() + idStr := strings.Split(uuid, "-") + return strings.ToLower(kind) + "-" + idStr[len(idStr)-1] +} + func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto model.Policy) (policyId uuid.UUID, err error) { dto.OrganizationId = organizationId @@ -82,6 +88,19 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_POlICY_TEMPLATE_NOT_FOUND", "policy template not found") } + if len(dto.PolicyResourceName) == 0 { + dto.PolicyResourceName = randomResouceName(policyTemplate.Kind) + } + + exists, err = u.repo.ExistByResourceName(ctx, dto.OrganizationId, dto.PolicyResourceName) + if err != nil { + return uuid.Nil, err + } + + if exists { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_CREATE_ALREADY_EXISTED_RESOURCE_NAME", "policy resource name already exists") + } + dto.TargetClusters = make([]model.Cluster, len(dto.TargetClusterIds)) for i, clusterId := range dto.TargetClusterIds { @@ -126,7 +145,12 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m err = policytemplate.ApplyTksPolicyTemplateCR(ctx, organization.PrimaryClusterId, policyTemplateCR) if err != nil { - log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + errYaml := "" + if policyCR != nil { + errYaml, _ = policyTemplateCR.YAML() + } + + log.Errorf(ctx, "error is :%s(%T), policyTemplateCR='%+v'", err.Error(), err, errYaml) return uuid.Nil, httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") } @@ -135,7 +159,12 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m err = policytemplate.ApplyTksPolicyCR(ctx, organization.PrimaryClusterId, policyCR) if err != nil { - log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + errYaml := "" + if policyCR != nil { + errYaml, _ = policyCR.YAML() + } + + log.Errorf(ctx, "error is :%s(%T), policyCR='%+v'", err.Error(), err, errYaml) return uuid.Nil, httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") } @@ -303,14 +332,14 @@ func (u *PolicyUsecase) Delete(ctx context.Context, organizationId string, polic return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } - exists, err := policytemplate.ExistsTksPolicyCR(ctx, organization.PrimaryClusterId, policy.PolicyName) + exists, err := policytemplate.ExistsTksPolicyCR(ctx, organization.PrimaryClusterId, policy.PolicyResourceName) if err != nil { log.Errorf(ctx, "failed to check TksPolicyCR: %v", err) return httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") } if exists { - err = policytemplate.DeleteTksPolicyCR(ctx, organization.PrimaryClusterId, policy.PolicyName) + err = policytemplate.DeleteTksPolicyCR(ctx, organization.PrimaryClusterId, policy.PolicyResourceName) if err != nil { log.Errorf(ctx, "failed to delete TksPolicyCR: %v", err) diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index 2b965c77..ebf6dff0 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -36,15 +36,16 @@ type PolicyResponse struct { TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` Mandatory bool `json:"mandatory"` - PolicyName string `json:"policyName" example:"label 정책"` - Description string `json:"description"` - TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - TemplateName string `json:"templateName" example:"필수 Label 검사"` - EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun" example:"deny"` - Parameters string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` - FilledParameters []*ParameterDef `json:"filledParameters"` - Match *Match `json:"match,omitempty"` - MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` + PolicyName string `json:"policyName" example:"label 정책"` + PolicyResourceName string `json:"policyResourceName,omitempty" example:"labelpolicy"` + Description string `json:"description"` + TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + TemplateName string `json:"templateName" example:"필수 Label 검사"` + EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun" example:"deny"` + Parameters string `json:"parameters" example:"{\"key\":\"value\"}"` + FilledParameters []*ParameterDef `json:"filledParameters"` + Match *Match `json:"match,omitempty"` + MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } @@ -52,13 +53,14 @@ type CreatePolicyRequest struct { TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` Mandatory bool `json:"mandatory"` - PolicyName string `json:"policyName" example:"label 정책"` - Description string `json:"description"` - TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun" example:"deny"` - Parameters string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` - Match *Match `json:"match,omitempty"` - MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` + PolicyName string `json:"policyName" example:"label 정책"` + PolicyResourceName string `json:"policyResourceName,omitempty" example:"labelpolicy"` + Description string `json:"description"` + TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun" example:"deny"` + Parameters string `json:"parameters" example:"{\"key\":\"value\"}"` + Match *Match `json:"match,omitempty"` + MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 0adb6c9f..c48e0404 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -129,14 +129,15 @@ var errorMap = map[ErrorCode]string{ "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE": "tks 템플릿에 대해 해당 동작을 수행할 수 없습니다.", // Policy - "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", - "P_NOT_FOUND_POLICY": "정책이 존재하지 않습니다.", - "P_INVALID_POLICY_NAME": "유효하지 않은 정책 이름입니다. 정책 이름을 확인하세요.", - "P_INVALID_MATCH": "유효하지 않은 match 설정입니다. match 설정을 확인하세요.", - "P_FAILED_FETCH_POLICY": "정책 ID에 해당하는 정책을 가져오는데 실패했습니다.", - "P_FAILED_FETCH_CLUSTER": "정책의 클러스터 정보를 가져오는데 실패했습니다.", - "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", - "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", + "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", + "P_NOT_FOUND_POLICY": "정책이 존재하지 않습니다.", + "P_INVALID_POLICY_NAME": "유효하지 않은 정책 이름입니다. 정책 이름을 확인하세요.", + "P_CREATE_ALREADY_EXISTED_RESOURCE_NAME": "유효하지 않은 정책 자원 이름(k8s 자원 이름)입니다. 정책 자원 이름을 확인하세요.", + "P_INVALID_MATCH": "유효하지 않은 match 설정입니다. match 설정을 확인하세요.", + "P_FAILED_FETCH_POLICY": "정책 ID에 해당하는 정책을 가져오는데 실패했습니다.", + "P_FAILED_FETCH_CLUSTER": "정책의 클러스터 정보를 가져오는데 실패했습니다.", + "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", + "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", } func (m ErrorCode) GetText() string { From f03b90da2ee3d8bcb876726f62be22dd3cd4bed6 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 3 Apr 2024 11:12:10 +0900 Subject: [PATCH 211/502] trivial. temporary commit --- internal/model/system-notification-rule.go | 3 +- internal/usecase/organization.go | 11 ++++++ scripts/init_postgres.sql | 43 ++++++++++++++++++++-- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index cfdbe12d..03883ce1 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -28,15 +28,16 @@ type SystemNotificationRule struct { Description string OrganizationId string Organization Organization `gorm:"foreignKey:OrganizationId"` + IsSystem bool `gorm:"default:false"` SystemNotificationTemplate SystemNotificationTemplate `gorm:"foreignKey:SystemNotificationTemplateId"` SystemNotificationTemplateId string SystemNotificationConditions []SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` + Clusters []Cluster `gorm:"many2many:system_notification_rule_clusters;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` TargetUsers []User `gorm:"many2many:system_notification_rule_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` TargetUserIds []string `gorm:"-:all"` MessageTitle string MessageContent string MessageActionProposal string - Status domain.SystemNotificationRuleStatus CreatorId *uuid.UUID `gorm:"type:uuid"` Creator *User `gorm:"foreignKey:CreatorId"` UpdatorId *uuid.UUID `gorm:"type:uuid"` diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index ea794543..15ff12bc 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -28,6 +28,7 @@ type IOrganizationUsecase interface { UpdatePrimaryClusterId(ctx context.Context, organizationId string, clusterId string) (err error) ChangeAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error Delete(ctx context.Context, organizationId string, accessToken string) error + createDefaultSystemNotificationRules(ctx context.Context, organizationId string, *model.Organization) (err error) } type OrganizationUsecase struct { @@ -94,6 +95,12 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization return "", errors.Wrap(err, "Failed to init workflow") } + // Create default SystemNotificationRule + err = u.createDefaultSystemNotificationRules(ctx, organizationId, in) + if err != nil { + return "" + } + return organizationId, nil } func (u *OrganizationUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (out *[]model.Organization, err error) { @@ -218,3 +225,7 @@ func (u *OrganizationUsecase) ChangeAdminId(ctx context.Context, organizationId return nil } + +func (u *OrganizationUsecase) createDefaultSystemNotificationRules(ctx context.Context, organizationId string, *model.Organization) error { + return nil +} diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index 98eb2b77..b802ede6 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -1,3 +1,4 @@ +## Roles insert into roles ( id, name, description, created_at, updated_at ) values ( '2ea4415c-9748-493f-91ba-4a64506b7be8', 'tks-admin', 'tks-admin', now(), now() ); insert into roles ( id, name, description, created_at, updated_at ) values ( 'b2b689f0-ceeb-46c2-b280-0bc06896acd1', 'admin', 'admin', now(), now() ); insert into roles ( id, name, description, created_at, updated_at ) values ( 'd3015140-2b12-487a-9516-cdeed7c17735', 'project-leader', 'project-leader', now(), now() ); @@ -5,6 +6,7 @@ insert into roles ( id, name, description, created_at, updated_at ) values ( 'f6 insert into roles ( id, name, description, created_at, updated_at ) values ( 'b7ac7e7d-d8bc-470d-b6b2-3e0cc8ba55cc', 'project-viewer', 'project-viewer', now(), now() ); insert into roles ( id, name, description, created_at, updated_at ) values ( 'ff4187a2-f3c1-46b3-8448-03a4b5e132e7', 'user', 'user', now(), now() ); +## Policies insert into policies ( role_id, name, description, c, create_priviledge, u, update_priviledge, r, read_priviledge, d, delete_priviledge, creator, created_at, updated_at ) values ( '2ea4415c-9748-493f-91ba-4a64506b7be8', 'organization', 'organization', 't', '', 't', '', 't', '', 't', '', '', now(), now() ); insert into policies ( role_id, name, description, c, create_priviledge, u, update_priviledge, r, read_priviledge, d, delete_priviledge, creator, created_at, updated_at ) values ( '2ea4415c-9748-493f-91ba-4a64506b7be8', 'project', 'project', 't', '', 't', '', 't', '', 't', '', '', now(), now() ); insert into policies ( role_id, name, description, c, create_priviledge, u, update_priviledge, r, read_priviledge, d, delete_priviledge, creator, created_at, updated_at ) values ( '2ea4415c-9748-493f-91ba-4a64506b7be8', 'user', 'user', 't', '', 't', '', 't', '', 't', '', '', now(), now() ); @@ -12,9 +14,13 @@ insert into policies ( role_id, name, description, c, create_priviledge, u, upda insert into policies ( role_id, name, description, c, create_priviledge, u, update_priviledge, r, read_priviledge, d, delete_priviledge, creator, created_at, updated_at ) values ( '2ea4415c-9748-493f-91ba-4a64506b7be8', 'service', 'service', 't', '', 't', '', 't', '', 't', '', '', now(), now() ); insert into policies ( role_id, name, description, c, create_priviledge, u, update_priviledge, r, read_priviledge, d, delete_priviledge, creator, created_at, updated_at ) values ( '2ea4415c-9748-493f-91ba-4a64506b7be8', 'k8s_resources', 'resources of k8s', 'f', '', 'f', '', 'f', '', 'f', '', '', now(), now() ); +## Organizations insert into organizations ( id, name, description, created_at, updated_at ) values ( 'master', 'master', 'tks', now(), now() ); + +## Users insert into users ( id, account_id, name, password, organization_id, role_id, created_at, updated_at ) values ( 'bf67de40-ce15-4dc0-b6c2-17f053ca504f', 'admin', 'admin', '$2a$10$Akf03nbLHk93sTtozm35XuINXkJeNX7A1T9o/Pxpg9R2B2PToBPOO', 'master', 'b2b689f0-ceeb-46c2-b280-0bc06896acd1', now(), now() ); +## StackTemplates insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) values ( '49901092-be76-4d4f-94e9-b84525f560b5', 'master', 'AWS Standard (x86)', 'included LMA', 'v1', 'AWS', 'x86', 'aws-reference', 'STANDARD', 'v1.25', 'AWS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) @@ -31,7 +37,6 @@ insert into stack_templates ( id, organization_id, name, description, version, c values ( '5678bf11-256f-4d2c-a673-f2fedb82de5b', 'master', 'BYOH Standard', 'included LMA', 'v1', 'AWS', 'x86', 'eks-reference', 'STANDARD', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) values ( '92f5e5ce-7ffd-4c3e-aff6-9b7fb03dd881', 'master', 'BYOH MSA Standard', 'included LMA, SERVICE MESH', 'v1', 'AWS', 'x86', 'eks-msa-reference', 'MSA', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]},{"name":"MSA","type":"SERVICE_MESH","applications":[{"name":"istio","version":"v1.17.2","description":"MSA 플랫폼"},{"name":"jagger","version":"1.35.0","description":"분산 서비스간 트랜잭션 추적을 위한 플랫폼"},{"name":"kiali","version":"v1.63.0","description":"MSA 구조 및 성능을 볼 수 있는 Dashboard"},{"name":"k8ssandra","version":"1.6.0","description":"분산 서비스간 호출 로그를 저장하는 스토리지"}]}]' ); - # BTV insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) values ( '2526ec49-28a2-4be9-8d18-2c39fc0993fd', 'master', 'BYOH Admin Standard (BTV)', 'included LMA', 'v1', 'BYOH', 'x86', 'tks-admin', 'STANDARD', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); @@ -39,14 +44,44 @@ insert into stack_templates ( id, organization_id, name, description, version, c values ( 'a76b5c97-7d55-46d8-9248-9952bfaff62c', 'master', 'BYOH MSA Standard (BTV SSU)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-ssu-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) values ( 'b5bbd6ea-5bf3-4d88-bb06-4a4c64c73c15', 'master', 'BYOH MSA Standard (BTV SUY)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-suy-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); - # PSNM insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) values ( 'c3396c68-03ec-4d41-991c-69e4a2ac16aa', 'master', 'psnm-backend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-backend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) values ( '23b07a65-1cb3-4609-9bba-e88c15e2e192', 'master', 'psnm-frontend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-frontend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); -# PROJECT +## Projects insert into project_roles ( id, name, description, created_at, updated_at ) values ( 'f4358b4e-adc3-447a-8ad9-c111c4b9a974', 'project-leader', 'project-leader', now(), now() ); insert into project_roles ( id, name, description, created_at, updated_at ) values ( '2071bd6f-26b3-4c1a-a3ab-439bc89f0011', 'project-member', 'project-member', now(), now() ); -insert into project_roles ( id, name, description, created_at, updated_at ) values ( 'f62c16e1-316c-4d7f-9cfa-dbe4ed7dfa17', 'project-viewer', 'project-viewer', now(), now() ); \ No newline at end of file +insert into project_roles ( id, name, description, created_at, updated_at ) values ( 'f62c16e1-316c-4d7f-9cfa-dbe4ed7dfa17', 'project-viewer', 'project-viewer', now(), now() ); + +/* +type SystemNotificationTemplate struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index:idx_name,unique"` + Organizations []Organization `gorm:"many2many:system_notification_template_organizations;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` + OrganizationIds []string `gorm:"-:all"` + Description string + MetricQuery string + MetricParameters []SystemNotificationMetricParameter `gorm:"foreignKey:SystemNotificationTemplateId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` + CreatorId *uuid.UUID + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID + Updator User `gorm:"foreignKey:UpdatorId"` +} + +*/ +## SystemNotificationTemplates +insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('d42d716f-dd2e-429b-897d-b602f6382790', 'node-cpu-high-load', 'node-cpu-high-load', '(avg by (taco_cluster, instance) (rate(node_cpu_seconds_total{mode="idle"}[60s]))) < 0', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', 'node-memory-high-utilization', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes) < 0.2', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-full', 'predict_linear(node_filesystem_free_bytes{mountpoint="/"}[6h], 24*3600) < 0', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', 'predict_linear(kubelet_volume_stats_available_bytes[6h], 24*3600) < 0', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', 'pod-restart-frequently', 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:]) > 2', null, null, now(), now() ); + From 827d074299236ebc579cd4e5c747a00e46fdac3a Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Wed, 3 Apr 2024 11:29:37 +0900 Subject: [PATCH 212/502] =?UTF-8?q?api=20route=20=EB=81=9D=EC=97=90=20?= =?UTF-8?q?=EA=B3=B5=EB=B0=B1=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/route/route.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/route/route.go b/internal/route/route.go index aabb8590..2f2eb649 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -320,7 +320,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.DeletePolicyTemplate, http.HandlerFunc(policyTemplateHandler.DeletePolicyTemplate))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetPolicyTemplate, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.UpdatePolicyTemplate))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/deploy ", customMiddleware.Handle(internalApi.GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateDeploy))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/deploy", customMiddleware.Handle(internalApi.GetPolicyTemplateDeploy, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateDeploy))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/statistics", customMiddleware.Handle(internalApi.ListPolicyTemplateStatistics, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateStatistics))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.ListPolicyTemplateVersions, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplateVersions))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplateVersion))).Methods(http.MethodPost) From 1eb90329e9947429c89201ad46c0612076447b4f Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 3 Apr 2024 14:29:13 +0900 Subject: [PATCH 213/502] feature. implementation alert system --- internal/delivery/http/organization.go | 8 +++ internal/model/system-notification-rule.go | 2 +- .../model/system-notification-template.go | 1 + .../repository/system-notification-rule.go | 10 ++++ internal/usecase/organization.go | 49 ++++++++++--------- pkg/domain/system-notification.go | 2 +- scripts/init_postgres.sql | 38 ++++---------- 7 files changed, 56 insertions(+), 54 deletions(-) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index f1a1bba1..d5fe5d2d 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -128,6 +128,14 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r } organization.AdminId = &admin.ID + // Default systemNotificationRules 생성 + err = h.usecase.MakeDefaultSystemNotificationRules(r.Context(), organizationId, &organization) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + var out domain.CreateOrganizationResponse if err = serializer.Map(r.Context(), organization, &out); err != nil { log.Error(r.Context(), err) diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index 03883ce1..49d9ddbf 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -32,12 +32,12 @@ type SystemNotificationRule struct { SystemNotificationTemplate SystemNotificationTemplate `gorm:"foreignKey:SystemNotificationTemplateId"` SystemNotificationTemplateId string SystemNotificationConditions []SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` - Clusters []Cluster `gorm:"many2many:system_notification_rule_clusters;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` TargetUsers []User `gorm:"many2many:system_notification_rule_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` TargetUserIds []string `gorm:"-:all"` MessageTitle string MessageContent string MessageActionProposal string + Status domain.SystemNotificationRuleStatus CreatorId *uuid.UUID `gorm:"type:uuid"` Creator *User `gorm:"foreignKey:CreatorId"` UpdatorId *uuid.UUID `gorm:"type:uuid"` diff --git a/internal/model/system-notification-template.go b/internal/model/system-notification-template.go index eabf2dd5..7639442b 100644 --- a/internal/model/system-notification-template.go +++ b/internal/model/system-notification-template.go @@ -20,6 +20,7 @@ type SystemNotificationTemplate struct { ID uuid.UUID `gorm:"primarykey"` Name string `gorm:"index:idx_name,unique"` + IsSystem bool `gorm:"default:false"` Organizations []Organization `gorm:"many2many:system_notification_template_organizations;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` OrganizationIds []string `gorm:"-:all"` Description string diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 44266e0d..b5da7c88 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -18,6 +18,7 @@ type ISystemNotificationRuleRepository interface { Fetch(ctx context.Context, pg *pagination.Pagination) ([]model.SystemNotificationRule, error) FetchWithOrganization(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotificationRule, err error) Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRuleId uuid.UUID, err error) + Creates(ctx context.Context, dto []model.SystemNotificationRule) (err error) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) } @@ -86,6 +87,15 @@ func (r *SystemNotificationRuleRepository) Create(ctx context.Context, dto model return dto.ID, nil } +func (r *SystemNotificationRuleRepository) Creates(ctx context.Context, rules []model.SystemNotificationRule) (err error) { + res := r.db.WithContext(ctx).Create(&rules) + if res.Error != nil { + return res.Error + } + + return nil +} + func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) { var m model.SystemNotificationRule res := r.db.WithContext(ctx).Preload(clause.Associations).First(&m, "id = ?", dto.ID) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 15ff12bc..80565f39 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -28,30 +28,30 @@ type IOrganizationUsecase interface { UpdatePrimaryClusterId(ctx context.Context, organizationId string, clusterId string) (err error) ChangeAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error Delete(ctx context.Context, organizationId string, accessToken string) error - createDefaultSystemNotificationRules(ctx context.Context, organizationId string, *model.Organization) (err error) + MakeDefaultSystemNotificationRules(ctx context.Context, organizationId string, organization *model.Organization) (err error) } type OrganizationUsecase struct { - repo repository.IOrganizationRepository - userRepo repository.IUserRepository - roleRepo repository.IRoleRepository - clusterRepo repository.IClusterRepository - stackTemplateRepo repository.IStackTemplateRepository - systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository - argo argowf.ArgoClient - kc keycloak.IKeycloak + repo repository.IOrganizationRepository + userRepo repository.IUserRepository + roleRepo repository.IRoleRepository + clusterRepo repository.IClusterRepository + stackTemplateRepo repository.IStackTemplateRepository + systemNotificationRuleRepo repository.ISystemNotificationRuleRepository + argo argowf.ArgoClient + kc keycloak.IKeycloak } func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClient, kc keycloak.IKeycloak) IOrganizationUsecase { return &OrganizationUsecase{ - repo: r.Organization, - userRepo: r.User, - roleRepo: r.Role, - clusterRepo: r.Cluster, - stackTemplateRepo: r.StackTemplate, - systemNotificationTemplateRepo: r.SystemNotificationTemplate, - argo: argoClient, - kc: kc, + repo: r.Organization, + userRepo: r.User, + roleRepo: r.Role, + clusterRepo: r.Cluster, + stackTemplateRepo: r.StackTemplate, + systemNotificationRuleRepo: r.SystemNotificationRule, + argo: argoClient, + kc: kc, } } @@ -95,12 +95,6 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization return "", errors.Wrap(err, "Failed to init workflow") } - // Create default SystemNotificationRule - err = u.createDefaultSystemNotificationRules(ctx, organizationId, in) - if err != nil { - return "" - } - return organizationId, nil } func (u *OrganizationUsecase) Fetch(ctx context.Context, pg *pagination.Pagination) (out *[]model.Organization, err error) { @@ -226,6 +220,13 @@ func (u *OrganizationUsecase) ChangeAdminId(ctx context.Context, organizationId return nil } -func (u *OrganizationUsecase) createDefaultSystemNotificationRules(ctx context.Context, organizationId string, *model.Organization) error { +func (u *OrganizationUsecase) MakeDefaultSystemNotificationRules(ctx context.Context, organizationId string, dto *model.Organization) error { + var rules []model.SystemNotificationRule + + err := u.systemNotificationRuleRepo.Creates(ctx, rules) + if err != nil { + return err + } + return nil } diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 6d875aa6..2d35b9ab 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -68,7 +68,7 @@ type CreateSystemNotificationRequest struct { Version string `json:"version"` GroupKey string `json:"groupKey"` TruncateSystemNotifications int `json:"truncateSystemNotifications"` - SystemNotifications []SystemNotification `json:"systemNotifications"` + SystemNotifications []SystemNotification `json:"alerts"` GroupLabels struct { SystemNotificationname string `json:"systemNotificationname"` } `json:"groupLabels"` diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index b802ede6..f57b52a8 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -55,33 +55,15 @@ insert into project_roles ( id, name, description, created_at, updated_at ) valu insert into project_roles ( id, name, description, created_at, updated_at ) values ( '2071bd6f-26b3-4c1a-a3ab-439bc89f0011', 'project-member', 'project-member', now(), now() ); insert into project_roles ( id, name, description, created_at, updated_at ) values ( 'f62c16e1-316c-4d7f-9cfa-dbe4ed7dfa17', 'project-viewer', 'project-viewer', now(), now() ); -/* -type SystemNotificationTemplate struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey"` - Name string `gorm:"index:idx_name,unique"` - Organizations []Organization `gorm:"many2many:system_notification_template_organizations;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` - OrganizationIds []string `gorm:"-:all"` - Description string - MetricQuery string - MetricParameters []SystemNotificationMetricParameter `gorm:"foreignKey:SystemNotificationTemplateId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` - CreatorId *uuid.UUID - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID - Updator User `gorm:"foreignKey:UpdatorId"` -} - -*/ ## SystemNotificationTemplates -insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('d42d716f-dd2e-429b-897d-b602f6382790', 'node-cpu-high-load', 'node-cpu-high-load', '(avg by (taco_cluster, instance) (rate(node_cpu_seconds_total{mode="idle"}[60s]))) < 0', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', 'node-memory-high-utilization', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes) < 0.2', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-full', 'predict_linear(node_filesystem_free_bytes{mountpoint="/"}[6h], 24*3600) < 0', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', 'predict_linear(kubelet_volume_stats_available_bytes[6h], 24*3600) < 0', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', 'pod-restart-frequently', 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:]) > 2', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('d42d716f-dd2e-429b-897d-b602f6382790', 'node-cpu-high-load', 'node-cpu-high-load', true, '(avg by (taco_cluster, instance) (rate(node_cpu_seconds_total{mode="idle"}[60s]))) < 0', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', true, 'node-memory-high-utilization', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes) < 0.2', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-full', true, 'predict_linear(node_filesystem_free_bytes{mountpoint="/"}[6h], 24*3600) < 0', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'predict_linear(kubelet_volume_stats_available_bytes[6h], 24*3600) < 0', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', true, 'pod-restart-frequently', 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:]) > 2', null, null, now(), now() ); From d2d6a93898afc61c39611424fe29a45b7887f246 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 2 Apr 2024 12:39:29 +0900 Subject: [PATCH 214/502] Add check duplicated role name in Role API.. --- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 ++++ internal/delivery/http/role.go | 47 ++++++++++++++++++- internal/repository/role.go | 10 ++-- internal/route/route.go | 1 + internal/usecase/role.go | 16 ++++++- pkg/domain/role.go | 5 ++ 7 files changed, 83 insertions(+), 5 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2ff26186..9daa7264 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -195,6 +195,7 @@ const ( UpdateTksRole GetPermissionsByRoleId UpdatePermissionsByRoleId + IsRoleNameExisted // Permission GetPermissionTemplates diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 4037874e..3e7ad407 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -611,6 +611,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdatePermissionsByRoleId", Group: "Role", }, + IsRoleNameExisted: { + Name: "IsRoleNameExisted", + Group: "Role", + }, GetPermissionTemplates: { Name: "GetPermissionTemplates", Group: "Permission", @@ -1130,6 +1134,8 @@ func (e Endpoint) String() string { return "GetPermissionsByRoleId" case UpdatePermissionsByRoleId: return "UpdatePermissionsByRoleId" + case IsRoleNameExisted: + return "IsRoleNameExisted" case GetPermissionTemplates: return "GetPermissionTemplates" case Admin_CreateUser: @@ -1546,6 +1552,8 @@ func GetEndpoint(name string) Endpoint { return GetPermissionsByRoleId case "UpdatePermissionsByRoleId": return UpdatePermissionsByRoleId + case "IsRoleNameExisted": + return IsRoleNameExisted case "GetPermissionTemplates": return GetPermissionTemplates case "Admin_CreateUser": diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index d9020890..49d718b7 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -20,9 +20,9 @@ type IRoleHandler interface { GetTksRole(w http.ResponseWriter, r *http.Request) DeleteTksRole(w http.ResponseWriter, r *http.Request) UpdateTksRole(w http.ResponseWriter, r *http.Request) - GetPermissionsByRoleId(w http.ResponseWriter, r *http.Request) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) + IsRoleNameExisted(w http.ResponseWriter, r *http.Request) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) @@ -264,6 +264,7 @@ func (h RoleHandler) UpdateTksRole(w http.ResponseWriter, r *http.Request) { // input to dto dto := model.Role{ ID: roleId, + Name: input.Name, Description: input.Description, } @@ -394,6 +395,7 @@ func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Re // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.ListTksRoleResponse // @Router /admin/organizations/{organizationId}/roles [get] +// @Security JWT func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) { // Same as ListTksRoles @@ -450,6 +452,7 @@ func (h RoleHandler) Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) // @Param roleId path string true "Role ID" // @Success 200 {object} domain.GetTksRoleResponse // @Router /admin/organizations/{organizationId}/roles/{roleId} [get] +// @Security JWT func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { // Same as GetTksRole @@ -481,3 +484,45 @@ func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } + +// IsRoleNameExisted godoc +// +// @Tags Roles +// @Summary Check whether the role name exists +// @Description Check whether the role name exists +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleName path string true "Role Name" +// @Success 200 {object} domain.CheckRoleNameResponse +// @Router /organizations/{organizationId}/roles/{roleName}/existence [get] +// @Security JWT +func (h RoleHandler) IsRoleNameExisted(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var organizationId, roleName string + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + if v, ok := vars["roleName"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleName = v + } + + // check role name exist + isExist, err := h.roleUsecase.IsRoleNameExisted(r.Context(), organizationId, roleName) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CheckRoleNameResponse + out.IsExist = isExist + + // response + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/repository/role.go b/internal/repository/role.go index f3b677e6..fcd9bb3f 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -3,6 +3,7 @@ package repository import ( "context" "fmt" + "github.com/pkg/errors" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" @@ -15,7 +16,7 @@ type IRoleRepository interface { Create(ctx context.Context, roleObj *model.Role) (string, error) ListTksRoles(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]*model.Role, error) GetTksRole(ctx context.Context, id string) (*model.Role, error) - GetTksRoleByRoleName(ctx context.Context, roleName string) (*model.Role, error) + GetTksRoleByRoleName(ctx context.Context, organizationId string, roleName string) (*model.Role, error) Delete(ctx context.Context, id string) error Update(ctx context.Context, roleObj *model.Role) error } @@ -24,9 +25,12 @@ type RoleRepository struct { db *gorm.DB } -func (r RoleRepository) GetTksRoleByRoleName(ctx context.Context, roleName string) (*model.Role, error) { +func (r RoleRepository) GetTksRoleByRoleName(ctx context.Context, oragnizationId string, roleName string) (*model.Role, error) { var role model.Role - if err := r.db.WithContext(ctx).Preload("Role").First(&role, "Role.name = ?", roleName).Error; err != nil { + if err := r.db.WithContext(ctx).First(&role, "organization_id = ? AND name = ?", oragnizationId, roleName).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } return nil, err } diff --git a/internal/route/route.go b/internal/route/route.go index 2f2eb649..538b5e97 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -291,6 +291,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}", customMiddleware.Handle(internalApi.UpdateTksRole, http.HandlerFunc(roleHandler.UpdateTksRole))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(roleHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(roleHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleName}/existence", customMiddleware.Handle(internalApi.IsRoleNameExisted, http.HandlerFunc(roleHandler.IsRoleNameExisted))).Methods(http.MethodGet) // Admin r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.Admin_ListTksRoles, http.HandlerFunc(roleHandler.Admin_ListTksRoles))).Methods(http.MethodGet) diff --git a/internal/usecase/role.go b/internal/usecase/role.go index 63121e04..6f88ae75 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -1,8 +1,8 @@ package usecase import ( - "github.com/openinfradev/tks-api/internal/model" "context" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" ) @@ -13,6 +13,7 @@ type IRoleUsecase interface { GetTksRole(ctx context.Context, id string) (*model.Role, error) DeleteTksRole(ctx context.Context, id string) error UpdateTksRole(ctx context.Context, role *model.Role) error + IsRoleNameExisted(ctx context.Context, organizationId string, roleName string) (bool, error) } type RoleUsecase struct { @@ -59,3 +60,16 @@ func (r RoleUsecase) UpdateTksRole(ctx context.Context, role *model.Role) error return nil } + +func (r RoleUsecase) IsRoleNameExisted(ctx context.Context, organizationId string, roleName string) (bool, error) { + role, err := r.repo.GetTksRoleByRoleName(ctx, organizationId, roleName) + if err != nil { + return false, err + } + + if role != nil { + return true, nil + } + + return false, nil +} diff --git a/pkg/domain/role.go b/pkg/domain/role.go index ab961b26..a2630f3e 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -58,5 +58,10 @@ type ListTksRoleResponse struct { } type UpdateTksRoleRequest struct { + Name string `json:"name" validate:"omitempty,min=0,max=100"` Description string `json:"description" validate:"omitempty,min=0,max=100"` } + +type CheckRoleNameResponse struct { + IsExist bool `json:"isExist"` +} From 3173d03c668a914a178ce401fd685b64a67585aa Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 2 Apr 2024 13:31:41 +0900 Subject: [PATCH 215/502] Enhance Update Users API to support request bundling for efficiency --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/user.go | 72 +++++++++++++++++++++++++++++++ internal/route/route.go | 1 + pkg/domain/user.go | 11 +++++ 4 files changed, 85 insertions(+) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 9daa7264..89fa6c1a 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -25,6 +25,7 @@ const ( ListUser GetUser DeleteUser + UpdateUsers UpdateUser ResetPassword CheckId diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 9a7748a9..39ee5cc3 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -25,6 +25,7 @@ type IUserHandler interface { Get(w http.ResponseWriter, r *http.Request) Delete(w http.ResponseWriter, r *http.Request) Update(w http.ResponseWriter, r *http.Request) + UpdateUsers(w http.ResponseWriter, r *http.Request) ResetPassword(w http.ResponseWriter, r *http.Request) GetMyProfile(w http.ResponseWriter, r *http.Request) @@ -347,6 +348,77 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } +// UpdateUsers godoc +// +// @Tags Users +// @Summary Update multiple users +// @Description Update multiple users +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body []domain.UpdateUsersRequest true "input" +// @Success 200 +// @Router /organizations/{organizationId}/users [put] +// @Security JWT +func (u UserHandler) UpdateUsers(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.UpdateUsersRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + users := make([]model.User, len(input.Users)) + for i, user := range input.Users { + if err = serializer.Map(r.Context(), user, &users[i]); err != nil { + ErrorJSON(w, r, err) + return + } + users[i].Organization = model.Organization{ + ID: organizationId, + } + + users[i].AccountId = user.AccountId + + for _, role := range roles { + if role.Name == user.Role { + users[i].Role = *role + break + } + } + + //ToDo: Implement transaction + _, err := u.usecase.UpdateByAccountIdByAdmin(r.Context(), user.AccountId, &users[i]) + if err != nil { + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + // ResetPassword godoc // // @Tags Users diff --git a/internal/route/route.go b/internal/route/route.go index 538b5e97..db6de985 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -112,6 +112,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.CreateUser, http.HandlerFunc(userHandler.Create))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.ListUser, http.HandlerFunc(userHandler.List))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.GetUser, http.HandlerFunc(userHandler.Get))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.UpdateUsers, http.HandlerFunc(userHandler.UpdateUsers))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.UpdateUser, http.HandlerFunc(userHandler.Update))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/reset-password", customMiddleware.Handle(internalApi.ResetPassword, http.HandlerFunc(userHandler.ResetPassword))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.DeleteUser, http.HandlerFunc(userHandler.Delete))).Methods(http.MethodDelete) diff --git a/pkg/domain/user.go b/pkg/domain/user.go index c955425a..6b701604 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -117,6 +117,17 @@ type UpdateUserRequest struct { Description string `json:"description" validate:"omitempty,min=0,max=100"` } +type UpdateUsersRequest struct { + Users []struct { + AccountId string `json:"accountId" validate:"required"` + Name string `json:"name" validate:"omitempty,min=1,max=30"` + Role string `json:"role" validate:"oneof=admin user"` + Email string `json:"email" validate:"omitempty,email"` + Department string `json:"department" validate:"omitempty,min=0,max=50"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` + } `json:"users"` +} + type UpdateUserResponse struct { User struct { ID string `json:"id"` From 40a90589c2a463943d1e47f4e42b8d413edd97eb Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 2 Apr 2024 13:48:17 +0900 Subject: [PATCH 216/502] Modify User model to get multiple role rather than only one role --- internal/delivery/http/organization.go | 15 ++- internal/delivery/http/role.go | 10 +- internal/delivery/http/user.go | 89 ++++++-------- internal/keycloak/keycloak.go | 36 +++++- internal/model/user.go | 3 +- internal/repository/role.go | 4 +- internal/repository/user.go | 113 ++++++++---------- internal/route/route.go | 2 +- internal/usecase/role.go | 18 ++- internal/usecase/user.go | 155 +++++++++++-------------- pkg/domain/admin/user.go | 26 ++--- pkg/domain/user.go | 48 ++++---- 12 files changed, 263 insertions(+), 256 deletions(-) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index d5fe5d2d..aa08410d 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -112,8 +112,21 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r return } + user := model.User{ + Organization: model.Organization{ + ID: organizationId, + }, + AccountId: input.AdminAccountId, + Name: input.AdminName, + Email: input.AdminEmail, + Roles: []model.Role{ + { + ID: adminRoleId, + }, + }, + } // Admin user 생성 - admin, err := h.userUsecase.CreateAdmin(r.Context(), organizationId, input.AdminAccountId, input.AdminName, input.AdminEmail) + admin, err := h.userUsecase.CreateAdmin(r.Context(), &user) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 49d718b7..e1f9c2c7 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -219,8 +219,16 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { roleId = v } + var organizationId string + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + // delete role - if err := h.roleUsecase.DeleteTksRole(r.Context(), roleId); err != nil { + if err := h.roleUsecase.DeleteTksRole(r.Context(), organizationId, roleId); err != nil { ErrorJSON(w, r, err) return } diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 39ee5cc3..845d9038 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -99,18 +99,10 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { user.Organization = model.Organization{ ID: organizationId, } - - roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } - for _, role := range roles { - if role.Name == input.Role { - user.Role = *role - break - } + for _, role := range input.Roles { + user.Roles = append(user.Roles, model.Role{ + ID: *role.ID, + }) } resUser, err := u.usecase.Create(ctx, &user) @@ -305,29 +297,31 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var user model.User - if err = serializer.Map(r.Context(), input, &user); err != nil { - ErrorJSON(w, r, err) - return - } user.Organization = model.Organization{ ID: organizationId, } user.AccountId = accountId - roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } - for _, role := range roles { - if role.Name == input.Role { - user.Role = *role - break + user.Email = input.Email + user.Name = input.Name + user.Department = input.Department + user.Description = input.Description + if input.Roles != nil { + for _, role := range *input.Roles { + user.Roles = append(user.Roles, model.Role{ + ID: *role.ID, + }) + } + } else { + orginUser, err := u.usecase.GetByAccountId(ctx, accountId, organizationId) + if err != nil { + ErrorJSON(w, r, err) + return } + user.Roles = orginUser.Roles } - resUser, err := u.usecase.UpdateByAccountIdByAdmin(ctx, accountId, &user) + resUser, err := u.usecase.UpdateByAccountIdByAdmin(ctx, &user) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) @@ -535,8 +529,9 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { return } + user.ID = requestUserInfo.GetUserId() user.OrganizationId = organizationId - resUser, err := u.usecase.Update(ctx, requestUserInfo.GetUserId(), &user) + resUser, err := u.usecase.Update(ctx, &user) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) @@ -778,7 +773,9 @@ func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Re } var roles []*model.Role - roles = append(roles, &user.Role) + for _, role := range user.Roles { + roles = append(roles, &role) + } var permissionSets []*model.PermissionSet for _, role := range roles { @@ -871,18 +868,10 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { Description: input.Description, } - roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } - - for _, role := range roles { - if role.Name == input.Role { - user.Role = *role - break - } + for _, role := range input.Roles { + user.Roles = append(user.Roles, model.Role{ + ID: *role.ID, + }) } user.Organization = model.Organization{ @@ -1136,21 +1125,13 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { user.Organization = model.Organization{ ID: organizationId, } - - roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } - for _, role := range roles { - if role.Name == input.Role { - user.Role = *role - break - } + for _, role := range input.Roles { + user.Roles = append(user.Roles, model.Role{ + ID: *role.ID, + }) } - resUser, err := u.usecase.UpdateByAccountIdByAdmin(ctx, accountId, &user) + resUser, err := u.usecase.UpdateByAccountIdByAdmin(ctx, &user) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index d7618fee..1a29a590 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -35,7 +35,8 @@ type IKeycloak interface { UpdateUser(ctx context.Context, organizationId string, user *gocloak.User) error JoinGroup(ctx context.Context, organizationId string, userId string, groupName string) error LeaveGroup(ctx context.Context, organizationId string, userId string, groupName string) error - + CreateGroup(ctx context.Context, organizationId string, groupName string) (string, error) + DeleteGroup(ctx context.Context, organizationId string, groupName string) error EnsureClientRoleWithClientName(ctx context.Context, organizationId string, clientName string, roleName string) error DeleteClientRoleWithClientName(ctx context.Context, organizationId string, clientName string, roleName string) error @@ -52,6 +53,39 @@ type Keycloak struct { adminCliToken *gocloak.JWT } +func (k *Keycloak) CreateGroup(ctx context.Context, organizationId string, groupName string) (string, error) { + token := k.adminCliToken + group := gocloak.Group{ + Name: gocloak.StringP(groupName), + } + groupId, err := k.client.CreateGroup(context.Background(), token.AccessToken, organizationId, group) + if err != nil { + return "", err + } + + return groupId, nil +} + +func (k *Keycloak) DeleteGroup(ctx context.Context, organizationId string, groupName string) error { + token := k.adminCliToken + groups, err := k.client.GetGroups(context.Background(), token.AccessToken, organizationId, gocloak.GetGroupsParams{ + Search: &groupName, + }) + if err != nil { + log.Error(ctx, err) + return httpErrors.NewInternalServerError(err, "", "") + } + if len(groups) == 0 { + return httpErrors.NewNotFoundError(fmt.Errorf("group not found"), "", "") + } + err = k.client.DeleteGroup(context.Background(), token.AccessToken, organizationId, *groups[0].ID) + if err != nil { + return err + } + + return nil +} + func (k *Keycloak) LoginAdmin(ctx context.Context, accountId string, password string) (*model.User, error) { JWTToken, err := k.client.LoginAdmin(context.Background(), accountId, password, DefaultMasterRealm) if err != nil { diff --git a/internal/model/user.go b/internal/model/user.go index c8a2c7de..da077818 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -12,8 +12,7 @@ type User struct { Password string `gorm:"-:all" json:"password"` Name string `json:"name"` Token string `json:"token"` - RoleId string - Role Role `gorm:"foreignKey:RoleId;references:ID" json:"role"` + Roles []Role `gorm:"many2many:user_roles;" json:"roles"` OrganizationId string Organization Organization `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` Creator string `json:"creator"` diff --git a/internal/repository/role.go b/internal/repository/role.go index fcd9bb3f..9f7b60a7 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -41,7 +41,9 @@ func (r RoleRepository) Create(ctx context.Context, roleObj *model.Role) (string if roleObj == nil { return "", fmt.Errorf("roleObj is nil") } - roleObj.ID = uuid.New().String() + if roleObj.ID == "" { + roleObj.ID = uuid.New().String() + } if err := r.db.WithContext(ctx).Create(roleObj).Error; err != nil { return "", err } diff --git a/internal/repository/user.go b/internal/repository/user.go index bdacb03b..30727f1f 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -14,14 +14,12 @@ import ( // Interface type IUserRepository interface { - CreateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, email string, - department string, description string, organizationId string, roleId string) (model.User, error) + Create(ctx context.Context, user *model.User) (*model.User, error) List(ctx context.Context, filters ...FilterFunc) (out *[]model.User, err error) ListWithPagination(ctx context.Context, pg *pagination.Pagination, organizationId string) (out *[]model.User, err error) Get(ctx context.Context, accountId string, organizationId string) (model.User, error) GetByUuid(ctx context.Context, userId uuid.UUID) (model.User, error) - UpdateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, roleId string, email string, - department string, description string) (model.User, error) + Update(ctx context.Context, user *model.User) (*model.User, error) UpdatePasswordAt(ctx context.Context, userId uuid.UUID, organizationId string, isTemporary bool) error DeleteWithUuid(ctx context.Context, uuid uuid.UUID) error Flush(ctx context.Context, organizationId string) error @@ -51,31 +49,33 @@ func NewUserRepository(db *gorm.DB) IUserRepository { } } -func (r *UserRepository) CreateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, email string, - department string, description string, organizationId string, roleId string) (model.User, error) { - - newUser := model.User{ - ID: uuid, - AccountId: accountId, - Name: name, - Email: email, - Department: department, - Description: description, - OrganizationId: organizationId, - RoleId: roleId, - PasswordUpdatedAt: time.Now(), - } - res := r.db.WithContext(ctx).Create(&newUser) +// func (r *UserRepository) CreateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, email string, +// +// department string, description string, organizationId string, roleId string) (model.User, error) { +func (r *UserRepository) Create(ctx context.Context, user *model.User) (*model.User, error) { + user.PasswordUpdatedAt = time.Now() + //newUser := model.User{ + // ID: uuid, + // AccountId: accountId, + // Name: name, + // Email: email, + // Department: department, + // Description: description, + // OrganizationId: organizationId, + // RoleId: roleId, + // PasswordUpdatedAt: time.Now(), + //} + res := r.db.WithContext(ctx).Create(user) if res.Error != nil { log.Error(ctx, res.Error.Error()) - return model.User{}, res.Error + return nil, res.Error } - user, err := r.getUserByAccountId(ctx, accountId, organizationId) + resp, err := r.getUserByAccountId(ctx, user.AccountId, user.Organization.ID) if err != nil { - return model.User{}, err + return nil, err } - return user, nil + return &resp, nil } func (r *UserRepository) List(ctx context.Context, filters ...FilterFunc) (*[]model.User, error) { @@ -83,7 +83,7 @@ func (r *UserRepository) List(ctx context.Context, filters ...FilterFunc) (*[]mo var res *gorm.DB if filters == nil { - res = r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Role").Find(&users) + res = r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Roles").Find(&users) } else { combinedFilter := func(filters ...FilterFunc) FilterFunc { return func(user *gorm.DB) *gorm.DB { @@ -94,7 +94,7 @@ func (r *UserRepository) List(ctx context.Context, filters ...FilterFunc) (*[]mo } } cFunc := combinedFilter(filters...) - res = cFunc(r.db.Model(&model.User{}).Preload("Organization").Preload("Role")).Find(&users) + res = cFunc(r.db.Model(&model.User{}).Preload("Organization").Preload("Roles")).Find(&users) } if res.Error != nil { @@ -118,7 +118,7 @@ func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination. pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.WithContext(ctx).Preload("Organization").Preload("Role").Model(&model.User{}).Where("users.organization_id = ?", organizationId), &users) + _, res := pg.Fetch(r.db.WithContext(ctx).Preload("Organization").Preload("Roles").Model(&model.User{}).Where("users.organization_id = ?", organizationId), &users) if res.Error != nil { log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error @@ -141,7 +141,7 @@ func (r *UserRepository) Get(ctx context.Context, accountId string, organization func (r *UserRepository) GetByUuid(ctx context.Context, userId uuid.UUID) (respUser model.User, err error) { user := model.User{} - res := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Role").Find(&user, "id = ?", userId) + res := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Roles").Find(&user, "id = ?", userId) if res.Error != nil { log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) @@ -153,29 +153,30 @@ func (r *UserRepository) GetByUuid(ctx context.Context, userId uuid.UUID) (respU return user, nil } -func (r *UserRepository) UpdateWithUuid(ctx context.Context, uuid uuid.UUID, accountId string, name string, roleId string, - email string, department string, description string) (model.User, error) { - var user model.User - res := r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", uuid).Updates(model.User{ - AccountId: accountId, - Name: name, - Email: email, - Department: department, - Description: description, - RoleId: roleId, + +// func (r *UserRepository) Update(ctx context.Context, uuid uuid.UUID, accountId string, name string, roleId string, +// +// email string, department string, description string) (model.User, error) { +func (r *UserRepository) Update(ctx context.Context, user *model.User) (*model.User, error) { + res := r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", user.ID).Updates(model.User{ + Name: user.Name, + Email: user.Email, + Department: user.Department, + Description: user.Description, + Roles: user.Roles, }) - if res.RowsAffected == 0 || res.Error != nil { - return model.User{}, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") - } + if res.Error != nil { log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) - return model.User{}, res.Error + return nil, res.Error } - res = r.db.Model(&model.User{}).Preload("Organization").Preload("Role").Where("id = ?", uuid).Find(&user) + + outUser := model.User{} + res = r.db.Model(&model.User{}).Preload("Organization").Preload("Roles").Where("users.id = ?", user.ID).Find(&outUser) if res.Error != nil { - return model.User{}, res.Error + return nil, res.Error } - return user, nil + return &outUser, nil } func (r *UserRepository) UpdatePasswordAt(ctx context.Context, userId uuid.UUID, organizationId string, isTemporary bool) error { @@ -217,32 +218,10 @@ func (r *UserRepository) GetRoleByName(ctx context.Context, roleName string) (mo return role, nil } -//func (r *UserRepository) FetchRoles() (*[]model.Role, error) { -// var roles []model.Role -// res := r.db.Find(&roles) -// -// if res.Error != nil { -// log.Errorf("error is :%s(%T)", res.Error.Error(), res.Error) -// return nil, res.Error -// } -// -// if res.RowsAffected == 0 { -// return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") -// } -// -// var out []model.Role -// for _, role := range roles { -// outRole := r.reflectRole(role) -// out = append(out, outRole) -// } -// -// return &out, nil -//} - // private members func (r *UserRepository) getUserByAccountId(ctx context.Context, accountId string, organizationId string) (model.User, error) { user := model.User{} - res := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Role"). + res := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Roles"). Find(&user, "account_id = ? AND organization_id = ?", accountId, organizationId) if res.Error != nil { log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) diff --git a/internal/route/route.go b/internal/route/route.go index db6de985..1608a576 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -79,7 +79,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), Audit: usecase.NewAuditUsecase(repoFactory), - Role: usecase.NewRoleUsecase(repoFactory), + Role: usecase.NewRoleUsecase(repoFactory, kc), Permission: usecase.NewPermissionUsecase(repoFactory), PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), Policy: usecase.NewPolicyUsecase(repoFactory), diff --git a/internal/usecase/role.go b/internal/usecase/role.go index 6f88ae75..a12b6482 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -2,6 +2,7 @@ package usecase import ( "context" + "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" @@ -11,22 +12,29 @@ type IRoleUsecase interface { CreateTksRole(ctx context.Context, role *model.Role) (string, error) ListTksRoles(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]*model.Role, error) GetTksRole(ctx context.Context, id string) (*model.Role, error) - DeleteTksRole(ctx context.Context, id string) error + DeleteTksRole(ctx context.Context, organizationId string, id string) error UpdateTksRole(ctx context.Context, role *model.Role) error IsRoleNameExisted(ctx context.Context, organizationId string, roleName string) (bool, error) } type RoleUsecase struct { repo repository.IRoleRepository + kc keycloak.IKeycloak } -func NewRoleUsecase(repo repository.Repository) *RoleUsecase { +func NewRoleUsecase(repo repository.Repository, kc keycloak.IKeycloak) *RoleUsecase { return &RoleUsecase{ repo: repo.Role, + kc: kc, } } func (r RoleUsecase) CreateTksRole(ctx context.Context, role *model.Role) (string, error) { + roleId, err := r.kc.CreateGroup(ctx, role.OrganizationID, role.Name) + if err != nil { + return "", err + } + role.ID = roleId return r.repo.Create(ctx, role) } @@ -48,7 +56,11 @@ func (r RoleUsecase) GetTksRole(ctx context.Context, id string) (*model.Role, er return role, nil } -func (r RoleUsecase) DeleteTksRole(ctx context.Context, id string) error { +func (r RoleUsecase) DeleteTksRole(ctx context.Context, organizationId string, id string) error { + err := r.kc.DeleteGroup(ctx, organizationId, id) + if err != nil { + return err + } return r.repo.Delete(ctx, id) } diff --git a/internal/usecase/user.go b/internal/usecase/user.go index ad8308f3..57780b57 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -19,14 +19,14 @@ import ( ) type IUserUsecase interface { - CreateAdmin(ctx context.Context, organizationId string, accountId string, accountName string, email string) (*model.User, error) + CreateAdmin(ctx context.Context, user *model.User) (*model.User, error) DeleteAdmin(ctx context.Context, organizationId string) error DeleteAll(ctx context.Context, organizationId string) error Create(ctx context.Context, user *model.User) (*model.User, error) List(ctx context.Context, organizationId string) (*[]model.User, error) ListWithPagination(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.User, error) Get(ctx context.Context, userId uuid.UUID) (*model.User, error) - Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) + Update(ctx context.Context, user *model.User) (*model.User, error) ResetPassword(ctx context.Context, userId uuid.UUID) error ResetPasswordByAccountId(ctx context.Context, accountId string, organizationId string) error GenerateRandomPassword(ctx context.Context) string @@ -35,7 +35,7 @@ type IUserUsecase interface { GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error - UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) + UpdateByAccountId(ctx context.Context, user *model.User) (*model.User, error) UpdatePasswordByAccountId(ctx context.Context, accountId string, originPassword string, newPassword string, organizationId string) error RenewalPasswordExpiredTime(ctx context.Context, userId uuid.UUID) error RenewalPasswordExpiredTimeByAccountId(ctx context.Context, accountId string, organizationId string) error @@ -43,7 +43,7 @@ type IUserUsecase interface { ValidateAccount(ctx context.Context, userId uuid.UUID, password string, organizationId string) error ValidateAccountByAccountId(ctx context.Context, accountId string, password string, organizationId string) error - UpdateByAccountIdByAdmin(ctx context.Context, accountId string, user *model.User) (*model.User, error) + UpdateByAccountIdByAdmin(ctx context.Context, user *model.User) (*model.User, error) } type UserUsecase struct { @@ -197,34 +197,23 @@ func (u *UserUsecase) DeleteAdmin(ctx context.Context, organizationId string) er return nil } -func (u *UserUsecase) CreateAdmin(ctx context.Context, organizationId string, accountId string, accountName string, email string) (*model.User, error) { +func (u *UserUsecase) CreateAdmin(ctx context.Context, user *model.User) (*model.User, error) { // Generate Admin user object randomPassword := helper.GenerateRandomString(passwordLength) - user := model.User{ - AccountId: accountId, - Password: randomPassword, - Email: email, - Role: model.Role{ - Name: "admin", - }, - Organization: model.Organization{ - ID: organizationId, - }, - Name: accountName, - } + user.Password = randomPassword // Create Admin user in keycloak & DB - resUser, err := u.Create(context.Background(), &user) + resUser, err := u.Create(context.Background(), user) if err != nil { return nil, err } // Send mail of temporary password - organizationInfo, err := u.organizationRepository.Get(ctx, organizationId) + organizationInfo, err := u.organizationRepository.Get(ctx, resUser.Organization.ID) if err != nil { return nil, err } - message, err := mail.MakeGeneratingOrganizationMessage(ctx, organizationId, organizationInfo.Name, user.Email, user.AccountId, randomPassword) + message, err := mail.MakeGeneratingOrganizationMessage(ctx, resUser.Organization.ID, organizationInfo.Name, user.Email, user.AccountId, randomPassword) if err != nil { return nil, httpErrors.NewInternalServerError(err, "", "") } @@ -346,35 +335,19 @@ func (u *UserUsecase) GetByEmail(ctx context.Context, email string, organization return &(*users)[0], nil } -func (u *UserUsecase) Update(ctx context.Context, userId uuid.UUID, user *model.User) (*model.User, error) { - storedUser, err := u.Get(ctx, userId) +func (u *UserUsecase) Update(ctx context.Context, user *model.User) (*model.User, error) { + storedUser, err := u.Get(ctx, user.ID) if err != nil { return nil, err } user.AccountId = storedUser.AccountId - return u.UpdateByAccountId(ctx, storedUser.AccountId, user) + return u.UpdateByAccountId(ctx, user) } -func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, user *model.User) (*model.User, error) { - var out model.User - - originUser, err := u.kc.GetUser(ctx, user.Organization.ID, accountId) - if err != nil { - return nil, err - } - - if (originUser.Email == nil || *originUser.Email != user.Email) || (originUser.FirstName == nil || *originUser.FirstName != user.Name) { - originUser.Email = gocloak.StringP(user.Email) - originUser.FirstName = gocloak.StringP(user.Name) - err = u.kc.UpdateUser(ctx, user.Organization.ID, originUser) - if err != nil { - return nil, err - } - } - +func (u *UserUsecase) UpdateByAccountId(ctx context.Context, user *model.User) (*model.User, error) { users, err := u.userRepository.List(ctx, u.userRepository.OrganizationFilter(user.Organization.ID), - u.userRepository.AccountIdFilter(accountId)) + u.userRepository.AccountIdFilter(user.AccountId)) if err != nil { if _, code := httpErrors.ErrorResponse(err); code == http.StatusNotFound { return nil, httpErrors.NewNotFoundError(httpErrors.NotFound, "", "") @@ -387,17 +360,22 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, accountId string, u return nil, fmt.Errorf("multiple users found") } - roleUuid := (*users)[0].Role.ID - if err != nil { - return nil, err + if ((*users)[0].Email != user.Email) || ((*users)[0].Name != user.Name) { + err = u.kc.UpdateUser(ctx, user.Organization.ID, &gocloak.User{ + Email: gocloak.StringP(user.Email), + FirstName: gocloak.StringP(user.Name), + }) + if err != nil { + return nil, err + } } - out, err = u.userRepository.UpdateWithUuid(ctx, (*users)[0].ID, user.AccountId, user.Name, roleUuid, user.Email, user.Department, user.Description) + resp, err := u.userRepository.Update(ctx, user) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") } - return &out, nil + return resp, nil } func (u *UserUsecase) Delete(ctx context.Context, userId uuid.UUID, organizationId string) error { @@ -441,7 +419,11 @@ func (u *UserUsecase) DeleteByAccountId(ctx context.Context, accountId string, o func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User, error) { // Create user in keycloak - groups := []string{fmt.Sprintf("%s@%s", user.Role.Name, user.Organization.ID)} + var groups []string + for _, role := range user.Roles { + groups = append(groups, fmt.Sprintf("%s@%s", role.Name, user.Organization.ID)) + } + userUuidStr, err := u.kc.CreateUser(ctx, user.Organization.ID, &gocloak.User{ Username: gocloak.StringP(user.AccountId), Credentials: &[]gocloak.CredentialRepresentation{ @@ -459,76 +441,69 @@ func (u *UserUsecase) Create(ctx context.Context, user *model.User) (*model.User return nil, err } - // Get user role - var roleUuid string - roles, err := u.roleRepository.ListTksRoles(ctx, user.Organization.ID, nil) - if err != nil { - return nil, err - } - if len(roles) == 0 { - return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") - } - for _, role := range roles { - if role.Name == user.Role.Name { - roleUuid = role.ID - } - } - if roleUuid == "" { - return nil, httpErrors.NewInternalServerError(fmt.Errorf("role not found"), "", "") - } - - // Generate user uuid - userUuid, err := uuid.Parse(userUuidStr) - if err != nil { + if user.ID, err = uuid.Parse(userUuidStr); err != nil { return nil, err } // Create user in DB - resUser, err := u.userRepository.CreateWithUuid(ctx, userUuid, user.AccountId, user.Name, user.Email, - user.Department, user.Description, user.Organization.ID, roleUuid) + resUser, err := u.userRepository.Create(ctx, user) + //resUser, err := u.userRepository.Create(ctx, userUuid, user.AccountId, user.Name, user.Email, + // user.Department, user.Description, user.Organization.ID, roleUuid) if err != nil { return nil, err } - return &resUser, nil + return resUser, nil } -func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, accountId string, newUser *model.User) (*model.User, error) { +func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, newUser *model.User) (*model.User, error) { + if newUser.AccountId == "" { + return nil, httpErrors.NewBadRequestError(fmt.Errorf("accountId is required"), "C_INVALID_ACCOUNT_ID", "") + } + deepCopyUser := *newUser - user, err := u.UpdateByAccountId(ctx, accountId, &deepCopyUser) + user, err := u.UpdateByAccountId(ctx, &deepCopyUser) if err != nil { return nil, err } - if newUser.Role.Name != user.Role.Name { - originGroupName := fmt.Sprintf("%s@%s", user.Role.Name, newUser.Organization.ID) - newGroupName := fmt.Sprintf("%s@%s", newUser.Role.Name, newUser.Organization.ID) - if err := u.kc.LeaveGroup(ctx, newUser.Organization.ID, user.ID.String(), originGroupName); err != nil { + var unassigningRoleIds, assigningRoleIds map[string]struct{} + for _, role := range newUser.Roles { + assigningRoleIds[role.ID] = struct{}{} + } + for _, role := range user.Roles { + if _, ok := assigningRoleIds[role.ID]; !ok { + unassigningRoleIds[role.ID] = struct{}{} + } else { + delete(assigningRoleIds, role.ID) + } + } + + for roleId := range unassigningRoleIds { + groupName := fmt.Sprintf("%s@%s", roleId, user.Organization.ID) + if err := u.kc.LeaveGroup(ctx, user.Organization.ID, user.ID.String(), groupName); err != nil { log.Errorf(ctx, "leave group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } - if err := u.kc.JoinGroup(ctx, newUser.Organization.ID, user.ID.String(), newGroupName); err != nil { + } + + for roleId := range assigningRoleIds { + groupName := fmt.Sprintf("%s@%s", roleId, user.Organization.ID) + if err := u.kc.JoinGroup(ctx, user.Organization.ID, user.ID.String(), groupName); err != nil { log.Errorf(ctx, "join group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } - - targetUser, err := u.userRepository.Get(ctx, newUser.AccountId, newUser.Organization.ID) - if err != nil { - return nil, err - } - err = u.authRepository.UpdateExpiredTimeOnToken(ctx, newUser.Organization.ID, targetUser.ID.String()) - if err != nil { - return nil, err - } } - *user, err = u.userRepository.UpdateWithUuid(ctx, user.ID, user.AccountId, user.Name, newUser.Role.ID, user.Email, - user.Department, user.Description) + err = u.authRepository.UpdateExpiredTimeOnToken(ctx, user.Organization.ID, user.ID.String()) + + user.Roles = newUser.Roles + resp, err := u.userRepository.Update(ctx, user) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") } - return user, nil + return resp, nil } func NewUserUsecase(r repository.Repository, kc keycloak.IKeycloak) IUserUsecase { diff --git a/pkg/domain/admin/user.go b/pkg/domain/admin/user.go index 0a9e6820..71961114 100644 --- a/pkg/domain/admin/user.go +++ b/pkg/domain/admin/user.go @@ -7,13 +7,13 @@ import ( ) type CreateUserRequest struct { - AccountId string `json:"accountId" validate:"required"` - Name string `json:"name" validate:"name"` - Email string `json:"email" validate:"required,email"` - Role string `json:"role" validate:"required"` - Department string `json:"department" validate:"min=0,max=50"` - Description string `json:"description" validate:"min=0,max=100"` - AdminPassword string `json:"adminPassword"` + AccountId string `json:"accountId" validate:"required"` + Name string `json:"name" validate:"name"` + Email string `json:"email" validate:"required,email"` + Roles []domain.UserCreationRole `json:"roles" validate:"required"` + Department string `json:"department" validate:"min=0,max=50"` + Description string `json:"description" validate:"min=0,max=100"` + AdminPassword string `json:"adminPassword"` } type CreateUserResponse struct { @@ -42,12 +42,12 @@ type GetUserResponse struct { } type UpdateUserRequest struct { - Name string `json:"name" validate:"name"` - Email string `json:"email" validate:"required,email"` - Department string `json:"department" validate:"min=0,max=50"` - Role string `json:"role" validate:"required"` - Description string `json:"description" validate:"min=0,max=100"` - AdminPassword string `json:"adminPassword"` + Name string `json:"name" validate:"name"` + Email string `json:"email" validate:"required,email"` + Department string `json:"department" validate:"min=0,max=50"` + Roles []domain.UserCreationRole `json:"roles" validate:"required"` + Description string `json:"description" validate:"min=0,max=100"` + AdminPassword string `json:"adminPassword"` } type UpdateUserResponse struct { diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 6b701604..9b094b8e 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -30,7 +30,7 @@ type UserResponse struct { Name string `json:"name"` Token string `json:"token"` RoleId string - Role RoleResponse `gorm:"foreignKey:RoleId;references:ID" json:"role"` + Roles []RoleResponse `json:"roles"` OrganizationId string Organization OrganizationResponse `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` Creator string `json:"creator"` @@ -45,13 +45,17 @@ type UserResponse struct { } type CreateUserRequest struct { - AccountId string `json:"accountId" validate:"required"` - Password string `json:"password" validate:"required"` - Name string `json:"name" validate:"name"` - Email string `json:"email" validate:"required,email"` - Department string `json:"department" validate:"min=0,max=50"` - Role string `json:"role" validate:"required,oneof=admin user"` - Description string `json:"description" validate:"min=0,max=100"` + AccountId string `json:"accountId" validate:"required"` + Password string `json:"password" validate:"required"` + Name string `json:"name" validate:"name"` + Email string `json:"email" validate:"required,email"` + Department string `json:"department" validate:"min=0,max=50"` + Roles []UserCreationRole `json:"roles" validate:"required"` + Description string `json:"description" validate:"min=0,max=100"` +} + +type UserCreationRole struct { + ID *string `json:"id" validate:"required"` } type SimpleUserResponse struct { @@ -67,7 +71,7 @@ type CreateUserResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Role RoleResponse `json:"role"` + Roles []SimpleRoleResponse `json:"roles"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` @@ -80,7 +84,7 @@ type GetUserResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Role RoleResponse `json:"role"` + Roles []SimpleRoleResponse `json:"role"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` @@ -99,7 +103,7 @@ type ListUserBody struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Role RoleResponse `json:"role"` + Roles []SimpleRoleResponse `json:"roles"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` @@ -110,11 +114,11 @@ type ListUserBody struct { } type UpdateUserRequest struct { - Name string `json:"name" validate:"omitempty,min=1,max=30"` - Role string `json:"role" validate:"oneof=admin user"` - Email string `json:"email" validate:"omitempty,email"` - Department string `json:"department" validate:"omitempty,min=0,max=50"` - Description string `json:"description" validate:"omitempty,min=0,max=100"` + Name string `json:"name" validate:"required,min=1,max=30"` + Roles *[]UserCreationRole `json:"roles" validate:"required"` + Email string `json:"email" validate:"required,email"` + Department string `json:"department" validate:"required,min=0,max=50"` + Description string `json:"description" validate:"required,min=0,max=100"` } type UpdateUsersRequest struct { @@ -133,7 +137,7 @@ type UpdateUserResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Role RoleResponse `json:"role"` + Roles []SimpleRoleResponse `json:"roles"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` @@ -148,7 +152,7 @@ type GetMyProfileResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Role RoleResponse `json:"role"` + Roles []RoleResponse `json:"roles"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` @@ -156,9 +160,9 @@ type GetMyProfileResponse struct { } type UpdateMyProfileRequest struct { Password string `json:"password" validate:"required"` - Name string `json:"name" validate:"omitempty,min=1,max=30"` - Email string `json:"email" validate:"omitempty,email"` - Department string `json:"department" validate:"omitempty,min=0,max=50"` + Name string `json:"name" validate:"required,min=1,max=30"` + Email string `json:"email" validate:"required,email"` + Department string `json:"department" validate:"required,min=0,max=50"` } type UpdateMyProfileResponse struct { @@ -166,7 +170,7 @@ type UpdateMyProfileResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Role RoleResponse `json:"role"` + Roles []SimpleRoleResponse `json:"role"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` From 8f425613d8fdfa8f92844eef5e406846449cf809 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 2 Apr 2024 14:55:22 +0900 Subject: [PATCH 217/502] bugfix. --- internal/delivery/http/user.go | 95 ++++++++++++++++++++++------------ internal/helper/util.go | 9 ++++ internal/repository/user.go | 20 +++++-- internal/usecase/user.go | 34 ++++++------ pkg/domain/admin/user.go | 4 +- pkg/domain/role.go | 6 +-- pkg/domain/user.go | 26 +++++----- 7 files changed, 123 insertions(+), 71 deletions(-) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 845d9038..c2578c69 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -100,9 +100,13 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { ID: organizationId, } for _, role := range input.Roles { - user.Roles = append(user.Roles, model.Role{ - ID: *role.ID, - }) + v, err := u.roleUsecase.GetTksRole(ctx, *role.ID) + if err != nil { + ErrorJSON(w, r, err) + return + } + + user.Roles = append(user.Roles, *v) } resUser, err := u.usecase.Create(ctx, &user) @@ -122,6 +126,8 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { log.Error(r.Context(), err) } + out.User.Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles) + ResponseJSON(w, r, http.StatusCreated, out) } @@ -169,6 +175,8 @@ func (u UserHandler) Get(w http.ResponseWriter, r *http.Request) { log.Error(r.Context(), err) } + out.User.Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles) + ResponseJSON(w, r, http.StatusOK, out) } @@ -211,6 +219,10 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { if err = serializer.Map(r.Context(), user, &out.Users[i]); err != nil { log.Error(r.Context(), err) } + + if out.Users[i].Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles); err != nil { + log.Error(r.Context(), err) + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { @@ -220,6 +232,18 @@ func (u UserHandler) List(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } +func (u UserHandler) convertUserRolesToSimpleRoleResponse(roles []model.Role) []domain.SimpleRoleResponse { + var simpleRoles []domain.SimpleRoleResponse + for _, role := range roles { + simpleRoles = append(simpleRoles, domain.SimpleRoleResponse{ + ID: role.ID, + Name: role.Name, + }) + } + + return simpleRoles +} + // Delete godoc // // @Tags Users @@ -297,28 +321,21 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var user model.User + if err = serializer.Map(r.Context(), input, &user); err != nil { + log.Error(r.Context(), err) + } user.Organization = model.Organization{ ID: organizationId, } user.AccountId = accountId - - user.Email = input.Email - user.Name = input.Name - user.Department = input.Department - user.Description = input.Description - if input.Roles != nil { - for _, role := range *input.Roles { - user.Roles = append(user.Roles, model.Role{ - ID: *role.ID, - }) - } - } else { - orginUser, err := u.usecase.GetByAccountId(ctx, accountId, organizationId) + for _, role := range input.Roles { + v, err := u.roleUsecase.GetTksRole(ctx, *role.ID) if err != nil { ErrorJSON(w, r, err) return } - user.Roles = orginUser.Roles + + user.Roles = append(user.Roles, *v) } resUser, err := u.usecase.UpdateByAccountIdByAdmin(ctx, &user) @@ -338,6 +355,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } + out.User.Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles) ResponseJSON(w, r, http.StatusOK, out) } @@ -371,12 +389,7 @@ func (u UserHandler) UpdateUsers(w http.ResponseWriter, r *http.Request) { return } - roles, err := u.roleUsecase.ListTksRoles(r.Context(), organizationId, nil) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } + ctx := r.Context() users := make([]model.User, len(input.Users)) for i, user := range input.Users { @@ -387,18 +400,20 @@ func (u UserHandler) UpdateUsers(w http.ResponseWriter, r *http.Request) { users[i].Organization = model.Organization{ ID: organizationId, } - users[i].AccountId = user.AccountId - for _, role := range roles { - if role.Name == user.Role { - users[i].Role = *role - break + for _, role := range user.Roles { + v, err := u.roleUsecase.GetTksRole(ctx, *role.ID) + if err != nil { + ErrorJSON(w, r, err) + return } + + users[i].Roles = append(users[i].Roles, *v) } //ToDo: Implement transaction - _, err := u.usecase.UpdateByAccountIdByAdmin(r.Context(), user.AccountId, &users[i]) + _, err := u.usecase.UpdateByAccountIdByAdmin(r.Context(), &users[i]) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) @@ -477,6 +492,8 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { return } + out.User.Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles) + ResponseJSON(w, r, http.StatusOK, out) } @@ -548,6 +565,8 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { return } + out.User.Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles) + ResponseJSON(w, r, http.StatusOK, out) } @@ -869,9 +888,13 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } for _, role := range input.Roles { - user.Roles = append(user.Roles, model.Role{ - ID: *role.ID, - }) + v, err := u.roleUsecase.GetTksRole(r.Context(), *role.ID) + if err != nil { + ErrorJSON(w, r, err) + return + } + + user.Roles = append(user.Roles, *v) } user.Organization = model.Organization{ @@ -945,6 +968,10 @@ func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { if err = serializer.Map(r.Context(), user, &out.Users[i]); err != nil { log.Error(r.Context(), err) } + + if out.Users[i].Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles); err != nil { + log.Error(r.Context(), err) + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { @@ -996,6 +1023,8 @@ func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { log.Error(r.Context(), err) } + out.User.Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles) + ResponseJSON(w, r, http.StatusOK, out) } @@ -1149,5 +1178,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { return } + out.User.Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles) + ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/helper/util.go b/internal/helper/util.go index 9e4e573a..b63bc911 100644 --- a/internal/helper/util.go +++ b/internal/helper/util.go @@ -93,3 +93,12 @@ func StringP(value string) *string { func UUIDP(value uuid.UUID) *uuid.UUID { return &value } + +func DeepCopy(src, dest interface{}) error { + bytes, err := json.Marshal(src) + if err != nil { + return err + } + + return json.Unmarshal(bytes, dest) +} diff --git a/internal/repository/user.go b/internal/repository/user.go index 30727f1f..2cdcecec 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -154,16 +154,12 @@ func (r *UserRepository) GetByUuid(ctx context.Context, userId uuid.UUID) (respU return user, nil } -// func (r *UserRepository) Update(ctx context.Context, uuid uuid.UUID, accountId string, name string, roleId string, -// -// email string, department string, description string) (model.User, error) { func (r *UserRepository) Update(ctx context.Context, user *model.User) (*model.User, error) { res := r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", user.ID).Updates(model.User{ Name: user.Name, Email: user.Email, Department: user.Department, Description: user.Description, - Roles: user.Roles, }) if res.Error != nil { @@ -171,8 +167,22 @@ func (r *UserRepository) Update(ctx context.Context, user *model.User) (*model.U return nil, res.Error } + var u model.User + if err := r.db.WithContext(ctx).Preload("Roles").First(&u, "id = ?", user.ID).Error; err != nil { + return nil, err + } + if err := r.db.WithContext(ctx).Model(&u).Association("Roles").Clear(); err != nil { + return nil, err + } + + for _, role := range user.Roles { + if err := r.db.WithContext(ctx).Model(&u).Association("Roles").Append(&role); err != nil { + return nil, err + } + } + outUser := model.User{} - res = r.db.Model(&model.User{}).Preload("Organization").Preload("Roles").Where("users.id = ?", user.ID).Find(&outUser) + res = r.db.WithContext(ctx).Preload("Organization").Preload("Roles").Model(&model.User{}).Where("users.id = ?", user.ID).Find(&outUser) if res.Error != nil { return nil, res.Error } diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 57780b57..5590b21a 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -369,6 +369,7 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, user *model.User) ( return nil, err } } + user.ID = (*users)[0].ID resp, err := u.userRepository.Update(ctx, user) if err != nil { @@ -461,44 +462,47 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, newUser *mod return nil, httpErrors.NewBadRequestError(fmt.Errorf("accountId is required"), "C_INVALID_ACCOUNT_ID", "") } - deepCopyUser := *newUser - user, err := u.UpdateByAccountId(ctx, &deepCopyUser) + originUser, err := u.userRepository.Get(ctx, newUser.AccountId, newUser.Organization.ID) if err != nil { return nil, err } - var unassigningRoleIds, assigningRoleIds map[string]struct{} + unassigningRoleIds, assigningRoleIds := make(map[string]model.Role), make(map[string]model.Role) for _, role := range newUser.Roles { - assigningRoleIds[role.ID] = struct{}{} + assigningRoleIds[role.ID] = role } - for _, role := range user.Roles { + for _, role := range originUser.Roles { if _, ok := assigningRoleIds[role.ID]; !ok { - unassigningRoleIds[role.ID] = struct{}{} + unassigningRoleIds[role.ID] = role } else { delete(assigningRoleIds, role.ID) } } - for roleId := range unassigningRoleIds { - groupName := fmt.Sprintf("%s@%s", roleId, user.Organization.ID) - if err := u.kc.LeaveGroup(ctx, user.Organization.ID, user.ID.String(), groupName); err != nil { + for _, role := range unassigningRoleIds { + groupName := fmt.Sprintf("%s@%s", role.Name, originUser.Organization.ID) + if err := u.kc.LeaveGroup(ctx, originUser.Organization.ID, originUser.ID.String(), groupName); err != nil { log.Errorf(ctx, "leave group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } } - for roleId := range assigningRoleIds { - groupName := fmt.Sprintf("%s@%s", roleId, user.Organization.ID) - if err := u.kc.JoinGroup(ctx, user.Organization.ID, user.ID.String(), groupName); err != nil { + for _, role := range assigningRoleIds { + groupName := fmt.Sprintf("%s@%s", role.Name, originUser.Organization.ID) + if err := u.kc.JoinGroup(ctx, originUser.Organization.ID, originUser.ID.String(), groupName); err != nil { log.Errorf(ctx, "join group in keycloak failed: %v", err) return nil, httpErrors.NewInternalServerError(err, "", "") } } - err = u.authRepository.UpdateExpiredTimeOnToken(ctx, user.Organization.ID, user.ID.String()) + err = u.authRepository.UpdateExpiredTimeOnToken(ctx, originUser.Organization.ID, originUser.ID.String()) + originUser.Name = newUser.Name + originUser.Email = newUser.Email + originUser.Department = newUser.Department + originUser.Description = newUser.Description + originUser.Roles = newUser.Roles - user.Roles = newUser.Roles - resp, err := u.userRepository.Update(ctx, user) + resp, err := u.userRepository.Update(ctx, &originUser) if err != nil { return nil, errors.Wrap(err, "updating user in repository failed") } diff --git a/pkg/domain/admin/user.go b/pkg/domain/admin/user.go index 71961114..0a85c596 100644 --- a/pkg/domain/admin/user.go +++ b/pkg/domain/admin/user.go @@ -30,7 +30,7 @@ type GetUserResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Role domain.RoleResponse `json:"role"` + Roles []domain.SimpleRoleResponse `json:"roles"` Organization domain.OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` @@ -55,7 +55,7 @@ type UpdateUserResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Role domain.RoleResponse `json:"role"` + Roles []domain.SimpleRoleResponse `json:"roles"` Organization domain.OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` diff --git a/pkg/domain/role.go b/pkg/domain/role.go index a2630f3e..f9e5d30d 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -27,10 +27,8 @@ type RoleResponse struct { } type SimpleRoleResponse = struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - OrganizationID string `json:"organizationId"` + ID string `json:"id"` + Name string `json:"name"` } type CreateTksRoleRequest struct { diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 9b094b8e..d4bc410b 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -30,7 +30,7 @@ type UserResponse struct { Name string `json:"name"` Token string `json:"token"` RoleId string - Roles []RoleResponse `json:"roles"` + Roles []SimpleRoleResponse `json:"roles"` OrganizationId string Organization OrganizationResponse `gorm:"foreignKey:OrganizationId;references:ID" json:"organization"` Creator string `json:"creator"` @@ -114,21 +114,21 @@ type ListUserBody struct { } type UpdateUserRequest struct { - Name string `json:"name" validate:"required,min=1,max=30"` - Roles *[]UserCreationRole `json:"roles" validate:"required"` - Email string `json:"email" validate:"required,email"` - Department string `json:"department" validate:"required,min=0,max=50"` - Description string `json:"description" validate:"required,min=0,max=100"` + Name string `json:"name" validate:"required""` + Roles []UserCreationRole `json:"roles" validate:"required"` + Email string `json:"email" validate:"required,email"` + Department string `json:"department" validate:"min=0,max=50"` + Description string `json:"description" validate:"min=0,max=100"` } type UpdateUsersRequest struct { Users []struct { - AccountId string `json:"accountId" validate:"required"` - Name string `json:"name" validate:"omitempty,min=1,max=30"` - Role string `json:"role" validate:"oneof=admin user"` - Email string `json:"email" validate:"omitempty,email"` - Department string `json:"department" validate:"omitempty,min=0,max=50"` - Description string `json:"description" validate:"omitempty,min=0,max=100"` + AccountId string `json:"accountId" validate:"required"` + Name string `json:"name" validate:"required,name"` + Roles []UserCreationRole `json:"roles" validate:"required"` + Email string `json:"email" validate:"required,email"` + Department string `json:"department" validate:"min=0,max=50"` + Description string `json:"description" validate:"min=0,max=100"` } `json:"users"` } @@ -152,7 +152,7 @@ type GetMyProfileResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Roles []RoleResponse `json:"roles"` + Roles []SimpleRoleResponse `json:"roles"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` From f753f638aaf6a862fbb8ac287aa5c77e88c30b73 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 3 Apr 2024 15:17:00 +0900 Subject: [PATCH 218/502] Add append/remove Users in role --- internal/delivery/api/endpoint.go | 3 + internal/delivery/http/role.go | 215 +++++++++++++++++++++++++++++- internal/delivery/http/user.go | 8 +- internal/repository/role.go | 4 +- internal/repository/user.go | 38 ++++-- internal/route/route.go | 3 + internal/usecase/role.go | 6 +- internal/usecase/user.go | 17 +++ pkg/domain/role.go | 13 ++ pkg/domain/user.go | 2 +- 10 files changed, 284 insertions(+), 25 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 89fa6c1a..d81480d4 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -197,6 +197,9 @@ const ( GetPermissionsByRoleId UpdatePermissionsByRoleId IsRoleNameExisted + AppendUsersToRole + GetUsersInRoleId + RemoveUsersFromRole // Permission GetPermissionTemplates diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index e1f9c2c7..fd738c2b 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -24,12 +24,17 @@ type IRoleHandler interface { UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) IsRoleNameExisted(w http.ResponseWriter, r *http.Request) + GetUsersInRoleId(w http.ResponseWriter, r *http.Request) + AppendUsersToRole(w http.ResponseWriter, r *http.Request) + RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) + Admin_ListTksRoles(w http.ResponseWriter, r *http.Request) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) } type RoleHandler struct { roleUsecase usecase.IRoleUsecase + userUsecase usecase.IUserUsecase permissionUsecase usecase.IPermissionUsecase } @@ -37,6 +42,7 @@ func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { return &RoleHandler{ roleUsecase: usecase.Role, permissionUsecase: usecase.Permission, + userUsecase: usecase.User, } } @@ -169,15 +175,20 @@ func (h RoleHandler) ListTksRoles(w http.ResponseWriter, r *http.Request) { func (h RoleHandler) GetTksRole(w http.ResponseWriter, r *http.Request) { // path parameter vars := mux.Vars(r) - var roleId string + var organizationId, roleId string if v, ok := vars["roleId"]; !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) } else { roleId = v } + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + } else { + organizationId = v + } // get role - role, err := h.roleUsecase.GetTksRole(r.Context(), roleId) + role, err := h.roleUsecase.GetTksRole(r.Context(), organizationId, roleId) if err != nil { ErrorJSON(w, r, err) return @@ -465,15 +476,20 @@ func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { // Same as GetTksRole vars := mux.Vars(r) - var roleId string + var organizationId, roleId string if v, ok := vars["roleId"]; !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) } else { roleId = v } + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + } else { + organizationId = v + } // get role - role, err := h.roleUsecase.GetTksRole(r.Context(), roleId) + role, err := h.roleUsecase.GetTksRole(r.Context(), organizationId, roleId) if err != nil { ErrorJSON(w, r, err) return @@ -534,3 +550,194 @@ func (h RoleHandler) IsRoleNameExisted(w http.ResponseWriter, r *http.Request) { // response ResponseJSON(w, r, http.StatusOK, out) } + +// AppendUsersToRole godoc +// +// @Tags Roles +// @Summary Append Users To Role +// @Description Append Users To Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Param body body domain.AppendUsersToRoleRequest true "Append Users To Role Request" +// @Success 200 +// @Router /organizations/{organizationId}/roles/{roleId}/users [post] +// @Security JWT +func (h RoleHandler) AppendUsersToRole(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var organizationId, roleId string + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + // request body + input := domain.AppendUsersToRoleRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + for _, user := range input.Users { + originUser, err := h.userUsecase.Get(r.Context(), user) + if err != nil { + ErrorJSON(w, r, err) + return + } + + role, err := h.roleUsecase.GetTksRole(r.Context(), organizationId, roleId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + originUser.Roles = append(originUser.Roles, *role) + + if _, err := h.userUsecase.UpdateByAccountIdByAdmin(r.Context(), originUser); err != nil { + ErrorJSON(w, r, err) + return + } + } + + // response + ResponseJSON(w, r, http.StatusOK, nil) +} + +// RemoveUsersFromRole godoc +// +// @Tags Roles +// @Summary Remove Users From Role +// @Description Remove Users From Role +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Param body body domain.RemoveUsersFromRoleRequest true "Remove Users From Role Request" +// @Success 200 +// @Router /organizations/{organizationId}/roles/{roleId}/users [delete] +// @Security JWT +func (h RoleHandler) RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var organizationId, roleId string + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + + // request body + input := domain.RemoveUsersFromRoleRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + for _, user := range input.Users { + originUser, err := h.userUsecase.Get(r.Context(), user) + if err != nil { + ErrorJSON(w, r, err) + return + } + + role, err := h.roleUsecase.GetTksRole(r.Context(), organizationId, roleId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + for i, r := range originUser.Roles { + if r.ID == role.ID { + originUser.Roles = append(originUser.Roles[:i], originUser.Roles[i+1:]...) + break + } + } + + if _, err := h.userUsecase.UpdateByAccountIdByAdmin(r.Context(), originUser); err != nil { + ErrorJSON(w, r, err) + return + } + } + + // response + ResponseJSON(w, r, http.StatusOK, nil) +} + +// GetUsersInRoleId godoc +// +// @Tags Roles +// @Summary Get Users By Role ID +// @Description Get Users By Role ID +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetUsersInRoleIdResponse +// @Router /organizations/{organizationId}/roles/{roleId}/users [get] +// @Security JWT +func (h RoleHandler) GetUsersInRoleId(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + var organizationId, roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + users, err := h.userUsecase.ListUsersByRole(r.Context(), organizationId, roleId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetUsersInRoleIdResponse + out.Users = make([]domain.SimpleUserResponse, len(*users)) + for i, user := range *users { + out.Users[i] = domain.SimpleUserResponse{ + ID: user.ID.String(), + AccountId: user.AccountId, + Name: user.Name, + Email: user.Email, + Department: user.Department, + } + } + + if err := serializer.Map(r.Context(), *pg, &out.Pagination); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index c2578c69..659671be 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -100,7 +100,7 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { ID: organizationId, } for _, role := range input.Roles { - v, err := u.roleUsecase.GetTksRole(ctx, *role.ID) + v, err := u.roleUsecase.GetTksRole(ctx, organizationId, *role.ID) if err != nil { ErrorJSON(w, r, err) return @@ -329,7 +329,7 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { } user.AccountId = accountId for _, role := range input.Roles { - v, err := u.roleUsecase.GetTksRole(ctx, *role.ID) + v, err := u.roleUsecase.GetTksRole(ctx, organizationId, *role.ID) if err != nil { ErrorJSON(w, r, err) return @@ -403,7 +403,7 @@ func (u UserHandler) UpdateUsers(w http.ResponseWriter, r *http.Request) { users[i].AccountId = user.AccountId for _, role := range user.Roles { - v, err := u.roleUsecase.GetTksRole(ctx, *role.ID) + v, err := u.roleUsecase.GetTksRole(ctx, organizationId, *role.ID) if err != nil { ErrorJSON(w, r, err) return @@ -888,7 +888,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } for _, role := range input.Roles { - v, err := u.roleUsecase.GetTksRole(r.Context(), *role.ID) + v, err := u.roleUsecase.GetTksRole(r.Context(), organizationId, *role.ID) if err != nil { ErrorJSON(w, r, err) return diff --git a/internal/repository/role.go b/internal/repository/role.go index 9f7b60a7..a6617686 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -15,7 +15,7 @@ import ( type IRoleRepository interface { Create(ctx context.Context, roleObj *model.Role) (string, error) ListTksRoles(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]*model.Role, error) - GetTksRole(ctx context.Context, id string) (*model.Role, error) + GetTksRole(ctx context.Context, organizationId string, id string) (*model.Role, error) GetTksRoleByRoleName(ctx context.Context, organizationId string, roleName string) (*model.Role, error) Delete(ctx context.Context, id string) error Update(ctx context.Context, roleObj *model.Role) error @@ -65,7 +65,7 @@ func (r RoleRepository) ListTksRoles(ctx context.Context, organizationId string, return roles, nil } -func (r RoleRepository) GetTksRole(ctx context.Context, id string) (*model.Role, error) { +func (r RoleRepository) GetTksRole(ctx context.Context, organizationId string, id string) (*model.Role, error) { var role model.Role if err := r.db.WithContext(ctx).First(&role, "id = ?", id).Error; err != nil { return nil, err diff --git a/internal/repository/user.go b/internal/repository/user.go index 2cdcecec..af2d8a1b 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -24,6 +24,8 @@ type IUserRepository interface { DeleteWithUuid(ctx context.Context, uuid uuid.UUID) error Flush(ctx context.Context, organizationId string) error + ListUsersByRole(ctx context.Context, organizationId string, roleId string, pg *pagination.Pagination) (*[]model.User, error) + AccountIdFilter(accountId string) FilterFunc OrganizationFilter(organization string) FilterFunc EmailFilter(email string) FilterFunc @@ -154,6 +156,28 @@ func (r *UserRepository) GetByUuid(ctx context.Context, userId uuid.UUID) (respU return user, nil } +func (r *UserRepository) ListUsersByRole(ctx context.Context, organizationId string, roleId string, pg *pagination.Pagination) (*[]model.User, error) { + var users []model.User + + if pg == nil { + pg = pagination.NewPagination(nil) + } + + _, res := pg.Fetch(r.db.WithContext(ctx).Preload("Organization").Preload("Roles").Model(&model.User{}). + Where("users.organization_id = ? AND roles.id = ?", organizationId, roleId). + Joins("JOIN user_roles ON users.id = user_roles.user_id"). + Joins("JOIN roles ON user_roles.role_id = roles.id"), &users) + if res.Error != nil { + log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) + return nil, res.Error + } + + var out []model.User + out = append(out, users...) + + return &out, nil +} + func (r *UserRepository) Update(ctx context.Context, user *model.User) (*model.User, error) { res := r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", user.ID).Updates(model.User{ Name: user.Name, @@ -167,20 +191,12 @@ func (r *UserRepository) Update(ctx context.Context, user *model.User) (*model.U return nil, res.Error } - var u model.User - if err := r.db.WithContext(ctx).Preload("Roles").First(&u, "id = ?", user.ID).Error; err != nil { - return nil, err - } - if err := r.db.WithContext(ctx).Model(&u).Association("Roles").Clear(); err != nil { + err := r.db.WithContext(ctx).Model(&user).Association("Roles").Replace(user.Roles) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) return nil, err } - for _, role := range user.Roles { - if err := r.db.WithContext(ctx).Model(&u).Association("Roles").Append(&role); err != nil { - return nil, err - } - } - outUser := model.User{} res = r.db.WithContext(ctx).Preload("Organization").Preload("Roles").Model(&model.User{}).Where("users.id = ?", user.ID).Find(&outUser) if res.Error != nil { diff --git a/internal/route/route.go b/internal/route/route.go index 1608a576..4a25c9ca 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -293,6 +293,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByRoleId, http.HandlerFunc(roleHandler.GetPermissionsByRoleId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/permissions", customMiddleware.Handle(internalApi.UpdatePermissionsByRoleId, http.HandlerFunc(roleHandler.UpdatePermissionsByRoleId))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleName}/existence", customMiddleware.Handle(internalApi.IsRoleNameExisted, http.HandlerFunc(roleHandler.IsRoleNameExisted))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/users", customMiddleware.Handle(internalApi.AppendUsersToRole, http.HandlerFunc(roleHandler.AppendUsersToRole))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/users", customMiddleware.Handle(internalApi.GetUsersInRoleId, http.HandlerFunc(roleHandler.GetUsersInRoleId))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/roles/{roleId}/users", customMiddleware.Handle(internalApi.RemoveUsersFromRole, http.HandlerFunc(roleHandler.RemoveUsersFromRole))).Methods(http.MethodDelete) // Admin r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/roles", customMiddleware.Handle(internalApi.Admin_ListTksRoles, http.HandlerFunc(roleHandler.Admin_ListTksRoles))).Methods(http.MethodGet) diff --git a/internal/usecase/role.go b/internal/usecase/role.go index a12b6482..a07f0e92 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -11,7 +11,7 @@ import ( type IRoleUsecase interface { CreateTksRole(ctx context.Context, role *model.Role) (string, error) ListTksRoles(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]*model.Role, error) - GetTksRole(ctx context.Context, id string) (*model.Role, error) + GetTksRole(ctx context.Context, orgainzationId string, id string) (*model.Role, error) DeleteTksRole(ctx context.Context, organizationId string, id string) error UpdateTksRole(ctx context.Context, role *model.Role) error IsRoleNameExisted(ctx context.Context, organizationId string, roleName string) (bool, error) @@ -47,8 +47,8 @@ func (r RoleUsecase) ListTksRoles(ctx context.Context, organizationId string, pg return roles, nil } -func (r RoleUsecase) GetTksRole(ctx context.Context, id string) (*model.Role, error) { - role, err := r.repo.GetTksRole(ctx, id) +func (r RoleUsecase) GetTksRole(ctx context.Context, organizationId string, id string) (*model.Role, error) { + role, err := r.repo.GetTksRole(ctx, organizationId, id) if err != nil { return nil, err } diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 5590b21a..c67fd1de 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -44,6 +44,8 @@ type IUserUsecase interface { ValidateAccountByAccountId(ctx context.Context, accountId string, password string, organizationId string) error UpdateByAccountIdByAdmin(ctx context.Context, user *model.User) (*model.User, error) + + ListUsersByRole(ctx context.Context, organizationId string, roleId string, pg *pagination.Pagination) (*[]model.User, error) } type UserUsecase struct { @@ -496,6 +498,11 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, newUser *mod } err = u.authRepository.UpdateExpiredTimeOnToken(ctx, originUser.Organization.ID, originUser.ID.String()) + if err != nil { + log.Errorf(ctx, "update expired time on token failed: %v", err) + return nil, httpErrors.NewInternalServerError(err, "", "") + } + originUser.Name = newUser.Name originUser.Email = newUser.Email originUser.Department = newUser.Department @@ -510,6 +517,16 @@ func (u *UserUsecase) UpdateByAccountIdByAdmin(ctx context.Context, newUser *mod return resp, nil } +func (u *UserUsecase) ListUsersByRole(ctx context.Context, organizationId string, roleId string, pg *pagination.Pagination) (*[]model.User, error) { + users, err := u.userRepository.ListUsersByRole(ctx, organizationId, roleId, pg) + if err != nil { + return nil, err + } + + return users, nil + +} + func NewUserUsecase(r repository.Repository, kc keycloak.IKeycloak) IUserUsecase { return &UserUsecase{ authRepository: r.Auth, diff --git a/pkg/domain/role.go b/pkg/domain/role.go index f9e5d30d..05449c73 100644 --- a/pkg/domain/role.go +++ b/pkg/domain/role.go @@ -63,3 +63,16 @@ type UpdateTksRoleRequest struct { type CheckRoleNameResponse struct { IsExist bool `json:"isExist"` } + +type AppendUsersToRoleRequest struct { + Users []uuid.UUID `json:"users" validate:"required"` +} + +type RemoveUsersFromRoleRequest struct { + Users []uuid.UUID `json:"users" validate:"required"` +} + +type GetUsersInRoleIdResponse struct { + Users []SimpleUserResponse `json:"users"` + Pagination PaginationResponse `json:"pagination"` +} diff --git a/pkg/domain/user.go b/pkg/domain/user.go index d4bc410b..82e53a5f 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -114,7 +114,7 @@ type ListUserBody struct { } type UpdateUserRequest struct { - Name string `json:"name" validate:"required""` + Name string `json:"name" validate:"required"` Roles []UserCreationRole `json:"roles" validate:"required"` Email string `json:"email" validate:"required,email"` Department string `json:"department" validate:"min=0,max=50"` From 86d71a11e3ef035b807a16b2c20526f1c01069dd Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 3 Apr 2024 15:30:15 +0900 Subject: [PATCH 219/502] minor fix. fix login response contents --- internal/delivery/http/auth.go | 6 ++++++ pkg/domain/auth.go | 19 +++++++------------ pkg/domain/user.go | 17 ----------------- 3 files changed, 13 insertions(+), 29 deletions(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index f3953183..5e8f702a 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -101,6 +101,12 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { if err = serializer.Map(r.Context(), user, &out.User); err != nil { log.Error(r.Context(), err) } + for _, role := range user.Roles { + out.User.Roles = append(out.User.Roles, domain.SimpleRoleResponse{ + ID: role.ID, + Name: role.Name, + }) + } ResponseJSON(w, r, http.StatusOK, out) } diff --git a/pkg/domain/auth.go b/pkg/domain/auth.go index ece8bcd0..238a9fb4 100644 --- a/pkg/domain/auth.go +++ b/pkg/domain/auth.go @@ -8,21 +8,16 @@ type LoginRequest struct { type LoginResponse struct { User struct { - AccountId string `json:"accountId"` - Name string `json:"name"` - Token string `json:"token"` - Role RoleIdRoleNameResponse `json:"role"` - Department string `json:"department"` - Organization OrganizationResponse `json:"organization"` - PasswordExpired bool `json:"passwordExpired"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Token string `json:"token"` + Roles []SimpleRoleResponse `json:"roles"` + Department string `json:"department"` + Organization OrganizationResponse `json:"organization"` + PasswordExpired bool `json:"passwordExpired"` } `json:"user"` } -type RoleIdRoleNameResponse struct { - ID string `json:"roleId"` - Name string `json:"roleName"` -} - type VerifyIdentityForLostIdRequest struct { OrganizationId string `json:"organizationId" validate:"required"` Email string `json:"email" validate:"required,email"` diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 82e53a5f..07071c12 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -6,23 +6,6 @@ import ( "github.com/google/uuid" ) -// // Deprecated: Policy is deprecated, use Permission instead. -// -// type Policy = struct { -// ID string `json:"id"` -// Name string `json:"name"` -// Create bool `json:"create"` -// CreatePriviledge string `json:"createPriviledge"` -// Update bool `json:"update"` -// UpdatePriviledge string `json:"updatePriviledge"` -// Read bool `json:"read"` -// ReadPriviledge string `json:"readPriviledge"` -// Delete bool `json:"delete"` -// DeletePriviledge string `json:"deletePriviledge"` -// Creator string `json:"creator"` -// CreatedAt time.Time `json:"createdAt"` -// UpdatedAt time.Time `json:"updatedAt"` -// } type UserResponse struct { ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` From 714c60d2e4ea5ea6d47b538c5c938bfabc3ea71c Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 3 Apr 2024 19:53:59 +0900 Subject: [PATCH 220/502] bugfix. user deletion error fixed --- internal/model/user.go | 9 +++++++++ internal/repository/user.go | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/internal/model/user.go b/internal/model/user.go index da077818..d03052ab 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -1,6 +1,7 @@ package model import ( + "gorm.io/gorm" "time" "github.com/google/uuid" @@ -25,3 +26,11 @@ type User struct { Department string `json:"department"` Description string `json:"description"` } + +func (u *User) BeforeDelete(db *gorm.DB) (err error) { + err = db.Table("user_roles").Unscoped().Where("user_id = ?", u.ID).Delete(nil).Error + if err != nil { + return err + } + return nil +} diff --git a/internal/repository/user.go b/internal/repository/user.go index af2d8a1b..fdbae67c 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -227,7 +227,13 @@ func (r *UserRepository) UpdatePasswordAt(ctx context.Context, userId uuid.UUID, } func (r *UserRepository) DeleteWithUuid(ctx context.Context, uuid uuid.UUID) error { - res := r.db.WithContext(ctx).Unscoped().Delete(&model.User{}, "id = ?", uuid) + var user model.User + if err := r.db.WithContext(ctx).Model(&model.User{}).Preload("Organization").Preload("Roles").Find(&user, "id = ?", uuid).Error; err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + return err + } + + res := r.db.WithContext(ctx).Unscoped().Delete(&user) if res.Error != nil { log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error From 2bfd44e3a89dc13957595e6e4867b21619a379de Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 4 Apr 2024 10:10:23 +0900 Subject: [PATCH 221/502] =?UTF-8?q?=ED=95=84=EC=88=98=EC=A0=95=EC=B1=85=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20API=20=EB=B2=84=EA=B7=B8=20=ED=94=BD?= =?UTF-8?q?=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/repository/policy.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/internal/repository/policy.go b/internal/repository/policy.go index ac8cc8dd..522727e4 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -234,16 +234,22 @@ func (r *PolicyRepository) UpdatePolicyTargetClusters(ctx context.Context, organ func (r *PolicyRepository) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) { return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { - if err = tx.Model(&model.Policy{}). - Where("organization_id = ? id in ?", organizationId, mandatoryPolicyIds). - Update("mandatory", true).Error; err != nil { - return err + if len(mandatoryPolicyIds) > 0 { + if err = tx.Model(&model.Policy{}). + Where("organization_id = ?", organizationId). + Where("id in ?", mandatoryPolicyIds). + Update("mandatory", true).Error; err != nil { + return err + } } - if err = tx.Model(&model.Policy{}). - Where("organization_id = ? id in ?", organizationId, nonMandatoryPolicyIds). - Update("mandatory", false).Error; err != nil { - return err + if len(nonMandatoryPolicyIds) > 0 { + if err = tx.Model(&model.Policy{}). + Where("organization_id = ?", organizationId). + Where("id in ?", nonMandatoryPolicyIds). + Update("mandatory", false).Error; err != nil { + return err + } } return nil From cd1cafdb554b62ee737e5bdfa6f0219a4e53323c Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 4 Apr 2024 16:17:41 +0900 Subject: [PATCH 222/502] bugfix. --- pkg/domain/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 07071c12..4091582d 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -67,7 +67,7 @@ type GetUserResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Roles []SimpleRoleResponse `json:"role"` + Roles []SimpleRoleResponse `json:"roles"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` From bca1310f917758c20098d60fbd782f87706c7327 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 4 Apr 2024 16:29:12 +0900 Subject: [PATCH 223/502] feature. implementation default data for system_notification_rule --- api/swagger/docs.go | 106 +++++------ api/swagger/swagger.json | 106 +++++------ api/swagger/swagger.yaml | 82 ++++----- internal/delivery/http/organization.go | 20 ++- .../delivery/http/system-notification-rule.go | 48 ++--- internal/model/system-notification-rule.go | 17 +- .../repository/system-notification-rule.go | 6 +- internal/usecase/organization.go | 46 ++--- internal/usecase/system-notification-rule.go | 166 +++++++++++++++++- pkg/domain/system-notification-rule.go | 61 ++++--- pkg/domain/system-notification-template.go | 6 + scripts/init_postgres.sql | 23 +++ 12 files changed, 401 insertions(+), 286 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 89f1284e..14763b2a 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -10573,32 +10573,26 @@ const docTemplate = `{ "name": { "type": "string" }, - "systemNotificationConditions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "duration": { - "type": "integer" - }, - "enableEmail": { - "type": "boolean" - }, - "enablePortal": { - "type": "boolean" - }, - "order": { - "type": "integer" - }, - "parameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" - } - }, - "severity": { - "type": "string" + "systemNotificationCondition": { + "type": "object", + "properties": { + "duration": { + "type": "string" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" } + }, + "severity": { + "type": "string" } } }, @@ -13224,7 +13218,7 @@ const docTemplate = `{ "type": "object", "properties": { "duration": { - "type": "integer" + "type": "string" }, "enableEmail": { "type": "boolean" @@ -13232,9 +13226,6 @@ const docTemplate = `{ "enablePortal": { "type": "boolean" }, - "order": { - "type": "integer" - }, "parameters": { "type": "array", "items": { @@ -13243,6 +13234,9 @@ const docTemplate = `{ }, "severity": { "type": "string" + }, + "systemNotificationRuleId": { + "type": "string" } } }, @@ -13377,11 +13371,8 @@ const docTemplate = `{ "name": { "type": "string" }, - "systemNotificationConditions": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" - } + "systemNotificationCondition": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" }, "systemNotificationTemplate": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" @@ -13975,32 +13966,29 @@ const docTemplate = `{ "name": { "type": "string" }, - "systemNotificationConditions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "duration": { - "type": "integer" - }, - "enableEmail": { - "type": "boolean" - }, - "enablePortal": { - "type": "boolean" - }, - "order": { - "type": "integer" - }, - "parameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" - } - }, - "severity": { - "type": "string" + "systemNotificationCondition": { + "type": "object", + "properties": { + "duration": { + "type": "string" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" } + }, + "severity": { + "type": "string" + }, + "systemNotificationRuleId": { + "type": "string" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 751a13e4..d788e4ac 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -10567,32 +10567,26 @@ "name": { "type": "string" }, - "systemNotificationConditions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "duration": { - "type": "integer" - }, - "enableEmail": { - "type": "boolean" - }, - "enablePortal": { - "type": "boolean" - }, - "order": { - "type": "integer" - }, - "parameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" - } - }, - "severity": { - "type": "string" + "systemNotificationCondition": { + "type": "object", + "properties": { + "duration": { + "type": "string" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" } + }, + "severity": { + "type": "string" } } }, @@ -13218,7 +13212,7 @@ "type": "object", "properties": { "duration": { - "type": "integer" + "type": "string" }, "enableEmail": { "type": "boolean" @@ -13226,9 +13220,6 @@ "enablePortal": { "type": "boolean" }, - "order": { - "type": "integer" - }, "parameters": { "type": "array", "items": { @@ -13237,6 +13228,9 @@ }, "severity": { "type": "string" + }, + "systemNotificationRuleId": { + "type": "string" } } }, @@ -13371,11 +13365,8 @@ "name": { "type": "string" }, - "systemNotificationConditions": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" - } + "systemNotificationCondition": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" }, "systemNotificationTemplate": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" @@ -13969,32 +13960,29 @@ "name": { "type": "string" }, - "systemNotificationConditions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "duration": { - "type": "integer" - }, - "enableEmail": { - "type": "boolean" - }, - "enablePortal": { - "type": "boolean" - }, - "order": { - "type": "integer" - }, - "parameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" - } - }, - "severity": { - "type": "string" + "systemNotificationCondition": { + "type": "object", + "properties": { + "duration": { + "type": "string" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" } + }, + "severity": { + "type": "string" + }, + "systemNotificationRuleId": { + "type": "string" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index d5ae8da5..41c238b6 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1142,25 +1142,21 @@ definitions: type: string name: type: string - systemNotificationConditions: - items: - properties: - duration: - type: integer - enableEmail: - type: boolean - enablePortal: - type: boolean - order: - type: integer - parameters: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' - type: array - severity: - type: string - type: object - type: array + systemNotificationCondition: + properties: + duration: + type: string + enableEmail: + type: boolean + enablePortal: + type: boolean + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object systemNotificationTemplateId: type: string targetUserIds: @@ -2899,19 +2895,19 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse: properties: duration: - type: integer + type: string enableEmail: type: boolean enablePortal: type: boolean - order: - type: integer parameters: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' type: array severity: type: string + systemNotificationRuleId: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse: properties: @@ -3000,10 +2996,8 @@ definitions: type: string name: type: string - systemNotificationConditions: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse' - type: array + systemNotificationCondition: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse' systemNotificationTemplate: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse' targetUsers: @@ -3393,25 +3387,23 @@ definitions: type: string name: type: string - systemNotificationConditions: - items: - properties: - duration: - type: integer - enableEmail: - type: boolean - enablePortal: - type: boolean - order: - type: integer - parameters: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' - type: array - severity: - type: string - type: object - type: array + systemNotificationCondition: + properties: + duration: + type: string + enableEmail: + type: boolean + enablePortal: + type: boolean + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + systemNotificationRuleId: + type: string + type: object systemNotificationTemplateId: type: string targetUserIds: diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index d5fe5d2d..0f19ac5b 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -17,18 +17,20 @@ import ( ) type OrganizationHandler struct { - usecase usecase.IOrganizationUsecase - userUsecase usecase.IUserUsecase - roleUsecase usecase.IRoleUsecase - permissionUsecase usecase.IPermissionUsecase + usecase usecase.IOrganizationUsecase + userUsecase usecase.IUserUsecase + roleUsecase usecase.IRoleUsecase + permissionUsecase usecase.IPermissionUsecase + systemNotificationRuleUsecase usecase.ISystemNotificationRuleUsecase } func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { return &OrganizationHandler{ - usecase: u.Organization, - userUsecase: u.User, - roleUsecase: u.Role, - permissionUsecase: u.Permission, + usecase: u.Organization, + userUsecase: u.User, + roleUsecase: u.Role, + permissionUsecase: u.Permission, + systemNotificationRuleUsecase: u.SystemNotificationRule, } } @@ -129,7 +131,7 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r organization.AdminId = &admin.ID // Default systemNotificationRules 생성 - err = h.usecase.MakeDefaultSystemNotificationRules(r.Context(), organizationId, &organization) + err = h.systemNotificationRuleUsecase.MakeDefaultSystemNotificationRules(r.Context(), organizationId, &organization) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index c7b354d2..a1ca5370 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -60,13 +60,6 @@ func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.Resp } dto.OrganizationId = organizationId - dto.SystemNotificationConditions = make([]model.SystemNotificationCondition, len(input.SystemNotificationConditions)) - for i, systemNotificationCondition := range input.SystemNotificationConditions { - if err := serializer.Map(r.Context(), systemNotificationCondition, &dto.SystemNotificationConditions[i]); err != nil { - log.Info(r.Context(), err) - } - } - id, err := h.usecase.Create(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) @@ -125,15 +118,9 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.Respon } } - out.SystemNotificationRules[i].SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) - for j, condition := range systemNotificationRule.SystemNotificationConditions { - if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRules[i].SystemNotificationConditions[j]); err != nil { - log.Info(r.Context(), err) - } - err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRules[i].SystemNotificationConditions[j].Parameters) - if err != nil { - log.Error(r.Context(), err) - } + err = json.Unmarshal(systemNotificationRule.SystemNotificationCondition.Parameter, &out.SystemNotificationRules[i].SystemNotificationCondition.Parameters) + if err != nil { + log.Error(r.Context(), err) } } @@ -188,16 +175,9 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons } } - out.SystemNotificationRule.SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) - for i, condition := range systemNotificationRule.SystemNotificationConditions { - if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRule.SystemNotificationConditions[i]); err != nil { - log.Info(r.Context(), err) - } - log.Info(r.Context(), condition.Parameter) - err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRule.SystemNotificationConditions[i].Parameters) - if err != nil { - log.Error(r.Context(), err) - } + err = json.Unmarshal(systemNotificationRule.SystemNotificationCondition.Parameter, &out.SystemNotificationRule.SystemNotificationCondition.Parameters) + if err != nil { + log.Error(r.Context(), err) } ResponseJSON(w, r, http.StatusOK, out) @@ -249,13 +229,6 @@ func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.Resp dto.OrganizationId = organizationId dto.ID = systemNotificationRuleId - dto.SystemNotificationConditions = make([]model.SystemNotificationCondition, len(input.SystemNotificationConditions)) - for i, systemNotificationCondition := range input.SystemNotificationConditions { - if err := serializer.Map(r.Context(), systemNotificationCondition, &dto.SystemNotificationConditions[i]); err != nil { - log.Info(r.Context(), err) - } - } - err = h.usecase.Update(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) @@ -328,6 +301,15 @@ func (h *SystemNotificationRuleHandler) CheckSystemNotificationRuleName(w http.R } } + /* + // [TEST] + err = h.usecase.MakeDefaultSystemNotificationRules(r.Context(), "oolw6roj6", nil) + if err != nil { + ErrorJSON(w, r, err) + return + } + */ + var out domain.CheckSystemNotificationRuleNameResponse out.Existed = exist diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index 49d9ddbf..76534929 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -11,9 +11,8 @@ type SystemNotificationCondition struct { gorm.Model SystemNotificationRuleId uuid.UUID - Order int Severity string - Duration int + Duration string Parameter datatypes.JSON Parameters []domain.SystemNotificationParameter `gorm:"-:all"` EnableEmail bool `gorm:"default:false"` @@ -27,13 +26,13 @@ type SystemNotificationRule struct { Name string `gorm:"index,unique"` Description string OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` - IsSystem bool `gorm:"default:false"` - SystemNotificationTemplate SystemNotificationTemplate `gorm:"foreignKey:SystemNotificationTemplateId"` - SystemNotificationTemplateId string - SystemNotificationConditions []SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` - TargetUsers []User `gorm:"many2many:system_notification_rule_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` - TargetUserIds []string `gorm:"-:all"` + Organization Organization `gorm:"foreignKey:OrganizationId"` + IsSystem bool `gorm:"default:false"` + SystemNotificationTemplateId uuid.UUID + SystemNotificationTemplate SystemNotificationTemplate `gorm:"foreignKey:SystemNotificationTemplateId"` + SystemNotificationCondition SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId"` + TargetUsers []User `gorm:"many2many:system_notification_rule_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` + TargetUserIds []string `gorm:"-:all"` MessageTitle string MessageContent string MessageActionProposal string diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index b5da7c88..7d92f850 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -106,7 +106,7 @@ func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model m.Name = dto.Name m.Description = dto.Description m.SystemNotificationTemplateId = dto.SystemNotificationTemplateId - //m.SystemNotificationConditions = dto.SystemNotificationConditions + m.SystemNotificationCondition = dto.SystemNotificationCondition m.MessageTitle = dto.MessageTitle m.MessageContent = dto.MessageContent m.MessageActionProposal = dto.MessageActionProposal @@ -121,10 +121,6 @@ func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model if err != nil { return err } - err = r.db.WithContext(ctx).Model(&m).Association("SystemNotificationConditions").Replace(dto.SystemNotificationConditions) - if err != nil { - return err - } return nil } diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 80565f39..23904c70 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -28,30 +28,31 @@ type IOrganizationUsecase interface { UpdatePrimaryClusterId(ctx context.Context, organizationId string, clusterId string) (err error) ChangeAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error Delete(ctx context.Context, organizationId string, accessToken string) error - MakeDefaultSystemNotificationRules(ctx context.Context, organizationId string, organization *model.Organization) (err error) } type OrganizationUsecase struct { - repo repository.IOrganizationRepository - userRepo repository.IUserRepository - roleRepo repository.IRoleRepository - clusterRepo repository.IClusterRepository - stackTemplateRepo repository.IStackTemplateRepository - systemNotificationRuleRepo repository.ISystemNotificationRuleRepository - argo argowf.ArgoClient - kc keycloak.IKeycloak + repo repository.IOrganizationRepository + userRepo repository.IUserRepository + roleRepo repository.IRoleRepository + clusterRepo repository.IClusterRepository + stackTemplateRepo repository.IStackTemplateRepository + systemNotificationRuleRepo repository.ISystemNotificationRuleRepository + systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository + argo argowf.ArgoClient + kc keycloak.IKeycloak } func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClient, kc keycloak.IKeycloak) IOrganizationUsecase { return &OrganizationUsecase{ - repo: r.Organization, - userRepo: r.User, - roleRepo: r.Role, - clusterRepo: r.Cluster, - stackTemplateRepo: r.StackTemplate, - systemNotificationRuleRepo: r.SystemNotificationRule, - argo: argoClient, - kc: kc, + repo: r.Organization, + userRepo: r.User, + roleRepo: r.Role, + clusterRepo: r.Cluster, + stackTemplateRepo: r.StackTemplate, + systemNotificationRuleRepo: r.SystemNotificationRule, + systemNotificationTemplateRepo: r.SystemNotificationTemplate, + argo: argoClient, + kc: kc, } } @@ -219,14 +220,3 @@ func (u *OrganizationUsecase) ChangeAdminId(ctx context.Context, organizationId return nil } - -func (u *OrganizationUsecase) MakeDefaultSystemNotificationRules(ctx context.Context, organizationId string, dto *model.Organization) error { - var rules []model.SystemNotificationRule - - err := u.systemNotificationRuleRepo.Creates(ctx, rules) - if err != nil { - return err - } - - return nil -} diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 096e552f..8dcc54f8 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -10,6 +10,7 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/pkg/errors" "gorm.io/gorm" @@ -22,6 +23,7 @@ type ISystemNotificationRuleUsecase interface { Update(ctx context.Context, dto model.SystemNotificationRule) error Delete(ctx context.Context, systemNotificationRuleId uuid.UUID) error GetByName(ctx context.Context, name string) (model.SystemNotificationRule, error) + MakeDefaultSystemNotificationRules(ctx context.Context, organizationId string, dto *model.Organization) error } type SystemNotificationRuleUsecase struct { @@ -66,9 +68,7 @@ func (u *SystemNotificationRuleUsecase) Create(ctx context.Context, dto model.Sy } // Make parameters - for i, condition := range dto.SystemNotificationConditions { - dto.SystemNotificationConditions[i].Parameter = []byte(helper.ModelToJson(condition.Parameters)) - } + dto.SystemNotificationCondition.Parameter = []byte(helper.ModelToJson(dto.SystemNotificationCondition.Parameters)) systemNotificationRuleId, err = u.repo.Create(ctx, dto) if err != nil { @@ -98,11 +98,6 @@ func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.Sy } } - for i, condition := range dto.SystemNotificationConditions { - dto.SystemNotificationConditions[i].SystemNotificationRuleId = dto.ID - dto.SystemNotificationConditions[i].Parameter = []byte(helper.ModelToJson(condition.Parameters)) - } - err = u.repo.Update(ctx, dto) if err != nil { return err @@ -160,3 +155,158 @@ func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, systemNotifi } return } + +func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx context.Context, organizationId string, dto *model.Organization) error { + organization, err := u.organizationRepo.Get(ctx, organizationId) + if err != nil { + return err + } + + organizationAdmin, err := u.userRepo.GetByUuid(ctx, *organization.AdminId) + if err != nil { + return err + } + + pg := pagination.NewPaginationWithFilter("is_system", "", "$eq", []string{"1"}) + templates, err := u.systemNotificationTemplateRepo.Fetch(ctx, pg) + if err != nil { + return err + } + + rules := make([]model.SystemNotificationRule, 0) + for _, template := range templates { + if template.Name == domain.SN_TYPE_NODE_CPU_HIGH_LOAD { + ruleId := uuid.New() + rules = append(rules, model.SystemNotificationRule{ + ID: ruleId, + Name: domain.SN_TYPE_NODE_CPU_HIGH_LOAD + "-critical", + Description: "", + OrganizationId: organizationId, + IsSystem: true, + SystemNotificationTemplateId: template.ID, + SystemNotificationCondition: model.SystemNotificationCondition{ + SystemNotificationRuleId: ruleId, + Severity: "critical", + Duration: "3m", + Parameter: []byte("[{\"order\": 0, \"value\": \"10\", \"operator\": \"<\"}]"), + EnableEmail: true, + EnablePortal: true, + }, + TargetUsers: []model.User{organizationAdmin}, + MessageTitle: "스택 (<>)의 노드(<>)의 idle process의 cpu 점유율이 3분 동안 0% 입니다. (현재 사용률 {{$VALUE}})", + MessageContent: "워커 노드 CPU가 과부하 상태입니다. 일시적인 서비스 Traffic 증가, Workload의 SW 오류, Server HW Fan Fail등 다양한 원인으로 인해 발생할 수 있습니다.", + MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행 되는 pod중 CPU 자원을 많이 점유하는 pod의 설정을 점검해 보시길 제안드립니다. 예를 들어 pod spec의 limit 설정으로 과도한 CPU자원 점유을 막을 수 있습니다.", + Status: domain.SystemNotificationRuleStatus_PENDING, + CreatorId: organization.AdminId, + UpdatorId: organization.AdminId, + }) + } else if template.Name == domain.SN_TYPE_NODE_MEMORY_HIGH_UTILIZATION { + ruleId := uuid.New() + rules = append(rules, model.SystemNotificationRule{ + ID: ruleId, + Name: domain.SN_TYPE_NODE_MEMORY_HIGH_UTILIZATION + "-warning", + Description: "", + OrganizationId: organizationId, + IsSystem: true, + SystemNotificationTemplateId: template.ID, + SystemNotificationCondition: model.SystemNotificationCondition{ + SystemNotificationRuleId: ruleId, + Severity: "warning", + Duration: "3m", + Parameter: []byte("[{\"order\": 0, \"value\": \"0.2\", \"operator\": \"<\"}]"), + EnableEmail: true, + EnablePortal: true, + }, + TargetUsers: []model.User{organizationAdmin}, + MessageTitle: "스택 (<>)의 노드(<>)의 Memory 사용량이 3분동안 80% 를 넘어서고 있습니다. (현재 사용률 <>)", + MessageContent: "워커 노드의 Memory 사용량이 80%를 넘었습니다. 일시적인 서비스 증가 및 SW 오류등 다양한 원인으로 발생할 수 있습니다.", + MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행되는 pod중 Memory 사용량이 높은 pod들에 대한 점검을 제안드립니다.", + Status: domain.SystemNotificationRuleStatus_PENDING, + CreatorId: organization.AdminId, + UpdatorId: organization.AdminId, + }) + } else if template.Name == domain.SN_TYPE_NODE_DISK_FULL { + ruleId := uuid.New() + rules = append(rules, model.SystemNotificationRule{ + ID: ruleId, + Name: domain.SN_TYPE_NODE_DISK_FULL + "-critical", + Description: "", + OrganizationId: organizationId, + IsSystem: true, + SystemNotificationTemplateId: template.ID, + SystemNotificationCondition: model.SystemNotificationCondition{ + SystemNotificationRuleId: ruleId, + Severity: "critical", + Duration: "3m", + Parameter: []byte("[{\"order\": 0, \"value\": \"0\", \"operator\": \"<\"}]"), + EnableEmail: true, + EnablePortal: true, + }, + TargetUsers: []model.User{organizationAdmin}, + MessageTitle: "지난 6시간동안의 추세로 봤을 때, 스택 (<>)의 노드(<>)의 root 볼륨은 24시간 안에 Disk full이 예상됨", + MessageContent: "현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰 것으로 예상됩니다.", + MessageActionProposal: "Disk 용량 최적화(삭제 및 Backup)을 수행하시길 권고합니다. 삭제할 내역이 없으면 증설 계획을 수립해 주십시요.", + Status: domain.SystemNotificationRuleStatus_PENDING, + CreatorId: organization.AdminId, + UpdatorId: organization.AdminId, + }) + } else if template.Name == domain.SN_TYPE_PVC_FULL { + ruleId := uuid.New() + rules = append(rules, model.SystemNotificationRule{ + ID: ruleId, + Name: domain.SN_TYPE_PVC_FULL + "-critical", + Description: "", + OrganizationId: organizationId, + IsSystem: true, + SystemNotificationTemplateId: template.ID, + SystemNotificationCondition: model.SystemNotificationCondition{ + SystemNotificationRuleId: ruleId, + Severity: "critical", + Duration: "3m", + Parameter: []byte("[{\"order\": 0, \"value\": \"0\", \"operator\": \"<\"}]"), + EnableEmail: true, + EnablePortal: true, + }, + TargetUsers: []model.User{organizationAdmin}, + MessageTitle: "지난 6시간동안의 추세로 봤을 때, 스택 (<>)의 파드(<>)가 24시간 안에 Disk full이 예상됨", + MessageContent: "현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰것으로 예상됩니다. (<> 스택, <> PVC)", + MessageActionProposal: "Disk 용량 최적화(삭제 및 Backup)을 수행하시길 권고합니다. 삭제할 내역이 없으면 증설 계획을 수립해 주십시요.", + Status: domain.SystemNotificationRuleStatus_PENDING, + CreatorId: organization.AdminId, + UpdatorId: organization.AdminId, + }) + } else if template.Name == domain.SN_TYPE_POD_RESTART_FREQUENTLY { + ruleId := uuid.New() + rules = append(rules, model.SystemNotificationRule{ + ID: ruleId, + Name: domain.SN_TYPE_POD_RESTART_FREQUENTLY + "-critical", + Description: "", + OrganizationId: organizationId, + IsSystem: true, + SystemNotificationTemplateId: template.ID, + SystemNotificationCondition: model.SystemNotificationCondition{ + SystemNotificationRuleId: ruleId, + Severity: "critical", + Duration: "3m", + Parameter: []byte("[{\"order\": 0, \"value\": \"2\", \"operator\": \">\"}]"), + EnableEmail: true, + EnablePortal: true, + }, + TargetUsers: []model.User{organizationAdmin}, + MessageTitle: "스택 (<>)의 파드(<>)가 30분 동안 5회 이상 재기동 (<> 회)", + MessageContent: "특정 Pod가 빈번하게 재기동 되고 있습니다. 점검이 필요합니다. (<> 스택, <> 파드)", + MessageActionProposal: "pod spec. 에 대한 점검이 필요합니다. pod의 log 및 status를 확인해 주세요.", + Status: domain.SystemNotificationRuleStatus_PENDING, + CreatorId: organization.AdminId, + UpdatorId: organization.AdminId, + }) + } + } + + err = u.repo.Creates(ctx, rules) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index 25380f6a..13e1acf3 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -30,19 +30,19 @@ func (m SystemNotificationRuleStatus) FromString(s string) SystemNotificationRul } type SystemNotificationRuleResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - MessageTitle string `json:"messageTitle"` - MessageContent string `json:"messageContent"` - MessageActionProposal string `json:"messageActionProposal"` - TargetUsers []SimpleUserResponse `json:"targetUsers"` - SystemNotificationTemplate SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplate"` - SystemNotificationConditions []SystemNotificationConditionResponse `json:"systemNotificationConditions"` - Creator SimpleUserResponse `json:"creator"` - Updator SimpleUserResponse `json:"updator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle"` + MessageContent string `json:"messageContent"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUsers []SimpleUserResponse `json:"targetUsers"` + SystemNotificationTemplate SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplate"` + SystemNotificationCondition SystemNotificationConditionResponse `json:"systemNotificationCondition"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type SystemNotificationParameter struct { @@ -52,12 +52,12 @@ type SystemNotificationParameter struct { } type SystemNotificationConditionResponse struct { - Order int `json:"order"` - Severity string `json:"severity"` - Duration int `json:"duration"` - Parameters []SystemNotificationParameter `json:"parameters"` - EnableEmail bool `json:"enableEmail"` - EnablePortal bool `json:"enablePortal"` + SystemNotificationRuleId string `json:"systemNotificationRuleId"` + Severity string `json:"severity"` + Duration string `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` } type SimpleSystemNotificationRuleResponse struct { @@ -83,14 +83,13 @@ type CreateSystemNotificationRuleRequest struct { MessageActionProposal string `json:"messageActionProposal"` TargetUserIds []string `json:"targetUserIds"` SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` - SystemNotificationConditions []struct { - Order int `json:"order"` + SystemNotificationCondition struct { Severity string `json:"severity"` - Duration int `json:"duration"` + Duration string `json:"duration"` Parameters []SystemNotificationParameter `json:"parameters"` EnableEmail bool `json:"enableEmail"` EnablePortal bool `json:"enablePortal"` - } `json:"systemNotificationConditions"` + } `json:"systemNotificationCondition"` } type CreateSystemNotificationRuleResponse struct { @@ -105,14 +104,14 @@ type UpdateSystemNotificationRuleRequest struct { MessageActionProposal string `json:"messageActionProposal"` TargetUserIds []string `json:"targetUserIds"` SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` - SystemNotificationConditions []struct { - Order int `json:"order"` - Severity string `json:"severity"` - Duration int `json:"duration"` - Parameters []SystemNotificationParameter `json:"parameters"` - EnableEmail bool `json:"enableEmail"` - EnablePortal bool `json:"enablePortal"` - } `json:"systemNotificationConditions"` + SystemNotificationCondition struct { + SystemNotificationRuleId string `json:"systemNotificationRuleId"` + Severity string `json:"severity"` + Duration string `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` + } `json:"systemNotificationCondition"` } type CheckSystemNotificationRuleNameResponse struct { diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index 00d9b0c0..d7f575fa 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -4,6 +4,12 @@ import ( "time" ) +const SN_TYPE_NODE_CPU_HIGH_LOAD = "node-cpu-high-load" +const SN_TYPE_NODE_MEMORY_HIGH_UTILIZATION = "node-memory-high-utilization" +const SN_TYPE_NODE_DISK_FULL = "node-disk-full" +const SN_TYPE_PVC_FULL = "pvc_full" +const SN_TYPE_POD_RESTART_FREQUENTLY = "pod-restart-frequently" + type SystemNotificationTemplateResponse struct { ID string `json:"id"` Name string `json:"name"` diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index f57b52a8..27e7b678 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -67,3 +67,26 @@ values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'p insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', true, 'pod-restart-frequently', 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:]) > 2', null, null, now(), now() ); +## SystemNotificationTemplates -> SystemNotificationMetricParameters +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 0, 'd42d716f-dd2e-429b-897d-b602f6382790', 'STACK', '$labels.taco_cluster', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 1, 'd42d716f-dd2e-429b-897d-b602f6382790', 'INSTANCE', '$labels.instance', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 0, 'f11eefa4-5a16-44fc-8dae-4662e7fba023', 'STACK', '$labels.taco_cluster', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 1, 'f11eefa4-5a16-44fc-8dae-4662e7fba023', 'INSTANCE', '$labels.instance', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 0, '1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'STACK', '$labels.taco_cluster', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 1, '1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'INSTANCE', '$labels.instance', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 0, '68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'STACK', '$labels.taco_cluster', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 1, '68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'PVC', '$labels.persistentvolumeclaim', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 0, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'STACK', '$labels.taco_cluster', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 1, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'POD', '$labels.pod', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 3, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'NAMESPACE', '$labels.namespace', now(), now() ); From 47468ad763d6047b363153d4e8f7f81f66d5dfa0 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 4 Apr 2024 16:39:29 +0900 Subject: [PATCH 224/502] User Admin API: bugfix --- internal/delivery/http/user.go | 137 +++++---------------------------- internal/keycloak/keycloak.go | 2 +- internal/route/route.go | 2 - pkg/domain/admin/user.go | 70 ----------------- pkg/domain/user.go | 44 ++++++++++- 5 files changed, 62 insertions(+), 193 deletions(-) delete mode 100644 pkg/domain/admin/user.go diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 659671be..cbde62ba 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -6,8 +6,6 @@ import ( "net/http" "strings" - admin_domain "github.com/openinfradev/tks-api/pkg/domain/admin" - "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" @@ -40,8 +38,6 @@ type IUserHandler interface { // Admin Admin_Create(w http.ResponseWriter, r *http.Request) - Admin_List(w http.ResponseWriter, r *http.Request) - Admin_Get(w http.ResponseWriter, r *http.Request) Admin_Delete(w http.ResponseWriter, r *http.Request) Admin_Update(w http.ResponseWriter, r *http.Request) } @@ -836,14 +832,15 @@ func convertModelToMergedPermissionSetResponse(ctx context.Context, permission * } // Admin_Create godoc +// // @Tags Users -// @Summary Create user by admin -// @Description Create user by admin +// @Summary Create user by admin in Admin Portal +// @Description Create user by admin in Admin Portal // @Accept json // @Produce json // @Param organizationId path string true "organizationId" -// @Param body body admin_domain.CreateUserRequest true "create user request" -// @Success 200 {object} admin_domain.CreateUserResponse "create user response" +// @Param body body domain.Admin_CreateUserRequest true "create user request" +// @Success 200 {object} domain.Admin_CreateUserResponse "create user response" // @Router /admin/organizations/{organizationId}/users [post] // @Security JWT @@ -855,7 +852,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { return } - input := admin_domain.CreateUserRequest{} + input := domain.Admin_CreateUserRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -922,121 +919,23 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { return } - var out admin_domain.CreateUserResponse + var out domain.Admin_CreateUserResponse out.ID = resUser.ID.String() ResponseJSON(w, r, http.StatusCreated, out) } -// Admin_List godoc -// @Tags Users -// @Summary Get user list by admin -// @Description Get user list by admin -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param limit query string false "pageSize" -// @Param page query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} admin_domain.ListUserResponse "user list response" -// @Router /admin/organizations/{organizationId}/users [get] -// @Security JWT - -func (u UserHandler) Admin_List(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "", "")) - return - } - - urlParams := r.URL.Query() - pg := pagination.NewPagination(&urlParams) - users, err := u.usecase.ListWithPagination(r.Context(), organizationId, pg) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } - - var out admin_domain.ListUserResponse - out.Users = make([]domain.ListUserBody, len(*users)) - for i, user := range *users { - if err = serializer.Map(r.Context(), user, &out.Users[i]); err != nil { - log.Error(r.Context(), err) - } - - if out.Users[i].Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles); err != nil { - log.Error(r.Context(), err) - } - } - - if out.Pagination, err = pg.Response(r.Context()); err != nil { - log.Info(r.Context(), err) - } - - ResponseJSON(w, r, http.StatusOK, out) -} - -// Admin_Get godoc -// -// @Tags Users -// @Summary Get user detail by admin -// @Description Get user detail by admin -// @Accept json -// @Produce json -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" -// @Success 200 {object} admin_domain.GetUserResponse -// @Router /admin/organizations/{organizationId}/users/{accountId} [get] -func (u UserHandler) Admin_Get(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - userId, ok := vars["accountId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("accountId not found in path"), "C_INVALID_ACCOUNT_ID", "")) - return - } - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) - return - } - - user, err := u.usecase.GetByAccountId(r.Context(), userId, organizationId) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - - if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { - ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - return - } - - ErrorJSON(w, r, err) - return - } - - var out admin_domain.GetUserResponse - if err = serializer.Map(r.Context(), *user, &out.User); err != nil { - log.Error(r.Context(), err) - } - - out.User.Roles = u.convertUserRolesToSimpleRoleResponse(user.Roles) - - ResponseJSON(w, r, http.StatusOK, out) -} - // Admin_Delete godoc // @Tags Users -// @Summary Delete user by admin -// @Description Delete user by admin +// @Summary Delete user by admin in Admin Portal +// @Description Delete user by admin in Admin Portal // @Accept json // @Produce json +// @Param body body domain.DeleteUserRequest true "input" // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Success 200 {object} admin_domain.User +// @Success 200 // @Router /admin/organizations/{organizationId}/users/{accountId} [delete] // @Security JWT @@ -1053,7 +952,7 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { return } - input := admin_domain.DeleteUserRequest{} + input := domain.DeleteUserRequest{} // TKS 관리자가 아닌 경우 Password 확인 if organizationId != "master" { @@ -1096,14 +995,14 @@ func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { // Admin_Update godoc // // @Tags Users -// @Summary Update user by admin -// @Description Update user by admin +// @Summary Update user by admin in Admin Portal +// @Description Update user by admin in Admin Portal // @Accept json // @Produce json // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Param body body admin_domain.UpdateUserRequest true "input" -// @Success 200 {object} admin_domain.UpdateUserResponse +// @Param body body domain.Admin_UpdateUserRequest true "input" +// @Success 200 {object} domain.Admin_UpdateUserResponse // @Router /admin/organizations/{organizationId}/users/{accountId} [put] // @Security JWT func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { @@ -1119,7 +1018,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { return } - input := admin_domain.UpdateUserRequest{} + input := domain.Admin_UpdateUserRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -1171,7 +1070,7 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { return } - var out admin_domain.UpdateUserResponse + var out domain.Admin_UpdateUserResponse if err = serializer.Map(r.Context(), *resUser, &out.User); err != nil { log.Error(r.Context(), err) ErrorJSON(w, r, err) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 1a29a590..a2225784 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -56,7 +56,7 @@ type Keycloak struct { func (k *Keycloak) CreateGroup(ctx context.Context, organizationId string, groupName string) (string, error) { token := k.adminCliToken group := gocloak.Group{ - Name: gocloak.StringP(groupName), + Name: gocloak.StringP(groupName + "@" + organizationId), } groupId, err := k.client.CreateGroup(context.Background(), token.AccessToken, organizationId, group) if err != nil { diff --git a/internal/route/route.go b/internal/route/route.go index 4a25c9ca..0ab35832 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -127,8 +127,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/users/{accountId}/permissions", customMiddleware.Handle(internalApi.GetPermissionsByAccountId, http.HandlerFunc(userHandler.GetPermissionsByAccountId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_CreateUser, http.HandlerFunc(userHandler.Admin_Create))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_ListUser, http.HandlerFunc(userHandler.Admin_List))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_GetUser, http.HandlerFunc(userHandler.Admin_Get))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_UpdateUser, http.HandlerFunc(userHandler.Admin_Update))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_DeleteUser, http.HandlerFunc(userHandler.Admin_Delete))).Methods(http.MethodDelete) diff --git a/pkg/domain/admin/user.go b/pkg/domain/admin/user.go deleted file mode 100644 index 0a85c596..00000000 --- a/pkg/domain/admin/user.go +++ /dev/null @@ -1,70 +0,0 @@ -package admin - -import ( - "time" - - "github.com/openinfradev/tks-api/pkg/domain" -) - -type CreateUserRequest struct { - AccountId string `json:"accountId" validate:"required"` - Name string `json:"name" validate:"name"` - Email string `json:"email" validate:"required,email"` - Roles []domain.UserCreationRole `json:"roles" validate:"required"` - Department string `json:"department" validate:"min=0,max=50"` - Description string `json:"description" validate:"min=0,max=100"` - AdminPassword string `json:"adminPassword"` -} - -type CreateUserResponse struct { - ID string `json:"id"` -} - -type ListUserResponse struct { - Users []domain.ListUserBody `json:"users"` - Pagination domain.PaginationResponse `json:"pagination"` -} - -type GetUserResponse struct { - User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Roles []domain.SimpleRoleResponse `json:"roles"` - Organization domain.OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - Creator string `json:"creator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - } `json:"user"` -} - -type UpdateUserRequest struct { - Name string `json:"name" validate:"name"` - Email string `json:"email" validate:"required,email"` - Department string `json:"department" validate:"min=0,max=50"` - Roles []domain.UserCreationRole `json:"roles" validate:"required"` - Description string `json:"description" validate:"min=0,max=100"` - AdminPassword string `json:"adminPassword"` -} - -type UpdateUserResponse struct { - User struct { - ID string `json:"id"` - AccountId string `json:"accountId"` - Name string `json:"name"` - Roles []domain.SimpleRoleResponse `json:"roles"` - Organization domain.OrganizationResponse `json:"organization"` - Email string `json:"email"` - Department string `json:"department"` - Description string `json:"description"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - } `json:"user"` -} - -type DeleteUserRequest struct { - AdminPassword string `json:"adminPassword"` -} diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 4091582d..cdf30644 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -153,7 +153,7 @@ type UpdateMyProfileResponse struct { ID string `json:"id"` AccountId string `json:"accountId"` Name string `json:"name"` - Roles []SimpleRoleResponse `json:"role"` + Roles []SimpleRoleResponse `json:"roles"` Organization OrganizationResponse `json:"organization"` Email string `json:"email"` Department string `json:"department"` @@ -168,3 +168,45 @@ type UpdatePasswordRequest struct { type CheckExistedResponse struct { Existed bool `json:"existed"` } + +type Admin_CreateUserRequest struct { + AccountId string `json:"accountId" validate:"required"` + Name string `json:"name" validate:"name"` + Email string `json:"email" validate:"required,email"` + Roles []UserCreationRole `json:"roles" validate:"required"` + Department string `json:"department" validate:"min=0,max=50"` + Description string `json:"description" validate:"min=0,max=100"` + AdminPassword string `json:"adminPassword"` +} + +type Admin_CreateUserResponse struct { + ID string `json:"id"` +} + +type Admin_UpdateUserRequest struct { + Name string `json:"name" validate:"name"` + Email string `json:"email" validate:"required,email"` + Department string `json:"department" validate:"min=0,max=50"` + Roles []UserCreationRole `json:"roles" validate:"required"` + Description string `json:"description" validate:"min=0,max=100"` + AdminPassword string `json:"adminPassword"` +} + +type Admin_UpdateUserResponse struct { + User struct { + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Roles []SimpleRoleResponse `json:"roles"` + Organization OrganizationResponse `json:"organization"` + Email string `json:"email"` + Department string `json:"department"` + Description string `json:"description"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + } `json:"user"` +} + +type DeleteUserRequest struct { + AdminPassword string `json:"adminPassword"` +} From c8027f996f1d6591cd968918a87b6f8fdc206ccd Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 4 Apr 2024 16:45:11 +0900 Subject: [PATCH 225/502] trivial fix. --- internal/delivery/http/user.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index cbde62ba..9c0913c0 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -927,6 +927,7 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { } // Admin_Delete godoc +// // @Tags Users // @Summary Delete user by admin in Admin Portal // @Description Delete user by admin in Admin Portal From 28465b644a2d856eb586d96b97badbbe531f2652 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 4 Apr 2024 16:51:00 +0900 Subject: [PATCH 226/502] trivial fix. --- internal/delivery/http/user.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 9c0913c0..c9aa9678 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -843,7 +843,6 @@ func convertModelToMergedPermissionSetResponse(ctx context.Context, permission * // @Success 200 {object} domain.Admin_CreateUserResponse "create user response" // @Router /admin/organizations/{organizationId}/users [post] // @Security JWT - func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] @@ -939,7 +938,6 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { // @Success 200 // @Router /admin/organizations/{organizationId}/users/{accountId} [delete] // @Security JWT - func (u UserHandler) Admin_Delete(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) userId, ok := vars["accountId"] From 113a227d6099f363c46167885c354519f2a57f9b Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 4 Apr 2024 16:54:07 +0900 Subject: [PATCH 227/502] =?UTF-8?q?ParameterDef=20=EC=A0=84=EB=8B=AC=20?= =?UTF-8?q?=EC=95=88=20=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/repository/policy-template.go | 4 ++-- internal/usecase/policy-template.go | 4 ++-- pkg/domain/admin/policy-template.go | 14 +++++++------- pkg/domain/policy-template.go | 20 ++++++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 9127f8cd..cc320189 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -32,7 +32,7 @@ type IPolicyTemplateRepository interface { ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) - CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) + CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) GetLatestTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID) (version string, err error) } @@ -373,7 +373,7 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(ctx context.Conte }) } -func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { +func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) { var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db.WithContext(ctx).Limit(1). Where("policy_template_id = ?", policyTemplateId).Where("version = ?", version). diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 41c03b00..9dcedef3 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -32,7 +32,7 @@ type IPolicyTemplateUsecase interface { GetPolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) ListPolicyTemplateVersions(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) DeletePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string) (err error) - CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) + CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) @@ -395,7 +395,7 @@ func (u *PolicyTemplateUsecase) DeletePolicyTemplateVersion(ctx context.Context, return u.repo.DeletePolicyTemplateVersion(ctx, policyTemplateId, version) } -func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []domain.ParameterDef, rego string, libs []string) (version string, err error) { +func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) { policyTemplate, err := u.repo.GetByID(ctx, policyTemplateId) if err != nil { diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index c3d9cf46..6433f6b6 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -43,12 +43,12 @@ type SimplePolicyTemplateResponse struct { } type CreatePolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` - Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` - Deprecated bool `json:"deprecated" example:"false"` - Description string `json:"description,omitempty" example:"이 정책은 ..."` - ParametersSchema []domain.ParameterDef `json:"parametersSchema,omitempty"` + TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" Rego string `json:"rego" example:"rego 코드" validate:"required"` @@ -130,7 +130,7 @@ type CreatePolicyTemplateVersionRequest struct { CurrentVersion string `json:"currentVersion" example:"v1.0.0" validate:"required"` ExpectedVersion string `json:"expectedVersion" example:"v1.1.0" validate:"required"` - ParametersSchema []domain.ParameterDef `json:"parametersSchema,omitempty"` + ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" Rego string `json:"rego" example:"rego 코드" validate:"required"` diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index f4ea64e1..e1ead8cb 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -14,15 +14,15 @@ type PolicyTemplateResponse struct { CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` - TemplateName string `json:"templateName" example:"필수 Label 검사"` - Kind string `json:"kind" example:"K8sRequiredLabels"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` - Deprecated bool `json:"deprecated" example:"false"` - Version string `json:"version,omitempty" example:"v1.0.1"` - Description string `json:"description,omitempty" example:"이 정책은 ..."` - ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` - Rego string `json:"rego" example:"rego 코드"` - Libs []string `json:"libs" example:"rego 코드"` + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Kind string `json:"kind" example:"K8sRequiredLabels"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + Version string `json:"version,omitempty" example:"v1.0.1"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` } type SimplePolicyTemplateResponse struct { @@ -104,7 +104,7 @@ type CreatePolicyTemplateVersionRequest struct { CurrentVersion string `json:"currentVersion" example:"v1.0.0" validate:"required"` ExpectedVersion string `json:"expectedVersion" example:"v1.1.0" validate:"required"` - ParametersSchema []ParameterDef `json:"parametersSchema,omitempty"` + ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" Rego string `json:"rego" example:"rego 코드" validate:"required"` From cb689b5a7dd7ae43960e62d38f82c6dcae10411b Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 4 Apr 2024 17:17:01 +0900 Subject: [PATCH 228/502] bugfix. fix error on Oragnization Creation API --- internal/delivery/http/organization.go | 11 +++- internal/keycloak/keycloak.go | 82 -------------------------- 2 files changed, 8 insertions(+), 85 deletions(-) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 9a33c772..e8c8c320 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -114,6 +114,13 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r return } + role, err := h.roleUsecase.GetTksRole(r.Context(), organizationId, adminRoleId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + user := model.User{ Organization: model.Organization{ ID: organizationId, @@ -122,9 +129,7 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r Name: input.AdminName, Email: input.AdminEmail, Roles: []model.Role{ - { - ID: adminRoleId, - }, + *role, }, } // Admin user 생성 diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index a2225784..ffc7ad1f 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -267,50 +267,6 @@ func (k *Keycloak) CreateRealm(ctx context.Context, organizationId string) (stri return "", err } } - adminGroupUuid, err := k.createGroup(ctx, token.AccessToken, organizationId, "admin@"+organizationId) - if err != nil { - return realmUUID, err - } - - realmManagementClientUuid, err := k.getClientByClientId(ctx, token.AccessToken, organizationId, "realm-management") - if err != nil { - return realmUUID, err - } - - realmAdminRole, err := k.getClientRole(ctx, token.AccessToken, organizationId, realmManagementClientUuid, "realm-admin") - if err != nil { - return realmUUID, err - } - - err = k.addClientRoleToGroup(ctx, token.AccessToken, organizationId, realmManagementClientUuid, adminGroupUuid, - &gocloak.Role{ - ID: realmAdminRole.ID, - Name: realmAdminRole.Name, - }) - - if err != nil { - return "", err - } - - userGroupUuid, err := k.createGroup(ctx, token.AccessToken, organizationId, "user@"+organizationId) - if err != nil { - return "", err - } - - viewUserRole, err := k.getClientRole(ctx, token.AccessToken, organizationId, realmManagementClientUuid, "view-users") - if err != nil { - return "", err - } - - err = k.addClientRoleToGroup(ctx, token.AccessToken, organizationId, realmManagementClientUuid, userGroupUuid, - &gocloak.Role{ - ID: viewUserRole.ID, - Name: viewUserRole.Name, - }) - - if err != nil { - return "", err - } // TODO: implement leader, member, viewer //leaderGroup, err := c.ensureGroup(ctx, token, realmName, "leader@"+realmName) @@ -810,44 +766,6 @@ func (k *Keycloak) ensureGroup(ctx context.Context, token *gocloak.JWT, realm st return groups[0], err } -func (k *Keycloak) createGroup(ctx context.Context, accessToken string, realm string, groupName string) (string, error) { - id, err := k.client.CreateGroup(context.Background(), accessToken, realm, gocloak.Group{Name: gocloak.StringP(groupName)}) - if err != nil { - log.Error(ctx, "Creating Group is failed", err) - return "", err - } - return id, nil -} - -func (k *Keycloak) getClientByClientId(ctx context.Context, accessToken string, realm string, clientId string) ( - string, error) { - clients, err := k.client.GetClients(context.Background(), accessToken, realm, gocloak.GetClientsParams{ClientID: &clientId}) - if err != nil { - log.Error(ctx, "Getting Client is failed", err) - return "", err - } - return *clients[0].ID, nil -} - -func (k *Keycloak) getClientRole(ctx context.Context, accessToken string, realm string, clientUuid string, - roleName string) (*gocloak.Role, error) { - role, err := k.client.GetClientRole(context.Background(), accessToken, realm, clientUuid, roleName) - if err != nil { - log.Error(ctx, "Getting Client Role is failed", err) - return nil, err - } - return role, nil -} - -func (k *Keycloak) addClientRoleToGroup(ctx context.Context, accessToken string, realm string, clientUuid string, - groupUuid string, role *gocloak.Role) error { - err := k.client.AddClientRolesToGroup(context.Background(), accessToken, realm, clientUuid, groupUuid, []gocloak.Role{*role}) - if err != nil { - log.Error(ctx, "Adding Client Role to Group is failed", err) - return err - } - return nil -} func (k *Keycloak) createClientProtocolMapper(ctx context.Context, accessToken string, realm string, id string, mapper gocloak.ProtocolMapperRepresentation) (string, error) { From 77ea05477c88c40250c89385eab2b6e1c37dce7f Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 4 Apr 2024 17:18:40 +0900 Subject: [PATCH 229/502] swagger fix --- internal/delivery/http/organization.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index e8c8c320..4821dbdd 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -37,13 +37,13 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { // CreateOrganization godoc // // @Tags Organizations -// @Summary Create organization -// @Description Create organization +// @Summary Create organization in Admin portal +// @Description Create organization in Admin portal // @Accept json // @Produce json // @Param body body domain.CreateOrganizationRequest true "create organization request" // @Success 200 {object} object -// @Router /organizations [post] +// @Router /admin/organizations [post] // @Security JWT func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r *http.Request) { input := domain.CreateOrganizationRequest{} From fa2d7acd750cc3909d9db08e67fab3296f15472d Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 4 Apr 2024 17:42:22 +0900 Subject: [PATCH 230/502] =?UTF-8?q?=EA=B8=B0=EC=A1=B4=20=EB=B2=84=EC=A0=84?= =?UTF-8?q?=EA=B3=BC=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EB=B9=84?= =?UTF-8?q?=EA=B5=90=EC=B6=94=EC=B6=9C=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/api/endpoint.go | 2 + .../delivery/api/generated_endpoints.go.go | 16 +++ internal/delivery/http/policy-template.go | 133 ++++++++++++++++++ internal/delivery/http/role.go | 20 +-- internal/delivery/http/user.go | 10 +- internal/policy-template/paramdef-util.go | 62 ++++++++ internal/route/route.go | 2 + internal/usecase/policy-template.go | 73 ++++++++++ pkg/domain/admin/policy-template.go | 10 ++ pkg/domain/policy-template.go | 21 ++- 10 files changed, 333 insertions(+), 16 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index d81480d4..2fef58a9 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -232,6 +232,7 @@ const ( Admin_GetPolicyTemplateVersion Admin_ExistsPolicyTemplateKind Admin_ExistsPolicyTemplateName + Admin_ExtractParameters // ClusterPolicyStatus ListClusterPolicyStatus @@ -264,6 +265,7 @@ const ( GetPolicyTemplateVersion ExistsPolicyTemplateKind ExistsPolicyTemplateName + ExtractParameters // PolicyTemplateExample ListPolicyTemplateExample diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 3e7ad407..fc3e3c83 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -703,6 +703,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_ExistsPolicyTemplateName", Group: "PolicyTemplate", }, + Admin_ExtractParameters: { + Name: "Admin_ExtractParameters", + Group: "PolicyTemplate", + }, ListClusterPolicyStatus: { Name: "ListClusterPolicyStatus", Group: "ClusterPolicyStatus", @@ -807,6 +811,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "ExistsPolicyTemplateName", Group: "OrganizationPolicyTemplate", }, + ExtractParameters: { + Name: "ExtractParameters", + Group: "OrganizationPolicyTemplate", + }, ListPolicyTemplateExample: { Name: "ListPolicyTemplateExample", Group: "PolicyTemplateExample", @@ -1180,6 +1188,8 @@ func (e Endpoint) String() string { return "Admin_ExistsPolicyTemplateKind" case Admin_ExistsPolicyTemplateName: return "Admin_ExistsPolicyTemplateName" + case Admin_ExtractParameters: + return "Admin_ExtractParameters" case ListClusterPolicyStatus: return "ListClusterPolicyStatus" case GetClusterPolicyTemplateStatus: @@ -1232,6 +1242,8 @@ func (e Endpoint) String() string { return "ExistsPolicyTemplateKind" case ExistsPolicyTemplateName: return "ExistsPolicyTemplateName" + case ExtractParameters: + return "ExtractParameters" case ListPolicyTemplateExample: return "ListPolicyTemplateExample" case GetPolicyTemplateExample: @@ -1598,6 +1610,8 @@ func GetEndpoint(name string) Endpoint { return Admin_ExistsPolicyTemplateKind case "Admin_ExistsPolicyTemplateName": return Admin_ExistsPolicyTemplateName + case "Admin_ExtractParameters": + return Admin_ExtractParameters case "ListClusterPolicyStatus": return ListClusterPolicyStatus case "GetClusterPolicyTemplateStatus": @@ -1650,6 +1664,8 @@ func GetEndpoint(name string) Endpoint { return ExistsPolicyTemplateKind case "ExistsPolicyTemplateName": return ExistsPolicyTemplateName + case "ExtractParameters": + return ExtractParameters case "ListPolicyTemplateExample": return ListPolicyTemplateExample case "GetPolicyTemplateExample": diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index e396827b..a1de8b04 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -39,6 +39,7 @@ type IPolicyTemplateHandler interface { Admin_GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) Admin_DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) Admin_ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) + Admin_ExtractParameters(w http.ResponseWriter, r *http.Request) CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) @@ -53,6 +54,7 @@ type IPolicyTemplateHandler interface { GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) + ExtractParameters(w http.ResponseWriter, r *http.Request) RegoCompile(w http.ResponseWriter, r *http.Request) } @@ -357,6 +359,61 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplateVersions(w http.Response ResponseJSON(w, r, http.StatusOK, out) } +// Admin_ExtractParameters godoc +// +// @Tags PolicyTemplate +// @Summary [Admin_ExtractParameters] 정책 템플릿 파라미터 추출 +// @Description 정책 템플릿 파라미터를 기존 버전의 수정불가능한 파라미터를 포함해서 추출한다. +// @Accept json +// @Produce json +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param version path string true "버전(v0.0.0 형식)" +// @Param body body admin_domain.ExtractParametersRequest true "Rego 코드" +// @Success 200 {object} admin_domain.ExtractParametersResponse +// @Router /admin/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters [post] +// @Security JWT +func (h *PolicyTemplateHandler) Admin_ExtractParameters(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + version, ok := vars["version"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid version"), "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) + return + } + + input := admin_domain.ExtractParametersRequest{} + + err = UnmarshalRequestInput(r, &input) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + response, err := h.usecase.ExtractPolicyParameters(r.Context(), nil, id, version, input.Rego, input.Libs) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusCreated, response) +} + // Admin_ListPolicyTemplateStatistics godoc // // @Tags PolicyTemplate @@ -1465,3 +1522,79 @@ func (h *PolicyTemplateHandler) ExistsPolicyTemplateKind(w http.ResponseWriter, ResponseJSON(w, r, http.StatusOK, out) } + +// ExtractParameters godoc +// +// @Tags PolicyTemplate +// @Summary [ExtractParameters] 정책 템플릿 파라미터 추출 +// @Description 정책 템플릿 파라미터를 기존 버전의 수정불가능한 파라미터를 포함해서 추출한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param version path string true "버전(v0.0.0 형식)" +// @Param body body domain.ExtractParametersRequest true "Rego 코드" +// @Success 200 {object} domain.ExtractParametersResponse +// @Router /organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters [post] +// @Security JWT +func (h *PolicyTemplateHandler) ExtractParameters(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyTemplateId, ok := vars["policyTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + + version, ok := vars["version"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid version"), "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) + return + } + + id, err := uuid.Parse(policyTemplateId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_INVALID_POLICY_TEMPLATE_VERSION", "")) + return + } + + input := domain.ExtractParametersRequest{} + + err = UnmarshalRequestInput(r, &input) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.ExtractParametersResponse + + response, err := h.usecase.ExtractPolicyParameters(r.Context(), &organizationId, id, version, input.Rego, input.Libs) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + if err := serializer.Map(r.Context(), response, &out); err != nil { + log.Info(r.Context(), err) + } + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusCreated, response) +} diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index fd738c2b..978f2275 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -515,9 +515,9 @@ func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { // @Summary Check whether the role name exists // @Description Check whether the role name exists // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleName path string true "Role Name" -// @Success 200 {object} domain.CheckRoleNameResponse +// @Param organizationId path string true "Organization ID" +// @Param roleName path string true "Role Name" +// @Success 200 {object} domain.CheckRoleNameResponse // @Router /organizations/{organizationId}/roles/{roleName}/existence [get] // @Security JWT func (h RoleHandler) IsRoleNameExisted(w http.ResponseWriter, r *http.Request) { @@ -558,8 +558,8 @@ func (h RoleHandler) IsRoleNameExisted(w http.ResponseWriter, r *http.Request) { // @Description Append Users To Role // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" // @Param body body domain.AppendUsersToRoleRequest true "Append Users To Role Request" // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId}/users [post] @@ -621,8 +621,8 @@ func (h RoleHandler) AppendUsersToRole(w http.ResponseWriter, r *http.Request) { // @Description Remove Users From Role // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" // @Param body body domain.RemoveUsersFromRoleRequest true "Remove Users From Role Request" // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId}/users [delete] @@ -688,14 +688,14 @@ func (h RoleHandler) RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) // @Summary Get Users By Role ID // @Description Get Users By Role ID // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" // @Param pageSize query string false "pageSize" // @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} domain.GetUsersInRoleIdResponse +// @Success 200 {object} domain.GetUsersInRoleIdResponse // @Router /organizations/{organizationId}/roles/{roleId}/users [get] // @Security JWT func (h RoleHandler) GetUsersInRoleId(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index c9aa9678..4a572974 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -363,8 +363,8 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { // @Description Update multiple users // @Accept json // @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body []domain.UpdateUsersRequest true "input" +// @Param organizationId path string true "organizationId" +// @Param body body []domain.UpdateUsersRequest true "input" // @Success 200 // @Router /organizations/{organizationId}/users [put] // @Security JWT @@ -932,9 +932,9 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { // @Description Delete user by admin in Admin Portal // @Accept json // @Produce json -// @Param body body domain.DeleteUserRequest true "input" -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" +// @Param body body domain.DeleteUserRequest true "input" +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" // @Success 200 // @Router /admin/organizations/{organizationId}/users/{accountId} [delete] // @Security JWT diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go index cc735b1b..32e2de8e 100644 --- a/internal/policy-template/paramdef-util.go +++ b/internal/policy-template/paramdef-util.go @@ -33,6 +33,28 @@ func GetNewParamDefs(paramdefs1 []*domain.ParameterDef, paramdefs2 []*domain.Par return result, nil } +func GetNewExtractedParamDefs(paramdefs []*domain.ParameterDef, extractedParamdefs []*domain.ParameterDef) (newParamdefs []*domain.ParameterDef, err error) { + result := []*domain.ParameterDef{} + + if len(paramdefs) > len(extractedParamdefs) { + return nil, errors.New("not compatible, parameter number reduced") + } + + for _, extractedParamdef := range extractedParamdefs { + paramdef := findParamDefByName(paramdefs, extractedParamdef.Key) + + if paramdef == nil { + // Not found, it's new parameter + extractedParamdef.MarkNewRecursive() + result = append(result, extractedParamdef) + } else if !CompareParamDefAndExtractedParamDef(paramdef, extractedParamdef) { + return nil, fmt.Errorf("not compatible, parameter definition of '%s' is changed", extractedParamdef.Key) + } + } + + return result, nil +} + func findParamDefByName(paramdefs []*domain.ParameterDef, name string) *domain.ParameterDef { for _, paramdef := range paramdefs { if paramdef.Key == name { @@ -81,6 +103,46 @@ func CompareParamDef(paramdef1 *domain.ParameterDef, paramdef2 *domain.Parameter return true } +func CompareParamDefAndExtractedParamDef(paramdef *domain.ParameterDef, extractedParamdef *domain.ParameterDef) bool { + if paramdef == nil || extractedParamdef == nil { + return extractedParamdef == paramdef + } + + if paramdef.Key != extractedParamdef.Key { + return false + } + + if paramdef.IsArray != extractedParamdef.IsArray { + return false + } + + // object 기반이면 true, string 등 any 기반이면 false + paramDefIsObjectBased := paramdef.Type == "object" || paramdef.Type == "object[]" + + // ovject 기반이면 true, any, anㅛ[] 등 기반이면 false + extractedParamdefIsObjectBased := paramdef.Type == "object" || paramdef.Type == "object[]" + + if paramDefIsObjectBased != extractedParamdefIsObjectBased { + return false + } + + if len(paramdef.Children) != len(extractedParamdef.Children) { + return false + } + + for _, child := range paramdef.Children { + child2 := extractedParamdef.GetChildrenByName(child.Key) + + equals := CompareParamDefAndExtractedParamDef(child, child2) + + if !equals { + return false + } + } + + return true +} + func ParamDefsToJSONSchemaProeprties(paramdefs []*domain.ParameterDef) *apiextensionsv1.JSONSchemaProps { if paramdefs == nil { return nil diff --git a/internal/route/route.go b/internal/route/route.go index 0ab35832..db460a75 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -315,6 +315,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions", customMiddleware.Handle(internalApi.Admin_CreatePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.Admin_CreatePolicyTemplateVersion))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.Admin_DeletePolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.Admin_DeletePolicyTemplateVersion))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.Admin_GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.Admin_GetPolicyTemplateVersion))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters", customMiddleware.Handle(internalApi.Admin_ExtractParameters, http.HandlerFunc(policyTemplateHandler.Admin_ExtractParameters))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.Admin_ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.Admin_ExistsPolicyTemplateKind))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.Admin_ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.Admin_ExistsPolicyTemplateName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/policy-templates/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(policyTemplateHandler.RegoCompile))).Methods(http.MethodPost) @@ -331,6 +332,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}", customMiddleware.Handle(internalApi.GetPolicyTemplateVersion, http.HandlerFunc(policyTemplateHandler.GetPolicyTemplateVersion))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateKind))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.ExistsPolicyTemplateName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters", customMiddleware.Handle(internalApi.ExtractParameters, http.HandlerFunc(policyTemplateHandler.ExtractParameters))).Methods(http.MethodPost) policyHandler := delivery.NewPolicyHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/mandatory-policies", customMiddleware.Handle(internalApi.GetMandatoryPolicies, http.HandlerFunc(policyHandler.GetMandatoryPolicies))).Methods(http.MethodGet) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 9dcedef3..ca555625 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -43,6 +43,8 @@ type IPolicyTemplateUsecase interface { ListPolicyTemplateStatistics(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (statistics []model.UsageCount, err error) GetPolicyTemplateDeploy(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (deployInfo domain.GetPolicyTemplateDeployResponse, err error) + + ExtractPolicyParameters(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string, rego string, libs []string) (response *domain.RegoCompileResponse, err error) } type PolicyTemplateUsecase struct { @@ -520,3 +522,74 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateDeploy(ctx context.Context, org return deployVersions, nil } + +func (u *PolicyTemplateUsecase) ExtractPolicyParameters(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string, rego string, libs []string) (response *domain.RegoCompileResponse, err error) { + policyTemplate, err := u.repo.GetPolicyTemplateVersion(ctx, policyTemplateId, version) + + if err != nil { + return nil, err + } + + if policyTemplate == nil { + return nil, httpErrors.NewBadRequestError(fmt.Errorf( + "failed to fetch policy template"), + "PT_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + if !policyTemplate.IsPermittedToOrganization(organizationId) { + // 다른 Organization의 템플릿을 조작하려고 함, 보안을 위해서 해당 식별자 존재 자체를 알려주면 안되므로 not found + if *organizationId != *policyTemplate.OrganizationId { + return nil, httpErrors.NewNotFoundError(fmt.Errorf( + "policy template version not found"), + "PT_NOT_FOUND_POLICY_TEMPLATE", "") + } + } + + modules := map[string]*ast.Module{} + + response = &domain.RegoCompileResponse{} + response.Errors = []domain.RegoCompieError{} + + mod, err := ast.ParseModuleWithOpts("rego", rego, ast.ParserOptions{}) + if err != nil { + return nil, err + } + modules["rego"] = mod + + compiler := ast.NewCompiler() + compiler.Compile(modules) + + if compiler.Failed() { + for _, compileError := range compiler.Errors { + response.Errors = append(response.Errors, domain.RegoCompieError{ + Status: 400, + Code: "PT_INVALID_REGO_SYNTAX", + Message: "invalid rego syntax", + Text: fmt.Sprintf("[%d:%d] %s", + compileError.Location.Row, compileError.Location.Col, + compileError.Message), + }) + } + } + + extractedParamDefs := policytemplate.ExtractParameter(modules) + paramdefs := policyTemplate.ParametersSchema + + newParams, err := policytemplate.GetNewExtractedParamDefs(paramdefs, extractedParamDefs) + + response.ParametersSchema = []*domain.ParameterDef{} + + if err != nil { + response.Errors = append(response.Errors, domain.RegoCompieError{ + Status: 400, + Code: "PT_NOT_COMPATIBLE_PARAMS", + Message: "new parameters are not compatible to current version", + Text: err.Error(), + }) + } else { + response.ParametersSchema = append(response.ParametersSchema, paramdefs...) + response.ParametersSchema = append(response.ParametersSchema, newParams...) + } + + return response, nil +} diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index 6433f6b6..0613c7b9 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -177,3 +177,13 @@ type RegoCompileResponse struct { ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` Errors []domain.RegoCompieError `json:"errors,omitempty"` } + +type ExtractParametersRequest struct { + Rego string `json:"rego" example:"Rego 코드" validate:"required"` + Libs []string `json:"libs,omitempty"` +} + +type ExtractParametersResponse struct { + ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` + Errors []domain.RegoCompieError `json:"errors,omitempty"` +} diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index e1ead8cb..265104aa 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -147,7 +147,16 @@ type ParameterDef struct { Type string `json:"type" examples:"string[]"` DefaultValue string `json:"defaultValue"` Children []*ParameterDef `json:"children"` - IsArray bool `json:"isArray" examples:"true"` + IsArray bool `json:"isArray" examples:"true"` + IsNew bool `json:"isNew,omitempty" examples:"true"` +} + +func (pd *ParameterDef) MarkNewRecursive() { + pd.IsNew = true + + for _, child := range pd.Children { + child.MarkNewRecursive() + } } func (pd *ParameterDef) GetChildrenByName(name string) *ParameterDef { @@ -176,3 +185,13 @@ type RegoCompileResponse struct { ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` Errors []RegoCompieError `json:"errors,omitempty"` } + +type ExtractParametersRequest struct { + Rego string `json:"rego" example:"Rego 코드" validate:"required"` + Libs []string `json:"libs,omitempty"` +} + +type ExtractParametersResponse struct { + ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` + Errors []RegoCompieError `json:"errors,omitempty"` +} From 9a3139b0223b9a96d1442da8280d093cf6e0c1d2 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 4 Apr 2024 17:59:01 +0900 Subject: [PATCH 231/502] change dashboard resource format --- internal/usecase/dashboard.go | 31 +++++++++++++++++++++++++------ pkg/domain/dashboard.go | 5 ++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 67337c0a..176ae035 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -186,11 +186,30 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri filteredClusters := funk.Filter(clusters, func(x model.Cluster) bool { return x.Status != domain.ClusterStatus_DELETED }) + + var normal, abnormal int if filteredClusters != nil { - out.Stack = fmt.Sprintf("%d 개", len(filteredClusters.([]model.Cluster))) - } else { - out.Stack = "0 개" + for _, cluster := range filteredClusters.([]model.Cluster) { + clientSet, err := kubernetes.GetClientFromClusterId(ctx, cluster.ID.String()) + if err != nil { + return out, errors.Wrap(err, "Failed to get client set for user cluster") + } + // get cluster info + clusterInfo, err := clientSet.CoreV1().Services("kube-system").List(context.TODO(), metav1.ListOptions{LabelSelector: "kubernetes.io/cluster-service"}) + if err != nil { + abnormal++ + log.Debugf(ctx, "Failed to get cluster info: %v\n", err) + continue + } + if clusterInfo.Items[0].ObjectMeta.Labels["kubernetes.io/cluster-service"] == "true" { + normal++ + } else { + abnormal++ + } + } } + out.Stack.Normal = strconv.Itoa(normal) + out.Stack.Abnormal = strconv.Itoa(abnormal) // CPU /* @@ -210,7 +229,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri cpu = cpu + cpuVal } } - out.Cpu = fmt.Sprintf("%d 개", cpu) + out.Cpu = strconv.Itoa(cpu) // Memory result, err = thanosClient.Get(ctx, "sum by (taco_cluster) (machine_memory_bytes)") @@ -228,7 +247,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri memory = memory + memory_ } } - out.Memory = fmt.Sprintf("%v GiB", math.Round(memory)) + out.Memory = fmt.Sprintf("%v", math.Round(memory)) // Storage result, err = thanosClient.Get(ctx, "sum by (taco_cluster) (kubelet_volume_stats_capacity_bytes)") @@ -246,7 +265,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri storage = storage + storage_ } } - out.Storage = fmt.Sprintf("%v GiB", math.Round(storage)) + out.Storage = fmt.Sprintf("%v", math.Round(storage)) return } diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 672b1d0c..bbdb1229 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -115,7 +115,10 @@ type GetDashboardChartResponse struct { } type DashboardResource struct { - Stack string `json:"stack"` + Stack struct { + Normal string `json:"normal"` + Abnormal string `json:"abnormal"` + } `json:"stack"` Cpu string `json:"cpu"` Memory string `json:"memory"` Storage string `json:"storage"` From 78e40e2979cd5bb4b620ca8ec9649731db7a7112 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 4 Apr 2024 18:07:15 +0900 Subject: [PATCH 232/502] feature. add & update default snr --- api/swagger/docs.go | 997 +++++++++++++----- api/swagger/swagger.json | 997 +++++++++++++----- api/swagger/swagger.yaml | 614 ++++++++--- internal/delivery/http/role.go | 20 +- .../delivery/http/system-notification-rule.go | 2 +- internal/delivery/http/user.go | 10 +- internal/usecase/system-notification-rule.go | 6 +- pkg/domain/system-notification-template.go | 2 +- scripts/init_postgres.sql | 12 +- 9 files changed, 1919 insertions(+), 741 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 3b318de7..71b72122 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -202,6 +202,45 @@ const docTemplate = `{ } } }, + "/admin/organizations": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create organization in Admin portal", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Create organization in Admin portal", + "parameters": [ + { + "description": "create organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -241,6 +280,11 @@ const docTemplate = `{ }, "/admin/organizations/{organizationId}/roles": { "get": { + "security": [ + { + "JWT": [] + } + ], "description": "Admin List Tks Roles", "produces": [ "application/json" @@ -270,6 +314,11 @@ const docTemplate = `{ }, "/admin/organizations/{organizationId}/roles/{roleId}": { "get": { + "security": [ + { + "JWT": [] + } + ], "description": "Admin Get Tks Role", "produces": [ "application/json" @@ -304,9 +353,14 @@ const docTemplate = `{ } } }, - "/admin/organizations/{organizationId}/users/{accountId}": { - "get": { - "description": "Get user detail by admin", + "/admin/organizations/{organizationId}/users": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create user by admin in Admin Portal", "consumes": [ "application/json" ], @@ -316,7 +370,7 @@ const docTemplate = `{ "tags": [ "Users" ], - "summary": "Get user detail by admin", + "summary": "Create user by admin in Admin Portal", "parameters": [ { "type": "string", @@ -326,29 +380,33 @@ const docTemplate = `{ "required": true }, { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true + "description": "create user request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserRequest" + } } ], "responses": { "200": { - "description": "OK", + "description": "create user response", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserResponse" } } } - }, + } + }, + "/admin/organizations/{organizationId}/users/{accountId}": { "put": { "security": [ { "JWT": [] } ], - "description": "Update user by admin", + "description": "Update user by admin in Admin Portal", "consumes": [ "application/json" ], @@ -358,7 +416,7 @@ const docTemplate = `{ "tags": [ "Users" ], - "summary": "Update user by admin", + "summary": "Update user by admin in Admin Portal", "parameters": [ { "type": "string", @@ -380,7 +438,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserRequest" } } ], @@ -388,8 +446,56 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete user by admin in Admin Portal", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete user by admin in Admin Portal", + "parameters": [ + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest" } + }, + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" } } } @@ -2532,43 +2638,6 @@ const docTemplate = `{ } } } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create organization", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Create organization", - "parameters": [ - { - "description": "create organization request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object" - } - } - } } }, "/organizations/name/{name}/existence": { @@ -7096,25 +7165,36 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stack-templates": { + "/organizations/{organizationId}/roles/{roleId}/users": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplates", - "consumes": [ - "application/json" - ], + "description": "Get Users By Role ID", "produces": [ "application/json" ], "tags": [ - "StackTemplates" + "Roles" ], - "summary": "Get Organization StackTemplates", + "summary": "Get Users By Role ID", "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -7154,18 +7234,18 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersInRoleIdResponse" } } } }, - "put": { + "post": { "security": [ { "JWT": [] } ], - "description": "Remove organization stackTemplates", + "description": "Append Users To Role", "consumes": [ "application/json" ], @@ -7173,17 +7253,31 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "Roles" ], - "summary": "Remove organization stackTemplates", + "summary": "Append Users To Role", "parameters": [ { - "description": "Remove organization stack templates request", + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Append Users To Role Request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppendUsersToRoleRequest" } } ], @@ -7193,13 +7287,13 @@ const docTemplate = `{ } } }, - "post": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Add organization stackTemplates", + "description": "Remove Users From Role", "consumes": [ "application/json" ], @@ -7207,17 +7301,31 @@ const docTemplate = `{ "application/json" ], "tags": [ - "StackTemplates" + "Roles" ], - "summary": "Add organization stackTemplates", + "summary": "Remove Users From Role", "parameters": [ { - "description": "Add organization stack templates request", + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Remove Users From Role Request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveUsersFromRoleRequest" } } ], @@ -7228,42 +7336,55 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "/organizations/{organizationId}/roles/{roleName}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplate", - "consumes": [ - "application/json" - ], + "description": "Check whether the role name exists", "produces": [ "application/json" ], "tags": [ - "StackTemplates" + "Roles" + ], + "summary": "Check whether the role name exists", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role Name", + "name": "roleName", + "in": "path", + "required": true + } ], - "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckRoleNameResponse" } } } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/stack-templates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", + "description": "Get Organization StackTemplates", "consumes": [ "application/json" ], @@ -7271,16 +7392,176 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "StackTemplates" ], - "summary": "Get Stacks", + "summary": "Get Organization StackTemplates", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove organization stackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Remove organization stackTemplates", + "parameters": [ + { + "description": "Remove organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add organization stackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Add organization stackTemplates", + "parameters": [ + { + "description": "Add organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization StackTemplate", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stacks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stacks", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true }, { "type": "string", @@ -8460,6 +8741,50 @@ const docTemplate = `{ } } }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update multiple users", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update multiple users", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUsersRequest" + } + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, "post": { "security": [ { @@ -9148,6 +9473,129 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserRequest": { + "type": "object", + "required": [ + "accountId", + "email", + "roles" + ], + "properties": { + "accountId": { + "type": "string" + }, + "adminPassword": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserRequest": { + "type": "object", + "required": [ + "email", + "roles" + ], + "properties": { + "adminPassword": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -9394,6 +9842,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.AppendUsersToRoleRequest": { + "type": "object", + "required": [ + "users" + ], + "properties": { + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse": { "type": "object", "properties": { @@ -9550,6 +10012,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CheckRoleNameResponse": { + "type": "object", + "properties": { + "isExist": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse": { "type": "object", "properties": { @@ -10680,7 +11150,7 @@ const docTemplate = `{ "accountId", "email", "password", - "role" + "roles" ], "properties": { "accountId": { @@ -10705,12 +11175,11 @@ const docTemplate = `{ "password": { "type": "string" }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } } } }, @@ -10741,8 +11210,11 @@ const docTemplate = `{ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } } } } @@ -10866,6 +11338,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest": { + "type": "object", + "properties": { + "adminPassword": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { @@ -11268,8 +11748,11 @@ const docTemplate = `{ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } } } } @@ -11667,8 +12150,11 @@ const docTemplate = `{ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } }, "updatedAt": { "type": "string" @@ -11677,6 +12163,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetUsersInRoleIdResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "users": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse": { "type": "object", "properties": { @@ -11872,8 +12372,11 @@ const docTemplate = `{ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } }, "updatedAt": { "type": "string" @@ -11920,8 +12423,11 @@ const docTemplate = `{ "passwordExpired": { "type": "boolean" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } }, "token": { "type": "string" @@ -12716,6 +13222,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RemoveUsersFromRoleRequest": { + "type": "object", + "required": [ + "users" + ], + "properties": { + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ResourceQuota": { "type": "object", "properties": { @@ -12744,49 +13264,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse": { - "type": "object", - "properties": { - "roleId": { - "type": "string" - }, - "roleName": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" - }, - "organizationId": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest": { "type": "object", "properties": { @@ -12892,6 +13369,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -13602,6 +14090,9 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest": { "type": "object", "required": [ + "department", + "email", + "name", "password" ], "properties": { @@ -13647,8 +14138,11 @@ const docTemplate = `{ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } } } } @@ -14049,11 +14543,21 @@ const docTemplate = `{ "type": "string", "maxLength": 100, "minLength": 0 + }, + "name": { + "type": "string", + "maxLength": 100, + "minLength": 0 } } }, "github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest": { "type": "object", + "required": [ + "email", + "name", + "roles" + ], "properties": { "department": { "type": "string", @@ -14069,16 +14573,13 @@ const docTemplate = `{ "type": "string" }, "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 + "type": "string" }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } } } }, @@ -14112,8 +14613,11 @@ const docTemplate = `{ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } }, "updatedAt": { "type": "string" @@ -14122,6 +14626,50 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateUsersRequest": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "required": [ + "accountId", + "email", + "name", + "roles" + ], + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } + } + } + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter": { "type": "object", "properties": { @@ -14136,6 +14684,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UserCreationRole": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ @@ -14381,49 +14940,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse": { "type": "object", "properties": { @@ -14607,77 +15123,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest": { - "type": "object", - "required": [ - "email", - "role" - ], - "properties": { - "adminPassword": { - "type": "string" - }, - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string" - }, - "role": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, "github_com_openinfradev_tks-api_pkg_httpErrors.RestError": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index d513ac30..89f6e889 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -196,6 +196,45 @@ } } }, + "/admin/organizations": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create organization in Admin portal", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Create organization in Admin portal", + "parameters": [ + { + "description": "create organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -235,6 +274,11 @@ }, "/admin/organizations/{organizationId}/roles": { "get": { + "security": [ + { + "JWT": [] + } + ], "description": "Admin List Tks Roles", "produces": [ "application/json" @@ -264,6 +308,11 @@ }, "/admin/organizations/{organizationId}/roles/{roleId}": { "get": { + "security": [ + { + "JWT": [] + } + ], "description": "Admin Get Tks Role", "produces": [ "application/json" @@ -298,9 +347,14 @@ } } }, - "/admin/organizations/{organizationId}/users/{accountId}": { - "get": { - "description": "Get user detail by admin", + "/admin/organizations/{organizationId}/users": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Create user by admin in Admin Portal", "consumes": [ "application/json" ], @@ -310,7 +364,7 @@ "tags": [ "Users" ], - "summary": "Get user detail by admin", + "summary": "Create user by admin in Admin Portal", "parameters": [ { "type": "string", @@ -320,29 +374,33 @@ "required": true }, { - "type": "string", - "description": "accountId", - "name": "accountId", - "in": "path", - "required": true + "description": "create user request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserRequest" + } } ], "responses": { "200": { - "description": "OK", + "description": "create user response", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserResponse" } } } - }, + } + }, + "/admin/organizations/{organizationId}/users/{accountId}": { "put": { "security": [ { "JWT": [] } ], - "description": "Update user by admin", + "description": "Update user by admin in Admin Portal", "consumes": [ "application/json" ], @@ -352,7 +410,7 @@ "tags": [ "Users" ], - "summary": "Update user by admin", + "summary": "Update user by admin in Admin Portal", "parameters": [ { "type": "string", @@ -374,7 +432,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserRequest" } } ], @@ -382,8 +440,56 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserResponse" + } + } + } + }, + "delete": { + "security": [ + { + "JWT": [] + } + ], + "description": "Delete user by admin in Admin Portal", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete user by admin in Admin Portal", + "parameters": [ + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest" } + }, + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "accountId", + "name": "accountId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" } } } @@ -2526,43 +2632,6 @@ } } } - }, - "post": { - "security": [ - { - "JWT": [] - } - ], - "description": "Create organization", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Organizations" - ], - "summary": "Create organization", - "parameters": [ - { - "description": "create organization request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object" - } - } - } } }, "/organizations/name/{name}/existence": { @@ -7090,25 +7159,36 @@ } } }, - "/organizations/{organizationId}/stack-templates": { + "/organizations/{organizationId}/roles/{roleId}/users": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplates", - "consumes": [ - "application/json" - ], + "description": "Get Users By Role ID", "produces": [ "application/json" ], "tags": [ - "StackTemplates" + "Roles" ], - "summary": "Get Organization StackTemplates", + "summary": "Get Users By Role ID", "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -7148,18 +7228,18 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersInRoleIdResponse" } } } }, - "put": { + "post": { "security": [ { "JWT": [] } ], - "description": "Remove organization stackTemplates", + "description": "Append Users To Role", "consumes": [ "application/json" ], @@ -7167,17 +7247,31 @@ "application/json" ], "tags": [ - "StackTemplates" + "Roles" ], - "summary": "Remove organization stackTemplates", + "summary": "Append Users To Role", "parameters": [ { - "description": "Remove organization stack templates request", + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Append Users To Role Request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppendUsersToRoleRequest" } } ], @@ -7187,13 +7281,13 @@ } } }, - "post": { + "delete": { "security": [ { "JWT": [] } ], - "description": "Add organization stackTemplates", + "description": "Remove Users From Role", "consumes": [ "application/json" ], @@ -7201,17 +7295,31 @@ "application/json" ], "tags": [ - "StackTemplates" + "Roles" ], - "summary": "Add organization stackTemplates", + "summary": "Remove Users From Role", "parameters": [ { - "description": "Add organization stack templates request", + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role ID", + "name": "roleId", + "in": "path", + "required": true + }, + { + "description": "Remove Users From Role Request", "name": "body", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveUsersFromRoleRequest" } } ], @@ -7222,42 +7330,55 @@ } } }, - "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "/organizations/{organizationId}/roles/{roleName}/existence": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Organization StackTemplate", - "consumes": [ - "application/json" - ], + "description": "Check whether the role name exists", "produces": [ "application/json" ], "tags": [ - "StackTemplates" + "Roles" + ], + "summary": "Check whether the role name exists", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Role Name", + "name": "roleName", + "in": "path", + "required": true + } ], - "summary": "Get Organization StackTemplate", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckRoleNameResponse" } } } } }, - "/organizations/{organizationId}/stacks": { + "/organizations/{organizationId}/stack-templates": { "get": { "security": [ { "JWT": [] } ], - "description": "Get Stacks", + "description": "Get Organization StackTemplates", "consumes": [ "application/json" ], @@ -7265,16 +7386,176 @@ "application/json" ], "tags": [ - "Stacks" + "StackTemplates" ], - "summary": "Get Stacks", + "summary": "Get Organization StackTemplates", "parameters": [ { "type": "string", - "description": "organizationId", - "name": "organizationId", - "in": "path", - "required": true + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Remove organization stackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Remove organization stackTemplates", + "parameters": [ + { + "description": "Remove organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Add organization stackTemplates", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Add organization stackTemplates", + "parameters": [ + { + "description": "Add organization stack templates request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddOrganizationStackTemplatesRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization StackTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization StackTemplate", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stacks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stacks", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true }, { "type": "string", @@ -8454,6 +8735,50 @@ } } }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update multiple users", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update multiple users", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "input", + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUsersRequest" + } + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, "post": { "security": [ { @@ -9142,6 +9467,129 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserRequest": { + "type": "object", + "required": [ + "accountId", + "email", + "roles" + ], + "properties": { + "accountId": { + "type": "string" + }, + "adminPassword": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserRequest": { + "type": "object", + "required": [ + "email", + "roles" + ], + "properties": { + "adminPassword": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserResponse": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "department": { + "type": "string" + }, + "description": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organization": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } + }, + "updatedAt": { + "type": "string" + } + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -9388,6 +9836,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.AppendUsersToRoleRequest": { + "type": "object", + "required": [ + "users" + ], + "properties": { + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse": { "type": "object", "properties": { @@ -9544,6 +10006,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.CheckRoleNameResponse": { + "type": "object", + "properties": { + "isExist": { + "type": "boolean" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse": { "type": "object", "properties": { @@ -10674,7 +11144,7 @@ "accountId", "email", "password", - "role" + "roles" ], "properties": { "accountId": { @@ -10699,12 +11169,11 @@ "password": { "type": "string" }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } } } }, @@ -10735,8 +11204,11 @@ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } } } } @@ -10860,6 +11332,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest": { + "type": "object", + "properties": { + "adminPassword": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { @@ -11262,8 +11742,11 @@ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } } } } @@ -11661,8 +12144,11 @@ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } }, "updatedAt": { "type": "string" @@ -11671,6 +12157,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetUsersInRoleIdResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "users": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse": { "type": "object", "properties": { @@ -11866,8 +12366,11 @@ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } }, "updatedAt": { "type": "string" @@ -11914,8 +12417,11 @@ "passwordExpired": { "type": "boolean" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } }, "token": { "type": "string" @@ -12710,6 +13216,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.RemoveUsersFromRoleRequest": { + "type": "object", + "required": [ + "users" + ], + "properties": { + "users": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ResourceQuota": { "type": "object", "properties": { @@ -12738,49 +13258,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse": { - "type": "object", - "properties": { - "roleId": { - "type": "string" - }, - "roleName": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain.RoleResponse": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" - }, - "organizationId": { - "type": "string" - }, - "type": { - "type": "string" - }, - "updatedAt": { - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest": { "type": "object", "properties": { @@ -12886,6 +13363,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse": { "type": "object", "properties": { @@ -13596,6 +14084,9 @@ "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest": { "type": "object", "required": [ + "department", + "email", + "name", "password" ], "properties": { @@ -13641,8 +14132,11 @@ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } } } } @@ -14043,11 +14537,21 @@ "type": "string", "maxLength": 100, "minLength": 0 + }, + "name": { + "type": "string", + "maxLength": 100, + "minLength": 0 } } }, "github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest": { "type": "object", + "required": [ + "email", + "name", + "roles" + ], "properties": { "department": { "type": "string", @@ -14063,16 +14567,13 @@ "type": "string" }, "name": { - "type": "string", - "maxLength": 30, - "minLength": 1 + "type": "string" }, - "role": { - "type": "string", - "enum": [ - "admin", - "user" - ] + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } } } }, @@ -14106,8 +14607,11 @@ "organization": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } }, "updatedAt": { "type": "string" @@ -14116,6 +14620,50 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateUsersRequest": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "required": [ + "accountId", + "email", + "name", + "roles" + ], + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string", + "maxLength": 50, + "minLength": 0 + }, + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole" + } + } + } + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter": { "type": "object", "properties": { @@ -14130,6 +14678,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UserCreationRole": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest": { "type": "object", "required": [ @@ -14375,49 +14934,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "creator": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse": { "type": "object", "properties": { @@ -14601,77 +15117,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest": { - "type": "object", - "required": [ - "email", - "role" - ], - "properties": { - "adminPassword": { - "type": "string" - }, - "department": { - "type": "string", - "maxLength": 50, - "minLength": 0 - }, - "description": { - "type": "string", - "maxLength": 100, - "minLength": 0 - }, - "email": { - "type": "string" - }, - "name": { - "type": "string" - }, - "role": { - "type": "string" - } - } - }, - "github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse": { - "type": "object", - "properties": { - "user": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "department": { - "type": "string" - }, - "description": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse" - }, - "role": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse" - }, - "updatedAt": { - "type": "string" - } - } - } - } - }, "github_com_openinfradev_tks-api_pkg_httpErrors.RestError": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 6f4c6153..ec528918 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -165,6 +165,90 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserRequest: + properties: + accountId: + type: string + adminPassword: + type: string + department: + maxLength: 50 + minLength: 0 + type: string + description: + maxLength: 100 + minLength: 0 + type: string + email: + type: string + name: + type: string + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole' + type: array + required: + - accountId + - email + - roles + type: object + github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserResponse: + properties: + id: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserRequest: + properties: + adminPassword: + type: string + department: + maxLength: 50 + minLength: 0 + type: string + description: + maxLength: 100 + minLength: 0 + type: string + email: + type: string + name: + type: string + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole' + type: array + required: + - email + - roles + type: object + github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserResponse: + properties: + user: + properties: + accountId: + type: string + createdAt: + type: string + department: + type: string + description: + type: string + email: + type: string + id: + type: string + name: + type: string + organization: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array + updatedAt: + type: string + type: object + type: object github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse: properties: appGroupType: @@ -343,6 +427,15 @@ definitions: description: application version type: string type: object + github_com_openinfradev_tks-api_pkg_domain.AppendUsersToRoleRequest: + properties: + users: + items: + type: string + type: array + required: + - users + type: object github_com_openinfradev_tks-api_pkg_domain.ApplicationResponse: properties: appGroupId: @@ -451,6 +544,11 @@ definitions: existed: type: boolean type: object + github_com_openinfradev_tks-api_pkg_domain.CheckRoleNameResponse: + properties: + isExist: + type: boolean + type: object github_com_openinfradev_tks-api_pkg_domain.CheckStackTemplateNameResponse: properties: existed: @@ -1232,16 +1330,15 @@ definitions: type: string password: type: string - role: - enum: - - admin - - user - type: string + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole' + type: array required: - accountId - email - password - - role + - roles type: object github_com_openinfradev_tks-api_pkg_domain.CreateUserResponse: properties: @@ -1261,8 +1358,10 @@ definitions: type: string organization: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array type: object type: object github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse: @@ -1344,6 +1443,11 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest: + properties: + adminPassword: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.EndpointResponse: properties: group: @@ -1607,8 +1711,10 @@ definitions: type: string organization: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array type: object type: object github_com_openinfradev_tks-api_pkg_domain.GetOrganizationResponse: @@ -1862,12 +1968,23 @@ definitions: type: string organization: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array updatedAt: type: string type: object type: object + github_com_openinfradev_tks-api_pkg_domain.GetUsersInRoleIdResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + users: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetUsersPermissionsResponse: properties: permissions: @@ -1996,8 +2113,10 @@ definitions: type: string organization: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array updatedAt: type: string type: object @@ -2028,8 +2147,10 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' passwordExpired: type: boolean - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array token: type: string type: object @@ -2564,6 +2685,15 @@ definitions: type: object type: array type: object + github_com_openinfradev_tks-api_pkg_domain.RemoveUsersFromRoleRequest: + properties: + users: + items: + type: string + type: array + required: + - users + type: object github_com_openinfradev_tks-api_pkg_domain.ResourceQuota: properties: quotas: @@ -2582,34 +2712,6 @@ definitions: usage: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.RoleIdRoleNameResponse: - properties: - roleId: - type: string - roleName: - type: string - type: object - github_com_openinfradev_tks-api_pkg_domain.RoleResponse: - properties: - createdAt: - type: string - creator: - type: string - description: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - organizationId: - type: string - type: - type: string - updatedAt: - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.RollbackAppServeAppRequest: properties: taskId: @@ -2680,6 +2782,13 @@ definitions: example: v1.0.1 type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse: + properties: + id: + type: string + name: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateResponse: properties: cloudService: @@ -3162,6 +3271,9 @@ definitions: password: type: string required: + - department + - email + - name - password type: object github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileResponse: @@ -3180,8 +3292,10 @@ definitions: type: string organization: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array type: object type: object github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest: @@ -3449,6 +3563,10 @@ definitions: maxLength: 100 minLength: 0 type: string + name: + maxLength: 100 + minLength: 0 + type: string type: object github_com_openinfradev_tks-api_pkg_domain.UpdateUserRequest: properties: @@ -3463,14 +3581,15 @@ definitions: email: type: string name: - maxLength: 30 - minLength: 1 - type: string - role: - enum: - - admin - - user type: string + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole' + type: array + required: + - email + - name + - roles type: object github_com_openinfradev_tks-api_pkg_domain.UpdateUserResponse: properties: @@ -3492,12 +3611,45 @@ definitions: type: string organization: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array updatedAt: type: string type: object type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateUsersRequest: + properties: + users: + items: + properties: + accountId: + type: string + department: + maxLength: 50 + minLength: 0 + type: string + description: + maxLength: 100 + minLength: 0 + type: string + email: + type: string + name: + type: string + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UserCreationRole' + type: array + required: + - accountId + - email + - name + - roles + type: object + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter: properties: name: @@ -3507,6 +3659,13 @@ definitions: value: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.UserCreationRole: + properties: + id: + type: string + required: + - id + type: object github_com_openinfradev_tks-api_pkg_domain.VerifyIdentityForLostIdRequest: properties: email: @@ -3674,34 +3833,6 @@ definitions: policyTemplate: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse' type: object - github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse: - properties: - user: - properties: - accountId: - type: string - createdAt: - type: string - creator: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' - updatedAt: - type: string - type: object - type: object github_com_openinfradev_tks-api_pkg_domain_admin.ListPolicyTemplateResponse: properties: pagination: @@ -3828,54 +3959,6 @@ definitions: example: 필수 Label 검사 type: string type: object - github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest: - properties: - adminPassword: - type: string - department: - maxLength: 50 - minLength: 0 - type: string - description: - maxLength: 100 - minLength: 0 - type: string - email: - type: string - name: - type: string - role: - type: string - required: - - email - - role - type: object - github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse: - properties: - user: - properties: - accountId: - type: string - createdAt: - type: string - department: - type: string - description: - type: string - email: - type: string - id: - type: string - name: - type: string - organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.OrganizationResponse' - role: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RoleResponse' - updatedAt: - type: string - type: object - type: object github_com_openinfradev_tks-api_pkg_httpErrors.RestError: properties: code: @@ -4013,6 +4096,30 @@ paths: summary: Get Audit tags: - Audits + /admin/organizations: + post: + consumes: + - application/json + description: Create organization in Admin portal + parameters: + - description: create organization request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: object + security: + - JWT: [] + summary: Create organization in Admin portal + tags: + - Organizations /admin/organizations/{organizationId}/projects: get: consumes: @@ -4052,6 +4159,8 @@ paths: description: OK schema: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse' + security: + - JWT: [] summary: Admin List Tks Roles tags: - Roles @@ -4076,15 +4185,52 @@ paths: description: OK schema: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetTksRoleResponse' + security: + - JWT: [] summary: Admin Get Tks Role tags: - Roles + /admin/organizations/{organizationId}/users: + post: + consumes: + - application/json + description: Create user by admin in Admin Portal + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: create user request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserRequest' + produces: + - application/json + responses: + "200": + description: create user response + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_CreateUserResponse' + security: + - JWT: [] + summary: Create user by admin in Admin Portal + tags: + - Users /admin/organizations/{organizationId}/users/{accountId}: - get: + delete: consumes: - application/json - description: Get user detail by admin + description: Delete user by admin in Admin Portal parameters: + - description: input + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest' - description: organizationId in: path name: organizationId @@ -4100,15 +4246,15 @@ paths: responses: "200": description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.GetUserResponse' - summary: Get user detail by admin + security: + - JWT: [] + summary: Delete user by admin in Admin Portal tags: - Users put: consumes: - application/json - description: Update user by admin + description: Update user by admin in Admin Portal parameters: - description: organizationId in: path @@ -4125,17 +4271,17 @@ paths: name: body required: true schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserRequest' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.UpdateUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateUserResponse' security: - JWT: [] - summary: Update user by admin + summary: Update user by admin in Admin Portal tags: - Users /admin/policy-templates: @@ -5496,29 +5642,6 @@ paths: summary: Get organization list tags: - Organizations - post: - consumes: - - application/json - description: Create organization - parameters: - - description: create organization request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - type: object - security: - - JWT: [] - summary: Create organization - tags: - - Organizations /organizations/{organizationId}: delete: consumes: @@ -8408,6 +8531,143 @@ paths: summary: Update Permissions By Role ID tags: - Roles + /organizations/{organizationId}/roles/{roleId}/users: + delete: + consumes: + - application/json + description: Remove Users From Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string + - description: Remove Users From Role Request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RemoveUsersFromRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Remove Users From Role + tags: + - Roles + get: + description: Get Users By Role ID + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string + - description: pageSize + in: query + name: pageSize + type: string + - description: pageNumber + in: query + name: pageNumber + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetUsersInRoleIdResponse' + security: + - JWT: [] + summary: Get Users By Role ID + tags: + - Roles + post: + consumes: + - application/json + description: Append Users To Role + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role ID + in: path + name: roleId + required: true + type: string + - description: Append Users To Role Request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppendUsersToRoleRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Append Users To Role + tags: + - Roles + /organizations/{organizationId}/roles/{roleName}/existence: + get: + description: Check whether the role name exists + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Role Name + in: path + name: roleName + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckRoleNameResponse' + security: + - JWT: [] + summary: Check whether the role name exists + tags: + - Roles /organizations/{organizationId}/stack-templates: get: consumes: @@ -9308,6 +9568,34 @@ paths: summary: Create user tags: - Users + put: + consumes: + - application/json + description: Update multiple users + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: input + in: body + name: body + required: true + schema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateUsersRequest' + type: array + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Update multiple users + tags: + - Users /organizations/{organizationId}/users/{accountId}: delete: consumes: diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index fd738c2b..978f2275 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -515,9 +515,9 @@ func (h RoleHandler) Admin_GetTksRole(w http.ResponseWriter, r *http.Request) { // @Summary Check whether the role name exists // @Description Check whether the role name exists // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleName path string true "Role Name" -// @Success 200 {object} domain.CheckRoleNameResponse +// @Param organizationId path string true "Organization ID" +// @Param roleName path string true "Role Name" +// @Success 200 {object} domain.CheckRoleNameResponse // @Router /organizations/{organizationId}/roles/{roleName}/existence [get] // @Security JWT func (h RoleHandler) IsRoleNameExisted(w http.ResponseWriter, r *http.Request) { @@ -558,8 +558,8 @@ func (h RoleHandler) IsRoleNameExisted(w http.ResponseWriter, r *http.Request) { // @Description Append Users To Role // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" // @Param body body domain.AppendUsersToRoleRequest true "Append Users To Role Request" // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId}/users [post] @@ -621,8 +621,8 @@ func (h RoleHandler) AppendUsersToRole(w http.ResponseWriter, r *http.Request) { // @Description Remove Users From Role // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" // @Param body body domain.RemoveUsersFromRoleRequest true "Remove Users From Role Request" // @Success 200 // @Router /organizations/{organizationId}/roles/{roleId}/users [delete] @@ -688,14 +688,14 @@ func (h RoleHandler) RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) // @Summary Get Users By Role ID // @Description Get Users By Role ID // @Produce json -// @Param organizationId path string true "Organization ID" -// @Param roleId path string true "Role ID" +// @Param organizationId path string true "Organization ID" +// @Param roleId path string true "Role ID" // @Param pageSize query string false "pageSize" // @Param pageNumber query string false "pageNumber" // @Param soertColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} domain.GetUsersInRoleIdResponse +// @Success 200 {object} domain.GetUsersInRoleIdResponse // @Router /organizations/{organizationId}/roles/{roleId}/users [get] // @Security JWT func (h RoleHandler) GetUsersInRoleId(w http.ResponseWriter, r *http.Request) { diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index a1ca5370..c87e22dc 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -301,8 +301,8 @@ func (h *SystemNotificationRuleHandler) CheckSystemNotificationRuleName(w http.R } } + // [TEST] /* - // [TEST] err = h.usecase.MakeDefaultSystemNotificationRules(r.Context(), "oolw6roj6", nil) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index c9aa9678..4a572974 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -363,8 +363,8 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { // @Description Update multiple users // @Accept json // @Produce json -// @Param organizationId path string true "organizationId" -// @Param body body []domain.UpdateUsersRequest true "input" +// @Param organizationId path string true "organizationId" +// @Param body body []domain.UpdateUsersRequest true "input" // @Success 200 // @Router /organizations/{organizationId}/users [put] // @Security JWT @@ -932,9 +932,9 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { // @Description Delete user by admin in Admin Portal // @Accept json // @Produce json -// @Param body body domain.DeleteUserRequest true "input" -// @Param organizationId path string true "organizationId" -// @Param accountId path string true "accountId" +// @Param body body domain.DeleteUserRequest true "input" +// @Param organizationId path string true "organizationId" +// @Param accountId path string true "accountId" // @Success 200 // @Router /admin/organizations/{organizationId}/users/{accountId} [delete] // @Security JWT diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 8dcc54f8..33ffaf0d 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -193,7 +193,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "스택 (<>)의 노드(<>)의 idle process의 cpu 점유율이 3분 동안 0% 입니다. (현재 사용률 {{$VALUE}})", + MessageTitle: "스택 (<>)의 노드(<>)의 idle process의 cpu 점유율이 3분 동안 0% 입니다. (현재 사용률 {{$value}})", MessageContent: "워커 노드 CPU가 과부하 상태입니다. 일시적인 서비스 Traffic 증가, Workload의 SW 오류, Server HW Fan Fail등 다양한 원인으로 인해 발생할 수 있습니다.", MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행 되는 pod중 CPU 자원을 많이 점유하는 pod의 설정을 점검해 보시길 제안드립니다. 예를 들어 pod spec의 limit 설정으로 과도한 CPU자원 점유을 막을 수 있습니다.", Status: domain.SystemNotificationRuleStatus_PENDING, @@ -218,7 +218,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "스택 (<>)의 노드(<>)의 Memory 사용량이 3분동안 80% 를 넘어서고 있습니다. (현재 사용률 <>)", + MessageTitle: "스택 (<>)의 노드(<>)의 Memory 사용량이 3분동안 80% 를 넘어서고 있습니다. (현재 사용률 {{$value}})", MessageContent: "워커 노드의 Memory 사용량이 80%를 넘었습니다. 일시적인 서비스 증가 및 SW 오류등 다양한 원인으로 발생할 수 있습니다.", MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행되는 pod중 Memory 사용량이 높은 pod들에 대한 점검을 제안드립니다.", Status: domain.SystemNotificationRuleStatus_PENDING, @@ -293,7 +293,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "스택 (<>)의 파드(<>)가 30분 동안 5회 이상 재기동 (<> 회)", + MessageTitle: "스택 (<>)의 파드(<>)가 30분 동안 5회 이상 재기동 ({{$value}} 회)", MessageContent: "특정 Pod가 빈번하게 재기동 되고 있습니다. 점검이 필요합니다. (<> 스택, <> 파드)", MessageActionProposal: "pod spec. 에 대한 점검이 필요합니다. pod의 log 및 status를 확인해 주세요.", Status: domain.SystemNotificationRuleStatus_PENDING, diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index d7f575fa..851fdb95 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -7,7 +7,7 @@ import ( const SN_TYPE_NODE_CPU_HIGH_LOAD = "node-cpu-high-load" const SN_TYPE_NODE_MEMORY_HIGH_UTILIZATION = "node-memory-high-utilization" const SN_TYPE_NODE_DISK_FULL = "node-disk-full" -const SN_TYPE_PVC_FULL = "pvc_full" +const SN_TYPE_PVC_FULL = "pvc-full" const SN_TYPE_POD_RESTART_FREQUENTLY = "pod-restart-frequently" type SystemNotificationTemplateResponse struct { diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index 27e7b678..e0feb969 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -57,15 +57,15 @@ insert into project_roles ( id, name, description, created_at, updated_at ) valu ## SystemNotificationTemplates insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('d42d716f-dd2e-429b-897d-b602f6382790', 'node-cpu-high-load', 'node-cpu-high-load', true, '(avg by (taco_cluster, instance) (rate(node_cpu_seconds_total{mode="idle"}[60s]))) < 0', null, null, now(), now() ); +values ('d42d716f-dd2e-429b-897d-b602f6382790', 'node-cpu-high-load', 'node-cpu-high-load', true, '(avg by (taco_cluster, instance) (rate(node_cpu_seconds_total{mode="idle"}[60s])))', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', true, 'node-memory-high-utilization', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes) < 0.2', null, null, now(), now() ); +values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', true, 'node-memory-high-utilization', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-full', true, 'predict_linear(node_filesystem_free_bytes{mountpoint="/"}[6h], 24*3600) < 0', null, null, now(), now() ); +values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-full', true, 'predict_linear(node_filesystem_free_bytes{mountpoint="/"}[6h], 24*3600)', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'predict_linear(kubelet_volume_stats_available_bytes[6h], 24*3600) < 0', null, null, now(), now() ); +values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'predict_linear(kubelet_volume_stats_available_bytes[6h], 24*3600)', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', true, 'pod-restart-frequently', 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:]) > 2', null, null, now(), now() ); +values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', true, 'pod-restart-frequently', 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:])', null, null, now(), now() ); ## SystemNotificationTemplates -> SystemNotificationMetricParameters insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) @@ -89,4 +89,4 @@ values ( 0, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'STACK', '$labels.taco_clust insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) values ( 1, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'POD', '$labels.pod', now(), now() ); insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) -values ( 3, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'NAMESPACE', '$labels.namespace', now(), now() ); +values ( 2, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'NAMESPACE', '$labels.namespace', now(), now() ); From 2cb3156f59848bc188481ca676d8860251bd2765 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 4 Apr 2024 18:14:06 +0900 Subject: [PATCH 233/502] =?UTF-8?q?Admin=5FGetPolicyTemplateVersion=20api?= =?UTF-8?q?=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy-template.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index e396827b..0fff93fb 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -457,12 +457,6 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateDeploy(w http.ResponseWri // @Security JWT func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateVersion(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), - "C_INVALID_ORGANIZATION_ID", "")) - return - } policyTemplateId, ok := vars["policyTemplateId"] if !ok { @@ -482,7 +476,7 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateVersion(w http.ResponseWr return } - policyTemplate, err := h.usecase.GetPolicyTemplateVersion(r.Context(), &organizationId, id, version) + policyTemplate, err := h.usecase.GetPolicyTemplateVersion(r.Context(), nil, id, version) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "PT_NOT_FOUND_POLICY_TEMPLATE_VERSION", "")) From 2abebcfb2bdf13e62fe987e2519e487438a4ece3 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 4 Apr 2024 20:40:40 +0900 Subject: [PATCH 234/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=8B=9C=20=EB=8C=80=EC=83=81=20=ED=81=B4=EB=9F=AC=EC=8A=A4?= =?UTF-8?q?=ED=84=B0=20=EC=9D=B4=EB=A6=84=EB=8F=84=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy.go | 24 ++++++++++++++++++++++++ pkg/domain/policy.go | 5 +++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 3c5ade9a..b30d6fa0 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -318,6 +318,14 @@ func (h *PolicyHandler) GetPolicy(w http.ResponseWriter, r *http.Request) { log.Error(r.Context(), err) } + out.Policy.TargetClusters = make([]domain.SimpleClusterResponse, len(policy.TargetClusters)) + + for i, targetCluster := range policy.TargetClusters { + if err = serializer.Map(r.Context(), targetCluster, &out.Policy.TargetClusters[i]); err != nil { + log.Error(r.Context(), err) + } + } + ResponseJSON(w, r, http.StatusOK, out) } @@ -363,6 +371,14 @@ func (h *PolicyHandler) ListPolicy(w http.ResponseWriter, r *http.Request) { log.Info(r.Context(), err) continue } + + out.Policies[i].TargetClusters = make([]domain.SimpleClusterResponse, len(policy.TargetClusters)) + + for j, targetCluster := range policy.TargetClusters { + if err = serializer.Map(r.Context(), targetCluster, &out.Policies[i].TargetClusters[j]); err != nil { + log.Error(r.Context(), err) + } + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { @@ -793,6 +809,14 @@ func (h *PolicyHandler) GetPolicyEdit(w http.ResponseWriter, r *http.Request) { log.Error(r.Context(), err) } + out.Policy.TargetClusters = make([]domain.SimpleClusterResponse, len(policy.TargetClusters)) + + for i, targetCluster := range policy.TargetClusters { + if err = serializer.Map(r.Context(), targetCluster, &out.Policy.TargetClusters[i]); err != nil { + log.Error(r.Context(), err) + } + } + parameterSchema := policy.PolicyTemplate.ParametersSchema parameters := policy.Parameters diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index ebf6dff0..f7687a0b 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -33,8 +33,9 @@ type PolicyResponse struct { CreatedAt time.Time `json:"createdAt" format:"date-time"` UpdatedAt time.Time `json:"updatedAt" format:"date-time"` - TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` - Mandatory bool `json:"mandatory"` + // TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` + TargetClusters []SimpleClusterResponse `json:"targetClusters"` + Mandatory bool `json:"mandatory"` PolicyName string `json:"policyName" example:"label 정책"` PolicyResourceName string `json:"policyResourceName,omitempty" example:"labelpolicy"` From 1c3e502e54243c49d4821fc67ab6bed2b3d6bc1e Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 5 Apr 2024 01:52:57 +0900 Subject: [PATCH 235/502] =?UTF-8?q?GetPolicyStatistics=20API=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 40 ++++++++++++++ internal/delivery/http/policy.go | 37 +++++++++++++ internal/model/policy.go | 5 ++ internal/repository/policy-template.go | 44 +++++++++++++++ internal/repository/policy.go | 15 ++++++ internal/route/route.go | 1 + internal/usecase/policy.go | 54 +++++++++++++++++++ pkg/domain/policy.go | 22 +++++++- 9 files changed, 217 insertions(+), 2 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2fef58a9..6dcaa81c 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -242,6 +242,7 @@ const ( // Policy GetMandatoryPolicies SetMandatoryPolicies + GetPolicyStatistics ListPolicy CreatePolicy DeletePolicy diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index fc3e3c83..36a25417 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -51,6 +51,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "DeleteUser", Group: "User", }, + UpdateUsers: { + Name: "UpdateUsers", + Group: "User", + }, UpdateUser: { Name: "UpdateUser", Group: "User", @@ -615,6 +619,18 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "IsRoleNameExisted", Group: "Role", }, + AppendUsersToRole: { + Name: "AppendUsersToRole", + Group: "Role", + }, + GetUsersInRoleId: { + Name: "GetUsersInRoleId", + Group: "Role", + }, + RemoveUsersFromRole: { + Name: "RemoveUsersFromRole", + Group: "Role", + }, GetPermissionTemplates: { Name: "GetPermissionTemplates", Group: "Permission", @@ -727,6 +743,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "SetMandatoryPolicies", Group: "Policy", }, + GetPolicyStatistics: { + Name: "GetPolicyStatistics", + Group: "Policy", + }, ListPolicy: { Name: "ListPolicy", Group: "Policy", @@ -862,6 +882,8 @@ func (e Endpoint) String() string { return "GetUser" case DeleteUser: return "DeleteUser" + case UpdateUsers: + return "UpdateUsers" case UpdateUser: return "UpdateUser" case ResetPassword: @@ -1144,6 +1166,12 @@ func (e Endpoint) String() string { return "UpdatePermissionsByRoleId" case IsRoleNameExisted: return "IsRoleNameExisted" + case AppendUsersToRole: + return "AppendUsersToRole" + case GetUsersInRoleId: + return "GetUsersInRoleId" + case RemoveUsersFromRole: + return "RemoveUsersFromRole" case GetPermissionTemplates: return "GetPermissionTemplates" case Admin_CreateUser: @@ -1200,6 +1228,8 @@ func (e Endpoint) String() string { return "GetMandatoryPolicies" case SetMandatoryPolicies: return "SetMandatoryPolicies" + case GetPolicyStatistics: + return "GetPolicyStatistics" case ListPolicy: return "ListPolicy" case CreatePolicy: @@ -1284,6 +1314,8 @@ func GetEndpoint(name string) Endpoint { return GetUser case "DeleteUser": return DeleteUser + case "UpdateUsers": + return UpdateUsers case "UpdateUser": return UpdateUser case "ResetPassword": @@ -1566,6 +1598,12 @@ func GetEndpoint(name string) Endpoint { return UpdatePermissionsByRoleId case "IsRoleNameExisted": return IsRoleNameExisted + case "AppendUsersToRole": + return AppendUsersToRole + case "GetUsersInRoleId": + return GetUsersInRoleId + case "RemoveUsersFromRole": + return RemoveUsersFromRole case "GetPermissionTemplates": return GetPermissionTemplates case "Admin_CreateUser": @@ -1622,6 +1660,8 @@ func GetEndpoint(name string) Endpoint { return GetMandatoryPolicies case "SetMandatoryPolicies": return SetMandatoryPolicies + case "GetPolicyStatistics": + return GetPolicyStatistics case "ListPolicy": return ListPolicy case "CreatePolicy": diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index b30d6fa0..def185b6 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -36,6 +36,7 @@ type IPolicyHandler interface { GetClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) GetPolicyEdit(w http.ResponseWriter, r *http.Request) + GetPolicyStatistics(w http.ResponseWriter, r *http.Request) } func NewPolicyHandler(u usecase.Usecase) IPolicyHandler { @@ -829,3 +830,39 @@ func (h *PolicyHandler) GetPolicyEdit(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } + +// GetPolicyStatistics godoc +// +// @Tags Policy +// @Summary [GetPolicyStatistics] 정책 템플릿, 정책 통계 조회 +// @Description 템플릿, 정책의 통계를 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Success 200 {object} domain.PolicyStatisticsResponse +// @Router /organizations/{organizationId}/policy-statistics [get] +// @Security JWT +func (h *PolicyHandler) GetPolicyStatistics(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + out, err := h.usecase.GetPolicyStatistics(r.Context(), organizationId) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/model/policy.go b/internal/model/policy.go index d86a9045..574d31bc 100644 --- a/internal/model/policy.go +++ b/internal/model/policy.go @@ -83,3 +83,8 @@ type UsageCount struct { OrganizationName string UsageCount int } + +type PolicyCount struct { + EnforcementAction string + Count int64 +} diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index cc320189..f472a1cf 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -34,6 +34,8 @@ type IPolicyTemplateRepository interface { DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) GetLatestTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID) (version string, err error) + CountTksTemplateByOrganization(ctx context.Context, organizationId string) (count int64, err error) + CountOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) } type PolicyTemplateRepository struct { @@ -160,6 +162,48 @@ func (r *PolicyTemplateRepository) FetchForOrganization(ctx context.Context, org return policyTemplates, nil } +func (r *PolicyTemplateRepository) CountTksTemplateByOrganization(ctx context.Context, organizationId string) (count int64, err error) { + subQueryAloowedAll := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id") + subQueryMatchId := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id"). + Where("organization_id = ?", organizationId) + + err = r.db.WithContext(ctx). + Model(&model.PolicyTemplate{}). + Where( + // tks 템플릿인 경우 + r.db.Where("type = ?", "tks"). + Where( + // permitted_organizations이 비어있거나 + r.db.Where("id not in (?)", subQueryAloowedAll). + Or("id in (?)", subQueryMatchId), + // permitted_organization에 매칭되는 템플릿 아이디가 있거나 + ), + ).Count(&count).Error + + return +} + +func (r *PolicyTemplateRepository) CountOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) { + subQueryAloowedAll := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id") + subQueryMatchId := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id"). + Where("organization_id = ?", organizationId) + + err = r.db.WithContext(ctx). + Model(&model.PolicyTemplate{}). + Where( + // tks 템플릿인 경우 + r.db.Where("type = ?", "tks"). + Where( + // permitted_organizations이 비어있거나 + r.db.Where("id not in (?)", subQueryAloowedAll). + Or("id in (?)", subQueryMatchId), + // permitted_organization에 매칭되는 템플릿 아이디가 있거나 + ), + ).Count(&count).Error + + return +} + func (r *PolicyTemplateRepository) ExistsBy(ctx context.Context, key string, value interface{}) (exists bool, err error) { query := fmt.Sprintf("%s = ?", key) diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 522727e4..96cc6186 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -30,6 +30,7 @@ type IPolicyRepository interface { UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusters []model.Cluster) (err error) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) GetUsageCountByTemplateId(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (usageCounts []model.UsageCount, err error) + CountPolicyByEnforcementAction(ctx context.Context, organizationId string) (policyCount []model.PolicyCount, err error) } type PolicyRepository struct { @@ -281,3 +282,17 @@ func (r *PolicyRepository) GetUsageCountByTemplateId(ctx context.Context, organi return } + +func (r *PolicyRepository) CountPolicyByEnforcementAction(ctx context.Context, organizationId string) (policyCount []model.PolicyCount, err error) { + + err = r.db.WithContext(ctx).Model(&model.Policy{}). + Select("enforcement_action", "count(enforcement_action) as count"). + Where("organization_id = ?", organizationId). + Group("enforcement_action").Scan(&policyCount).Error + + if err != nil { + return nil, err + } + + return +} diff --git a/internal/route/route.go b/internal/route/route.go index db460a75..c1036726 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -337,6 +337,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa policyHandler := delivery.NewPolicyHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/mandatory-policies", customMiddleware.Handle(internalApi.GetMandatoryPolicies, http.HandlerFunc(policyHandler.GetMandatoryPolicies))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/mandatory-policies", customMiddleware.Handle(internalApi.SetMandatoryPolicies, http.HandlerFunc(policyHandler.SetMandatoryPolicies))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-statistics", customMiddleware.Handle(internalApi.GetPolicyStatistics, http.HandlerFunc(policyHandler.GetPolicyStatistics))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies", customMiddleware.Handle(internalApi.ListPolicy, http.HandlerFunc(policyHandler.ListPolicy))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies", customMiddleware.Handle(internalApi.CreatePolicy, http.HandlerFunc(policyHandler.CreatePolicy))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}/clusters", customMiddleware.Handle(internalApi.UpdatePolicyTargetClusters, http.HandlerFunc(policyHandler.UpdatePolicyTargetClusters))).Methods(http.MethodPatch) diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 3a2bbf9c..12d56d69 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -38,6 +38,7 @@ type IPolicyUsecase interface { GetClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID) (clusterPolicyTemplateStatusResponse *domain.GetClusterPolicyTemplateStatusResponse, err error) UpdateClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID, currentVersion string, targetVerson string) (err error) + GetPolicyStatistics(ctx context.Context, organizationId string) (response *domain.PolicyStatisticsResponse, err error) } type PolicyUsecase struct { @@ -629,6 +630,59 @@ func (u *PolicyUsecase) GetClusterPolicyTemplateStatus(ctx context.Context, clus return &result, nil } +func (u *PolicyUsecase) GetPolicyStatistics(ctx context.Context, organizationId string) (response *domain.PolicyStatisticsResponse, err error) { + result := domain.PolicyStatisticsResponse{} + + orgTemplateCount, err := u.templateRepo.CountOrganizationTemplate(ctx, organizationId) + if err != nil { + return nil, err + } + + tksTemplateCount, err := u.templateRepo.CountTksTemplateByOrganization(ctx, organizationId) + if err != nil { + return nil, err + } + + policyStatistics, err := u.repo.CountPolicyByEnforcementAction(ctx, organizationId) + if err != nil { + return nil, err + } + + var policyTotal int64 + var deny int64 + var dryrun int64 + var warn int64 + + for _, stat := range policyStatistics { + switch stat.EnforcementAction { + case "deny": + deny = stat.Count + policyTotal += deny + case "dryrun": + dryrun = stat.Count + policyTotal += dryrun + case "warn": + warn = stat.Count + policyTotal += warn + } + } + + result.Template = domain.TemplateCount{ + TksTemplate: tksTemplateCount, + OrganizationTemplate: orgTemplateCount, + Total: tksTemplateCount + orgTemplateCount, + } + + result.Policy = domain.PolicyCount{ + Deny: deny, + Warn: warn, + Dryrun: dryrun, + Total: policyTotal, + } + + return &result, nil +} + func extractNewTemplateParameter(paramdefs []*domain.ParameterDef, newParamDefs []*domain.ParameterDef) (policyParameters []domain.UpdatedPolicyTemplateParameter, err error) { diffParamDef, err := policytemplate.GetNewParamDefs(paramdefs, newParamDefs) diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index f7687a0b..88b18343 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -183,7 +183,25 @@ type PolicyUpdate struct { } type UpdateClusterPolicyTemplateStatusRequest struct { - TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` - TemplateTargetVerson string `json:"templateTargetVerson" example:"v1.0.3"` + TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` + TemplateTargetVerson string `json:"templateTargetVerson" example:"v1.0.3"` // PolicyUpdate []PolicyUpdate `json:"policyUpdate"` } + +type TemplateCount struct { + TksTemplate int64 `json:"tksTemplate"` + OrganizationTemplate int64 `json:"organizationTemplate"` + Total int64 `json:"total"` +} + +type PolicyCount struct { + Deny int64 `json:"deny"` + Warn int64 `json:"warn"` + Dryrun int64 `json:"dryrun"` + Total int64 `json:"total"` +} + +type PolicyStatisticsResponse struct { + Template TemplateCount `json:"templateCount"` + Policy PolicyCount `json:"policyCount"` +} From 7e664ba0664eb734b7a1c8e5a2df0bc8761c6797 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 5 Apr 2024 10:27:31 +0900 Subject: [PATCH 236/502] bugfix. Fix internal k8s API call with admin token --- internal/usecase/project.go | 8 ++++---- internal/usecase/stack.go | 2 +- pkg/kubernetes/kubernetes.go | 18 ++++++++++++++++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 51b0b524..d0dc5ebb 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -531,7 +531,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o return nil } func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -564,7 +564,7 @@ func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizat return nil } func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -622,7 +622,7 @@ func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organiza return nil } func (u *ProjectUsecase) CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to create project namespace.") @@ -724,7 +724,7 @@ func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationI kubeconfigs := make([]string, 0) for _, pn := range projectNamespaces { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, pn.StackId) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, pn.StackId, kubernetes.KubeconfigForUser) if err != nil { log.Error(ctx, err) return "", errors.Wrap(err, "Failed to retrieve kubeconfig.") diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 7c9bd129..1921aaab 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -482,7 +482,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) } func (u *StackUsecase) GetKubeConfig(ctx context.Context, stackId domain.StackId) (kubeConfig string, err error) { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId.String()) + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId.String(), kubernetes.KubeconfigForUser) //kubeconfig, err := kubernetes.GetKubeConfig("cmsai5k5l") if err != nil { return "", err diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index 00555cad..d8238850 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + v1 "k8s.io/api/core/v1" "os" "strings" @@ -24,6 +25,13 @@ import ( "github.com/openinfradev/tks-api/pkg/log" ) +type KubeConfigType string + +const ( + KubeconfigForAdmin KubeConfigType = "admin" + KubeconfigForUser KubeConfigType = "user" +) + func getAdminConfig(ctx context.Context) (*rest.Config, error) { kubeconfigPath := viper.GetString("kubeconfig-path") if kubeconfigPath == "" { @@ -115,13 +123,19 @@ func GetAwsAccountIdSecret(ctx context.Context) (awsAccountId string, err error) return } -func GetKubeConfig(ctx context.Context, clusterId string) ([]byte, error) { +func GetKubeConfig(ctx context.Context, clusterId string, configType KubeConfigType) ([]byte, error) { clientset, err := GetClientAdminCluster(ctx) if err != nil { return nil, err } - secrets, err := clientset.CoreV1().Secrets(clusterId).Get(context.TODO(), clusterId+"-tks-user-kubeconfig", metav1.GetOptions{}) + var secrets *v1.Secret + + if configType == KubeconfigForAdmin { + secrets, err = clientset.CoreV1().Secrets(clusterId).Get(context.TODO(), clusterId+"-tks-kubeconfig", metav1.GetOptions{}) + } else if configType == KubeconfigForUser { + secrets, err = clientset.CoreV1().Secrets(clusterId).Get(context.TODO(), clusterId+"-tks-user-kubeconfig", metav1.GetOptions{}) + } if err != nil { log.Error(ctx, err) return nil, err From ae013acded71770716513ea6f2de860e65762187 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 5 Apr 2024 10:31:24 +0900 Subject: [PATCH 237/502] trivial. add api for making default systemNotificationRules --- api/swagger/docs.go | 241 +++++++++++++++++- api/swagger/swagger.json | 241 +++++++++++++++++- api/swagger/swagger.yaml | 158 +++++++++++- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 40 +++ .../delivery/http/system-notification-rule.go | 40 ++- .../repository/system-notification-rule.go | 15 ++ internal/route/route.go | 1 + internal/usecase/system-notification-rule.go | 7 +- 9 files changed, 712 insertions(+), 32 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 71b72122..ae842179 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1023,6 +1023,59 @@ const docTemplate = `{ } } }, + "/admin/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿 파라미터를 기존 버전의 수정불가능한 파라미터를 포함해서 추출한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_ExtractParameters] 정책 템플릿 파라미터 추출", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersResponse" + } + } + } + } + }, "/admin/stack-templates": { "get": { "security": [ @@ -4800,6 +4853,66 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿 파라미터를 기존 버전의 수정불가능한 파라미터를 포함해서 추출한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ExtractParameters] 정책 템플릿 파라미터 추출", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExtractParametersRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExtractParametersResponse" + } + } + } + } + }, "/organizations/{organizationId}/primary-cluster": { "patch": { "security": [ @@ -8104,6 +8217,40 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/system-notification-rules/default-system-rules": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "MakeDefaultSystemNotificationRules", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationRules" + ], + "summary": "MakeDefaultSystemNotificationRules", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/system-notification-rules/name/{name}/existence": { "get": { "security": [ @@ -11265,7 +11412,15 @@ const docTemplate = `{ "type": "string" }, "stack": { - "type": "string" + "type": "object", + "properties": { + "abnormal": { + "type": "string" + }, + "normal": { + "type": "string" + } + } }, "storage": { "type": "string" @@ -11373,6 +11528,41 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ExtractParametersRequest": { + "type": "object", + "required": [ + "rego" + ], + "properties": { + "libs": { + "type": "array", + "items": { + "type": "string" + } + }, + "rego": { + "type": "string", + "example": "Rego 코드" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ExtractParametersResponse": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError" + } + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -12631,6 +12821,9 @@ const docTemplate = `{ "isArray": { "type": "boolean" }, + "isNew": { + "type": "boolean" + }, "key": { "type": "string" }, @@ -12745,15 +12938,12 @@ const docTemplate = `{ "type": "string", "example": "labelpolicy" }, - "targetClusterIds": { + "targetClusters": { + "description": "TargetClusterIds []string ` + "`" + `json:\"targetClusterIds\" example:\"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90\"` + "`" + `", "type": "array", "items": { - "type": "string" - }, - "example": [ - "83bf8081-f0c5-4b31-826d-23f6f366ec90", - "83bf8081-f0c5-4b31-826d-23f6f366ec90" - ] + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" + } }, "templateId": { "type": "string", @@ -14913,6 +15103,41 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersRequest": { + "type": "object", + "required": [ + "rego" + ], + "properties": { + "libs": { + "type": "array", + "items": { + "type": "string" + } + }, + "rego": { + "type": "string", + "example": "Rego 코드" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersResponse": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError" + } + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 89f6e889..5d59d3ef 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1017,6 +1017,59 @@ } } }, + "/admin/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿 파라미터를 기존 버전의 수정불가능한 파라미터를 포함해서 추출한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_ExtractParameters] 정책 템플릿 파라미터 추출", + "parameters": [ + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersResponse" + } + } + } + } + }, "/admin/stack-templates": { "get": { "security": [ @@ -4794,6 +4847,66 @@ } } }, + "/organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "정책 템플릿 파라미터를 기존 버전의 수정불가능한 파라미터를 포함해서 추출한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[ExtractParameters] 정책 템플릿 파라미터 추출", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "버전(v0.0.0 형식)", + "name": "version", + "in": "path", + "required": true + }, + { + "description": "Rego 코드", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExtractParametersRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExtractParametersResponse" + } + } + } + } + }, "/organizations/{organizationId}/primary-cluster": { "patch": { "security": [ @@ -8098,6 +8211,40 @@ } } }, + "/organizations/{organizationId}/system-notification-rules/default-system-rules": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "MakeDefaultSystemNotificationRules", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationRules" + ], + "summary": "MakeDefaultSystemNotificationRules", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/system-notification-rules/name/{name}/existence": { "get": { "security": [ @@ -11259,7 +11406,15 @@ "type": "string" }, "stack": { - "type": "string" + "type": "object", + "properties": { + "abnormal": { + "type": "string" + }, + "normal": { + "type": "string" + } + } }, "storage": { "type": "string" @@ -11367,6 +11522,41 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ExtractParametersRequest": { + "type": "object", + "required": [ + "rego" + ], + "properties": { + "libs": { + "type": "array", + "items": { + "type": "string" + } + }, + "rego": { + "type": "string", + "example": "Rego 코드" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ExtractParametersResponse": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError" + } + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.FilterResponse": { "type": "object", "properties": { @@ -12625,6 +12815,9 @@ "isArray": { "type": "boolean" }, + "isNew": { + "type": "boolean" + }, "key": { "type": "string" }, @@ -12739,15 +12932,12 @@ "type": "string", "example": "labelpolicy" }, - "targetClusterIds": { + "targetClusters": { + "description": "TargetClusterIds []string `json:\"targetClusterIds\" example:\"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90\"`", "type": "array", "items": { - "type": "string" - }, - "example": [ - "83bf8081-f0c5-4b31-826d-23f6f366ec90", - "83bf8081-f0c5-4b31-826d-23f6f366ec90" - ] + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" + } }, "templateId": { "type": "string", @@ -14907,6 +15097,41 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersRequest": { + "type": "object", + "required": [ + "rego" + ], + "properties": { + "libs": { + "type": "array", + "items": { + "type": "string" + } + }, + "rego": { + "type": "string", + "example": "Rego 코드" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersResponse": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError" + } + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ec528918..04af21fa 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1394,7 +1394,12 @@ definitions: memory: type: string stack: - type: string + properties: + abnormal: + type: string + normal: + type: string + type: object storage: type: string type: object @@ -1465,6 +1470,29 @@ definitions: existed: type: boolean type: object + github_com_openinfradev_tks-api_pkg_domain.ExtractParametersRequest: + properties: + libs: + items: + type: string + type: array + rego: + example: Rego 코드 + type: string + required: + - rego + type: object + github_com_openinfradev_tks-api_pkg_domain.ExtractParametersResponse: + properties: + errors: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError' + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.FilterResponse: properties: column: @@ -2285,6 +2313,8 @@ definitions: type: string isArray: type: boolean + isNew: + type: boolean key: type: string type: @@ -2362,12 +2392,11 @@ definitions: policyResourceName: example: labelpolicy type: string - targetClusterIds: - example: - - 83bf8081-f0c5-4b31-826d-23f6f366ec90 - - 83bf8081-f0c5-4b31-826d-23f6f366ec90 + targetClusters: + description: TargetClusterIds []string `json:"targetClusterIds" + example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` items: - type: string + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse' type: array templateId: example: d98ef5f1-4a68-4047-a446-2207787ce3ff @@ -3816,6 +3845,29 @@ definitions: existed: type: boolean type: object + github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersRequest: + properties: + libs: + items: + type: string + type: array + rego: + example: Rego 코드 + type: string + required: + - rego + type: object + github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersResponse: + properties: + errors: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.RegoCompieError' + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain_admin.GetPolicyTemplateDeployResponse: properties: deployVersion: @@ -4568,6 +4620,40 @@ paths: summary: '[Admin_GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' tags: - PolicyTemplate + /admin/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters: + post: + consumes: + - application/json + description: 정책 템플릿 파라미터를 기존 버전의 수정불가능한 파라미터를 포함해서 추출한다. + parameters: + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: 버전(v0.0.0 형식) + in: path + name: version + required: true + type: string + - description: Rego 코드 + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExtractParametersResponse' + security: + - JWT: [] + summary: '[Admin_ExtractParameters] 정책 템플릿 파라미터 추출' + tags: + - PolicyTemplate /admin/policy-templates/kind/{policyTemplateKind}/existence: get: consumes: @@ -6945,6 +7031,45 @@ paths: summary: '[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' tags: - PolicyTemplate + /organizations/{organizationId}/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters: + post: + consumes: + - application/json + description: 정책 템플릿 파라미터를 기존 버전의 수정불가능한 파라미터를 포함해서 추출한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: 버전(v0.0.0 형식) + in: path + name: version + required: true + type: string + - description: Rego 코드 + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExtractParametersRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExtractParametersResponse' + security: + - JWT: [] + summary: '[ExtractParameters] 정책 템플릿 파라미터 추출' + tags: + - PolicyTemplate /organizations/{organizationId}/policy-templates/kind/{policyTemplateKind}/existence: get: consumes: @@ -9215,6 +9340,27 @@ paths: summary: Update SystemNotificationRule tags: - SystemNotificationRules + /organizations/{organizationId}/system-notification-rules/default-system-rules: + post: + consumes: + - application/json + description: MakeDefaultSystemNotificationRules + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: MakeDefaultSystemNotificationRules + tags: + - SystemNotificationRules /organizations/{organizationId}/system-notification-rules/name/{name}/existence: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2fef58a9..f0b9c8b2 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -136,6 +136,7 @@ const ( CheckSystemNotificationRuleName DeleteSystemNotificationRule UpdateSystemNotificationRule + MakeDefaultSystemNotificationRules // SystemNotification CreateSystemNotification diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index fc3e3c83..450fb21b 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -51,6 +51,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "DeleteUser", Group: "User", }, + UpdateUsers: { + Name: "UpdateUsers", + Group: "User", + }, UpdateUser: { Name: "UpdateUser", Group: "User", @@ -411,6 +415,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdateSystemNotificationRule", Group: "SystemNotificationRule", }, + MakeDefaultSystemNotificationRules: { + Name: "MakeDefaultSystemNotificationRules", + Group: "SystemNotificationRule", + }, CreateSystemNotification: { Name: "CreateSystemNotification", Group: "SystemNotification", @@ -615,6 +623,18 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "IsRoleNameExisted", Group: "Role", }, + AppendUsersToRole: { + Name: "AppendUsersToRole", + Group: "Role", + }, + GetUsersInRoleId: { + Name: "GetUsersInRoleId", + Group: "Role", + }, + RemoveUsersFromRole: { + Name: "RemoveUsersFromRole", + Group: "Role", + }, GetPermissionTemplates: { Name: "GetPermissionTemplates", Group: "Permission", @@ -862,6 +882,8 @@ func (e Endpoint) String() string { return "GetUser" case DeleteUser: return "DeleteUser" + case UpdateUsers: + return "UpdateUsers" case UpdateUser: return "UpdateUser" case ResetPassword: @@ -1042,6 +1064,8 @@ func (e Endpoint) String() string { return "DeleteSystemNotificationRule" case UpdateSystemNotificationRule: return "UpdateSystemNotificationRule" + case MakeDefaultSystemNotificationRules: + return "MakeDefaultSystemNotificationRules" case CreateSystemNotification: return "CreateSystemNotification" case GetSystemNotifications: @@ -1144,6 +1168,12 @@ func (e Endpoint) String() string { return "UpdatePermissionsByRoleId" case IsRoleNameExisted: return "IsRoleNameExisted" + case AppendUsersToRole: + return "AppendUsersToRole" + case GetUsersInRoleId: + return "GetUsersInRoleId" + case RemoveUsersFromRole: + return "RemoveUsersFromRole" case GetPermissionTemplates: return "GetPermissionTemplates" case Admin_CreateUser: @@ -1284,6 +1314,8 @@ func GetEndpoint(name string) Endpoint { return GetUser case "DeleteUser": return DeleteUser + case "UpdateUsers": + return UpdateUsers case "UpdateUser": return UpdateUser case "ResetPassword": @@ -1464,6 +1496,8 @@ func GetEndpoint(name string) Endpoint { return DeleteSystemNotificationRule case "UpdateSystemNotificationRule": return UpdateSystemNotificationRule + case "MakeDefaultSystemNotificationRules": + return MakeDefaultSystemNotificationRules case "CreateSystemNotification": return CreateSystemNotification case "GetSystemNotifications": @@ -1566,6 +1600,12 @@ func GetEndpoint(name string) Endpoint { return UpdatePermissionsByRoleId case "IsRoleNameExisted": return IsRoleNameExisted + case "AppendUsersToRole": + return AppendUsersToRole + case "GetUsersInRoleId": + return GetUsersInRoleId + case "RemoveUsersFromRole": + return RemoveUsersFromRole case "GetPermissionTemplates": return GetPermissionTemplates case "Admin_CreateUser": diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index c87e22dc..c143c9d7 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -302,16 +302,42 @@ func (h *SystemNotificationRuleHandler) CheckSystemNotificationRuleName(w http.R } // [TEST] - /* - err = h.usecase.MakeDefaultSystemNotificationRules(r.Context(), "oolw6roj6", nil) - if err != nil { - ErrorJSON(w, r, err) - return - } - */ + err = h.usecase.MakeDefaultSystemNotificationRules(r.Context(), "oolw6roj6", nil) + if err != nil { + ErrorJSON(w, r, err) + return + } var out domain.CheckSystemNotificationRuleNameResponse out.Existed = exist ResponseJSON(w, r, http.StatusOK, out) } + +// MakeDefaultSystemNotificationRules godoc +// +// @Tags SystemNotificationRules +// @Summary MakeDefaultSystemNotificationRules +// @Description MakeDefaultSystemNotificationRules +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/system-notification-rules/default-system-rules [POST] +// @Security JWT +func (h *SystemNotificationRuleHandler) MakeDefaultSystemNotificationRules(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + err := h.usecase.MakeDefaultSystemNotificationRules(r.Context(), organizationId, nil) + if err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 7d92f850..ce29f0d3 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -9,6 +9,7 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/domain" ) // Interfaces @@ -20,6 +21,7 @@ type ISystemNotificationRuleRepository interface { Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRuleId uuid.UUID, err error) Creates(ctx context.Context, dto []model.SystemNotificationRule) (err error) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) + UpdateStatus(ctx context.Context, systemNotificationRuleId uuid.UUID, status domain.SystemNotificationRuleStatus) (err error) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) } @@ -132,3 +134,16 @@ func (r *SystemNotificationRuleRepository) Delete(ctx context.Context, dto model } return nil } + +func (r *SystemNotificationRuleRepository) UpdateStatus(ctx context.Context, systemNotificationRuleId uuid.UUID, status domain.SystemNotificationRuleStatus) error { + res := r.db.WithContext(ctx).Model(&model.SystemNotificationRule{}). + Where("id = ?", systemNotificationRuleId). + Updates(map[string]interface{}{ + "Status": status, + }) + if res.Error != nil { + return res.Error + } + + return nil +} diff --git a/internal/route/route.go b/internal/route/route.go index db460a75..d3958026 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -232,6 +232,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa systemNotificationRuleHandler := delivery.NewSystemNotificationRuleHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/default-system-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.MakeDefaultSystemNotificationRules))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/name/{name}/existence", customMiddleware.Handle(internalApi.CheckSystemNotificationRuleName, http.HandlerFunc(systemNotificationRuleHandler.CheckSystemNotificationRuleName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 33ffaf0d..5631e33e 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -75,8 +75,6 @@ func (u *SystemNotificationRuleUsecase) Create(ctx context.Context, dto model.Sy return uuid.Nil, err } - // [TODO] update kubernetes resources - return } @@ -103,7 +101,10 @@ func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.Sy return err } - // [TODO] update kubernetes resources + // update status for appling kubernetes + if err = u.repo.UpdateStatus(ctx, dto.ID, domain.SystemNotificationRuleStatus_PENDING); err != nil { + return err + } return nil } From 016d1ed6d2b27794be49d41a4d5a2e342c278ea7 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 5 Apr 2024 11:25:05 +0900 Subject: [PATCH 238/502] feature. change scheme for systemNotification --- internal/model/system-notification.go | 11 ++++---- internal/repository/system-notification.go | 31 +++++++++++----------- internal/usecase/system-notification.go | 23 ++++++++-------- pkg/domain/system-notification.go | 9 +++---- 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go index 3c5678cc..bd380cb6 100644 --- a/internal/model/system-notification.go +++ b/internal/model/system-notification.go @@ -14,17 +14,16 @@ type SystemNotification struct { gorm.Model ID uuid.UUID `gorm:"primarykey"` + Name string OrganizationId string Organization Organization `gorm:"foreignKey:OrganizationId"` - Name string - Code string - Description string - Grade string - Message string ClusterId domain.ClusterId Cluster Cluster `gorm:"foreignKey:ClusterId"` + Severity string + MessageTitle string + MessageContent string + MessageActionProposal string Node string - CheckPoint string GrafanaUrl string FiredAt *time.Time `gorm:"-:all"` TakedAt *time.Time `gorm:"-:all"` diff --git a/internal/repository/system-notification.go b/internal/repository/system-notification.go index 58bb1336..2a810edd 100644 --- a/internal/repository/system-notification.go +++ b/internal/repository/system-notification.go @@ -85,20 +85,19 @@ func (r *SystemNotificationRepository) FetchPodRestart(ctx context.Context, orga func (r *SystemNotificationRepository) Create(ctx context.Context, dto model.SystemNotification) (systemNotificationId uuid.UUID, err error) { systemNotification := model.SystemNotification{ - ID: uuid.New(), - OrganizationId: dto.OrganizationId, - Name: dto.Name, - Code: dto.Code, - Message: dto.Message, - Description: dto.Description, - Grade: dto.Grade, - ClusterId: dto.ClusterId, - Node: dto.Node, - GrafanaUrl: dto.GrafanaUrl, - CheckPoint: dto.CheckPoint, - Summary: dto.Summary, - RawData: dto.RawData, - Status: domain.SystemNotificationActionStatus_CREATED, + ID: uuid.New(), + OrganizationId: dto.OrganizationId, + Name: dto.Name, + Severity: dto.Severity, + MessageTitle: dto.MessageTitle, + MessageContent: dto.MessageContent, + MessageActionProposal: dto.MessageActionProposal, + ClusterId: dto.ClusterId, + Node: dto.Node, + GrafanaUrl: dto.GrafanaUrl, + Summary: dto.Summary, + RawData: dto.RawData, + Status: domain.SystemNotificationActionStatus_CREATED, } res := r.db.WithContext(ctx).Create(&systemNotification) if res.Error != nil { @@ -110,7 +109,9 @@ func (r *SystemNotificationRepository) Create(ctx context.Context, dto model.Sys func (r *SystemNotificationRepository) Update(ctx context.Context, dto model.SystemNotification) (err error) { res := r.db.WithContext(ctx).Model(&model.SystemNotification{}). Where("id = ?", dto.ID). - Updates(map[string]interface{}{"Description": dto.Description}) + Updates(map[string]interface{}{ + "MessageTitle": dto.MessageTitle, + }) if res.Error != nil { return res.Error } diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 94738a27..a8c085b0 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -102,18 +102,17 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre } dto := model.SystemNotification{ - OrganizationId: organizationId, - Name: systemNotification.Labels.SystemNotificationName, - Code: systemNotification.Labels.SystemNotificationName, - Grade: systemNotification.Labels.Severity, - Node: node, - Message: systemNotification.Annotations.Message, - Description: systemNotification.Annotations.Description, - CheckPoint: systemNotification.Annotations.Checkpoint, - Summary: systemNotification.Annotations.Summary, - ClusterId: domain.ClusterId(clusterId), - GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, systemNotification, domain.ClusterId(clusterId)), - RawData: rawData, + OrganizationId: organizationId, + Name: systemNotification.Labels.SystemNotificationName, + Severity: systemNotification.Labels.Severity, + Node: node, + MessageTitle: systemNotification.Annotations.Message, + MessageContent: systemNotification.Annotations.Description, + MessageActionProposal: systemNotification.Annotations.Checkpoint, + Summary: systemNotification.Annotations.Summary, + ClusterId: domain.ClusterId(clusterId), + GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, systemNotification, domain.ClusterId(clusterId)), + RawData: rawData, } _, err = u.repo.Create(ctx, dto) diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 2d35b9ab..4a46ca45 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -79,11 +79,10 @@ type CreateSystemNotificationRequest struct { type SystemNotificationResponse struct { ID string `json:"id"` OrganizationId string `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - Message string `json:"message"` - Code string `json:"code"` - Grade string `json:"grade"` + Severity string `json:"grade"` + MessageTitle string `json:"messageTitle"` + MessageContent string `json:"messageContent"` + MessageActionProposal string `json:"messageActionProposal"` Cluster SimpleClusterResponse `json:"cluster"` GrafanaUrl string `json:"grafanaUrl"` Node string `json:"node"` From 100041f276a75eaa6412f609c30c78a89db69c58 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 5 Apr 2024 12:54:00 +0900 Subject: [PATCH 239/502] bugfix. fix bugs on connection to remote cluster with kubeconfig & k8s role resource name --- internal/delivery/http/project.go | 6 ++ internal/keycloak/keycloak.go | 24 +++++- internal/usecase/project.go | 120 ++++++++++++++---------------- pkg/kubernetes/kubernetes.go | 32 +++++++- 4 files changed, 110 insertions(+), 72 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index ee9dc2e8..2db13574 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1310,6 +1310,12 @@ func (p ProjectHandler) CreateProjectNamespace(w http.ResponseWriter, r *http.Re } // tasks for keycloak & k8s + // ToDo: Check if the namespace is already created + if err := p.usecase.EnsureNamespaceForCluster(r.Context(), organizationId, projectNamespaceReq.StackId, projectNamespaceReq.Namespace); err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if err := p.usecase.EnsureRequiredSetupForCluster(r.Context(), organizationId, projectId, projectNamespaceReq.StackId); err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index ffc7ad1f..9332e946 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -484,12 +484,20 @@ func (k *Keycloak) EnsureClientRoleWithClientName(ctx context.Context, organizat Name: gocloak.StringP(roleName), } - _, err = k.client.CreateClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, role) + r, err := k.client.GetClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, roleName) if err != nil { - log.Error(ctx, "Creating Client Role is failed", err) + log.Error(ctx, "Getting Client Role is failed", err) return err } + if r == nil { + _, err = k.client.CreateClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, role) + if err != nil { + log.Error(ctx, "Creating Client Role is failed", err) + return err + } + } + return nil } @@ -519,12 +527,20 @@ func (k *Keycloak) DeleteClientRoleWithClientName(ctx context.Context, organizat return nil } - err = k.client.DeleteClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, *roles[0].ID) + r, err := k.client.GetClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, roleName) if err != nil { - log.Error(ctx, "Deleting Client Role is failed", err) + log.Error(ctx, "Getting Client Role is failed", err) return err } + if r != nil { + err = k.client.DeleteClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, *roles[0].ID) + if err != nil { + log.Error(ctx, "Deleting Client Role is failed", err) + return err + } + } + return nil } diff --git a/internal/usecase/project.go b/internal/usecase/project.go index d0dc5ebb..94d00b9b 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -51,6 +51,7 @@ type IProjectUsecase interface { UpdateProjectNamespace(ctx context.Context, pn *model.ProjectNamespace) error DeleteProjectNamespace(ctx context.Context, organizationId string, projectId string, projectNamespace string, stackId string) error GetAppCount(ctx context.Context, organizationId string, projectId string, namespace string) (appCount int, err error) + EnsureNamespaceForCluster(ctx context.Context, organizationId string, stackId string, namespaceName string) error EnsureRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error MayRemoveRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error @@ -446,7 +447,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to get project namespace in database.") } var alreadySetUp bool @@ -464,24 +465,24 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga if err := u.createK8SInitialResource(ctx, organizationId, projectId, stackId); err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } if err := u.createKeycloakClientRoles(ctx, organizationId, projectId, stackId+"-k8s-api"); err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } projectMembers, err := u.GetProjectMembers(ctx, projectId, ProjectAll, nil) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } for _, pm := range projectMembers { err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } } @@ -490,8 +491,7 @@ func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, orga func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error { pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } var nsCount int for _, pn := range pns { @@ -506,26 +506,22 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o } if err := u.deleteK8SInitialResource(ctx, organizationId, projectId, stackId); err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } projectMembers, err := u.GetProjectMembers(ctx, projectId, ProjectAll, nil) if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } for _, pm := range projectMembers { err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, stackId+"-k8s-api", pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } } if err := u.deleteKeycloakClientRoles(ctx, organizationId, projectId, stackId+"-k8s-api"); err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } return nil @@ -533,32 +529,22 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to get kubeconfig.") } - pr, err := u.GetProject(ctx, organizationId, projectId) + err = kubernetes.EnsureClusterRole(ctx, kubeconfig, projectId) if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") - } - - err = kubernetes.EnsureClusterRole(ctx, kubeconfig, pr.Name) - if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } - err = kubernetes.EnsureCommonClusterRole(ctx, kubeconfig, pr.Name) + err = kubernetes.EnsureCommonClusterRole(ctx, kubeconfig, projectId) if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } - err = kubernetes.EnsureCommonClusterRoleBinding(ctx, kubeconfig, pr.Name) + err = kubernetes.EnsureCommonClusterRoleBinding(ctx, kubeconfig, projectId) if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } return nil @@ -567,42 +553,36 @@ func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizat kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to get kubeconfig.") } - pr, err := u.GetProject(ctx, organizationId, projectId) + err = kubernetes.RemoveClusterRole(ctx, kubeconfig, projectId) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to remove cluster roles.") } - err = kubernetes.RemoveClusterRole(ctx, kubeconfig, pr.Name) + err = kubernetes.RemoveCommonClusterRole(ctx, kubeconfig, projectId) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to remove common cluster roles.") } - err = kubernetes.RemoveCommonClusterRole(ctx, kubeconfig, pr.Name) + err = kubernetes.RemoveCommonClusterRoleBinding(ctx, kubeconfig, projectId) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") - } - - err = kubernetes.RemoveCommonClusterRoleBinding(ctx, kubeconfig, pr.Name) - if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to remove common cluster role bindings.") } return nil } func (u *ProjectUsecase) createKeycloakClientRoles(ctx context.Context, organizationId string, projectId string, clientId string) error { // create Roles in keycloak - for _, role := range []string{strconv.Itoa(ProjectLeader), strconv.Itoa(ProjectMember), strconv.Itoa(ProjectViewer)} { + roles := []string{"project-leader", "project-member", "project-viewer"} + for _, role := range roles { err := u.kc.EnsureClientRoleWithClientName(ctx, organizationId, clientId, role+"@"+projectId) if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to create keycloak client role.") } } @@ -616,7 +596,7 @@ func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organiza err := u.kc.DeleteClientRoleWithClientName(ctx, organizationId, clientId, role+"@"+projectId) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to delete keycloak client roles.") } } return nil @@ -625,38 +605,32 @@ func (u *ProjectUsecase) CreateK8SNSRoleBinding(ctx context.Context, organizatio kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") - } - - pr, err := u.GetProject(ctx, organizationId, projectId) - if err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to get kubeconfig.") } - err = kubernetes.EnsureRoleBinding(ctx, kubeconfig, pr.Name, namespace) + err = kubernetes.EnsureRoleBinding(ctx, kubeconfig, projectId, namespace) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to create K8s role binding.") } return nil } func (u *ProjectUsecase) DeleteK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error { //TODO implement me - panic("implement me") + return nil } func (u *ProjectUsecase) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error { pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to get project member.") } err = u.assignEachKeycloakClientRoleToMember(ctx, organizationId, projectId, clientId, pm.ProjectUserId.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } return nil } @@ -665,7 +639,7 @@ func (u *ProjectUsecase) assignEachKeycloakClientRoleToMember(ctx context.Contex err := u.kc.AssignClientRoleToUser(ctx, organizationId, userId, clientId, roleName+"@"+projectId) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to assign each KeycloakClientRole to member.") } return nil } @@ -674,12 +648,12 @@ func (u *ProjectUsecase) UnassignKeycloakClientRoleToMember(ctx context.Context, pm, err := u.GetProjectMember(ctx, projectMemberId) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to get project member.") } err = u.unassignKeycloakClientRoleToMember(ctx, organizationId, projectId, clientId, pm.ProjectUser.ID.String(), pm.ProjectRole.Name) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return err } return nil } @@ -688,7 +662,7 @@ func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, err := u.kc.UnassignClientRoleToUser(ctx, organizationId, userId, clientId, roleName+"@"+projectId) if err != nil { log.Error(ctx, err) - return errors.Wrap(err, "Failed to create project namespace.") + return errors.Wrap(err, "Failed to un-assign each KeycloakClientRole to member.") } return nil } @@ -834,3 +808,19 @@ func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, organizationId s return } + +func (u *ProjectUsecase) EnsureNamespaceForCluster(ctx context.Context, organizationId string, stackId string, namespaceName string) error { + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to get kubeconfig.") + } + + err = kubernetes.EnsureNamespace(ctx, kubeconfig, namespaceName) + if err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to create K8s namespace resource.") + } + + return nil +} diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index d8238850..e54b2790 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -346,7 +346,7 @@ func RemoveClusterRoleBinding(ctx context.Context, kubeconfig []byte, projectNam return nil } -func EnsureRoleBinding(ctx context.Context, kubeconfig []byte, projectName string, namespace string) error { +func EnsureRoleBinding(ctx context.Context, kubeconfig []byte, projectId string, namespace string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { log.Error(ctx, err) @@ -356,8 +356,8 @@ func EnsureRoleBinding(ctx context.Context, kubeconfig []byte, projectName strin clientset := kubernetes.NewForConfigOrDie(config_user) for _, role := range []string{leaderRole, memberRole, viewerRole} { - obj := generateClusterRoleToRoleBinding(role+"@"+projectName, projectName+"-"+role, namespace, projectName+"-"+role) - if _, err = clientset.RbacV1().RoleBindings(namespace).Get(context.Background(), projectName+"-"+role, metav1.GetOptions{}); err != nil { + obj := generateClusterRoleToRoleBinding(role+"@"+projectId, projectId+"-"+role, projectId+"-"+role, namespace) + if _, err = clientset.RbacV1().RoleBindings(namespace).Get(context.Background(), projectId+"-"+role, metav1.GetOptions{}); err != nil { _, err = clientset.RbacV1().RoleBindings(namespace).Create(context.Background(), obj, metav1.CreateOptions{}) if err != nil { log.Error(ctx, err) @@ -428,6 +428,32 @@ func getClusterRole(role, objName string) *rbacV1.ClusterRole { return &clusterRole } +func EnsureNamespace(ctx context.Context, kubeconfig []byte, projectName string) error { + config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + log.Error(ctx, err) + return err + } + + clientset := kubernetes.NewForConfigOrDie(config_user) + + if n, err := clientset.CoreV1().Namespaces().Get(context.Background(), projectName, metav1.GetOptions{}); err != nil { + _, err = clientset.CoreV1().Namespaces().Create(context.Background(), &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: projectName, + }, + }, metav1.CreateOptions{}) + if err != nil { + log.Error(ctx, err) + return err + } + } else { + log.Info(ctx, "Namespace already exists", n) + } + + return nil +} + func EnsureCommonClusterRole(ctx context.Context, kubeconfig []byte, projectName string) error { config_user, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) if err != nil { From 4194e208dc0d1fbcb21b39f7db3e3af698037d08 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 5 Apr 2024 13:44:12 +0900 Subject: [PATCH 240/502] trivial. fixes minor --- api/swagger/docs.go | 19 ++++++++----------- api/swagger/swagger.json | 19 ++++++++----------- api/swagger/swagger.yaml | 14 ++++++-------- pkg/domain/system-notification.go | 2 +- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index ae842179..b6862ad2 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -13968,21 +13968,12 @@ const docTemplate = `{ "cluster": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" }, - "code": { - "type": "string" - }, "createdAt": { "type": "string" }, - "description": { - "type": "string" - }, "firedAt": { "type": "string" }, - "grade": { - "type": "string" - }, "grafanaUrl": { "type": "string" }, @@ -13992,10 +13983,13 @@ const docTemplate = `{ "lastTaker": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, - "message": { + "messageActionProposal": { "type": "string" }, - "name": { + "messageContent": { + "type": "string" + }, + "messageTitle": { "type": "string" }, "node": { @@ -14010,6 +14004,9 @@ const docTemplate = `{ "rawData": { "type": "string" }, + "severity": { + "type": "string" + }, "status": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 5d59d3ef..3c0b563b 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -13962,21 +13962,12 @@ "cluster": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" }, - "code": { - "type": "string" - }, "createdAt": { "type": "string" }, - "description": { - "type": "string" - }, "firedAt": { "type": "string" }, - "grade": { - "type": "string" - }, "grafanaUrl": { "type": "string" }, @@ -13986,10 +13977,13 @@ "lastTaker": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" }, - "message": { + "messageActionProposal": { "type": "string" }, - "name": { + "messageContent": { + "type": "string" + }, + "messageTitle": { "type": "string" }, "node": { @@ -14004,6 +13998,9 @@ "rawData": { "type": "string" }, + "severity": { + "type": "string" + }, "status": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 04af21fa..a564257e 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -3081,25 +3081,21 @@ definitions: type: string cluster: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse' - code: - type: string createdAt: type: string - description: - type: string firedAt: type: string - grade: - type: string grafanaUrl: type: string id: type: string lastTaker: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' - message: + messageActionProposal: type: string - name: + messageContent: + type: string + messageTitle: type: string node: type: string @@ -3109,6 +3105,8 @@ definitions: type: integer rawData: type: string + severity: + type: string status: type: string systemNotificationActions: diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 4a46ca45..1710f230 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -79,7 +79,7 @@ type CreateSystemNotificationRequest struct { type SystemNotificationResponse struct { ID string `json:"id"` OrganizationId string `json:"organizationId"` - Severity string `json:"grade"` + Severity string `json:"severity"` MessageTitle string `json:"messageTitle"` MessageContent string `json:"messageContent"` MessageActionProposal string `json:"messageActionProposal"` From ab9206070edda1f8f5dd184069e8c249f9a721b5 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 5 Apr 2024 14:02:25 +0900 Subject: [PATCH 241/502] =?UTF-8?q?Operator=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/model/policy-template.go | 4 ++ internal/policy-template/tkscluster.go | 46 +++++++----- internal/policy-template/tkspolicy.go | 28 ++++++-- internal/policy-template/tkspolicytemplate.go | 27 +++++-- internal/usecase/policy-template.go | 8 +-- internal/usecase/policy.go | 70 +++++++++++++++---- 6 files changed, 133 insertions(+), 50 deletions(-) diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index a9db7a1e..b93be8c3 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -59,6 +59,10 @@ func (pt *PolicyTemplate) IsOrganizationTemplate() bool { return !pt.IsTksTemplate() } +func (pt *PolicyTemplate) ResoureName() string { + return strings.ToLower(pt.Kind) +} + func (pt *PolicyTemplate) IsPermittedToOrganization(organizationId *string) bool { // tks Admin은 organizationId가 nil if organizationId == nil { diff --git a/internal/policy-template/tkscluster.go b/internal/policy-template/tkscluster.go index 0fb2fa7f..c2bbc826 100644 --- a/internal/policy-template/tkscluster.go +++ b/internal/policy-template/tkscluster.go @@ -14,17 +14,21 @@ var TKSClusterGVR = schema.GroupVersionResource{ Resource: "tksclusters", } -type TKSClusterSpec struct { - ClusterName string `json:"clusterName" validate:"required"` - Context string `json:"context" validate:"required"` - TemplatesRef TemplateReference `json:"templateref,omitempty"` +// ============== Copied Fron Operator Start ============== + +// TemplateReference defines the desired state of TKSCluster +type TemplateReference struct { + Policies map[string]string `json:"polices,omitempty"` + Templates map[string]string `json:"templates,omitempty"` } -type TKSProxy struct { - ControllerManager *DeploymentInfo `json:"controllerManager,omitempty"` - Audit *DeploymentInfo `json:"audit,omitempty"` +// TKSClusterSpec defines the desired state of TKSCluster +type TKSClusterSpec struct { + ClusterName string `json:"clusterName" validate:"required"` + Context string `json:"context" validate:"required"` } +// DeploymentInfo defines the observed status of the proxy type DeploymentInfo struct { Image string `json:"image,omitempty"` Args []string `json:"args,omitempty"` @@ -32,22 +36,25 @@ type DeploymentInfo struct { NumReplicas int `json:"numReplicas,omitempty"` } -type TemplateReference struct { - Policies map[string]string `json:"polices,omitempty"` - Templates map[string]string `json:"templates,omitempty"` +// TKSProxy defines the observed proxy state for each cluster +type TKSProxy struct { + Status string `json:"status" enums:"ready,warn,error"` + ControllerManager *DeploymentInfo `json:"controllerManager,omitempty"` + Audit *DeploymentInfo `json:"audit,omitempty"` } +// TKSClusterStatus defines the observed state of TKSCluster type TKSClusterStatus struct { - Status string `json:"status" enums:"running,deleting,error"` - Error string `json:"error,omitempty"` - TKSProxy TKSProxy `json:"tksproxy,omitempty"` - LastStatusCheckTime int64 `json:"laststatuschecktime,omitempty"` - Policies map[string]string `json:"polices,omitempty"` - Templates map[string]string `json:"templates,omitempty"` - LastUpdate string `json:"lastUpdate"` - UpdateQueue map[string]bool `json:"updateQueue,omitempty"` + Status string `json:"status" enums:"running,deleting,error"` + Error string `json:"error,omitempty"` + TKSProxy TKSProxy `json:"tksproxy,omitempty"` + LastStatusCheckTime int64 `json:"laststatuschecktime,omitempty"` + Templates map[string][]string `json:"templates,omitempty"` + LastUpdate string `json:"lastUpdate"` + UpdateQueue map[string]bool `json:"updateQueue,omitempty"` } +// TKSCluster is the Schema for the tksclusters API type TKSCluster struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -56,12 +63,15 @@ type TKSCluster struct { Status TKSClusterStatus `json:"status,omitempty"` } +// TKSClusterList contains a list of TKSCluster type TKSClusterList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []TKSCluster `json:"items"` } +// ============== Copied Fron Operator End ============== + func GetTksClusterCR(ctx context.Context, primaryClusterId string, name string) (*TKSCluster, error) { dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) diff --git a/internal/policy-template/tkspolicy.go b/internal/policy-template/tkspolicy.go index 9c32892f..daa987c1 100644 --- a/internal/policy-template/tkspolicy.go +++ b/internal/policy-template/tkspolicy.go @@ -20,29 +20,36 @@ var TKSPolicyGVR = schema.GroupVersionResource{ Resource: "tkspolicies", } +// ============== Copied Fron Operator Start ============== +// match.Match는 domain.Match로 변경해야 함s + +// TKSPolicySpec defines the desired state of TKSPolicy type TKSPolicySpec struct { Clusters []string `json:"clusters"` Template string `json:"template" validate:"required"` - // map[string]interface를 쓸 수 없어서 apiextensionsv1.JSON 사용 - Params *apiextensionsv1.JSON `json:"params,omitempty"` - Match *domain.Match `json:"match,omitempty"` + Params *apiextensionsv1.JSON `json:"params,omitempty"` + Match *domain.Match `json:"match,omitempty"` + EnforcementAction string `json:"enforcementAction,omitempty"` } +// PolicyStatus defines the constraints state on the cluster type PolicyStatus struct { - ConstraintStatus string `json:"status" enums:"ready,applying,deleting,error"` - Reason string `json:"reason"` + ConstraintStatus string `json:"constraintStatus" enums:"ready,applying,deleting,error"` + Reason string `json:"reason,omitempty"` LastUpdate string `json:"lastUpdate"` TemplateVersion string `json:"templateVersion"` } // TKSPolicyStatus defines the observed state of TKSPolicy type TKSPolicyStatus struct { - Clusters map[string]PolicyStatus `json:"clusters"` + Clusters map[string]PolicyStatus `json:"clusters,omitempty"` LastUpdate string `json:"lastUpdate"` UpdateQueue map[string]bool `json:"updateQueue,omitempty"` + Reason string `json:"reason,omitempty"` } +// TKSPolicy is the Schema for the tkspolicies API type TKSPolicy struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -51,6 +58,15 @@ type TKSPolicy struct { Status TKSPolicyStatus `json:"status,omitempty"` } +// TKSPolicyList contains a list of TKSPolicy +type TKSPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TKSPolicy `json:"items"` +} + +// ============== Copied Fron Operator End ============== + func (tksPolicy *TKSPolicy) JSON() (string, error) { result, err := json.MarshalIndent(tksPolicy, "", " ") diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index a561fb32..3d0dce84 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -56,25 +56,31 @@ type Code struct { Source *Anything `json:"source"` } +// ============== Copied Fron Operator Start ============== +// CRD, Target struct는 이 파일의 것을 사용 + +// TKSPolicyTemplateSpec defines the desired state of TKSPolicyTemplate type TKSPolicyTemplateSpec struct { CRD CRD `json:"crd,omitempty"` Targets []Target `json:"targets,omitempty"` Clusters []string `json:"clusters,omitempty"` - ToLatest []string `json:"toLatest,omitempty"` Version string `json:"version"` + ToLatest []string `json:"toLatest,omitempty"` } +// TemplateStatus defines the constraints state of ConstraintTemplate on the cluster type TemplateStatus struct { - ConstraintTemplateStatus string `json:"status" enums:"ready,applying,deleting,error"` - Reason string `json:"reason"` + ConstraintTemplateStatus string `json:"constraintTemplateStatus" enums:"ready,applying,deleting,error"` + Reason string `json:"reason,omitempty"` LastUpdate string `json:"lastUpdate"` Version string `json:"version"` } +// TKSPolicyTemplateStatus defines the observed state of TKSPolicyTemplate type TKSPolicyTemplateStatus struct { - TemplateStatus map[string]*TemplateStatus `json:"clusterStatus"` - LastUpdate string `json:"lastUpdate"` - UpdateQueue map[string]bool `json:"updateQueue,omitempty"` + TemplateStatus map[string]TemplateStatus `json:"templateStatus,omitempty"` + LastUpdate string `json:"lastUpdate"` + UpdateQueue map[string]bool `json:"updateQueue,omitempty"` } // TKSPolicyTemplate is the Schema for the tkspolicytemplates API @@ -86,6 +92,15 @@ type TKSPolicyTemplate struct { Status TKSPolicyTemplateStatus `json:"status,omitempty"` } +// TKSPolicyTemplateList contains a list of TKSPolicyTemplate +type TKSPolicyTemplateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TKSPolicyTemplate `json:"items"` +} + +// ============== Copied Fron Operator End ============== + func (tksPolicyTemplate *TKSPolicyTemplate) JSON() (string, error) { result, err := json.MarshalIndent(tksPolicyTemplate, "", " ") diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index ca555625..0e3632b8 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -493,9 +493,7 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateDeploy(ctx context.Context, org } for clusterId, status := range tksPolicyTemplate.Status.TemplateStatus { - if status != nil { - deployVersions.DeployVersion[clusterId] = status.Version - } + deployVersions.DeployVersion[clusterId] = status.Version } } @@ -515,9 +513,7 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateDeploy(ctx context.Context, org } for clusterId, status := range tksPolicyTemplate.Status.TemplateStatus { - if status != nil { - deployVersions.DeployVersion[clusterId] = status.Version - } + deployVersions.DeployVersion[clusterId] = status.Version } return deployVersions, nil diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 12d56d69..bd391809 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -395,7 +395,34 @@ func (u *PolicyUsecase) UpdatePolicyTargetClusters(ctx context.Context, organiza targetClusters[i] = cluster } - return u.repo.UpdatePolicyTargetClusters(ctx, organizationId, policyId, currentClusterIds, targetClusters) + organization, err := u.organizationRepo.Get(ctx, organizationId) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + + err = u.repo.UpdatePolicyTargetClusters(ctx, organizationId, policyId, currentClusterIds, targetClusters) + if err != nil { + return err + } + + policy, err := u.repo.GetByID(ctx, organizationId, policyId) + if err != nil { + return httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "") + } + + policyCR := policytemplate.PolicyToTksPolicyCR(policy) + + err = policytemplate.ApplyTksPolicyCR(ctx, organization.PrimaryClusterId, policyCR) + + if err != nil { + log.Errorf(ctx, "failed to apply TksPolicyCR: %v", err) + return err + } + + return nil } func (u *PolicyUsecase) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) { @@ -474,10 +501,10 @@ func (u *PolicyUsecase) ListClusterPolicyStatus(ctx context.Context, clusterId s primaryClusterId := cluster.Organization.PrimaryClusterId - tksClusterCR, err := policytemplate.GetTksClusterCR(ctx, primaryClusterId, clusterId) - if err != nil { - return nil, err - } + // tksClusterCR, err := policytemplate.GetTksClusterCR(ctx, primaryClusterId, clusterId) + // if err != nil { + // return nil, err + // } result := make([]domain.ClusterPolicyStatusResponse, len(*policies)) @@ -490,12 +517,20 @@ func (u *PolicyUsecase) ListClusterPolicyStatus(ctx context.Context, clusterId s result[i].PolicyDescription = policy.Description result[i].PolicyMandatory = policy.Mandatory latestVersion, _ := u.templateRepo.GetLatestTemplateVersion(ctx, policy.TemplateId) - version, ok := tksClusterCR.Status.Templates[policy.PolicyTemplate.Kind] - if ok { - result[i].TemplateCurrentVersion = version + tksPolicyTemplateCR, err := policytemplate.GetTksPolicyTemplateCR(ctx, primaryClusterId, policy.PolicyTemplate.ResoureName()) + if err != nil { + return nil, err } + result[i].TemplateCurrentVersion = tksPolicyTemplateCR.Spec.Version + + // version, ok := tksClusterCR.Status.Templates[policy.PolicyTemplate.Kind] + + // if ok { + // result[i].TemplateCurrentVersion = version + // } + result[i].TemplateLatestVerson = latestVersion result[i].TemplateDescription = policy.PolicyTemplate.Description } @@ -580,16 +615,23 @@ func (u *PolicyUsecase) GetClusterPolicyTemplateStatus(ctx context.Context, clus primaryClusterId := cluster.Organization.PrimaryClusterId - tksClusterCR, err := policytemplate.GetTksClusterCR(ctx, primaryClusterId, clusterId) + // tksClusterCR, err := policytemplate.GetTksClusterCR(ctx, primaryClusterId, clusterId) + // if err != nil { + // return nil, err + // } + + // version, ok := tksClusterCR.Status.Templates[latestTemplate.Kind] + // + // if !ok { + // return nil, fmt.Errorf("version not found in CR") + // } + + tksPolicyTemplateCR, err := policytemplate.GetTksPolicyTemplateCR(ctx, primaryClusterId, latestTemplate.ResoureName()) if err != nil { return nil, err } - version, ok := tksClusterCR.Status.Templates[latestTemplate.Kind] - - if !ok { - return nil, fmt.Errorf("version not found in CR") - } + version := tksPolicyTemplateCR.Spec.Version currentTemplate, err := u.templateRepo.GetPolicyTemplateVersion(ctx, policyTemplateId, version) if err != nil { From 01feaf8d43c603b64bf0ffa6a1c3f2bee3f03435 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 5 Apr 2024 14:24:32 +0900 Subject: [PATCH 242/502] =?UTF-8?q?EnforcementAction=20=EC=A0=84=EB=8B=AC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/policy-operator.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 6ad98fff..45de64ac 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -42,10 +42,11 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { }, Spec: TKSPolicySpec{ - Clusters: policy.TargetClusterIds, - Template: policy.PolicyTemplate.Kind, - Match: policy.Match, - Params: &jsonParams, + EnforcementAction: policy.EnforcementAction, + Clusters: policy.TargetClusterIds, + Template: policy.PolicyTemplate.Kind, + Match: policy.Match, + Params: &jsonParams, }, } } From 70dc95c70dd2f6b72a4d55cfb6516121c8a170e9 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 5 Apr 2024 15:55:32 +0900 Subject: [PATCH 243/502] trivial. minor bug fixes --- api/swagger/docs.go | 79 ++++++++++++++++++ api/swagger/swagger.json | 79 ++++++++++++++++++ api/swagger/swagger.yaml | 50 +++++++++++ internal/usecase/organization.go | 1 + pkg/domain/alert.go | 137 ------------------------------- 5 files changed, 209 insertions(+), 137 deletions(-) delete mode 100644 pkg/domain/alert.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index b6862ad2..5caaa8ac 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -4239,6 +4239,43 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/policy-statistics": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿, 정책의 통계를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[GetPolicyStatistics] 정책 템플릿, 정책 통계 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatisticsResponse" + } + } + } + } + }, "/organizations/{organizationId}/policy-templates": { "get": { "security": [ @@ -12872,6 +12909,23 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyCount": { + "type": "object", + "properties": { + "deny": { + "type": "integer" + }, + "dryrun": { + "type": "integer" + }, + "total": { + "type": "integer" + }, + "warn": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyParameter": { "type": "object", "properties": { @@ -12962,6 +13016,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyStatisticsResponse": { + "type": "object", + "properties": { + "policyCount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyCount" + }, + "templateCount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateCount" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyStatus": { "type": "object", "properties": { @@ -14118,6 +14183,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.TemplateCount": { + "type": "object", + "properties": { + "organizationTemplate": { + "type": "integer" + }, + "tksTemplate": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.TemplateResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 3c0b563b..f8637d71 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -4233,6 +4233,43 @@ } } }, + "/organizations/{organizationId}/policy-statistics": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿, 정책의 통계를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[GetPolicyStatistics] 정책 템플릿, 정책 통계 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatisticsResponse" + } + } + } + } + }, "/organizations/{organizationId}/policy-templates": { "get": { "security": [ @@ -12866,6 +12903,23 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyCount": { + "type": "object", + "properties": { + "deny": { + "type": "integer" + }, + "dryrun": { + "type": "integer" + }, + "total": { + "type": "integer" + }, + "warn": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyParameter": { "type": "object", "properties": { @@ -12956,6 +13010,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyStatisticsResponse": { + "type": "object", + "properties": { + "policyCount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyCount" + }, + "templateCount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateCount" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyStatus": { "type": "object", "properties": { @@ -14112,6 +14177,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.TemplateCount": { + "type": "object", + "properties": { + "organizationTemplate": { + "type": "integer" + }, + "tksTemplate": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.TemplateResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index a564257e..63a6e9ca 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2346,6 +2346,17 @@ definitions: value: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyCount: + properties: + deny: + type: integer + dryrun: + type: integer + total: + type: integer + warn: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain.PolicyParameter: properties: name: @@ -2410,6 +2421,13 @@ definitions: updator: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyStatisticsResponse: + properties: + policyCount: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyCount' + templateCount: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateCount' + type: object github_com_openinfradev_tks-api_pkg_domain.PolicyStatus: properties: policyId: @@ -3180,6 +3198,15 @@ definitions: required: - metricQuery type: object + github_com_openinfradev_tks-api_pkg_domain.TemplateCount: + properties: + organizationTemplate: + type: integer + tksTemplate: + type: integer + total: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain.TemplateResponse: properties: children: @@ -6690,6 +6717,29 @@ paths: summary: '[ExistsPolicyName] 정책 아름 존재 여부 확인' tags: - Policy + /organizations/{organizationId}/policy-statistics: + get: + consumes: + - application/json + description: 템플릿, 정책의 통계를 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatisticsResponse' + security: + - JWT: [] + summary: '[GetPolicyStatistics] 정책 템플릿, 정책 통계 조회' + tags: + - Policy /organizations/{organizationId}/policy-templates: get: consumes: diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 23904c70..7e5c3d07 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -112,6 +112,7 @@ func (u *OrganizationUsecase) Fetch(ctx context.Context, pg *pagination.Paginati continue } for _, user := range *users { + user := user if user.ID == *organization.AdminId { (*organizations)[i].Admin = &user } diff --git a/pkg/domain/alert.go b/pkg/domain/alert.go deleted file mode 100644 index a60073bf..00000000 --- a/pkg/domain/alert.go +++ /dev/null @@ -1,137 +0,0 @@ -package domain - -import ( - "time" - - "github.com/google/uuid" -) - -// enum -type AlertActionStatus int32 - -const ( - AlertActionStatus_CREATED AlertActionStatus = iota - AlertActionStatus_INPROGRESS - AlertActionStatus_CLOSED - AlertActionStatus_ERROR -) - -var alertActionStatus = [...]string{ - "CREATED", - "INPROGRESS", - "CLOSED", - "ERROR", -} - -func (m AlertActionStatus) String() string { return alertActionStatus[(m)] } -func (m AlertActionStatus) FromString(s string) AlertActionStatus { - for i, v := range alertActionStatus { - if v == s { - return AlertActionStatus(i) - } - } - return AlertActionStatus_ERROR -} - -type CreateAlertRequestAlert struct { - Status string `json:"status"` - GeneratorURL string `json:"generatorURL"` - FingerPrint string `json:"fingerprint"` - StartsAt time.Time `json:"startsAt"` - EndsAt time.Time `json:"endsAt"` - Labels struct { - AlertName string `json:"alertname"` - Container string `json:"container"` - Endpoint string `json:"endpoint"` - Job string `json:"job"` - Namespace string `json:"namespace"` - Pod string `json:"pod"` - Prometheus string `json:"prometheus"` - Service string `json:"service"` - Severity string `json:"severity"` - Instance string `json:"instance"` - TacoCluster string `json:"taco_cluster"` - } `json:"labels"` - Annotations struct { - Message string `json:"message"` - Summary string `json:"summary"` - Description string `json:"description"` - Checkpoint string `json:"Checkpoint"` - Discriminative string `json:"discriminative"` - } `json:"annotations"` -} - -type CreateAlertRequest struct { - Receiver string `json:"receiver"` - Status string `json:"status"` - ExternalURL string `json:"externalURL"` - Version string `json:"version"` - GroupKey string `json:"groupKey"` - TruncateAlerts int `json:"truncateAlerts"` - Alerts []CreateAlertRequestAlert `json:"alerts"` - GroupLabels struct { - Alertname string `json:"alertname"` - } `json:"groupLabels"` - //CommonLabels string `json:"commonLabels"` - //CommonAnnotations string `json:"commonAnnotations"` -} - -type AlertResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - Message string `json:"message"` - Code string `json:"code"` - Grade string `json:"grade"` - Cluster SimpleClusterResponse `json:"cluster"` - GrafanaUrl string `json:"grafanaUrl"` - Node string `json:"node"` - FiredAt *time.Time `json:"firedAt"` - TakedAt *time.Time `json:"takedAt"` - ClosedAt *time.Time `json:"closedAt"` - Status string `json:"status"` - ProcessingSec int `json:"processingSec"` - TakedSec int `json:"takedSec"` - AlertActions []AlertActionResponse `json:"alertActions"` - LastTaker SimpleUserResponse `json:"lastTaker"` - RawData string `json:"rawData"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - -type AlertActionResponse struct { - ID uuid.UUID `json:"id"` - AlertId uuid.UUID `json:"alertId"` - Content string `json:"content"` - Status string `json:"status"` - Taker SimpleUserResponse `json:"taker"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - -type GetAlertsResponse struct { - Alerts []AlertResponse `json:"alerts"` - Pagination PaginationResponse `json:"pagination"` -} - -type GetAlertResponse struct { - Alert AlertResponse `json:"alert"` -} - -type CreateAlertResponse struct { - ID string `json:"id"` -} - -type UpdateAlertRequest struct { - Description string `json:"description"` -} - -type CreateAlertActionRequest struct { - Content string `json:"content"` - Status string `json:"status" validate:"oneof=INPROGRESS CLOSED"` -} - -type CreateAlertActionResponse struct { - ID string `json:"id"` -} From 23230a6efd022346ea187773f31ae8e71076cbd0 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 5 Apr 2024 16:17:30 +0900 Subject: [PATCH 244/502] trivial. minor bugfix --- internal/delivery/http/system-notification-rule.go | 7 ------- internal/usecase/system-notification.go | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index c143c9d7..0f97dabe 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -301,13 +301,6 @@ func (h *SystemNotificationRuleHandler) CheckSystemNotificationRuleName(w http.R } } - // [TEST] - err = h.usecase.MakeDefaultSystemNotificationRules(r.Context(), "oolw6roj6", nil) - if err != nil { - ErrorJSON(w, r, err) - return - } - var out domain.CheckSystemNotificationRuleNameResponse out.Existed = exist diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index a8c085b0..42872e3d 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -273,7 +273,7 @@ func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryC case "pvc-full": url = primaryGrafanaEndpoint + "/d/tks_cluster_dashboard/tks-kubernetes-view-cluster-global?var-taco_cluster=" + clusterId.String() + "&kiosk" default: - log.Errorf(ctx, "Invalid systemNotification name %s", systemNotification.Labels.SystemNotificationName) + url = "" } return From f581f7c02b837286395c6d6282699b1020b2368c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 5 Apr 2024 16:39:15 +0900 Subject: [PATCH 245/502] trivial. change schema for systemNotification --- internal/usecase/system-notification.go | 8 ++--- pkg/domain/system-notification.go | 42 ++++++++++++------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 42872e3d..bd7e3c72 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -97,13 +97,13 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre */ node := "" - if strings.Contains(systemNotification.Labels.SystemNotificationName, "node") { + if strings.Contains(systemNotification.Labels.AlertName, "node") { node = systemNotification.Labels.Instance } dto := model.SystemNotification{ OrganizationId: organizationId, - Name: systemNotification.Labels.SystemNotificationName, + Name: systemNotification.Labels.AlertName, Severity: systemNotification.Labels.Severity, Node: node, MessageTitle: systemNotification.Annotations.Message, @@ -239,7 +239,7 @@ func (u *SystemNotificationUsecase) makeAdditionalInfo(systemNotification *model } } -func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, systemNotification domain.SystemNotification, clusterId domain.ClusterId) (url string) { +func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, systemNotification domain.SystemNotificationRequest, clusterId domain.ClusterId) (url string) { primaryGrafanaEndpoint := "" appGroups, err := u.appGroupRepo.Fetch(ctx, primaryCluster.ID, nil) if err == nil { @@ -261,7 +261,7 @@ func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryC // tks_node_dashboard/tks-kubernetes-view-nodes?orgId=1&refresh=30s&var-datasource=default&var-taco_cluster=c19rjkn4j&var-job=prometheus-node-exporter&var-hostname=All&var-node=10.0.168.71:9100&var-device=All&var-maxmount=%2F&var-show_hostname=prometheus-node-exporter-xt4vb - switch systemNotification.Labels.SystemNotificationName { + switch systemNotification.Labels.AlertName { case "node-memory-high-utilization": url = primaryGrafanaEndpoint + "/d/tks_node_dashboard/tks-kubernetes-view-nodes?var-taco_cluster=" + clusterId.String() + "&kiosk" case "node-cpu-high-load": diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 1710f230..786f293c 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -33,24 +33,24 @@ func (m SystemNotificationActionStatus) FromString(s string) SystemNotificationA return SystemNotificationActionStatus_ERROR } -type SystemNotification struct { +type SystemNotificationRequest struct { Status string `json:"status"` GeneratorURL string `json:"generatorURL"` FingerPrint string `json:"fingerprint"` StartsAt time.Time `json:"startsAt"` EndsAt time.Time `json:"endsAt"` Labels struct { - SystemNotificationName string `json:"systemNotificationname"` - Container string `json:"container"` - Endpoint string `json:"endpoint"` - Job string `json:"job"` - Namespace string `json:"namespace"` - Pod string `json:"pod"` - Prometheus string `json:"prometheus"` - Service string `json:"service"` - Severity string `json:"severity"` - Instance string `json:"instance"` - TacoCluster string `json:"taco_cluster"` + AlertName string `json:"alertname"` + Container string `json:"container"` + Endpoint string `json:"endpoint"` + Job string `json:"job"` + Namespace string `json:"namespace"` + Pod string `json:"pod"` + Prometheus string `json:"prometheus"` + Service string `json:"service"` + Severity string `json:"severity"` + Instance string `json:"instance"` + TacoCluster string `json:"taco_cluster"` } `json:"labels"` Annotations struct { Message string `json:"message"` @@ -62,15 +62,15 @@ type SystemNotification struct { } type CreateSystemNotificationRequest struct { - Receiver string `json:"receiver"` - Status string `json:"status"` - ExternalURL string `json:"externalURL"` - Version string `json:"version"` - GroupKey string `json:"groupKey"` - TruncateSystemNotifications int `json:"truncateSystemNotifications"` - SystemNotifications []SystemNotification `json:"alerts"` - GroupLabels struct { - SystemNotificationname string `json:"systemNotificationname"` + Receiver string `json:"receiver"` + Status string `json:"status"` + ExternalURL string `json:"externalURL"` + Version string `json:"version"` + GroupKey string `json:"groupKey"` + TruncatedAlerts int `json:"truncatedAlerts"` + SystemNotifications []SystemNotificationRequest `json:"alerts"` + GroupLabels struct { + SystemNotificationname string `json:"alertname"` } `json:"groupLabels"` //CommonLabels string `json:"commonLabels"` //CommonAnnotations string `json:"commonAnnotations"` From 167105cc6742eeaf09f2db3e67a4d9305a9ad86f Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 5 Apr 2024 17:23:49 +0900 Subject: [PATCH 246/502] =?UTF-8?q?TKSPolicyTemplate=EC=9D=98=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=ED=95=84=EB=93=9C=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/policy-operator.go | 2 +- internal/usecase/policy.go | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 45de64ac..56223c4f 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -44,7 +44,7 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { Spec: TKSPolicySpec{ EnforcementAction: policy.EnforcementAction, Clusters: policy.TargetClusterIds, - Template: policy.PolicyTemplate.Kind, + Template: policy.PolicyTemplate.ResoureName(), Match: policy.Match, Params: &jsonParams, }, diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index bd391809..4c9f7470 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -125,6 +125,13 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m dto.TemplateId = policyTemplate.ID policyCR := policytemplate.PolicyToTksPolicyCR(&dto) + + // DB 생성 전 policy DTO에 PolicyTemplate 필드를 넣어주면 탬플릿이 생성될 수 있으므로, + // dto에 세팅하지 않고 변환 후 필요한 템플릿 리소스 이름을 따로 넣어 줌 + if len(policyCR.Spec.Template) == 0 { + policyCR.Spec.Template = policyTemplate.ResoureName() + } + policyTemplateCR := policytemplate.PolicyTemplateToTksPolicyTemplateCR(policyTemplate) organization, err := u.organizationRepo.Get(ctx, organizationId) From 19faca1024a8ab376873a2392a9d0170e30f1f83 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 5 Apr 2024 20:48:30 +0900 Subject: [PATCH 247/502] =?UTF-8?q?Kind=20=EB=8C=80=EC=8B=A0=20resource=20?= =?UTF-8?q?name=EC=9D=B4=20=ED=85=9C=ED=94=8C=EB=A6=BF=EC=97=90=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/model/policy-template.go | 7 ++++++- internal/policy-template/policy-operator.go | 2 +- internal/usecase/policy.go | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index b93be8c3..98800e7c 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -108,7 +108,12 @@ func (pt *PolicyTemplate) AfterFind(tx *gorm.DB) (err error) { supportedVersion := pt.SupportedVersions[0] pt.Version = supportedVersion.Version pt.Rego = supportedVersion.Rego - pt.Libs = strings.Split(supportedVersion.Libs, FILE_DELIMETER) + + if len(strings.TrimSpace(supportedVersion.Libs)) == 0 { + pt.Libs = []string{} + } else { + pt.Libs = strings.Split(supportedVersion.Libs, FILE_DELIMETER) + } // 마찬가지로 에러 무시 _ = json.Unmarshal([]byte(supportedVersion.ParameterSchema), &pt.ParametersSchema) diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 56223c4f..45de64ac 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -44,7 +44,7 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { Spec: TKSPolicySpec{ EnforcementAction: policy.EnforcementAction, Clusters: policy.TargetClusterIds, - Template: policy.PolicyTemplate.ResoureName(), + Template: policy.PolicyTemplate.Kind, Match: policy.Match, Params: &jsonParams, }, diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 4c9f7470..ec188464 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -129,7 +129,7 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m // DB 생성 전 policy DTO에 PolicyTemplate 필드를 넣어주면 탬플릿이 생성될 수 있으므로, // dto에 세팅하지 않고 변환 후 필요한 템플릿 리소스 이름을 따로 넣어 줌 if len(policyCR.Spec.Template) == 0 { - policyCR.Spec.Template = policyTemplate.ResoureName() + policyCR.Spec.Template = policyTemplate.Kind } policyTemplateCR := policytemplate.PolicyTemplateToTksPolicyTemplateCR(policyTemplate) From beec97bdc8295549ced52777466e7e08848195b8 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sat, 6 Apr 2024 00:14:52 +0900 Subject: [PATCH 248/502] =?UTF-8?q?ParamDef=20->=20JSONSchemaProps=20?= =?UTF-8?q?=EB=B3=80=ED=99=98=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/paramdef-util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go index 32e2de8e..ccf4fa27 100644 --- a/internal/policy-template/paramdef-util.go +++ b/internal/policy-template/paramdef-util.go @@ -177,7 +177,7 @@ func convert(paramdefs []*domain.ParameterDef) map[string]apiextensionsv1.JSONSc } case isObject: result[paramdef.Key] = *ParamDefsToJSONSchemaProeprties(paramdef.Children) - _: + default: result[paramdef.Key] = apiextensionsv1.JSONSchemaProps{Type: paramdef.Type} } From 40a29cf6309f87d7018182229f5f817ccdc3b384 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sat, 6 Apr 2024 21:31:47 +0900 Subject: [PATCH 249/502] =?UTF-8?q?=EB=8B=A8=EC=88=9C=20=EC=9D=B8=EC=9E=90?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy.go | 4 ++-- internal/route/route.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index def185b6..d431e871 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -652,7 +652,7 @@ func (h *PolicyHandler) ListClusterPolicyStatus(w http.ResponseWriter, r *http.R // @Param clusterId path string true "클러스터 식별자(uuid)" // @Param templateId path string true "정책 템플릿 식별자(uuid)" // @Success 200 {object} domain.GetClusterPolicyTemplateStatusResponse -// @Router /clusters/{clusterId}/policy-templates/{templateId} [get] +// @Router /clusters/{clusterId}/policy-templates/{policyTemplateId} [get] // @Security JWT func (h *PolicyHandler) GetClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -698,7 +698,7 @@ func (h *PolicyHandler) GetClusterPolicyTemplateStatus(w http.ResponseWriter, r // @Param templateId path string true "정책 템플릿 식별자(uuid)" // @Param body body domain.UpdateClusterPolicyTemplateStatusRequest true "update cluster policy template status request" // @Success 200 {object} nil -// @Router /clusters/{clusterId}/policy-templates/{templateId} [patch] +// @Router /clusters/{clusterId}/policy-templates/{policyTemplateId} [patch] // @Security JWT func (h *PolicyHandler) UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/route/route.go b/internal/route/route.go index ee7ae1a5..57c01ec0 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -349,8 +349,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyName, http.HandlerFunc(policyHandler.ExistsPolicyName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-status", customMiddleware.Handle(internalApi.ListClusterPolicyStatus, http.HandlerFunc(policyHandler.ListClusterPolicyStatus))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{templateId}", customMiddleware.Handle(internalApi.GetClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.GetClusterPolicyTemplateStatus))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{templateId}", customMiddleware.Handle(internalApi.UpdateClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.UpdateClusterPolicyTemplateStatus))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.GetClusterPolicyTemplateStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdateClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.UpdateClusterPolicyTemplateStatus))).Methods(http.MethodPatch) // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) From f20bd691bdc1e2c3b0dfc19f74e962dceedda4f5 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 8 Apr 2024 09:29:07 +0900 Subject: [PATCH 250/502] =?UTF-8?q?=EB=8B=A4=EC=9D=8C=20api=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DeletePolicesForStack - AddPoliciesForStack - DeletePermittedPolicyTemplatesForOrganization - AddPermittedPolicyTemplatesForOrganization --- internal/delivery/api/endpoint.go | 4 + .../delivery/api/generated_endpoints.go.go | 32 +++ internal/delivery/http/policy-template.go | 163 ++++++++++- internal/delivery/http/policy.go | 178 ++++++++++++ internal/model/cluster.go | 1 + internal/model/organization.go | 2 +- internal/model/policy-template.go | 4 +- internal/model/policy.go | 4 +- internal/policy-template/policy-operator.go | 15 +- internal/policy-template/tkspolicy.go | 45 ++++ internal/policy-template/tkspolicytemplate.go | 5 + internal/repository/organization.go | 30 +++ internal/repository/policy.go | 31 +++ internal/route/route.go | 5 + internal/usecase/policy-template.go | 60 +++++ internal/usecase/policy.go | 253 ++++++++++++++++-- pkg/domain/admin/policy-template.go | 12 + pkg/domain/policy-template.go | 12 + 18 files changed, 815 insertions(+), 41 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 9ba9b96d..83477d83 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -234,6 +234,8 @@ const ( Admin_ExistsPolicyTemplateKind Admin_ExistsPolicyTemplateName Admin_ExtractParameters + Admin_AddPermittedPolicyTemplatesForOrganization + Admin_DeletePermittedPolicyTemplatesForOrganization // ClusterPolicyStatus ListClusterPolicyStatus @@ -252,6 +254,8 @@ const ( UpdatePolicyTargetClusters ExistsPolicyName GetPolicyEdit + AddPoliciesForStack + DeletePoliciesForStack // OrganizationPolicyTemplate ListPolicyTemplate diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index d7963f31..42cf4171 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -727,6 +727,14 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_ExtractParameters", Group: "PolicyTemplate", }, + Admin_AddPermittedPolicyTemplatesForOrganization: { + Name: "Admin_AddPermittedPolicyTemplatesForOrganization", + Group: "PolicyTemplate", + }, + Admin_DeletePermittedPolicyTemplatesForOrganization: { + Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", + Group: "PolicyTemplate", + }, ListClusterPolicyStatus: { Name: "ListClusterPolicyStatus", Group: "ClusterPolicyStatus", @@ -783,6 +791,14 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyEdit", Group: "Policy", }, + AddPoliciesForStack: { + Name: "AddPoliciesForStack", + Group: "Policy", + }, + DeletePoliciesForStack: { + Name: "DeletePoliciesForStack", + Group: "Policy", + }, ListPolicyTemplate: { Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", @@ -1224,6 +1240,10 @@ func (e Endpoint) String() string { return "Admin_ExistsPolicyTemplateName" case Admin_ExtractParameters: return "Admin_ExtractParameters" + case Admin_AddPermittedPolicyTemplatesForOrganization: + return "Admin_AddPermittedPolicyTemplatesForOrganization" + case Admin_DeletePermittedPolicyTemplatesForOrganization: + return "Admin_DeletePermittedPolicyTemplatesForOrganization" case ListClusterPolicyStatus: return "ListClusterPolicyStatus" case GetClusterPolicyTemplateStatus: @@ -1252,6 +1272,10 @@ func (e Endpoint) String() string { return "ExistsPolicyName" case GetPolicyEdit: return "GetPolicyEdit" + case AddPoliciesForStack: + return "AddPoliciesForStack" + case DeletePoliciesForStack: + return "DeletePoliciesForStack" case ListPolicyTemplate: return "ListPolicyTemplate" case CreatePolicyTemplate: @@ -1658,6 +1682,10 @@ func GetEndpoint(name string) Endpoint { return Admin_ExistsPolicyTemplateName case "Admin_ExtractParameters": return Admin_ExtractParameters + case "Admin_AddPermittedPolicyTemplatesForOrganization": + return Admin_AddPermittedPolicyTemplatesForOrganization + case "Admin_DeletePermittedPolicyTemplatesForOrganization": + return Admin_DeletePermittedPolicyTemplatesForOrganization case "ListClusterPolicyStatus": return ListClusterPolicyStatus case "GetClusterPolicyTemplateStatus": @@ -1686,6 +1714,10 @@ func GetEndpoint(name string) Endpoint { return ExistsPolicyName case "GetPolicyEdit": return GetPolicyEdit + case "AddPoliciesForStack": + return AddPoliciesForStack + case "DeletePoliciesForStack": + return DeletePoliciesForStack case "ListPolicyTemplate": return ListPolicyTemplate case "CreatePolicyTemplate": diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 1136cde3..1a98126b 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -40,6 +40,9 @@ type IPolicyTemplateHandler interface { Admin_DeletePolicyTemplateVersion(w http.ResponseWriter, r *http.Request) Admin_ListPolicyTemplateVersions(w http.ResponseWriter, r *http.Request) Admin_ExtractParameters(w http.ResponseWriter, r *http.Request) + Admin_AddPermittedPolicyTemplatesForOrganization(w http.ResponseWriter, r *http.Request) + Admin_UpdatePermittedPolicyTemplatesForOrganization(w http.ResponseWriter, r *http.Request) + Admin_DeletePermittedPolicyTemplatesForOrganization(w http.ResponseWriter, r *http.Request) CreatePolicyTemplate(w http.ResponseWriter, r *http.Request) UpdatePolicyTemplate(w http.ResponseWriter, r *http.Request) @@ -747,6 +750,159 @@ func (h *PolicyTemplateHandler) Admin_ExistsPolicyTemplateKind(w http.ResponseWr ResponseJSON(w, r, http.StatusOK, out) } +// Admin_AddPermittedPolicyTemplatesForOrganization godoc +// +// @Tags PolicyTemplate +// @Summary [Admin_AddPermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 추가 +// @Description 특정 조직에 대해 허용된 tks 템플릿 목록을 추가한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param body body admin_domain.AddPermittedPolicyTemplatesForOrganizationRequest true "update pemitted policy template request" +// @Success 200 {object} nil +// @Router /admin/organizations/{organizationId}/policyTemplates [post] +// @Security JWT +func (h *PolicyTemplateHandler) Admin_AddPermittedPolicyTemplatesForOrganization(w http.ResponseWriter, r *http.Request) { + // TODO: API 형상 추후 반드시 검토 + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := admin_domain.AddPermittedPolicyTemplatesForOrganizationRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ids := make([]uuid.UUID, len(input.PolicyTemplateIds)) + + for i, policyTemplateId := range input.PolicyTemplateIds { + id, err := uuid.Parse(policyTemplateId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + ids[i] = id + } + + err = h.usecase.AddPermittedPolicyTemplatesForOrganization(r.Context(), organizationId, ids) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +func (h *PolicyTemplateHandler) Admin_UpdatePermittedPolicyTemplatesForOrganization(w http.ResponseWriter, r *http.Request) { + // TODO: API 형상 추후 반드시 검토 + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := admin_domain.UpdatePermittedPolicyTemplatesForOrganizationRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ids := make([]uuid.UUID, len(input.PolicyTemplateIds)) + + for i, policyTemplateId := range input.PolicyTemplateIds { + id, err := uuid.Parse(policyTemplateId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + ids[i] = id + } + + err = h.usecase.UpdatePermittedPolicyTemplatesForOrganization(r.Context(), organizationId, ids) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +// Admin_DeletePermittedPolicyTemplatesForOrganization godoc +// +// @Tags PolicyTemplate +// @Summary [Admin_DeletePermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 제거 +// @Description 특정 조직에 대해 허용된 tks 템플릿의 허용 상태를 해제(제거)한다. tks 우형 템플릿에 대해서만 동작하고 organization 유형 템플릿에 대해서는 거부된다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param body body admin_domain.DeletePermittedPolicyTemplatesForOrganizationRequest true "delete pemitted policy template request" +// @Success 200 {object} nil +// @Router /admin/organizations/{organizationId}/policyTemplates [put] +// @Security JWT +func (h *PolicyTemplateHandler) Admin_DeletePermittedPolicyTemplatesForOrganization(w http.ResponseWriter, r *http.Request) { + // TODO: API 형상 추후 반드시 검토 + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := admin_domain.DeletePermittedPolicyTemplatesForOrganizationRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ids := make([]uuid.UUID, len(input.PolicyTemplateIds)) + + for i, policyTemplateId := range input.PolicyTemplateIds { + id, err := uuid.Parse(policyTemplateId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + ids[i] = id + } + + err = h.usecase.DeletePermittedPolicyTemplatesForOrganization(r.Context(), organizationId, ids) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + // CompileRego godoc // // @Tags PolicyTemplate @@ -1583,12 +1739,5 @@ func (h *PolicyTemplateHandler) ExtractParameters(w http.ResponseWriter, r *http log.Info(r.Context(), err) } - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - - ErrorJSON(w, r, err) - return - } - ResponseJSON(w, r, http.StatusCreated, response) } diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index d431e871..2134543e 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -37,6 +37,9 @@ type IPolicyHandler interface { UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) GetPolicyEdit(w http.ResponseWriter, r *http.Request) GetPolicyStatistics(w http.ResponseWriter, r *http.Request) + AddPoliciesForStack(w http.ResponseWriter, r *http.Request) + UpdatePoliciesForStack(w http.ResponseWriter, r *http.Request) + DeletePoliciesForStack(w http.ResponseWriter, r *http.Request) } func NewPolicyHandler(u usecase.Usecase) IPolicyHandler { @@ -866,3 +869,178 @@ func (h *PolicyHandler) GetPolicyStatistics(w http.ResponseWriter, r *http.Reque ResponseJSON(w, r, http.StatusOK, out) } + +// AddPoliciesForStack godoc +// +// @Tags Policy +// @Summary [AddPoliciesForStack] 특정 스택의 정책 목록 추가 +// @Description 특정 스택의 정책 목록을 정책 식별자 리스트로 지정해서 추가한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param stackId path string true "스택 식별자" +// @Param body body domain.AddPoliciesForStackRequest true "add policies for stack request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stacks/{stackId}/policies [post] +// @Security JWT +func (h *PolicyHandler) AddPoliciesForStack(w http.ResponseWriter, r *http.Request) { + // TODO: API 형상 추후 반드시 검토 + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("stackId not found in path"), + "C_INVALID_STACK_ID", "")) + return + } + + input := domain.AddPoliciesForStackRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ids := make([]uuid.UUID, len(input.PolicyIds)) + + for i, policyId := range input.PolicyIds { + id, err := uuid.Parse(policyId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_ID", "")) + return + } + ids[i] = id + } + + err = h.usecase.AddPoliciesForClusterID(r.Context(), organizationId, domain.ClusterId(stackId), ids) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +func (h *PolicyHandler) UpdatePoliciesForStack(w http.ResponseWriter, r *http.Request) { + // TODO: API 형상 추후 반드시 검토 + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("stackId not found in path"), + "C_INVALID_STACK_ID", "")) + return + } + + input := domain.UpdatePoliciesForStackRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ids := make([]uuid.UUID, len(input.PolicyIds)) + + for i, policyId := range input.PolicyIds { + id, err := uuid.Parse(policyId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_ID", "")) + return + } + ids[i] = id + } + + err = h.usecase.UpdatePoliciesForClusterID(r.Context(), organizationId, domain.ClusterId(stackId), ids) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + +// DeletePoliciesForStack godoc +// +// @Tags Policy +// @Summary [DeletePoliciesForStack] 특정 스택의 정책 제거 +// @Description 특정 스택에서 정책 식별자로 지정된 정책을 제거한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param stackId path string true "스택 식별자" +// @Param body body domain.DeletePoliciesForStackRequest true "delete policies for stack request" +// @Router /organizations/{organizationId}/stacks/{stackId}/policies [put] +// @Security JWT +func (h *PolicyHandler) DeletePoliciesForStack(w http.ResponseWriter, r *http.Request) { + // TODO: API 형상 추후 반드시 검토 + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("stackId not found in path"), + "C_INVALID_STACK_ID", "")) + return + } + + input := domain.DeletePoliciesForStackRequest{} + + err := UnmarshalRequestInput(r, &input) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ids := make([]uuid.UUID, len(input.PolicyIds)) + + for i, policyId := range input.PolicyIds { + id, err := uuid.Parse(policyId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "C_INVALID_POLICY_ID", "")) + return + } + ids[i] = id + } + + err = h.usecase.DeletePoliciesForClusterID(r.Context(), organizationId, domain.ClusterId(stackId), ids) + + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 4e7480f6..004de271 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -42,6 +42,7 @@ type Cluster struct { Creator User `gorm:"foreignKey:CreatorId"` UpdatorId *uuid.UUID `gorm:"type:uuid"` Updator User `gorm:"foreignKey:UpdatorId"` + Policies []Policy `gorm:"many2many:policy_target_clusters"` } func (m *Cluster) SetDefaultConf() { diff --git a/internal/model/organization.go b/internal/model/organization.go index f912f774..ada78d11 100644 --- a/internal/model/organization.go +++ b/internal/model/organization.go @@ -21,7 +21,7 @@ type Organization struct { CreatorId *uuid.UUID `gorm:"type:uuid"` StackTemplates []StackTemplate `gorm:"many2many:stack_template_organizations;"` StackTemplateIds []uuid.UUID `gorm:"-:all"` - PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organiations;"` + PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organizations;"` PolicyTemplateIds []uuid.UUID `gorm:"-:all"` SystemNotificationTemplates []SystemNotificationTemplate `gorm:"many2many:system_notification_template_organizations"` SystemNotificationTemplateIds []uuid.UUID `gorm:"-:all"` diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index 98800e7c..1864a214 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -78,7 +78,9 @@ func (pt *PolicyTemplate) IsPermittedToOrganization(organizationId *string) bool } func (pt *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { - pt.ID = uuid.New() + if pt.ID == uuid.Nil { + pt.ID = uuid.New() + } jsonByte, err := json.Marshal(pt.ParametersSchema) diff --git a/internal/model/policy.go b/internal/model/policy.go index 574d31bc..edfd1ae9 100644 --- a/internal/model/policy.go +++ b/internal/model/policy.go @@ -40,7 +40,9 @@ type Policy struct { } func (p *Policy) BeforeCreate(tx *gorm.DB) (err error) { - p.ID = uuid.New() + if p.ID == uuid.Nil { + p.ID = uuid.New() + } if p.Match != nil { jsonBytes, err := json.Marshal(p.Match) diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 45de64ac..cb10995f 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -10,6 +10,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ( + PartOfKey = "app.kubernetes.io/part-of" + PartOfVal = "tks-policy-operator" + TksLabelPrefix = "tks/" + PolicyIDLabel = TksLabelPrefix + "policy-id" + TemplateIDLabel = TksLabelPrefix + "policy-template-id" +) + func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { if policy == nil { return nil @@ -18,7 +26,9 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { jsonParams := apiextensionsv1.JSON{Raw: []byte(policy.Parameters)} labels := map[string]string{} - labels["app.kubernetes.io/part-of"] = "tks-policy-operator" + labels[PartOfKey] = PartOfVal + labels[PolicyIDLabel] = policy.ID.String() + labels[TemplateIDLabel] = policy.TemplateId.String() if policy.MatchYaml != nil { var match domain.Match @@ -57,7 +67,8 @@ func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) * } labels := map[string]string{} - labels["app.kubernetes.io/part-of"] = "tks-policy-operator" + labels[PartOfKey] = PartOfVal + labels[TemplateIDLabel] = policyTemplate.ID.String() return &TKSPolicyTemplate{ TypeMeta: metav1.TypeMeta{ diff --git a/internal/policy-template/tkspolicy.go b/internal/policy-template/tkspolicy.go index daa987c1..11b50a94 100644 --- a/internal/policy-template/tkspolicy.go +++ b/internal/policy-template/tkspolicy.go @@ -67,6 +67,10 @@ type TKSPolicyList struct { // ============== Copied Fron Operator End ============== +func (tksPolicy *TKSPolicy) GetPolicyID() string { + return tksPolicy.ObjectMeta.Labels[PolicyIDLabel] +} + func (tksPolicy *TKSPolicy) JSON() (string, error) { result, err := json.MarshalIndent(tksPolicy, "", " ") @@ -226,3 +230,44 @@ func ExistsTksPolicyCR(ctx context.Context, primaryClusterId string, name string } return true, nil } + +func ListTksPolicyCR(ctx context.Context, primaryClusterId string) ([]*TKSPolicy, error) { + if syncToKubernetes() { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return nil, err + } + + results, err := dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). + List(ctx, metav1.ListOptions{}) + + if err != nil { + return nil, err + } + + tkspolicies := make([]*TKSPolicy, len(results.Items)) + + for i, result := range results.Items { + jsonBytes, err := json.Marshal(result.Object) + + if err != nil { + return nil, err + } + + var tksPolicy TKSPolicy + err = json.Unmarshal(jsonBytes, &tksPolicy) + + if err != nil { + return nil, err + } + + tkspolicies[i] = &tksPolicy + } + + return tkspolicies, nil + } + + tkspolicies := make([]*TKSPolicy, 0) + return tkspolicies, nil +} diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index 3d0dce84..412d9007 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -200,6 +200,11 @@ func DeleteTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, nam err = dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). Delete(ctx, name, metav1.DeleteOptions{}) + // 삭제할 리소스가 존재하지 않았다면 성공으로 처리 + if errors.IsNotFound(err) { + return nil + } + return err } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 2ca270b6..7949bd35 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -26,6 +26,9 @@ type IOrganizationRepository interface { RemoveSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplates []model.SystemNotificationTemplate) (err error) Delete(ctx context.Context, organizationId string) (err error) InitWorkflow(ctx context.Context, organizationId string, workflowId string, status domain.OrganizationStatus) error + AddPermittedPolicyTemplatesByID(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) + UpdatePermittedPolicyTemplatesByID(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) + DeletePermittedPolicyTemplatesByID(ctx context.Context, organizationId string, policyTemplateids []uuid.UUID) (err error) } type OrganizationRepository struct { @@ -227,3 +230,30 @@ func (r *OrganizationRepository) RemoveSystemNotificationTemplates(ctx context.C return nil } + +func (r *OrganizationRepository) AddPermittedPolicyTemplatesByID(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) { + var organization model.Organization + organization.ID = organizationId + + err = r.db.WithContext(ctx).Model(&organization). + Association("PolicyTemplates").Append(policyTemplates) + + return err +} + +func (r *OrganizationRepository) UpdatePermittedPolicyTemplatesByID(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) { + var organization model.Organization + organization.ID = organizationId + + err = r.db.WithContext(ctx).Model(&organization). + Association("PolicyTemplates").Replace(policyTemplates) + + return err +} + +func (r *OrganizationRepository) DeletePermittedPolicyTemplatesByID(ctx context.Context, organizationId string, policyTemplateids []uuid.UUID) (err error) { + return r.db.WithContext(ctx). + Where("organization_id = ?", organizationId). + Where("policy_template_id in ?", policyTemplateids). + Delete(&model.PolicyTemplatePermittedOrganization{}).Error +} diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 96cc6186..844e9afd 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gorm.io/gorm" @@ -31,6 +32,9 @@ type IPolicyRepository interface { SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) GetUsageCountByTemplateId(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (usageCounts []model.UsageCount, err error) CountPolicyByEnforcementAction(ctx context.Context, organizationId string) (policyCount []model.PolicyCount, err error) + AddPoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policies []model.Policy) (err error) + UpdatePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policies []model.Policy) (err error) + DeletePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) } type PolicyRepository struct { @@ -296,3 +300,30 @@ func (r *PolicyRepository) CountPolicyByEnforcementAction(ctx context.Context, o return } + +func (r *PolicyRepository) AddPoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policies []model.Policy) (err error) { + var cluster model.Cluster + cluster.ID = clusterId + + err = r.db.WithContext(ctx).Model(&cluster). + Association("Policies").Append(policies) + + return err +} + +func (r *PolicyRepository) UpdatePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policies []model.Policy) (err error) { + var cluster model.Cluster + cluster.ID = clusterId + + err = r.db.WithContext(ctx).Model(&cluster). + Association("Policies").Replace(policies) + + return err +} + +func (r *PolicyRepository) DeletePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) { + return r.db.WithContext(ctx). + Where("cluster_id = ?", clusterId). + Where("policy_id in ?", policyIds). + Delete(&model.PolicyTargetCluster{}).Error +} diff --git a/internal/route/route.go b/internal/route/route.go index 57c01ec0..b8906bf6 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -319,6 +319,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/{policyTemplateId}/versions/{version}/extract-parameters", customMiddleware.Handle(internalApi.Admin_ExtractParameters, http.HandlerFunc(policyTemplateHandler.Admin_ExtractParameters))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/kind/{policyTemplateKind}/existence", customMiddleware.Handle(internalApi.Admin_ExistsPolicyTemplateKind, http.HandlerFunc(policyTemplateHandler.Admin_ExistsPolicyTemplateKind))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates/name/{policyTemplateName}/existence", customMiddleware.Handle(internalApi.Admin_ExistsPolicyTemplateName, http.HandlerFunc(policyTemplateHandler.Admin_ExistsPolicyTemplateName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/policyTemplates", customMiddleware.Handle(internalApi.Admin_AddPermittedPolicyTemplatesForOrganization, http.HandlerFunc(policyTemplateHandler.Admin_AddPermittedPolicyTemplatesForOrganization))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/policyTemplates", customMiddleware.Handle(internalApi.Admin_DeletePermittedPolicyTemplatesForOrganization, http.HandlerFunc(policyTemplateHandler.Admin_DeletePermittedPolicyTemplatesForOrganization))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/policy-templates/rego-compile", customMiddleware.Handle(internalApi.CompileRego, http.HandlerFunc(policyTemplateHandler.RegoCompile))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates", customMiddleware.Handle(internalApi.ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.ListPolicyTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-templates", customMiddleware.Handle(internalApi.CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.CreatePolicyTemplate))).Methods(http.MethodPost) @@ -347,6 +350,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.DeletePolicy, http.HandlerFunc(policyHandler.DeletePolicy))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.UpdatePolicy, http.HandlerFunc(policyHandler.UpdatePolicy))).Methods(http.MethodPatch) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyName, http.HandlerFunc(policyHandler.ExistsPolicyName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.AddPoliciesForStack, http.HandlerFunc(policyHandler.AddPoliciesForStack))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.DeletePoliciesForStack, http.HandlerFunc(policyHandler.DeletePoliciesForStack))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-status", customMiddleware.Handle(internalApi.ListClusterPolicyStatus, http.HandlerFunc(policyHandler.ListClusterPolicyStatus))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.GetClusterPolicyTemplateStatus))).Methods(http.MethodGet) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 0e3632b8..96f2c2ef 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -45,6 +45,10 @@ type IPolicyTemplateUsecase interface { GetPolicyTemplateDeploy(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (deployInfo domain.GetPolicyTemplateDeployResponse, err error) ExtractPolicyParameters(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string, rego string, libs []string) (response *domain.RegoCompileResponse, err error) + + AddPermittedPolicyTemplatesForOrganization(ctx context.Context, organizationId string, policyTemplateIds []uuid.UUID) (err error) + UpdatePermittedPolicyTemplatesForOrganization(ctx context.Context, organizationId string, policyTemplateIds []uuid.UUID) (err error) + DeletePermittedPolicyTemplatesForOrganization(ctx context.Context, organizationId string, policyTemplateIds []uuid.UUID) (err error) } type PolicyTemplateUsecase struct { @@ -166,6 +170,10 @@ func (u *PolicyTemplateUsecase) fillPermittedOrganizations(_ context.Context, or return } + if policyTemplate.IsOrganizationTemplate() { + return + } + // 정책 템플릿에서 허용된 조직 목록이 없다는 것은 모든 조직이 사용할 수 있음을 의미함 allPermitted := len(policyTemplate.PermittedOrganizationIds) == 0 @@ -589,3 +597,55 @@ func (u *PolicyTemplateUsecase) ExtractPolicyParameters(ctx context.Context, org return response, nil } + +func (u *PolicyTemplateUsecase) AddPermittedPolicyTemplatesForOrganization(ctx context.Context, organizationId string, policyTemplateIds []uuid.UUID) (err error) { + policyTemplates := make([]model.PolicyTemplate, len(policyTemplateIds)) + + for i, policyTemplateId := range policyTemplateIds { + result, err := u.repo.GetByID(ctx, policyTemplateId) + + if err != nil || result == nil { + return httpErrors.NewBadRequestError(fmt.Errorf( + "failed to fetch policy template"), + "PT_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + if result.IsOrganizationTemplate() { + return httpErrors.NewBadRequestError(fmt.Errorf( + "failed to permit organization to organization policy template"), + "PT_FAILED_TO_PERMIT_ORG_TEMPLATE", "") + } + + policyTemplates[i] = *result + } + + return u.organizationRepo.AddPermittedPolicyTemplatesByID(ctx, organizationId, policyTemplates) +} + +func (u *PolicyTemplateUsecase) UpdatePermittedPolicyTemplatesForOrganization(ctx context.Context, organizationId string, policyTemplateIds []uuid.UUID) (err error) { + policyTemplates := make([]model.PolicyTemplate, len(policyTemplateIds)) + + for i, policyTemplateId := range policyTemplateIds { + result, err := u.repo.GetByID(ctx, policyTemplateId) + + if err != nil || result == nil { + return httpErrors.NewBadRequestError(fmt.Errorf( + "failed to fetch policy template"), + "PT_FAILED_FETCH_POLICY_TEMPLATE", "") + } + + if result.IsOrganizationTemplate() { + return httpErrors.NewBadRequestError(fmt.Errorf( + "failed to permit organization to organization policy template"), + "PT_FAILED_TO_PERMIT_ORG_TEMPLATE", "") + } + + policyTemplates[i] = *result + } + + return u.organizationRepo.UpdatePermittedPolicyTemplatesByID(ctx, organizationId, policyTemplates) +} + +func (u *PolicyTemplateUsecase) DeletePermittedPolicyTemplatesForOrganization(ctx context.Context, organizationId string, policyTemplateIds []uuid.UUID) (err error) { + return u.organizationRepo.DeletePermittedPolicyTemplatesByID(ctx, organizationId, policyTemplateIds) +} diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index ec188464..08732137 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -39,6 +39,9 @@ type IPolicyUsecase interface { UpdateClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID, currentVersion string, targetVerson string) (err error) GetPolicyStatistics(ctx context.Context, organizationId string) (response *domain.PolicyStatisticsResponse, err error) + AddPoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) + UpdatePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) + DeletePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) } type PolicyUsecase struct { @@ -124,33 +127,53 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m dto.CreatorId = &userId dto.TemplateId = policyTemplate.ID - policyCR := policytemplate.PolicyToTksPolicyCR(&dto) + organization, err := u.organizationRepo.Get(ctx, organizationId) - // DB 생성 전 policy DTO에 PolicyTemplate 필드를 넣어주면 탬플릿이 생성될 수 있으므로, - // dto에 세팅하지 않고 변환 후 필요한 템플릿 리소스 이름을 따로 넣어 줌 - if len(policyCR.Spec.Template) == 0 { - policyCR.Spec.Template = policyTemplate.Kind + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } - policyTemplateCR := policytemplate.PolicyTemplateToTksPolicyTemplateCR(policyTemplate) + primaryClusterId := organization.PrimaryClusterId - organization, err := u.organizationRepo.Get(ctx, organizationId) + // k8s에 label로 policyID를 기록해 주기 위해 DB 컬럼 생성 시 ID를 생성하지 않고 미리 생성 + dto.ID = uuid.New() + err = createOrUpdatPolicy(ctx, &dto, policyTemplate, primaryClusterId) if err != nil { - log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + return uuid.Nil, err + } - return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + id, err := u.repo.Create(ctx, dto) + + if err != nil { + return uuid.Nil, err } - exists, err = policytemplate.ExistsTksPolicyTemplateCR(ctx, organization.PrimaryClusterId, policyTemplateCR.Name) + return id, nil +} + +func createOrUpdatPolicy(ctx context.Context, dto *model.Policy, policyTemplate *model.PolicyTemplate, primaryClusterId string) error { + policyCR := policytemplate.PolicyToTksPolicyCR(dto) + + // DB 생성 전 policy DTO에 PolicyTemplate 필드를 넣어주면 탬플릿이 생성될 수 있으므로, + // dto에 세팅하지 않고 변환 후 필요한 템플릿 리소스 이름을 따로 넣어 줌 + if len(policyCR.Spec.Template) == 0 { + policyCR.Spec.Template = policyTemplate.Kind + } + + policyTemplateCR := policytemplate.PolicyTemplateToTksPolicyTemplateCR(policyTemplate) + + exists, err := policytemplate.ExistsTksPolicyTemplateCR(ctx, primaryClusterId, policyTemplateCR.Name) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) - return uuid.Nil, httpErrors.NewInternalServerError(err, "P_FAILED_TO_CALL_KUBERNETES", "") + return httpErrors.NewInternalServerError(err, "P_FAILED_TO_CALL_KUBERNETES", "") } if !exists { - err = policytemplate.ApplyTksPolicyTemplateCR(ctx, organization.PrimaryClusterId, policyTemplateCR) + err = policytemplate.ApplyTksPolicyTemplateCR(ctx, primaryClusterId, policyTemplateCR) if err != nil { errYaml := "" @@ -160,22 +183,11 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m log.Errorf(ctx, "error is :%s(%T), policyTemplateCR='%+v'", err.Error(), err, errYaml) - return uuid.Nil, httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") + return httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") } } - err = policytemplate.ApplyTksPolicyCR(ctx, organization.PrimaryClusterId, policyCR) - - if err != nil { - errYaml := "" - if policyCR != nil { - errYaml, _ = policyCR.YAML() - } - - log.Errorf(ctx, "error is :%s(%T), policyCR='%+v'", err.Error(), err, errYaml) - - return uuid.Nil, httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") - } + err = policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, policyCR) // policyYaml, _ := policyCR.YAML() // policyTemplateYaml, _ := policyTemplateCR.YAML() @@ -189,13 +201,18 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m // fmt.Printf("%+v\n", policyTemplateCR.Spec.Targets[0].Rego) // fmt.Println("------------------------------------------------") - id, err := u.repo.Create(ctx, dto) - if err != nil { - return uuid.Nil, err + errYaml := "" + if policyCR != nil { + errYaml, _ = policyCR.YAML() + } + + log.Errorf(ctx, "error is :%s(%T), policyCR='%+v'", err.Error(), err, errYaml) + + return httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") } - return id, nil + return nil } func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, policyId uuid.UUID, @@ -732,6 +749,184 @@ func (u *PolicyUsecase) GetPolicyStatistics(ctx context.Context, organizationId return &result, nil } +func (u *PolicyUsecase) AddPoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) { + organization, err := u.organizationRepo.Get(ctx, organizationId) + + primaryClusterId := organization.PrimaryClusterId + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + + tkpolicies, err := policytemplate.ListTksPolicyCR(ctx, primaryClusterId) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return err + } + + ids := make([]string, len(policyIds)) + for i, policyId := range policyIds { + ids[i] = policyId.String() + } + + // mapset.NewSet([]string{}) + + for _, tkspolicy := range tkpolicies { + policyId := tkspolicy.GetPolicyID() + + // 추가 대상 + if slices.Contains(ids, policyId) { + // 현재 클러스터가 안 추가되어 있으면 + if !slices.Contains(tkspolicy.Spec.Clusters, string(clusterId)) { + tkspolicy.Spec.Clusters = append(tkspolicy.Spec.Clusters, string(clusterId)) + + err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, tkspolicy) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } + } + + } + } + + policies := []model.Policy{} + + for _, policyId := range policyIds { + policy, err := u.repo.GetByID(ctx, organizationId, policyId) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + continue + } + + policies = append(policies, *policy) + } + + return u.repo.AddPoliciesForClusterID(ctx, organizationId, clusterId, policies) +} + +func (u *PolicyUsecase) UpdatePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) { + organization, err := u.organizationRepo.Get(ctx, organizationId) + + primaryClusterId := organization.PrimaryClusterId + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + + tkpolicies, err := policytemplate.ListTksPolicyCR(ctx, primaryClusterId) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return err + } + + ids := make([]string, len(policyIds)) + for i, policyId := range policyIds { + ids[i] = policyId.String() + } + + // mapset.NewSet([]string{}) + + for _, tkspolicy := range tkpolicies { + policyId := tkspolicy.GetPolicyID() + + // 세팅 대상 + if slices.Contains(ids, policyId) { + // 현재 클러스터가 안 추가되어 있으면 + if !slices.Contains(tkspolicy.Spec.Clusters, string(clusterId)) { + tkspolicy.Spec.Clusters = append(tkspolicy.Spec.Clusters, string(clusterId)) + + err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, tkspolicy) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } + } + + } else { // 클리어 대상 + // 현재 클러스터가 추가되어 있으면 + if slices.Contains(tkspolicy.Spec.Clusters, string(clusterId)) { + newClusters := []string{} + + tkspolicy.Spec.Clusters = slices.Filter(newClusters, tkspolicy.Spec.Clusters, + func(s string) bool { return s != string(clusterId) }) + + err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, tkspolicy) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } + } + } + } + + policies := []model.Policy{} + + for _, policyId := range policyIds { + policy, err := u.repo.GetByID(ctx, organizationId, policyId) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + continue + } + + policies = append(policies, *policy) + } + + return u.repo.UpdatePoliciesForClusterID(ctx, organizationId, clusterId, policies) +} + +func (u *PolicyUsecase) DeletePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) { + organization, err := u.organizationRepo.Get(ctx, organizationId) + + primaryClusterId := organization.PrimaryClusterId + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + + tkpolicies, err := policytemplate.ListTksPolicyCR(ctx, primaryClusterId) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return err + } + + ids := make([]string, len(policyIds)) + for i, policyId := range policyIds { + ids[i] = policyId.String() + } + + for _, tkspolicy := range tkpolicies { + policyId := tkspolicy.GetPolicyID() + + if slices.Contains(ids, policyId) { + // 현재 클러스터가 추가되어 있으면 제거 + if slices.Contains(tkspolicy.Spec.Clusters, string(clusterId)) { + newClusters := []string{} + + tkspolicy.Spec.Clusters = slices.Filter(newClusters, tkspolicy.Spec.Clusters, + func(s string) bool { return s != string(clusterId) }) + err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, tkspolicy) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } + } + } + } + + return u.repo.DeletePoliciesForClusterID(ctx, organizationId, clusterId, policyIds) +} + func extractNewTemplateParameter(paramdefs []*domain.ParameterDef, newParamDefs []*domain.ParameterDef) (policyParameters []domain.UpdatedPolicyTemplateParameter, err error) { diffParamDef, err := policytemplate.GetNewParamDefs(paramdefs, newParamDefs) diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index 0613c7b9..c60a8a35 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -187,3 +187,15 @@ type ExtractParametersResponse struct { ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` Errors []domain.RegoCompieError `json:"errors,omitempty"` } + +type AddPermittedPolicyTemplatesForOrganizationRequest struct { + PolicyTemplateIds []string `json:"policyTemplateIds"` +} + +type UpdatePermittedPolicyTemplatesForOrganizationRequest struct { + PolicyTemplateIds []string `json:"policyTemplateIds"` +} + +type DeletePermittedPolicyTemplatesForOrganizationRequest struct { + PolicyTemplateIds []string `json:"policyTemplateIds"` +} diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 265104aa..536dbaf2 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -195,3 +195,15 @@ type ExtractParametersResponse struct { ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` Errors []RegoCompieError `json:"errors,omitempty"` } + +type AddPoliciesForStackRequest struct { + PolicyIds []string `json:"policyIds"` +} + +type UpdatePoliciesForStackRequest struct { + PolicyIds []string `json:"policyIds"` +} + +type DeletePoliciesForStackRequest struct { + PolicyIds []string `json:"policyIds"` +} From 5ab83d60a0cddf5787368a4a9b89dc9d8ed85be8 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 8 Apr 2024 11:27:00 +0900 Subject: [PATCH 251/502] feature. add policy when stack create --- api/swagger/docs.go | 6 ++++ api/swagger/swagger.json | 6 ++++ api/swagger/swagger.yaml | 4 +++ internal/model/cluster.go | 1 + internal/model/stack.go | 1 + internal/usecase/stack-template.go | 7 +++-- internal/usecase/stack.go | 1 + internal/usecase/system-notification.go | 4 +-- pkg/domain/cluster.go | 39 +++++++++++++------------ 9 files changed, 46 insertions(+), 23 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 5caaa8ac..46656d28 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -10746,6 +10746,12 @@ const docTemplate = `{ "organizationId": { "type": "string" }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, "stackTemplateId": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index f8637d71..130baeed 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -10740,6 +10740,12 @@ "organizationId": { "type": "string" }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, "stackTemplateId": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 63a6e9ca..529fffb5 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -910,6 +910,10 @@ definitions: type: string organizationId: type: string + policyIds: + items: + type: string + type: array stackTemplateId: type: string tksCpNode: diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 4e7480f6..394d5fbc 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -38,6 +38,7 @@ type Cluster struct { TksUserNodeMax int TksUserNodeType string Kubeconfig []byte `gorm:"-:all"` + PolicyIds []string `gorm:"-:all"` CreatorId *uuid.UUID `gorm:"type:uuid"` Creator User `gorm:"foreignKey:CreatorId"` UpdatorId *uuid.UUID `gorm:"type:uuid"` diff --git a/internal/model/stack.go b/internal/model/stack.go index 72300ee5..ab287fc5 100644 --- a/internal/model/stack.go +++ b/internal/model/stack.go @@ -30,6 +30,7 @@ type Stack = struct { Favorited bool ClusterEndpoint string Resource domain.DashboardStack + PolicyIds []string } type StackConf struct { diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index b397e01f..2eb0c715 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -57,10 +57,13 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTempla } services := "[" - for _, serviceId := range dto.ServiceIds { + for i, serviceId := range dto.ServiceIds { + if i > 1 { + services = services + "," + } switch serviceId { case "LMA": - services = services + internal.SERVICE_LMA + "," + services = services + internal.SERVICE_LMA case "SERVICE_MESH": services = services + internal.SERVICE_SERVICE_MESH } diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 1921aaab..32f6294e 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -135,6 +135,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom "infra_conf=" + strings.Replace(helper.ModelToJson(stackConf), "\"", "\\\"", -1), "cloud_service=" + dto.CloudService, "cluster_endpoint=" + dto.ClusterEndpoint, + "policy_ids=" + strings.Join(dto.PolicyIds, ","), }, }) if err != nil { diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index bd7e3c72..6156896b 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -273,8 +273,8 @@ func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryC case "pvc-full": url = primaryGrafanaEndpoint + "/d/tks_cluster_dashboard/tks-kubernetes-view-cluster-global?var-taco_cluster=" + clusterId.String() + "&kiosk" default: - url = "" + url = "/d/tks_cluster_dashboard" } - return + return url } diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index 0d7c854b..891abfad 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -140,25 +140,26 @@ func (m *ClusterConf) SetDefault() { } type CreateClusterRequest struct { - OrganizationId string `json:"organizationId" validate:"required"` - CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` - StackTemplateId string `json:"stackTemplateId" validate:"required"` - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` - CloudAccountId string `json:"cloudAccountId"` - ClusterType string `json:"clusterType"` - ByoClusterEndpointHost string `json:"byoClusterEndpointHost,omitempty"` - ByoClusterEndpointPort int `json:"byoClusterEndpointPort,omitempty"` - IsStack bool `json:"isStack,omitempty"` - TksCpNode int `json:"tksCpNode"` - TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` - TksCpNodeType string `json:"tksCpNodeType,omitempty"` - TksInfraNode int `json:"tksInfraNode"` - TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` - TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` - TksUserNode int `json:"tksUserNode"` - TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` - TksUserNodeType string `json:"tksUserNodeType,omitempty"` + OrganizationId string `json:"organizationId" validate:"required"` + CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + CloudAccountId string `json:"cloudAccountId"` + ClusterType string `json:"clusterType"` + ByoClusterEndpointHost string `json:"byoClusterEndpointHost,omitempty"` + ByoClusterEndpointPort int `json:"byoClusterEndpointPort,omitempty"` + IsStack bool `json:"isStack,omitempty"` + PolicyIds []string `json:"policyIds,omitempty"` + TksCpNode int `json:"tksCpNode"` + TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` + TksCpNodeType string `json:"tksCpNodeType,omitempty"` + TksInfraNode int `json:"tksInfraNode"` + TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` + TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` + TksUserNode int `json:"tksUserNode"` + TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` + TksUserNodeType string `json:"tksUserNodeType,omitempty"` } type ImportClusterRequest struct { From a228f7659c3cdeea1003123150fd9c6a46003631 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 8 Apr 2024 15:28:44 +0900 Subject: [PATCH 252/502] bugfix. fix error handling --- internal/keycloak/keycloak.go | 23 +++++++++++++---------- internal/usecase/project.go | 15 +-------------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 9332e946..7f99c050 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -4,7 +4,6 @@ import ( "context" "crypto/tls" "fmt" - "github.com/spf13/viper" "time" @@ -484,16 +483,20 @@ func (k *Keycloak) EnsureClientRoleWithClientName(ctx context.Context, organizat Name: gocloak.StringP(roleName), } - r, err := k.client.GetClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, roleName) + _, err = k.client.GetClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, roleName) if err != nil { - log.Error(ctx, "Getting Client Role is failed", err) - return err - } - - if r == nil { - _, err = k.client.CreateClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, role) - if err != nil { - log.Error(ctx, "Creating Client Role is failed", err) + if apiErr, ok := err.(*gocloak.APIError); ok { + if apiErr.Code == 404 { + _, err = k.client.CreateClientRole(context.Background(), token.AccessToken, organizationId, *targetClient.ID, role) + if err != nil { + log.Error(ctx, "Creating Client Role is failed", err) + return err + } + return nil + } else { + return err + } + } else { return err } } diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 94d00b9b..6a02db3d 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -444,25 +444,12 @@ func (u *ProjectUsecase) GetAppCount(ctx context.Context, organizationId string, } func (u *ProjectUsecase) EnsureRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error { - pns, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) + _, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to get project namespace in database.") } - var alreadySetUp bool - for _, pn := range pns { - if pn.StackId == stackId { - alreadySetUp = true - break - } - } - - // if already set up, it means that required setup is already done - if alreadySetUp { - return nil - } - if err := u.createK8SInitialResource(ctx, organizationId, projectId, stackId); err != nil { log.Error(ctx, err) return err From bd4278980cc62f4d83dea00ab9da4da05f1df5d9 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 8 Apr 2024 15:31:06 +0900 Subject: [PATCH 253/502] trivial. add is_system to systemNotificationTemplate & Role --- pkg/domain/system-notification-rule.go | 1 + pkg/domain/system-notification-template.go | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index 13e1acf3..a170e8fd 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -39,6 +39,7 @@ type SystemNotificationRuleResponse struct { TargetUsers []SimpleUserResponse `json:"targetUsers"` SystemNotificationTemplate SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplate"` SystemNotificationCondition SystemNotificationConditionResponse `json:"systemNotificationCondition"` + IsSystem bool `json:"isSystem"` Creator SimpleUserResponse `json:"creator"` Updator SimpleUserResponse `json:"updator"` CreatedAt time.Time `json:"createdAt"` diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index 851fdb95..88430c01 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -17,6 +17,7 @@ type SystemNotificationTemplateResponse struct { MetricQuery string `json:"metricQuery" validate:"required"` MetricParameters []SystemNotificationMetricParameterResponse `json:"metricParameters,omitempty"` Organizations []SimpleOrganizationResponse `json:"organizations,omitempty"` + IsSystem bool `json:"isSystem"` Creator SimpleUserResponse `json:"creator"` Updator SimpleUserResponse `json:"updator"` CreatedAt time.Time `json:"createdAt"` From 1b1b7e149fe3b0fba7175fbfe37a8887c244273c Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 8 Apr 2024 15:36:03 +0900 Subject: [PATCH 254/502] lint fix --- internal/usecase/system-notification.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 6156896b..eca9e6c2 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -256,8 +256,8 @@ func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryC } } - // check type - url = primaryGrafanaEndpoint + //// check type + //url = primaryGrafanaEndpoint // tks_node_dashboard/tks-kubernetes-view-nodes?orgId=1&refresh=30s&var-datasource=default&var-taco_cluster=c19rjkn4j&var-job=prometheus-node-exporter&var-hostname=All&var-node=10.0.168.71:9100&var-device=All&var-maxmount=%2F&var-show_hostname=prometheus-node-exporter-xt4vb From 47b56308f54ff62ec8cfb38459c97a248b7d271a Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 8 Apr 2024 15:58:51 +0900 Subject: [PATCH 255/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=20=EB=B2=84=EC=A0=84=EC=97=85=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/api/endpoint.go | 8 +- .../delivery/api/generated_endpoints.go.go | 42 ++++----- internal/delivery/http/policy.go | 89 ++++++++++--------- internal/model/permission.go | 8 +- internal/policy-template/paramdef-util.go | 4 +- internal/repository/policy.go | 2 +- internal/route/route.go | 6 +- internal/usecase/policy.go | 34 ++++--- pkg/domain/policy.go | 10 +-- pkg/httpErrors/errorCode.go | 1 + 10 files changed, 109 insertions(+), 95 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 83477d83..463b406d 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -237,10 +237,10 @@ const ( Admin_AddPermittedPolicyTemplatesForOrganization Admin_DeletePermittedPolicyTemplatesForOrganization - // ClusterPolicyStatus - ListClusterPolicyStatus - GetClusterPolicyTemplateStatus - UpdateClusterPolicyTemplateStatus + // StackPolicyStatus + ListStackPolicyStatus + GetStackPolicyTemplateStatus + UpdateStackPolicyTemplateStatus // Policy GetMandatoryPolicies diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 42cf4171..74b792b2 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -735,17 +735,17 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - ListClusterPolicyStatus: { - Name: "ListClusterPolicyStatus", - Group: "ClusterPolicyStatus", + ListStackPolicyStatus: { + Name: "ListStackPolicyStatus", + Group: "StackPolicyStatus", }, - GetClusterPolicyTemplateStatus: { - Name: "GetClusterPolicyTemplateStatus", - Group: "ClusterPolicyStatus", + GetStackPolicyTemplateStatus: { + Name: "GetStackPolicyTemplateStatus", + Group: "StackPolicyStatus", }, - UpdateClusterPolicyTemplateStatus: { - Name: "UpdateClusterPolicyTemplateStatus", - Group: "ClusterPolicyStatus", + UpdateStackPolicyTemplateStatus: { + Name: "UpdateStackPolicyTemplateStatus", + Group: "StackPolicyStatus", }, GetMandatoryPolicies: { Name: "GetMandatoryPolicies", @@ -1244,12 +1244,12 @@ func (e Endpoint) String() string { return "Admin_AddPermittedPolicyTemplatesForOrganization" case Admin_DeletePermittedPolicyTemplatesForOrganization: return "Admin_DeletePermittedPolicyTemplatesForOrganization" - case ListClusterPolicyStatus: - return "ListClusterPolicyStatus" - case GetClusterPolicyTemplateStatus: - return "GetClusterPolicyTemplateStatus" - case UpdateClusterPolicyTemplateStatus: - return "UpdateClusterPolicyTemplateStatus" + case ListStackPolicyStatus: + return "ListStackPolicyStatus" + case GetStackPolicyTemplateStatus: + return "GetStackPolicyTemplateStatus" + case UpdateStackPolicyTemplateStatus: + return "UpdateStackPolicyTemplateStatus" case GetMandatoryPolicies: return "GetMandatoryPolicies" case SetMandatoryPolicies: @@ -1686,12 +1686,12 @@ func GetEndpoint(name string) Endpoint { return Admin_AddPermittedPolicyTemplatesForOrganization case "Admin_DeletePermittedPolicyTemplatesForOrganization": return Admin_DeletePermittedPolicyTemplatesForOrganization - case "ListClusterPolicyStatus": - return ListClusterPolicyStatus - case "GetClusterPolicyTemplateStatus": - return GetClusterPolicyTemplateStatus - case "UpdateClusterPolicyTemplateStatus": - return UpdateClusterPolicyTemplateStatus + case "ListStackPolicyStatus": + return ListStackPolicyStatus + case "GetStackPolicyTemplateStatus": + return GetStackPolicyTemplateStatus + case "UpdateStackPolicyTemplateStatus": + return UpdateStackPolicyTemplateStatus case "GetMandatoryPolicies": return GetMandatoryPolicies case "SetMandatoryPolicies": diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 2134543e..c26d0ee5 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -32,9 +32,9 @@ type IPolicyHandler interface { GetMandatoryPolicies(w http.ResponseWriter, r *http.Request) SetMandatoryPolicies(w http.ResponseWriter, r *http.Request) ExistsPolicyName(w http.ResponseWriter, r *http.Request) - ListClusterPolicyStatus(w http.ResponseWriter, r *http.Request) - GetClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) - UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) + ListStackPolicyStatus(w http.ResponseWriter, r *http.Request) + GetStackPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) + UpdateStackPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) GetPolicyEdit(w http.ResponseWriter, r *http.Request) GetPolicyStatistics(w http.ResponseWriter, r *http.Request) AddPoliciesForStack(w http.ResponseWriter, r *http.Request) @@ -601,29 +601,30 @@ func (h *PolicyHandler) ExistsPolicyName(w http.ResponseWriter, r *http.Request) ResponseJSON(w, r, http.StatusOK, out) } -// ListClusterPolicyStatus godoc +// ListStackPolicyStatus godoc // -// @Tags ClusterPolicyStatus -// @Summary [ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회 +// @Tags StackPolicyStatus +// @Summary [ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회 // @Description 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. // @Accept json // @Produce json -// @Param clusterId path string true "클러스터 식별자(uuid)" -// @Param pageSize query string false "pageSize" -// @Param pageNumber query string false "pageNumber" -// @Param sortColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.ListClusterPolicyStatusResponse -// @Router /clusters/{clusterId}/policy-status [get] +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param stackId path string true "스택 식별자" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" +// @Param sortColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.ListStackPolicyStatusResponse +// @Router /organizations/{organizationId}/stacks/{stackId}/policy-status [get] // @Security JWT -func (h *PolicyHandler) ListClusterPolicyStatus(w http.ResponseWriter, r *http.Request) { +func (h *PolicyHandler) ListStackPolicyStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - clusterId, ok := vars["clusterId"] + stackId, ok := vars["stackId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), - "C_INVALID_CLUSTER_ID", "")) + "C_INVALID_STACK_ID", "")) return } @@ -631,39 +632,40 @@ func (h *PolicyHandler) ListClusterPolicyStatus(w http.ResponseWriter, r *http.R pg := pagination.NewPagination(&urlParams) - policyStatuses, err := h.usecase.ListClusterPolicyStatus(r.Context(), clusterId, pg) + policyStatuses, err := h.usecase.ListStackPolicyStatus(r.Context(), stackId, pg) if err != nil { ErrorJSON(w, r, err) return } - out := domain.ListClusterPolicyStatusResponse{ + out := domain.ListStackPolicyStatusResponse{ Polices: policyStatuses, } ResponseJSON(w, r, http.StatusOK, out) } -// GetClusterPolicyTemplateStatus godoc +// GetStackPolicyTemplateStatus godoc // -// @Tags ClusterPolicyStatus -// @Summary [GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회 +// @Tags StackPolicyStatus +// @Summary [GetStackPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회 // @Description 템플릿의 클러스터 버전 등 상태를 조회한다. // @Accept json // @Produce json -// @Param clusterId path string true "클러스터 식별자(uuid)" -// @Param templateId path string true "정책 템플릿 식별자(uuid)" -// @Success 200 {object} domain.GetClusterPolicyTemplateStatusResponse -// @Router /clusters/{clusterId}/policy-templates/{policyTemplateId} [get] +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param stackId path string true "스택 식별자" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Success 200 {object} domain.GetStackPolicyTemplateStatusResponse +// @Router /organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId} [get] // @Security JWT -func (h *PolicyHandler) GetClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) { +func (h *PolicyHandler) GetStackPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - clusterId, ok := vars["clusterId"] + stackId, ok := vars["stackId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), - "C_INVALID_CLUSTER_ID", "")) + "C_INVALID_STACK_ID", "")) return } @@ -680,7 +682,7 @@ func (h *PolicyHandler) GetClusterPolicyTemplateStatus(w http.ResponseWriter, r return } - out, err := h.usecase.GetClusterPolicyTemplateStatus(r.Context(), clusterId, id) + out, err := h.usecase.GetStackPolicyTemplateStatus(r.Context(), stackId, id) if err != nil { ErrorJSON(w, r, err) @@ -690,26 +692,27 @@ func (h *PolicyHandler) GetClusterPolicyTemplateStatus(w http.ResponseWriter, r ResponseJSON(w, r, http.StatusOK, out) } -// UpdateClusterPolicyTemplateStatus godoc +// UpdateStackPolicyTemplateStatus godoc // -// @Tags ClusterPolicyStatus -// @Summary [UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트 +// @Tags StackPolicyStatus +// @Summary [UpdateStackPolicyTemplateStatus] 템플릿 버전 업데이트 // @Description 해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다. // @Accept json // @Produce json -// @Param clusterId path string true "클러스터 식별자(uuid)" -// @Param templateId path string true "정책 템플릿 식별자(uuid)" -// @Param body body domain.UpdateClusterPolicyTemplateStatusRequest true "update cluster policy template status request" -// @Success 200 {object} nil -// @Router /clusters/{clusterId}/policy-templates/{policyTemplateId} [patch] +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param stackId path string true "스택 식별자" +// @Param policyTemplateId path string true "정책 템플릿 식별자(uuid)" +// @Param body body domain.UpdateStackPolicyTemplateStatusRequest true "update stack policy template status request" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId} [patch] // @Security JWT -func (h *PolicyHandler) UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) { +func (h *PolicyHandler) UpdateStackPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - clusterId, ok := vars["clusterId"] + stackId, ok := vars["stackId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), - "C_INVALID_CLUSTER_ID", "")) + "C_INVALID_STACK_ID", "")) return } @@ -719,7 +722,7 @@ func (h *PolicyHandler) UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, return } - input := domain.UpdateClusterPolicyTemplateStatusRequest{} + input := domain.UpdateStackPolicyTemplateStatusRequest{} err := UnmarshalRequestInput(r, &input) @@ -735,7 +738,7 @@ func (h *PolicyHandler) UpdateClusterPolicyTemplateStatus(w http.ResponseWriter, return } - err = h.usecase.UpdateClusterPolicyTemplateStatus(r.Context(), clusterId, id, + err = h.usecase.UpdateStackPolicyTemplateStatus(r.Context(), stackId, id, input.TemplateCurrentVersion, input.TemplateTargetVerson) if err != nil { diff --git a/internal/model/permission.go b/internal/model/permission.go index b81ec8a4..595596d3 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -285,9 +285,9 @@ func newPolicy() *Permission { api.Admin_ExistsPolicyTemplateName, api.Admin_ExistsPolicyTemplateKind, - // ClusterPolicyStatus - api.ListClusterPolicyStatus, - api.GetClusterPolicyTemplateStatus, + // StackPolicyStatus + api.ListStackPolicyStatus, + api.GetStackPolicyTemplateStatus, // Policy api.GetMandatoryPolicies, @@ -339,7 +339,7 @@ func newPolicy() *Permission { api.Admin_UpdatePolicyTemplate, // ClusterPolicyStatus - api.UpdateClusterPolicyTemplateStatus, + api.UpdateStackPolicyTemplateStatus, // Policy api.UpdatePolicy, diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go index ccf4fa27..55603847 100644 --- a/internal/policy-template/paramdef-util.go +++ b/internal/policy-template/paramdef-util.go @@ -23,9 +23,7 @@ func GetNewParamDefs(paramdefs1 []*domain.ParameterDef, paramdefs2 []*domain.Par if paramdef1 == nil { // Not found, it's new parameter result = append(result, paramdef2) - } - - if !CompareParamDef(paramdef2, paramdef1) { + } else if !CompareParamDef(paramdef2, paramdef1) { return nil, fmt.Errorf("not compatible, parameter definition of '%s' is changed", paramdef2.Key) } } diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 844e9afd..ca0e3cd1 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -124,7 +124,7 @@ func (r *PolicyRepository) FetchByClusterIdAndTemplaeId(ctx context.Context, clu Where("cluster_id = ?", clusterId) res := r.db.WithContext(ctx).Preload(clause.Associations). - Where("template_id = ?").Where("id in (?)", subQueryClusterId).Find(&out) + Where("template_id = ?", templateId).Where("id in (?)", subQueryClusterId).Find(&out) if res.Error != nil { return nil, res.Error diff --git a/internal/route/route.go b/internal/route/route.go index b8906bf6..2b0de38c 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -353,9 +353,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.AddPoliciesForStack, http.HandlerFunc(policyHandler.AddPoliciesForStack))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.DeletePoliciesForStack, http.HandlerFunc(policyHandler.DeletePoliciesForStack))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-status", customMiddleware.Handle(internalApi.ListClusterPolicyStatus, http.HandlerFunc(policyHandler.ListClusterPolicyStatus))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.GetClusterPolicyTemplateStatus))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdateClusterPolicyTemplateStatus, http.HandlerFunc(policyHandler.UpdateClusterPolicyTemplateStatus))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policy-status", customMiddleware.Handle(internalApi.ListStackPolicyStatus, http.HandlerFunc(policyHandler.ListStackPolicyStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetStackPolicyTemplateStatus, http.HandlerFunc(policyHandler.GetStackPolicyTemplateStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.UpdateStackPolicyTemplateStatus, http.HandlerFunc(policyHandler.UpdateStackPolicyTemplateStatus))).Methods(http.MethodPatch) // assets r.PathPrefix("/api/").HandlerFunc(http.NotFound) diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 08732137..2a7eb41a 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -17,6 +17,7 @@ import ( "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/utils/strings/slices" ) @@ -34,9 +35,9 @@ type IPolicyUsecase interface { UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusterIds []string) (err error) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) GetMandatoryPolicies(ctx context.Context, organizationId string) (response *domain.GetMandatoryPoliciesResponse, err error) - ListClusterPolicyStatus(ctx context.Context, clusterId string, pg *pagination.Pagination) (policyStatuses []domain.ClusterPolicyStatusResponse, err error) - GetClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID) (clusterPolicyTemplateStatusResponse *domain.GetClusterPolicyTemplateStatusResponse, err error) - UpdateClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID, + ListStackPolicyStatus(ctx context.Context, clusterId string, pg *pagination.Pagination) (policyStatuses []domain.StackPolicyStatusResponse, err error) + GetStackPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID) (clusterPolicyTemplateStatusResponse *domain.GetStackPolicyTemplateStatusResponse, err error) + UpdateStackPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID, currentVersion string, targetVerson string) (err error) GetPolicyStatistics(ctx context.Context, organizationId string) (response *domain.PolicyStatisticsResponse, err error) AddPoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) @@ -509,7 +510,7 @@ func (u *PolicyUsecase) GetMandatoryPolicies(ctx context.Context, organizationId return &out, nil } -func (u *PolicyUsecase) ListClusterPolicyStatus(ctx context.Context, clusterId string, pg *pagination.Pagination) (policyStatuses []domain.ClusterPolicyStatusResponse, err error) { +func (u *PolicyUsecase) ListStackPolicyStatus(ctx context.Context, clusterId string, pg *pagination.Pagination) (policyStatuses []domain.StackPolicyStatusResponse, err error) { policies, err := u.repo.FetchByClusterId(ctx, clusterId, pg) if err != nil { @@ -530,7 +531,7 @@ func (u *PolicyUsecase) ListClusterPolicyStatus(ctx context.Context, clusterId s // return nil, err // } - result := make([]domain.ClusterPolicyStatusResponse, len(*policies)) + result := make([]domain.StackPolicyStatusResponse, len(*policies)) for i, policy := range *policies { if err := serializer.Map(ctx, policy, &result[i]); err != nil { @@ -562,7 +563,7 @@ func (u *PolicyUsecase) ListClusterPolicyStatus(ctx context.Context, clusterId s return result, nil } -func (u *PolicyUsecase) UpdateClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID, +func (u *PolicyUsecase) UpdateStackPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID, currentVersion string, targetVerson string) (err error) { if currentVersion == targetVerson { // 버전 동일, 할일 없음 @@ -618,7 +619,7 @@ func (u *PolicyUsecase) UpdateClusterPolicyTemplateStatus(ctx context.Context, c return policytemplate.UpdateTksPolicyTemplateCR(ctx, primaryClusterId, tksPolicyTemplate) } -func (u *PolicyUsecase) GetClusterPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID) (clusterPolicyTemplateStatusResponse *domain.GetClusterPolicyTemplateStatusResponse, err error) { +func (u *PolicyUsecase) GetStackPolicyTemplateStatus(ctx context.Context, clusterId string, policyTemplateId uuid.UUID) (stackPolicyTemplateStatusResponse *domain.GetStackPolicyTemplateStatusResponse, err error) { policies, err := u.repo.FetchByClusterIdAndTemplaeId(ctx, clusterId, policyTemplateId) if err != nil { @@ -630,6 +631,10 @@ func (u *PolicyUsecase) GetClusterPolicyTemplateStatus(ctx context.Context, clus return nil, err } + if latestTemplate == nil { + return nil, httpErrors.NewBadRequestError(err, "P_FAILED_FETCH_TEMPLATE", "") + } + // policies가 빈 목록일 수도 있으므로 policy의 organization 정보는 못 가져올 수도 있음 // 따라서 cluster의 Organization에서 primaryClusterId를 가져옴 cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(clusterId)) @@ -650,13 +655,20 @@ func (u *PolicyUsecase) GetClusterPolicyTemplateStatus(ctx context.Context, clus // return nil, fmt.Errorf("version not found in CR") // } + var version string + tksPolicyTemplateCR, err := policytemplate.GetTksPolicyTemplateCR(ctx, primaryClusterId, latestTemplate.ResoureName()) if err != nil { - return nil, err + if errors.IsNotFound(err) { + // CR이 배포되지 않았으므로 최신 버전이 현재 버전임(앞으로 설치될 모든 정책은 이 버전으로 설치되므로) + version = latestTemplate.Version + } else { + return nil, err + } + } else { + version = tksPolicyTemplateCR.Spec.Version } - version := tksPolicyTemplateCR.Spec.Version - currentTemplate, err := u.templateRepo.GetPolicyTemplateVersion(ctx, policyTemplateId, version) if err != nil { return nil, err @@ -682,7 +694,7 @@ func (u *PolicyUsecase) GetClusterPolicyTemplateStatus(ctx context.Context, clus affectedPolicies[i].PolicyParameters = parsed } - result := domain.GetClusterPolicyTemplateStatusResponse{ + result := domain.GetStackPolicyTemplateStatusResponse{ TemplateName: currentTemplate.TemplateName, TemplateId: policyTemplateId.String(), TemplateDescription: currentTemplate.Description, diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index 88b18343..5416f828 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -125,7 +125,7 @@ type SetMandatoryPoliciesRequest struct { Policies []MandatoryPolicyPatchInfo `json:"policies"` } -type ClusterPolicyStatusResponse struct { +type StackPolicyStatusResponse struct { PolicyName string `json:"policyName" example:"org 레이블 요구"` PolicyId string `json:"policyId" example:"0091fe9b-e44b-423d-9562-ac2b73089593"` PolicyDescription string `json:"policyDescription" example:"org 레이블 설정 여부 검사"` @@ -137,11 +137,11 @@ type ClusterPolicyStatusResponse struct { TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` } -type ListClusterPolicyStatusResponse struct { - Polices []ClusterPolicyStatusResponse `json:"polices"` +type ListStackPolicyStatusResponse struct { + Polices []StackPolicyStatusResponse `json:"polices"` } -type GetClusterPolicyTemplateStatusResponse struct { +type GetStackPolicyTemplateStatusResponse struct { TemplateName string `json:"templateName" example:"레이블 요구"` TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` TemplateDescription string `json:"templateDescription" example:"파라미터로 설정된 레이블 검사"` @@ -182,7 +182,7 @@ type PolicyUpdate struct { UpdatedPolicyParameters []UpdatedPolicyParameters `json:"updatedPolicyParameters"` } -type UpdateClusterPolicyTemplateStatusRequest struct { +type UpdateStackPolicyTemplateStatusRequest struct { TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` TemplateTargetVerson string `json:"templateTargetVerson" example:"v1.0.3"` // PolicyUpdate []PolicyUpdate `json:"policyUpdate"` diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index c48e0404..3b90a6a9 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -136,6 +136,7 @@ var errorMap = map[ErrorCode]string{ "P_INVALID_MATCH": "유효하지 않은 match 설정입니다. match 설정을 확인하세요.", "P_FAILED_FETCH_POLICY": "정책 ID에 해당하는 정책을 가져오는데 실패했습니다.", "P_FAILED_FETCH_CLUSTER": "정책의 클러스터 정보를 가져오는데 실패했습니다.", + "P_FAILED_FETCH_TEMPLATE": "정책의 클러스터 정보를 가져오는데 실패했습니다.", "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", } From 59c946aa4885b130dc60bce25fd16790f601592f Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 8 Apr 2024 17:41:21 +0900 Subject: [PATCH 256/502] tirivial. update message for systemNotification --- internal/usecase/system-notification-rule.go | 20 ++++++++++---------- scripts/init_postgres.sql | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 5631e33e..7a03c18f 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -194,8 +194,8 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "스택 (<>)의 노드(<>)의 idle process의 cpu 점유율이 3분 동안 0% 입니다. (현재 사용률 {{$value}})", - MessageContent: "워커 노드 CPU가 과부하 상태입니다. 일시적인 서비스 Traffic 증가, Workload의 SW 오류, Server HW Fan Fail등 다양한 원인으로 인해 발생할 수 있습니다.", + MessageTitle: "CPU 사용량이 높습니다", + MessageContent: "스택 (<>)의 노드(<>)의 idle process의 cpu 점유율이 3분 동안 0% 입니다. (현재 사용률 {{$value}}). 워커 노드 CPU가 과부하 상태입니다. 일시적인 서비스 Traffic 증가, Workload의 SW 오류, Server HW Fan Fail등 다양한 원인으로 인해 발생할 수 있습니다.", MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행 되는 pod중 CPU 자원을 많이 점유하는 pod의 설정을 점검해 보시길 제안드립니다. 예를 들어 pod spec의 limit 설정으로 과도한 CPU자원 점유을 막을 수 있습니다.", Status: domain.SystemNotificationRuleStatus_PENDING, CreatorId: organization.AdminId, @@ -219,8 +219,8 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "스택 (<>)의 노드(<>)의 Memory 사용량이 3분동안 80% 를 넘어서고 있습니다. (현재 사용률 {{$value}})", - MessageContent: "워커 노드의 Memory 사용량이 80%를 넘었습니다. 일시적인 서비스 증가 및 SW 오류등 다양한 원인으로 발생할 수 있습니다.", + MessageTitle: "메모리 사용량이 높습니다", + MessageContent: "스택 (<>)의 노드(<>)의 Memory 사용량이 3분동안 80% 를 넘어서고 있습니다. (현재 사용률 {{$value}}). 워커 노드의 Memory 사용량이 80%를 넘었습니다. 일시적인 서비스 증가 및 SW 오류등 다양한 원인으로 발생할 수 있습니다.", MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행되는 pod중 Memory 사용량이 높은 pod들에 대한 점검을 제안드립니다.", Status: domain.SystemNotificationRuleStatus_PENDING, CreatorId: organization.AdminId, @@ -244,8 +244,8 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "지난 6시간동안의 추세로 봤을 때, 스택 (<>)의 노드(<>)의 root 볼륨은 24시간 안에 Disk full이 예상됨", - MessageContent: "현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰 것으로 예상됩니다.", + MessageTitle: "노드 디스크 사용량이 높습니다.", + MessageContent: "지난 6시간동안의 추세로 봤을 때, 스택 (<>)의 노드(<>)의 root 볼륨은 24시간 안에 Disk full이 예상됨. 현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰 것으로 예상됩니다.", MessageActionProposal: "Disk 용량 최적화(삭제 및 Backup)을 수행하시길 권고합니다. 삭제할 내역이 없으면 증설 계획을 수립해 주십시요.", Status: domain.SystemNotificationRuleStatus_PENDING, CreatorId: organization.AdminId, @@ -269,8 +269,8 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "지난 6시간동안의 추세로 봤을 때, 스택 (<>)의 파드(<>)가 24시간 안에 Disk full이 예상됨", - MessageContent: "현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰것으로 예상됩니다. (<> 스택, <> PVC)", + MessageTitle: "PVC 사용량이 높습니다.", + MessageContent: "지난 6시간동안의 추세로 봤을 때, 스택 (<>)의 파드(<>)가 24시간 안에 Disk full이 예상됨. 현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰것으로 예상됩니다. (<> 스택, <> PVC)", MessageActionProposal: "Disk 용량 최적화(삭제 및 Backup)을 수행하시길 권고합니다. 삭제할 내역이 없으면 증설 계획을 수립해 주십시요.", Status: domain.SystemNotificationRuleStatus_PENDING, CreatorId: organization.AdminId, @@ -294,8 +294,8 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "스택 (<>)의 파드(<>)가 30분 동안 5회 이상 재기동 ({{$value}} 회)", - MessageContent: "특정 Pod가 빈번하게 재기동 되고 있습니다. 점검이 필요합니다. (<> 스택, <> 파드)", + MessageTitle: "스택의 Pod가 재기동되고 있습니다.", + MessageContent: "스택 (<>)의 파드(<>)가 30분 동안 5회 이상 재기동 ({{$value}} 회). 특정 Pod가 빈번하게 재기동 되고 있습니다. 점검이 필요합니다. (<> 스택, <> 파드)", MessageActionProposal: "pod spec. 에 대한 점검이 필요합니다. pod의 log 및 status를 확인해 주세요.", Status: domain.SystemNotificationRuleStatus_PENDING, CreatorId: organization.AdminId, diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index e0feb969..1949a37e 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -65,7 +65,9 @@ values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-ful insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'predict_linear(kubelet_volume_stats_available_bytes[6h], 24*3600)', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', true, 'pod-restart-frequently', 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:])', null, null, now(), now() ); +values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', 'pod-restart-frequently', true, 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:])', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('7355d0f9-7c14-4f70-92ea-a9868624ff82', 'policy-audited', 'policy-audited', true, 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system"}', null, null, now(), now() ); ## SystemNotificationTemplates -> SystemNotificationMetricParameters insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) @@ -90,3 +92,17 @@ insert into system_notification_metric_parameters ( "order", system_notification values ( 1, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'POD', '$labels.pod', now(), now() ); insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) values ( 2, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'NAMESPACE', '$labels.namespace', now(), now() ); +values ( 0, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'STACK', '$labels.taco_cluster', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 1, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'NAME', '$labels.name', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 2, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'KIND', '$labels.kind', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 3, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'VIOLATING_KIND', '$labels.violating_kind', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 4, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'VIOLATING_NAMESPACE', '$labels.violating_namespace', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 5, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'VIOLATING_NAME', '$labels.violating_name', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 6, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'VIOLATION_MSG', '$labels.violation_msg', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) From 93c08e93dc08d0d723897eba9fe3db05392a1fb8 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 8 Apr 2024 18:59:15 +0900 Subject: [PATCH 257/502] feature. add policy type to systemNotification --- api/swagger/docs.go | 838 ++++++++++++------ api/swagger/swagger.json | 838 ++++++++++++------ api/swagger/swagger.yaml | 528 +++++++---- internal/model/system-notification-rule.go | 1 + .../model/system-notification-template.go | 1 + internal/model/system-notification.go | 1 + internal/usecase/system-notification-rule.go | 31 + pkg/domain/system-notification-rule.go | 4 +- pkg/domain/system-notification-template.go | 6 + pkg/domain/system-notification.go | 4 +- scripts/init_postgres.sql | 24 +- 11 files changed, 1494 insertions(+), 782 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 46656d28..dcfb0919 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -241,6 +241,90 @@ const docTemplate = `{ } } }, + "/admin/organizations/{organizationId}/policyTemplates": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 조직에 대해 허용된 tks 템플릿의 허용 상태를 해제(제거)한다. tks 우형 템플릿에 대해서만 동작하고 organization 유형 템플릿에 대해서는 거부된다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_DeletePermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 제거", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "delete pemitted policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 조직에 대해 허용된 tks 템플릿 목록을 추가한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_AddPermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 추가", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update pemitted policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -2426,169 +2510,6 @@ const docTemplate = `{ } } }, - "/clusters/{clusterId}/policy-status": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "sortColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse" - } - } - } - } - }, - "/clusters/{clusterId}/policy-templates/{templateId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "templateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse" - } - } - } - }, - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "templateId", - "in": "path", - "required": true - }, - { - "description": "update cluster policy template status request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/clusters/{clusterId}/site-values": { "get": { "security": [ @@ -8095,14 +8016,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { + "/organizations/{organizationId}/stacks/{stackId}/policies": { + "put": { "security": [ { "JWT": [] } ], - "description": "Get Stack Status", + "description": "특정 스택에서 정책 식별자로 지정된 정책을 제거한다.", "consumes": [ "application/json" ], @@ -8110,43 +8031,43 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Stacks" + "Policy" ], - "summary": "Get Stack Status", + "summary": "[DeletePoliciesForStack] 특정 스택의 정책 제거", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", + "description": "스택 식별자", "name": "stackId", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK", + }, + { + "description": "delete policies for stack request", + "name": "body", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest" } } - } - } - }, - "/organizations/{organizationId}/system-notification-rules": { - "get": { + ], + "responses": {} + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotificationRules", + "description": "특정 스택의 정책 목록을 정책 식별자 리스트로 지정해서 추가한다.", "consumes": [ "application/json" ], @@ -8154,13 +8075,291 @@ const docTemplate = `{ "application/json" ], "tags": [ - "SystemNotificationRules" + "Policy" ], - "summary": "Get SystemNotificationRules", + "summary": "[AddPoliciesForStack] 특정 스택의 정책 목록 추가", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "add policies for stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/policy-status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[GetStackPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse" + } + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[UpdateStackPolicyTemplateStatus] 템플릿 버전 업데이트", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "update stack policy template status request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack Status", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/system-notification-rules": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotificationRules", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationRules" + ], + "summary": "Get SystemNotificationRules", + "parameters": [ + { + "type": "string", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true @@ -9646,6 +9845,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest": { + "type": "object", + "properties": { + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest": { "type": "object", "properties": { @@ -10350,46 +10560,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse": { - "type": "object", - "properties": { - "policyDescription": { - "type": "string", - "example": "org 레이블 설정 여부 검사" - }, - "policyId": { - "type": "string", - "example": "0091fe9b-e44b-423d-9562-ac2b73089593" - }, - "policyMandatory": { - "type": "boolean" - }, - "policyName": { - "type": "string", - "example": "org 레이블 요구" - }, - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateDescription": { - "type": "string", - "example": "파라미터로 설정된 레이블 검사" - }, - "templateId": { - "type": "string", - "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" - }, - "templateLatestVerson": { - "type": "string", - "example": "v1.0.3" - }, - "templateName": { - "type": "string", - "example": "레이블 요구" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ClusterResponse": { "type": "object", "properties": { @@ -11536,6 +11706,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest": { + "type": "object", + "properties": { + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest": { "type": "object", "properties": { @@ -11822,50 +12003,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse": { - "type": "object", - "properties": { - "affectedPolicies": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" - } - }, - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateDescription": { - "type": "string", - "example": "파라미터로 설정된 레이블 검사" - }, - "templateId": { - "type": "string", - "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" - }, - "templateLatestVerson": { - "type": "string", - "example": "v1.0.3" - }, - "templateLatestVersonReleaseDate": { - "type": "string", - "format": "date-time" - }, - "templateMandatory": { - "type": "boolean" - }, - "templateName": { - "type": "string", - "example": "레이블 요구" - }, - "updatedPolicyParameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { "type": "object", "properties": { @@ -12189,6 +12326,50 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse": { + "type": "object", + "properties": { + "affectedPolicies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" + } + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateLatestVersonReleaseDate": { + "type": "string", + "format": "date-time" + }, + "templateMandatory": { + "type": "boolean" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + }, + "updatedPolicyParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetStackResponse": { "type": "object", "properties": { @@ -12481,17 +12662,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse": { - "type": "object", - "properties": { - "polices": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -12561,6 +12731,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse": { + "type": "object", + "properties": { + "polices": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { "type": "object", "properties": { @@ -13761,6 +13942,46 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse": { + "type": "object", + "properties": { + "policyDescription": { + "type": "string", + "example": "org 레이블 설정 여부 검사" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyMandatory": { + "type": "boolean" + }, + "policyName": { + "type": "string", + "example": "org 레이블 요구" + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackResponse": { "type": "object", "properties": { @@ -14066,6 +14287,9 @@ const docTemplate = `{ "node": { "type": "string" }, + "notificationType": { + "type": "string" + }, "organizationId": { "type": "string" }, @@ -14113,6 +14337,9 @@ const docTemplate = `{ "id": { "type": "string" }, + "isSystem": { + "type": "boolean" + }, "messageActionProposal": { "type": "string" }, @@ -14163,6 +14390,9 @@ const docTemplate = `{ "id": { "type": "string" }, + "isSystem": { + "type": "boolean" + }, "metricParameters": { "type": "array", "items": { @@ -14326,19 +14556,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest": { - "type": "object", - "properties": { - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateTargetVerson": { - "type": "string", - "example": "v1.0.3" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest": { "type": "object", "properties": { @@ -14648,6 +14865,19 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest": { + "type": "object", + "properties": { + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateTargetVerson": { + "type": "string", + "example": "v1.0.3" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { "type": "object", "properties": { @@ -15045,6 +15275,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest": { + "type": "object", + "properties": { + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse": { "type": "object", "properties": { @@ -15169,6 +15410,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest": { + "type": "object", + "properties": { + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 130baeed..fd5e6aee 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -235,6 +235,90 @@ } } }, + "/admin/organizations/{organizationId}/policyTemplates": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 조직에 대해 허용된 tks 템플릿의 허용 상태를 해제(제거)한다. tks 우형 템플릿에 대해서만 동작하고 organization 유형 템플릿에 대해서는 거부된다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_DeletePermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 제거", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "delete pemitted policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 조직에 대해 허용된 tks 템플릿 목록을 추가한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_AddPermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 추가", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update pemitted policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -2420,169 +2504,6 @@ } } }, - "/clusters/{clusterId}/policy-status": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "sortColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse" - } - } - } - } - }, - "/clusters/{clusterId}/policy-templates/{templateId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "templateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse" - } - } - } - }, - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "templateId", - "in": "path", - "required": true - }, - { - "description": "update cluster policy template status request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/clusters/{clusterId}/site-values": { "get": { "security": [ @@ -8089,14 +8010,14 @@ } } }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { + "/organizations/{organizationId}/stacks/{stackId}/policies": { + "put": { "security": [ { "JWT": [] } ], - "description": "Get Stack Status", + "description": "특정 스택에서 정책 식별자로 지정된 정책을 제거한다.", "consumes": [ "application/json" ], @@ -8104,43 +8025,43 @@ "application/json" ], "tags": [ - "Stacks" + "Policy" ], - "summary": "Get Stack Status", + "summary": "[DeletePoliciesForStack] 특정 스택의 정책 제거", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "조직 식별자(o로 시작)", "name": "organizationId", "in": "path", "required": true }, { "type": "string", - "description": "stackId", + "description": "스택 식별자", "name": "stackId", "in": "path", "required": true - } - ], - "responses": { - "200": { - "description": "OK", + }, + { + "description": "delete policies for stack request", + "name": "body", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest" } } - } - } - }, - "/organizations/{organizationId}/system-notification-rules": { - "get": { + ], + "responses": {} + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get SystemNotificationRules", + "description": "특정 스택의 정책 목록을 정책 식별자 리스트로 지정해서 추가한다.", "consumes": [ "application/json" ], @@ -8148,13 +8069,291 @@ "application/json" ], "tags": [ - "SystemNotificationRules" + "Policy" ], - "summary": "Get SystemNotificationRules", + "summary": "[AddPoliciesForStack] 특정 스택의 정책 목록 추가", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "add policies for stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/policy-status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[GetStackPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse" + } + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[UpdateStackPolicyTemplateStatus] 템플릿 버전 업데이트", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "update stack policy template status request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Stack Status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Get Stack Status", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/system-notification-rules": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get SystemNotificationRules", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationRules" + ], + "summary": "Get SystemNotificationRules", + "parameters": [ + { + "type": "string", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true @@ -9640,6 +9839,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest": { + "type": "object", + "properties": { + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest": { "type": "object", "properties": { @@ -10344,46 +10554,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse": { - "type": "object", - "properties": { - "policyDescription": { - "type": "string", - "example": "org 레이블 설정 여부 검사" - }, - "policyId": { - "type": "string", - "example": "0091fe9b-e44b-423d-9562-ac2b73089593" - }, - "policyMandatory": { - "type": "boolean" - }, - "policyName": { - "type": "string", - "example": "org 레이블 요구" - }, - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateDescription": { - "type": "string", - "example": "파라미터로 설정된 레이블 검사" - }, - "templateId": { - "type": "string", - "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" - }, - "templateLatestVerson": { - "type": "string", - "example": "v1.0.3" - }, - "templateName": { - "type": "string", - "example": "레이블 요구" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ClusterResponse": { "type": "object", "properties": { @@ -11530,6 +11700,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest": { + "type": "object", + "properties": { + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest": { "type": "object", "properties": { @@ -11816,50 +11997,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse": { - "type": "object", - "properties": { - "affectedPolicies": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" - } - }, - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateDescription": { - "type": "string", - "example": "파라미터로 설정된 레이블 검사" - }, - "templateId": { - "type": "string", - "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" - }, - "templateLatestVerson": { - "type": "string", - "example": "v1.0.3" - }, - "templateLatestVersonReleaseDate": { - "type": "string", - "format": "date-time" - }, - "templateMandatory": { - "type": "boolean" - }, - "templateName": { - "type": "string", - "example": "레이블 요구" - }, - "updatedPolicyParameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { "type": "object", "properties": { @@ -12183,6 +12320,50 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse": { + "type": "object", + "properties": { + "affectedPolicies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" + } + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateLatestVersonReleaseDate": { + "type": "string", + "format": "date-time" + }, + "templateMandatory": { + "type": "boolean" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + }, + "updatedPolicyParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetStackResponse": { "type": "object", "properties": { @@ -12475,17 +12656,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse": { - "type": "object", - "properties": { - "polices": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -12555,6 +12725,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse": { + "type": "object", + "properties": { + "polices": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { "type": "object", "properties": { @@ -13755,6 +13936,46 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse": { + "type": "object", + "properties": { + "policyDescription": { + "type": "string", + "example": "org 레이블 설정 여부 검사" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyMandatory": { + "type": "boolean" + }, + "policyName": { + "type": "string", + "example": "org 레이블 요구" + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackResponse": { "type": "object", "properties": { @@ -14060,6 +14281,9 @@ "node": { "type": "string" }, + "notificationType": { + "type": "string" + }, "organizationId": { "type": "string" }, @@ -14107,6 +14331,9 @@ "id": { "type": "string" }, + "isSystem": { + "type": "boolean" + }, "messageActionProposal": { "type": "string" }, @@ -14157,6 +14384,9 @@ "id": { "type": "string" }, + "isSystem": { + "type": "boolean" + }, "metricParameters": { "type": "array", "items": { @@ -14320,19 +14550,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest": { - "type": "object", - "properties": { - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateTargetVerson": { - "type": "string", - "example": "v1.0.3" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest": { "type": "object", "properties": { @@ -14642,6 +14859,19 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest": { + "type": "object", + "properties": { + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateTargetVerson": { + "type": "string", + "example": "v1.0.3" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { "type": "object", "properties": { @@ -15039,6 +15269,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest": { + "type": "object", + "properties": { + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse": { "type": "object", "properties": { @@ -15163,6 +15404,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest": { + "type": "object", + "properties": { + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 529fffb5..1d148e55 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -158,6 +158,13 @@ definitions: required: - systemNotificationTemplateIds type: object + github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest: + properties: + policyIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest: properties: projectMembers: @@ -644,35 +651,6 @@ definitions: validity: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse: - properties: - policyDescription: - example: org 레이블 설정 여부 검사 - type: string - policyId: - example: 0091fe9b-e44b-423d-9562-ac2b73089593 - type: string - policyMandatory: - type: boolean - policyName: - example: org 레이블 요구 - type: string - templateCurrentVersion: - example: v1.0.1 - type: string - templateDescription: - example: 파라미터로 설정된 레이블 검사 - type: string - templateId: - example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 - type: string - templateLatestVerson: - example: v1.0.3 - type: string - templateName: - example: 레이블 요구 - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.ClusterResponse: properties: byoClusterEndpointHost: @@ -1452,6 +1430,13 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest: + properties: + policyIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest: properties: adminPassword: @@ -1638,37 +1623,6 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode' type: array type: object - github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse: - properties: - affectedPolicies: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus' - type: array - templateCurrentVersion: - example: v1.0.1 - type: string - templateDescription: - example: 파라미터로 설정된 레이블 검사 - type: string - templateId: - example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 - type: string - templateLatestVerson: - example: v1.0.3 - type: string - templateLatestVersonReleaseDate: - format: date-time - type: string - templateMandatory: - type: boolean - templateName: - example: 레이블 요구 - type: string - updatedPolicyParameters: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter' - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse: properties: cluster: @@ -1875,6 +1829,37 @@ definitions: kubeConfig: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse: + properties: + affectedPolicies: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus' + type: array + templateCurrentVersion: + example: v1.0.1 + type: string + templateDescription: + example: 파라미터로 설정된 레이블 검사 + type: string + templateId: + example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 + type: string + templateLatestVerson: + example: v1.0.3 + type: string + templateLatestVersonReleaseDate: + format: date-time + type: string + templateMandatory: + type: boolean + templateName: + example: 레이블 요구 + type: string + updatedPolicyParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetStackResponse: properties: stack: @@ -2064,13 +2049,6 @@ definitions: type: string type: array type: object - github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse: - properties: - polices: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse' - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse: properties: organizations: @@ -2116,6 +2094,13 @@ definitions: type: string type: array type: object + github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse: + properties: + polices: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse: properties: pagination: @@ -2920,6 +2905,35 @@ definitions: - tksInfraNode - tksUserNode type: object + github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse: + properties: + policyDescription: + example: org 레이블 설정 여부 검사 + type: string + policyId: + example: 0091fe9b-e44b-423d-9562-ac2b73089593 + type: string + policyMandatory: + type: boolean + policyName: + example: org 레이블 요구 + type: string + templateCurrentVersion: + example: v1.0.1 + type: string + templateDescription: + example: 파라미터로 설정된 레이블 검사 + type: string + templateId: + example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 + type: string + templateLatestVerson: + example: v1.0.3 + type: string + templateName: + example: 레이블 요구 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.StackResponse: properties: cloudAccount: @@ -3121,6 +3135,8 @@ definitions: type: string node: type: string + notificationType: + type: string organizationId: type: string processingSec: @@ -3152,6 +3168,8 @@ definitions: type: string id: type: string + isSystem: + type: boolean messageActionProposal: type: string messageContent: @@ -3183,6 +3201,8 @@ definitions: type: string id: type: string + isSystem: + type: boolean metricParameters: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse' @@ -3292,15 +3312,6 @@ definitions: description: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest: - properties: - templateCurrentVersion: - example: v1.0.1 - type: string - templateTargetVerson: - example: v1.0.3 - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest: properties: groupName: @@ -3509,6 +3520,15 @@ definitions: required: - name type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest: + properties: + templateCurrentVersion: + example: v1.0.1 + type: string + templateTargetVerson: + example: v1.0.3 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest: properties: description: @@ -3776,6 +3796,13 @@ definitions: startY: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest: + properties: + policyTemplateIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse: properties: id: @@ -3864,6 +3891,13 @@ definitions: example: v1.1.1 type: string type: object + github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest: + properties: + policyTemplateIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse: properties: existed: @@ -4201,6 +4235,62 @@ paths: summary: Create organization in Admin portal tags: - Organizations + /admin/organizations/{organizationId}/policyTemplates: + post: + consumes: + - application/json + description: 특정 조직에 대해 허용된 tks 템플릿 목록을 추가한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: update pemitted policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[Admin_AddPermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks + 템플릿 목록 추가' + tags: + - PolicyTemplate + put: + consumes: + - application/json + description: 특정 조직에 대해 허용된 tks 템플릿의 허용 상태를 해제(제거)한다. tks 우형 템플릿에 대해서만 동작하고 organization + 유형 템플릿에 대해서는 거부된다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: delete pemitted policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[Admin_DeletePermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 + tks 템플릿 목록 제거' + tags: + - PolicyTemplate /admin/organizations/{organizationId}/projects: get: consumes: @@ -5562,111 +5652,6 @@ paths: summary: Get nodes information for BYOH tags: - Clusters - /clusters/{clusterId}/policy-status: - get: - consumes: - - application/json - description: 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. - parameters: - - description: 클러스터 식별자(uuid) - in: path - name: clusterId - required: true - type: string - - description: pageSize - in: query - name: pageSize - type: string - - description: pageNumber - in: query - name: pageNumber - type: string - - description: sortColumn - in: query - name: sortColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse' - security: - - JWT: [] - summary: '[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회' - tags: - - ClusterPolicyStatus - /clusters/{clusterId}/policy-templates/{templateId}: - get: - consumes: - - application/json - description: 템플릿의 클러스터 버전 등 상태를 조회한다. - parameters: - - description: 클러스터 식별자(uuid) - in: path - name: clusterId - required: true - type: string - - description: 정책 템플릿 식별자(uuid) - in: path - name: templateId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse' - security: - - JWT: [] - summary: '[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회' - tags: - - ClusterPolicyStatus - patch: - consumes: - - application/json - description: 해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다. - parameters: - - description: 클러스터 식별자(uuid) - in: path - name: clusterId - required: true - type: string - - description: 정책 템플릿 식별자(uuid) - in: path - name: templateId - required: true - type: string - - description: update cluster policy template status request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: '[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트' - tags: - - ClusterPolicyStatus /clusters/{clusterId}/site-values: get: consumes: @@ -9175,6 +9160,187 @@ paths: summary: Get KubeConfig by stack tags: - Stacks + /organizations/{organizationId}/stacks/{stackId}/policies: + post: + consumes: + - application/json + description: 특정 스택의 정책 목록을 정책 식별자 리스트로 지정해서 추가한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: add policies for stack request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[AddPoliciesForStack] 특정 스택의 정책 목록 추가' + tags: + - Policy + put: + consumes: + - application/json + description: 특정 스택에서 정책 식별자로 지정된 정책을 제거한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: delete policies for stack request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest' + produces: + - application/json + responses: {} + security: + - JWT: [] + summary: '[DeletePoliciesForStack] 특정 스택의 정책 제거' + tags: + - Policy + /organizations/{organizationId}/stacks/{stackId}/policy-status: + get: + consumes: + - application/json + description: 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: pageSize + in: query + name: pageSize + type: string + - description: pageNumber + in: query + name: pageNumber + type: string + - description: sortColumn + in: query + name: sortColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse' + security: + - JWT: [] + summary: '[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회' + tags: + - StackPolicyStatus + /organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}: + get: + consumes: + - application/json + description: 템플릿의 클러스터 버전 등 상태를 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse' + security: + - JWT: [] + summary: '[GetStackPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회' + tags: + - StackPolicyStatus + patch: + consumes: + - application/json + description: 해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: update stack policy template status request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[UpdateStackPolicyTemplateStatus] 템플릿 버전 업데이트' + tags: + - StackPolicyStatus /organizations/{organizationId}/stacks/{stackId}/status: get: consumes: diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index 76534929..de12cfaf 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -25,6 +25,7 @@ type SystemNotificationRule struct { ID uuid.UUID `gorm:"primarykey"` Name string `gorm:"index,unique"` Description string + NotificationType string `gorm:"default:SYSTEM_NOTIFICATION"` OrganizationId string Organization Organization `gorm:"foreignKey:OrganizationId"` IsSystem bool `gorm:"default:false"` diff --git a/internal/model/system-notification-template.go b/internal/model/system-notification-template.go index 7639442b..48d5e427 100644 --- a/internal/model/system-notification-template.go +++ b/internal/model/system-notification-template.go @@ -20,6 +20,7 @@ type SystemNotificationTemplate struct { ID uuid.UUID `gorm:"primarykey"` Name string `gorm:"index:idx_name,unique"` + NotificationType string `gorm:"default:SYSTEM_NOTIFICATION"` IsSystem bool `gorm:"default:false"` Organizations []Organization `gorm:"many2many:system_notification_template_organizations;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` OrganizationIds []string `gorm:"-:all"` diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go index bd380cb6..ca707c70 100644 --- a/internal/model/system-notification.go +++ b/internal/model/system-notification.go @@ -15,6 +15,7 @@ type SystemNotification struct { ID uuid.UUID `gorm:"primarykey"` Name string + NotificationType string `gorm:"default:SYSTEM_NOTIFICATION"` OrganizationId string Organization Organization `gorm:"foreignKey:OrganizationId"` ClusterId domain.ClusterId diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 7a03c18f..e133fca6 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -183,6 +183,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Name: domain.SN_TYPE_NODE_CPU_HIGH_LOAD + "-critical", Description: "", OrganizationId: organizationId, + NotificationType: template.NotificationType, IsSystem: true, SystemNotificationTemplateId: template.ID, SystemNotificationCondition: model.SystemNotificationCondition{ @@ -208,6 +209,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Name: domain.SN_TYPE_NODE_MEMORY_HIGH_UTILIZATION + "-warning", Description: "", OrganizationId: organizationId, + NotificationType: template.NotificationType, IsSystem: true, SystemNotificationTemplateId: template.ID, SystemNotificationCondition: model.SystemNotificationCondition{ @@ -233,6 +235,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Name: domain.SN_TYPE_NODE_DISK_FULL + "-critical", Description: "", OrganizationId: organizationId, + NotificationType: template.NotificationType, IsSystem: true, SystemNotificationTemplateId: template.ID, SystemNotificationCondition: model.SystemNotificationCondition{ @@ -258,6 +261,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Name: domain.SN_TYPE_PVC_FULL + "-critical", Description: "", OrganizationId: organizationId, + NotificationType: template.NotificationType, IsSystem: true, SystemNotificationTemplateId: template.ID, SystemNotificationCondition: model.SystemNotificationCondition{ @@ -283,6 +287,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Name: domain.SN_TYPE_POD_RESTART_FREQUENTLY + "-critical", Description: "", OrganizationId: organizationId, + NotificationType: template.NotificationType, IsSystem: true, SystemNotificationTemplateId: template.ID, SystemNotificationCondition: model.SystemNotificationCondition{ @@ -301,6 +306,32 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c CreatorId: organization.AdminId, UpdatorId: organization.AdminId, }) + } else if template.Name == domain.SN_TYPE_POLICY_AUDITED { + ruleId := uuid.New() + rules = append(rules, model.SystemNotificationRule{ + ID: ruleId, + Name: domain.SN_TYPE_POLICY_AUDITED + "-critical", + Description: "", + OrganizationId: organizationId, + NotificationType: template.NotificationType, + IsSystem: true, + SystemNotificationTemplateId: template.ID, + SystemNotificationCondition: model.SystemNotificationCondition{ + SystemNotificationRuleId: ruleId, + Severity: "critical", + Duration: "3m", + Parameter: []byte("[{\"order\": 0, \"value\": \"2\", \"operator\": \">\"}]"), + EnableEmail: true, + EnablePortal: true, + }, + TargetUsers: []model.User{organizationAdmin}, + MessageTitle: "<> / <>", + MessageContent: "클러스터(<>)의 자원(<> - <> / <>)에서 정책(<> / <>)위반이 발생했습니다. 메시지: <>", + MessageActionProposal: "정책위반이 발생하였습니다.(<> / <>)", + Status: domain.SystemNotificationRuleStatus_PENDING, + CreatorId: organization.AdminId, + UpdatorId: organization.AdminId, + }) } } diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index a170e8fd..dc4747ca 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -9,13 +9,13 @@ type SystemNotificationRuleStatus int32 const ( SystemNotificationRuleStatus_PENDING SystemNotificationRuleStatus = iota - SystemNotificationRuleStatus_APPLYED + SystemNotificationRuleStatus_APPLIED SystemNotificationRuleStatus_ERROR ) var systemNotificationRuleStatus = [...]string{ "PENDING", - "APPLYED", + "APPLIED", "ERROR", } diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index 88430c01..c28de31e 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -9,6 +9,12 @@ const SN_TYPE_NODE_MEMORY_HIGH_UTILIZATION = "node-memory-high-utilization" const SN_TYPE_NODE_DISK_FULL = "node-disk-full" const SN_TYPE_PVC_FULL = "pvc-full" const SN_TYPE_POD_RESTART_FREQUENTLY = "pod-restart-frequently" +const SN_TYPE_POLICY_AUDITED = "policy-audited" + +const ( + NT_SYSTEM_NOTIFICATION = "SYSTEM_NOTIFICATION" + NT_POLICY = "POLICY" +) type SystemNotificationTemplateResponse struct { ID string `json:"id"` diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 786f293c..697f7968 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -58,6 +58,7 @@ type SystemNotificationRequest struct { Description string `json:"description"` Checkpoint string `json:"Checkpoint"` Discriminative string `json:"discriminative"` + AlertType string `json:"alertType"` } `json:"annotations"` } @@ -70,7 +71,7 @@ type CreateSystemNotificationRequest struct { TruncatedAlerts int `json:"truncatedAlerts"` SystemNotifications []SystemNotificationRequest `json:"alerts"` GroupLabels struct { - SystemNotificationname string `json:"alertname"` + SystemNotificationName string `json:"alertname"` } `json:"groupLabels"` //CommonLabels string `json:"commonLabels"` //CommonAnnotations string `json:"commonAnnotations"` @@ -95,6 +96,7 @@ type SystemNotificationResponse struct { SystemNotificationActions []SystemNotificationActionResponse `json:"systemNotificationActions"` LastTaker SimpleUserResponse `json:"lastTaker"` RawData string `json:"rawData"` + NotificationType string `json:"notificationType"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index 1949a37e..6b3fab26 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -56,18 +56,18 @@ insert into project_roles ( id, name, description, created_at, updated_at ) valu insert into project_roles ( id, name, description, created_at, updated_at ) values ( 'f62c16e1-316c-4d7f-9cfa-dbe4ed7dfa17', 'project-viewer', 'project-viewer', now(), now() ); ## SystemNotificationTemplates -insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('d42d716f-dd2e-429b-897d-b602f6382790', 'node-cpu-high-load', 'node-cpu-high-load', true, '(avg by (taco_cluster, instance) (rate(node_cpu_seconds_total{mode="idle"}[60s])))', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', true, 'node-memory-high-utilization', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-full', true, 'predict_linear(node_filesystem_free_bytes{mountpoint="/"}[6h], 24*3600)', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'predict_linear(kubelet_volume_stats_available_bytes[6h], 24*3600)', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', 'pod-restart-frequently', true, 'increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:])', null, null, now(), now() ); -insert into system_notification_templates ( id, name, description, is_system, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('7355d0f9-7c14-4f70-92ea-a9868624ff82', 'policy-audited', 'policy-audited', true, 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system"}', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('d42d716f-dd2e-429b-897d-b602f6382790', 'node-cpu-high-load', 'node-cpu-high-load', true, 'SYSTEM_NOTIFICATION', '(avg by (taco_cluster, instance) (rate(node_cpu_seconds_total{mode="idle"}[60s])))', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', true, 'SYSTEM_NOTIFICATION', 'node-memory-high-utilization', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-full', true, 'SYSTEM_NOTIFICATION', 'predict_linear(node_filesystem_free_bytes{mountpoint="/"}[6h], 24*3600)', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'SYSTEM_NOTIFICATION','predict_linear(kubelet_volume_stats_available_bytes[6h], 24*3600)', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', 'pod-restart-frequently', true, 'SYSTEM_NOTIFICATION','increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:])', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('7355d0f9-7c14-4f70-92ea-a9868624ff82', 'policy-audited', 'policy-audited', true, 'POLICY', 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system"}', null, null, now(), now() ); ## SystemNotificationTemplates -> SystemNotificationMetricParameters insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) From 9c700f5948db14c855d251ab4ff4ebba20a07658 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 8 Apr 2024 19:08:58 +0900 Subject: [PATCH 258/502] feature. add get systemNotificationTemplate in organization --- api/swagger/docs.go | 37 ++++++++++++ api/swagger/swagger.json | 37 ++++++++++++ api/swagger/swagger.yaml | 23 ++++++++ internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 +++ .../http/system-notification-template.go | 56 +++++++++++++++++++ internal/route/route.go | 1 + 7 files changed, 163 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index dcfb0919..54bf10c5 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -8808,6 +8808,43 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/system-notification-templates/{systemNotificationTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization SystemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Get Organization SystemNotificationTemplate", + "parameters": [ + { + "type": "string", + "description": "systemNotificationTemplateId", + "name": "systemNotificationTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse" + } + } + } + } + }, "/organizations/{organizationId}/system-notifications": { "get": { "security": [ diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index fd5e6aee..7438d314 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -8802,6 +8802,43 @@ } } }, + "/organizations/{organizationId}/system-notification-templates/{systemNotificationTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization SystemNotificationTemplate", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SystemNotificationTemplates" + ], + "summary": "Get Organization SystemNotificationTemplate", + "parameters": [ + { + "type": "string", + "description": "systemNotificationTemplateId", + "name": "systemNotificationTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse" + } + } + } + } + }, "/organizations/{organizationId}/system-notifications": { "get": { "security": [ diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 1d148e55..7c4d4863 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -9700,6 +9700,29 @@ paths: summary: Remove organization systemNotificationTemplates tags: - SystemNotificationTemplates + /organizations/{organizationId}/system-notification-templates/{systemNotificationTemplateId}: + get: + consumes: + - application/json + description: Get Organization SystemNotificationTemplate + parameters: + - description: systemNotificationTemplateId + in: path + name: systemNotificationTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetSystemNotificationTemplateResponse' + security: + - JWT: [] + summary: Get Organization SystemNotificationTemplate + tags: + - SystemNotificationTemplates /organizations/{organizationId}/system-notifications: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 463b406d..04283d98 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -126,6 +126,7 @@ const ( Admin_GetSystemNotificationTemplate Admin_CheckSystemNotificationTemplateName GetOrganizationSystemNotificationTemplates + GetOrganizationSystemNotificationTemplate AddOrganizationSystemNotificationTemplates RemoveOrganizationSystemNotificationTemplates diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 74b792b2..913956d2 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -383,6 +383,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, + GetOrganizationSystemNotificationTemplate: { + Name: "GetOrganizationSystemNotificationTemplate", + Group: "SystemNotificationTemplate", + }, AddOrganizationSystemNotificationTemplates: { Name: "AddOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", @@ -1068,6 +1072,8 @@ func (e Endpoint) String() string { return "Admin_CheckSystemNotificationTemplateName" case GetOrganizationSystemNotificationTemplates: return "GetOrganizationSystemNotificationTemplates" + case GetOrganizationSystemNotificationTemplate: + return "GetOrganizationSystemNotificationTemplate" case AddOrganizationSystemNotificationTemplates: return "AddOrganizationSystemNotificationTemplates" case RemoveOrganizationSystemNotificationTemplates: @@ -1510,6 +1516,8 @@ func GetEndpoint(name string) Endpoint { return Admin_CheckSystemNotificationTemplateName case "GetOrganizationSystemNotificationTemplates": return GetOrganizationSystemNotificationTemplates + case "GetOrganizationSystemNotificationTemplate": + return GetOrganizationSystemNotificationTemplate case "AddOrganizationSystemNotificationTemplates": return AddOrganizationSystemNotificationTemplates case "RemoveOrganizationSystemNotificationTemplates": diff --git a/internal/delivery/http/system-notification-template.go b/internal/delivery/http/system-notification-template.go index 3663a605..3597a4bf 100644 --- a/internal/delivery/http/system-notification-template.go +++ b/internal/delivery/http/system-notification-template.go @@ -262,6 +262,62 @@ func (h *SystemNotificationTemplateHandler) DeleteSystemNotificationTemplate(w h ResponseJSON(w, r, http.StatusOK, nil) } +// GetOrganizationSystemNotificationTemplate godoc +// +// @Tags SystemNotificationTemplates +// @Summary Get Organization SystemNotificationTemplate +// @Description Get Organization SystemNotificationTemplate +// @Accept json +// @Produce json +// @Param systemNotificationTemplateId path string true "systemNotificationTemplateId" +// @Success 200 {object} domain.GetSystemNotificationTemplateResponse +// @Router /organizations/{organizationId}/system-notification-templates/{systemNotificationTemplateId} [get] +// @Security JWT +func (h *SystemNotificationTemplateHandler) GetOrganizationSystemNotificationTemplate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + strId, ok := vars["systemNotificationTemplateId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationTemplateId"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + + systemNotificationTemplateId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_SYSTEM_NOTIFICATION_TEMPLATE_ID", "")) + return + } + + systemNotificationTemplate, err := h.usecase.Get(r.Context(), systemNotificationTemplateId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetSystemNotificationTemplateResponse + if err := serializer.Map(r.Context(), systemNotificationTemplate, &out.SystemNotificationTemplate); err != nil { + log.Info(r.Context(), err) + } + + out.SystemNotificationTemplate.Organizations = make([]domain.SimpleOrganizationResponse, len(systemNotificationTemplate.Organizations)) + for i, organization := range systemNotificationTemplate.Organizations { + if err := serializer.Map(r.Context(), organization, &out.SystemNotificationTemplate.Organizations[i]); err != nil { + log.Info(r.Context(), err) + continue + } + } + + out.SystemNotificationTemplate.MetricParameters = make([]domain.SystemNotificationMetricParameterResponse, len(systemNotificationTemplate.MetricParameters)) + for i, metricParameters := range systemNotificationTemplate.MetricParameters { + if err := serializer.Map(r.Context(), metricParameters, &out.SystemNotificationTemplate.MetricParameters[i]); err != nil { + log.Info(r.Context(), err) + continue + } + } + + ResponseJSON(w, r, http.StatusOK, out) +} + // GetOrganizationSystemNotificationTemplates godoc // // @Tags SystemNotificationTemplates diff --git a/internal/route/route.go b/internal/route/route.go index 2b0de38c..d2247a66 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -226,6 +226,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.DeleteSystemNotificationTemplate))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates/name/{name}/existence", customMiddleware.Handle(internalApi.Admin_CheckSystemNotificationTemplateName, http.HandlerFunc(systemNotificationTemplateHandler.CheckSystemNotificationTemplateName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.GetOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetOrganizationSystemNotificationTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates/{systemNotificationTemplateId}", customMiddleware.Handle(internalApi.GetOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetOrganizationSystemNotificationTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.AddOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.AddOrganizationSystemNotificationTemplates))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.RemoveOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.RemoveOrganizationSystemNotificationTemplates))).Methods(http.MethodPut) From 8b1dcb09049fd3c610754f72cf66355c1f80071c Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 9 Apr 2024 00:39:21 +0900 Subject: [PATCH 259/502] =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0?= =?UTF-8?q?=EA=B0=80=20=EB=B9=88=20=EA=B2=BD=EC=9A=B0=20CR=20=EB=B3=80?= =?UTF-8?q?=ED=99=98=EB=B2=84=EA=B7=B8=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/paramdef-util.go | 8 +++- internal/policy-template/policy-operator.go | 37 +++++++++++++++++-- internal/policy-template/tkspolicytemplate.go | 4 +- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go index 55603847..b136b42c 100644 --- a/internal/policy-template/paramdef-util.go +++ b/internal/policy-template/paramdef-util.go @@ -142,7 +142,7 @@ func CompareParamDefAndExtractedParamDef(paramdef *domain.ParameterDef, extracte } func ParamDefsToJSONSchemaProeprties(paramdefs []*domain.ParameterDef) *apiextensionsv1.JSONSchemaProps { - if paramdefs == nil { + if len(paramdefs) == 0 { return nil } @@ -174,7 +174,11 @@ func convert(paramdefs []*domain.ParameterDef) map[string]apiextensionsv1.JSONSc }, } case isObject: - result[paramdef.Key] = *ParamDefsToJSONSchemaProeprties(paramdef.Children) + props := ParamDefsToJSONSchemaProeprties(paramdef.Children) + + if props != nil { + result[paramdef.Key] = *props + } default: result[paramdef.Key] = apiextensionsv1.JSONSchemaProps{Type: paramdef.Type} } diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index cb10995f..84831e1f 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -1,6 +1,7 @@ package policytemplate import ( + "encoding/json" "strings" "github.com/openinfradev/tks-api/internal/model" @@ -23,7 +24,16 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { return nil } - jsonParams := apiextensionsv1.JSON{Raw: []byte(policy.Parameters)} + var params *apiextensionsv1.JSON = nil + + var jsonResult map[string]interface{} + + err := json.Unmarshal([]byte(policy.Parameters), &jsonResult) + + if err == nil && len(jsonResult) > 0 { + jsonParams := apiextensionsv1.JSON{Raw: []byte(policy.Parameters)} + params = &jsonParams + } labels := map[string]string{} labels[PartOfKey] = PartOfVal @@ -56,7 +66,7 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { Clusters: policy.TargetClusterIds, Template: policy.PolicyTemplate.Kind, Match: policy.Match, - Params: &jsonParams, + Params: params, }, } } @@ -94,14 +104,33 @@ func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) * }, Targets: []Target{{ Target: "admission.k8s.gatekeeper.sh", - Rego: policyTemplate.Rego, - Libs: policyTemplate.Libs, + Rego: stripCarriageReturn(policyTemplate.Rego), + Libs: stripCarriageReturns(policyTemplate.Libs), }}, Version: policyTemplate.Version, }, } } +func stripCarriageReturn(str string) string { + return strings.ReplaceAll(str, "\r", "") +} + +func stripCarriageReturns(strs []string) []string { + if strs == nil { + return nil + } + + result := make([]string, len(strs)) + + for i, str := range strs { + result[i] = stripCarriageReturn(str) + } + + return result + +} + func syncToKubernetes() bool { return true // return os.Getenv("SYNC_POLICY_TO_K8S") != "" diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index 412d9007..653952dd 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -46,8 +46,8 @@ type Validation struct { type Target struct { Target string `json:"target,omitempty"` - Rego string `json:"rego,omitempty"` - Libs []string `json:"libs,omitempty"` + Rego string `json:"rego,omitempty" yaml:"rego,omitempty,flow"` + Libs []string `json:"libs,omitempty" yaml:"libs,omitempty,flow"` Code []Code `json:"code,omitempty"` } From 7b8a40020adec1993ee0264aec1cc6e97fe78a36 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 9 Apr 2024 09:02:17 +0900 Subject: [PATCH 260/502] add policy-status widget --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/dashboard.go | 61 +++++++++++++++++++++++++- internal/policy-template/tkscluster.go | 41 +++++++++++------ internal/route/route.go | 1 + internal/usecase/dashboard.go | 14 ++++-- pkg/domain/dashboard.go | 10 +++++ 6 files changed, 109 insertions(+), 19 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 463b406d..645fe2a9 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -117,6 +117,7 @@ const ( GetChartDashboard // 대시보드/대시보드/조회 GetStacksDashboard // 대시보드/대시보드/조회 GetResourcesDashboard // 대시보드/대시보드/조회 + GetPolicyStatusDashboard // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index f299eeb4..f0294bfc 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -5,6 +5,7 @@ import ( "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" + policytemplate "github.com/openinfradev/tks-api/internal/policy-template" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" @@ -22,15 +23,18 @@ type IDashboardHandler interface { GetChart(w http.ResponseWriter, r *http.Request) GetStacks(w http.ResponseWriter, r *http.Request) GetResources(w http.ResponseWriter, r *http.Request) + GetPolicyStatus(w http.ResponseWriter, r *http.Request) } type DashboardHandler struct { - usecase usecase.IDashboardUsecase + usecase usecase.IDashboardUsecase + organizationUsecase usecase.IOrganizationUsecase } func NewDashboardHandler(h usecase.Usecase) IDashboardHandler { return &DashboardHandler{ - usecase: h.Dashboard, + usecase: h.Dashboard, + organizationUsecase: h.Organization, } } @@ -414,3 +418,56 @@ func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) ResponseJSON(w, r, http.StatusOK, out) } + +// GetPolicyStatus godoc +// +// @Tags Dashboards +// @Summary Get policy status +// @Description Get policy status +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetDashboardPolicyStatusResponse +// @Router /organizations/{organizationId}/dashboard/policy-status [get] +// @Security JWT +func (h *DashboardHandler) GetPolicyStatus(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + organization, err := h.organizationUsecase.Get(r.Context(), organizationId) + if err != nil { + log.Error(r.Context(), "Failed to retrieve organization") + ErrorJSON(w, r, fmt.Errorf("failed to retrieve organization")) + return + } + + tksClusters, err := policytemplate.GetTksClusterCRs(r.Context(), organization.PrimaryClusterId) + if err != nil { + log.Error(r.Context(), "Failed to retrieve tkscluster list", err) + ErrorJSON(w, r, err) + return + } + + var policyStatus domain.DashboardPolicyStatus + for _, c := range tksClusters { + switch status := c.Status.TKSProxy.Status; status { + case "ready": + policyStatus.Normal++ + case "warn": + policyStatus.Warning++ + case "error": + policyStatus.Error++ + default: + continue + } + } + + var out domain.GetDashboardPolicyStatusResponse + out.PolicyStatus = policyStatus + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/policy-template/tkscluster.go b/internal/policy-template/tkscluster.go index c2bbc826..2a6cd1df 100644 --- a/internal/policy-template/tkscluster.go +++ b/internal/policy-template/tkscluster.go @@ -2,10 +2,10 @@ package policytemplate import ( "context" - "encoding/json" "github.com/openinfradev/tks-api/pkg/kubernetes" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -14,7 +14,7 @@ var TKSClusterGVR = schema.GroupVersionResource{ Resource: "tksclusters", } -// ============== Copied Fron Operator Start ============== +// ============== Copied From Operator Start ============== // TemplateReference defines the desired state of TKSCluster type TemplateReference struct { @@ -70,35 +70,50 @@ type TKSClusterList struct { Items []TKSCluster `json:"items"` } -// ============== Copied Fron Operator End ============== +// ============== Copied From Operator End ============== -func GetTksClusterCR(ctx context.Context, primaryClusterId string, name string) (*TKSCluster, error) { +func GetTksClusterCR(ctx context.Context, primaryClusterId string, resourceName string) (*TKSCluster, error) { dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) - if err != nil { return nil, err } - result, err := dynamicClient.Resource(TKSClusterGVR).Namespace(primaryClusterId). - Get(ctx, name, metav1.GetOptions{}) + resource, err := dynamicClient.Resource(TKSClusterGVR).Namespace(primaryClusterId). + Get(ctx, resourceName, metav1.GetOptions{}) + if err != nil { + return nil, err + } + var tksCluster TKSCluster + unstructuredObj := resource.UnstructuredContent() + err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredObj, &tksCluster) if err != nil { return nil, err } - // Unstructured를 바로 TKSPolicyTemplate으로 컨버팅할 수 없기 때문에 json으로 변환 - jsonBytes, err := json.Marshal(result.Object) + return &tksCluster, nil +} +func GetTksClusterCRs(ctx context.Context, primaryClusterId string) (tksClusters []TKSCluster, err error) { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) if err != nil { return nil, err } - var tksCluster TKSCluster - err = json.Unmarshal(jsonBytes, &tksCluster) - + resources, err := dynamicClient.Resource(TKSClusterGVR).Namespace(primaryClusterId). + List(context.TODO(), metav1.ListOptions{}) if err != nil { return nil, err } - return &tksCluster, nil + var tksCluster TKSCluster + for _, resource := range resources.Items { + if err = runtime.DefaultUnstructuredConverter. + FromUnstructured(resource.UnstructuredContent(), &tksCluster); err != nil { + return nil, err + } + tksClusters = append(tksClusters, tksCluster) + } + + return tksClusters, nil } diff --git a/internal/route/route.go b/internal/route/route.go index 2b0de38c..8f1a0604 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -205,6 +205,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts/{chartType}", customMiddleware.Handle(internalApi.GetChartDashboard, http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/policy-status", customMiddleware.Handle(internalApi.GetPolicyStatusDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatus))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 176ae035..e404e2f7 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -180,6 +180,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri // Stack clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, uuid.Nil, nil) if err != nil { + log.Error(ctx, err) return out, err } @@ -201,10 +202,12 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri log.Debugf(ctx, "Failed to get cluster info: %v\n", err) continue } - if clusterInfo.Items[0].ObjectMeta.Labels["kubernetes.io/cluster-service"] == "true" { - normal++ - } else { - abnormal++ + if clusterInfo != nil && len(clusterInfo.Items) > 0 { + if clusterInfo.Items[0].ObjectMeta.Labels["kubernetes.io/cluster-service"] == "true" { + normal++ + } else { + abnormal++ + } } } } @@ -217,6 +220,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri */ result, err := thanosClient.Get(ctx, "sum by (taco_cluster) (machine_cpu_cores)") if err != nil { + log.Error(ctx, err) return out, err } cpu := 0 @@ -234,6 +238,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri // Memory result, err = thanosClient.Get(ctx, "sum by (taco_cluster) (machine_memory_bytes)") if err != nil { + log.Error(ctx, err) return out, err } memory := float64(0) @@ -252,6 +257,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri // Storage result, err = thanosClient.Get(ctx, "sum by (taco_cluster) (kubelet_volume_stats_capacity_bytes)") if err != nil { + log.Error(ctx, err) return out, err } storage := float64(0) diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index bbdb1229..6574c428 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -178,3 +178,13 @@ type UpdateDashboardRequest struct { type CommonDashboardResponse struct { Result string `json:"result"` } + +type DashboardPolicyStatus struct { + Normal int `json:"normal"` + Warning int `json:"warning"` + Error int `json:"error"` +} + +type GetDashboardPolicyStatusResponse struct { + PolicyStatus DashboardPolicyStatus `json:"statuses"` +} From 29d1a3eb21a1a382047cea086bdf4c3a51f42886 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 9 Apr 2024 09:03:27 +0900 Subject: [PATCH 261/502] add policy-status widget\n endpoint generate --- internal/delivery/api/generated_endpoints.go.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 74b792b2..bc02779f 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -355,6 +355,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetResourcesDashboard", Group: "Dashboard", }, + GetPolicyStatusDashboard: { + Name: "GetPolicyStatusDashboard", + Group: "Dashboard", + }, Admin_CreateSystemNotificationTemplate: { Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", @@ -1054,6 +1058,8 @@ func (e Endpoint) String() string { return "GetStacksDashboard" case GetResourcesDashboard: return "GetResourcesDashboard" + case GetPolicyStatusDashboard: + return "GetPolicyStatusDashboard" case Admin_CreateSystemNotificationTemplate: return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: @@ -1496,6 +1502,8 @@ func GetEndpoint(name string) Endpoint { return GetStacksDashboard case "GetResourcesDashboard": return GetResourcesDashboard + case "GetPolicyStatusDashboard": + return GetPolicyStatusDashboard case "Admin_CreateSystemNotificationTemplate": return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": From 30f4809ec82a5c2a829572e41fe46f97797f8523 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 9 Apr 2024 09:04:34 +0900 Subject: [PATCH 262/502] add policy-status widget\n swag init --- api/swagger/docs.go | 856 ++++++++++++++++++++++++++------------- api/swagger/swagger.json | 856 ++++++++++++++++++++++++++------------- api/swagger/swagger.yaml | 563 ++++++++++++++++--------- 3 files changed, 1546 insertions(+), 729 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 46656d28..8a1a4c9e 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -241,6 +241,90 @@ const docTemplate = `{ } } }, + "/admin/organizations/{organizationId}/policyTemplates": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 조직에 대해 허용된 tks 템플릿의 허용 상태를 해제(제거)한다. tks 우형 템플릿에 대해서만 동작하고 organization 유형 템플릿에 대해서는 거부된다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_DeletePermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 제거", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "delete pemitted policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 조직에 대해 허용된 tks 템플릿 목록을 추가한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_AddPermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 추가", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update pemitted policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -2426,169 +2510,6 @@ const docTemplate = `{ } } }, - "/clusters/{clusterId}/policy-status": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "sortColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse" - } - } - } - } - }, - "/clusters/{clusterId}/policy-templates/{templateId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "templateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse" - } - } - } - }, - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "templateId", - "in": "path", - "required": true - }, - { - "description": "update cluster policy template status request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/clusters/{clusterId}/site-values": { "get": { "security": [ @@ -3379,6 +3300,43 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/dashboard/policy-status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get policy status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get policy status", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboard/resources": { "get": { "security": [ @@ -8095,8 +8053,286 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { + "/organizations/{organizationId}/stacks/{stackId}/policies": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 스택에서 정책 식별자로 지정된 정책을 제거한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[DeletePoliciesForStack] 특정 스택의 정책 제거", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "delete policies for stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest" + } + } + ], + "responses": {} + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 스택의 정책 목록을 정책 식별자 리스트로 지정해서 추가한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[AddPoliciesForStack] 특정 스택의 정책 목록 추가", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "add policies for stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/policy-status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[GetStackPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse" + } + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[UpdateStackPolicyTemplateStatus] 템플릿 버전 업데이트", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "update stack policy template status request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { "security": [ { "JWT": [] @@ -9638,7 +9874,18 @@ const docTemplate = `{ "systemNotificationTemplateIds" ], "properties": { - "systemNotificationTemplateIds": { + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest": { + "type": "object", + "properties": { + "policyIds": { "type": "array", "items": { "type": "string" @@ -10350,46 +10597,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse": { - "type": "object", - "properties": { - "policyDescription": { - "type": "string", - "example": "org 레이블 설정 여부 검사" - }, - "policyId": { - "type": "string", - "example": "0091fe9b-e44b-423d-9562-ac2b73089593" - }, - "policyMandatory": { - "type": "boolean" - }, - "policyName": { - "type": "string", - "example": "org 레이블 요구" - }, - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateDescription": { - "type": "string", - "example": "파라미터로 설정된 레이블 검사" - }, - "templateId": { - "type": "string", - "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" - }, - "templateLatestVerson": { - "type": "string", - "example": "v1.0.3" - }, - "templateName": { - "type": "string", - "example": "레이블 요구" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ClusterResponse": { "type": "object", "properties": { @@ -11445,6 +11652,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus": { + "type": "object", + "properties": { + "error": { + "type": "integer" + }, + "normal": { + "type": "integer" + }, + "warning": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DashboardResource": { "type": "object", "properties": { @@ -11536,6 +11757,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest": { + "type": "object", + "properties": { + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest": { "type": "object", "properties": { @@ -11822,50 +12054,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse": { - "type": "object", - "properties": { - "affectedPolicies": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" - } - }, - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateDescription": { - "type": "string", - "example": "파라미터로 설정된 레이블 검사" - }, - "templateId": { - "type": "string", - "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" - }, - "templateLatestVerson": { - "type": "string", - "example": "v1.0.3" - }, - "templateLatestVersonReleaseDate": { - "type": "string", - "format": "date-time" - }, - "templateMandatory": { - "type": "boolean" - }, - "templateName": { - "type": "string", - "example": "레이블 요구" - }, - "updatedPolicyParameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { "type": "object", "properties": { @@ -11907,6 +12095,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse": { + "type": "object", + "properties": { + "statuses": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { @@ -12189,6 +12385,50 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse": { + "type": "object", + "properties": { + "affectedPolicies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" + } + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateLatestVersonReleaseDate": { + "type": "string", + "format": "date-time" + }, + "templateMandatory": { + "type": "boolean" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + }, + "updatedPolicyParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetStackResponse": { "type": "object", "properties": { @@ -12481,17 +12721,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse": { - "type": "object", - "properties": { - "polices": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -12561,6 +12790,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse": { + "type": "object", + "properties": { + "polices": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { "type": "object", "properties": { @@ -13761,6 +14001,46 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse": { + "type": "object", + "properties": { + "policyDescription": { + "type": "string", + "example": "org 레이블 설정 여부 검사" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyMandatory": { + "type": "boolean" + }, + "policyName": { + "type": "string", + "example": "org 레이블 요구" + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackResponse": { "type": "object", "properties": { @@ -14113,6 +14393,9 @@ const docTemplate = `{ "id": { "type": "string" }, + "isSystem": { + "type": "boolean" + }, "messageActionProposal": { "type": "string" }, @@ -14163,6 +14446,9 @@ const docTemplate = `{ "id": { "type": "string" }, + "isSystem": { + "type": "boolean" + }, "metricParameters": { "type": "array", "items": { @@ -14326,19 +14612,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest": { - "type": "object", - "properties": { - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateTargetVerson": { - "type": "string", - "example": "v1.0.3" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest": { "type": "object", "properties": { @@ -14648,6 +14921,19 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest": { + "type": "object", + "properties": { + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateTargetVerson": { + "type": "string", + "example": "v1.0.3" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { "type": "object", "properties": { @@ -15045,6 +15331,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest": { + "type": "object", + "properties": { + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse": { "type": "object", "properties": { @@ -15169,6 +15466,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest": { + "type": "object", + "properties": { + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 130baeed..dcd3e390 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -235,6 +235,90 @@ } } }, + "/admin/organizations/{organizationId}/policyTemplates": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 조직에 대해 허용된 tks 템플릿의 허용 상태를 해제(제거)한다. tks 우형 템플릿에 대해서만 동작하고 organization 유형 템플릿에 대해서는 거부된다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_DeletePermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 제거", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "delete pemitted policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 조직에 대해 허용된 tks 템플릿 목록을 추가한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyTemplate" + ], + "summary": "[Admin_AddPermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks 템플릿 목록 추가", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update pemitted policy template request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -2420,169 +2504,6 @@ } } }, - "/clusters/{clusterId}/policy-status": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "pageSize", - "name": "pageSize", - "in": "query" - }, - { - "type": "string", - "description": "pageNumber", - "name": "pageNumber", - "in": "query" - }, - { - "type": "string", - "description": "sortColumn", - "name": "sortColumn", - "in": "query" - }, - { - "type": "string", - "description": "sortOrder", - "name": "sortOrder", - "in": "query" - }, - { - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "description": "filters", - "name": "filters", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse" - } - } - } - } - }, - "/clusters/{clusterId}/policy-templates/{templateId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "templateId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse" - } - } - } - }, - "patch": { - "security": [ - { - "JWT": [] - } - ], - "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "ClusterPolicyStatus" - ], - "summary": "[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트", - "parameters": [ - { - "type": "string", - "description": "클러스터 식별자(uuid)", - "name": "clusterId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "정책 템플릿 식별자(uuid)", - "name": "templateId", - "in": "path", - "required": true - }, - { - "description": "update cluster policy template status request", - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, "/clusters/{clusterId}/site-values": { "get": { "security": [ @@ -3373,6 +3294,43 @@ } } }, + "/organizations/{organizationId}/dashboard/policy-status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get policy status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get policy status", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboard/resources": { "get": { "security": [ @@ -8089,8 +8047,286 @@ } } }, - "/organizations/{organizationId}/stacks/{stackId}/status": { - "get": { + "/organizations/{organizationId}/stacks/{stackId}/policies": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 스택에서 정책 식별자로 지정된 정책을 제거한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[DeletePoliciesForStack] 특정 스택의 정책 제거", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "delete policies for stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest" + } + } + ], + "responses": {} + }, + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "특정 스택의 정책 목록을 정책 식별자 리스트로 지정해서 추가한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[AddPoliciesForStack] 특정 스택의 정책 목록 추가", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "description": "add policies for stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/policy-status": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse" + } + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "템플릿의 클러스터 버전 등 상태를 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[GetStackPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse" + } + } + } + }, + "patch": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[UpdateStackPolicyTemplateStatus] 템플릿 버전 업데이트", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 템플릿 식별자(uuid)", + "name": "policyTemplateId", + "in": "path", + "required": true + }, + { + "description": "update stack policy template status request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/organizations/{organizationId}/stacks/{stackId}/status": { + "get": { "security": [ { "JWT": [] @@ -9632,7 +9868,18 @@ "systemNotificationTemplateIds" ], "properties": { - "systemNotificationTemplateIds": { + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest": { + "type": "object", + "properties": { + "policyIds": { "type": "array", "items": { "type": "string" @@ -10344,46 +10591,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse": { - "type": "object", - "properties": { - "policyDescription": { - "type": "string", - "example": "org 레이블 설정 여부 검사" - }, - "policyId": { - "type": "string", - "example": "0091fe9b-e44b-423d-9562-ac2b73089593" - }, - "policyMandatory": { - "type": "boolean" - }, - "policyName": { - "type": "string", - "example": "org 레이블 요구" - }, - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateDescription": { - "type": "string", - "example": "파라미터로 설정된 레이블 검사" - }, - "templateId": { - "type": "string", - "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" - }, - "templateLatestVerson": { - "type": "string", - "example": "v1.0.3" - }, - "templateName": { - "type": "string", - "example": "레이블 요구" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ClusterResponse": { "type": "object", "properties": { @@ -11439,6 +11646,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus": { + "type": "object", + "properties": { + "error": { + "type": "integer" + }, + "normal": { + "type": "integer" + }, + "warning": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DashboardResource": { "type": "object", "properties": { @@ -11530,6 +11751,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest": { + "type": "object", + "properties": { + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest": { "type": "object", "properties": { @@ -11816,50 +12048,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse": { - "type": "object", - "properties": { - "affectedPolicies": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" - } - }, - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateDescription": { - "type": "string", - "example": "파라미터로 설정된 레이블 검사" - }, - "templateId": { - "type": "string", - "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" - }, - "templateLatestVerson": { - "type": "string", - "example": "v1.0.3" - }, - "templateLatestVersonReleaseDate": { - "type": "string", - "format": "date-time" - }, - "templateMandatory": { - "type": "boolean" - }, - "templateName": { - "type": "string", - "example": "레이블 요구" - }, - "updatedPolicyParameters": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse": { "type": "object", "properties": { @@ -11901,6 +12089,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse": { + "type": "object", + "properties": { + "statuses": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { @@ -12183,6 +12379,50 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse": { + "type": "object", + "properties": { + "affectedPolicies": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus" + } + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateLatestVersonReleaseDate": { + "type": "string", + "format": "date-time" + }, + "templateMandatory": { + "type": "boolean" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + }, + "updatedPolicyParameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetStackResponse": { "type": "object", "properties": { @@ -12475,17 +12715,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse": { - "type": "object", - "properties": { - "polices": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -12555,6 +12784,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse": { + "type": "object", + "properties": { + "polices": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse": { "type": "object", "properties": { @@ -13755,6 +13995,46 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse": { + "type": "object", + "properties": { + "policyDescription": { + "type": "string", + "example": "org 레이블 설정 여부 검사" + }, + "policyId": { + "type": "string", + "example": "0091fe9b-e44b-423d-9562-ac2b73089593" + }, + "policyMandatory": { + "type": "boolean" + }, + "policyName": { + "type": "string", + "example": "org 레이블 요구" + }, + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateDescription": { + "type": "string", + "example": "파라미터로 설정된 레이블 검사" + }, + "templateId": { + "type": "string", + "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" + }, + "templateLatestVerson": { + "type": "string", + "example": "v1.0.3" + }, + "templateName": { + "type": "string", + "example": "레이블 요구" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackResponse": { "type": "object", "properties": { @@ -14107,6 +14387,9 @@ "id": { "type": "string" }, + "isSystem": { + "type": "boolean" + }, "messageActionProposal": { "type": "string" }, @@ -14157,6 +14440,9 @@ "id": { "type": "string" }, + "isSystem": { + "type": "boolean" + }, "metricParameters": { "type": "array", "items": { @@ -14320,19 +14606,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest": { - "type": "object", - "properties": { - "templateCurrentVersion": { - "type": "string", - "example": "v1.0.1" - }, - "templateTargetVerson": { - "type": "string", - "example": "v1.0.3" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest": { "type": "object", "properties": { @@ -14642,6 +14915,19 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest": { + "type": "object", + "properties": { + "templateCurrentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "templateTargetVerson": { + "type": "string", + "example": "v1.0.3" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest": { "type": "object", "properties": { @@ -15039,6 +15325,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest": { + "type": "object", + "properties": { + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse": { "type": "object", "properties": { @@ -15163,6 +15460,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest": { + "type": "object", + "properties": { + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 529fffb5..b1940af1 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -158,6 +158,13 @@ definitions: required: - systemNotificationTemplateIds type: object + github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest: + properties: + policyIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.AddProjectMemberRequest: properties: projectMembers: @@ -644,35 +651,6 @@ definitions: validity: type: integer type: object - github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse: - properties: - policyDescription: - example: org 레이블 설정 여부 검사 - type: string - policyId: - example: 0091fe9b-e44b-423d-9562-ac2b73089593 - type: string - policyMandatory: - type: boolean - policyName: - example: org 레이블 요구 - type: string - templateCurrentVersion: - example: v1.0.1 - type: string - templateDescription: - example: 파라미터로 설정된 레이블 검사 - type: string - templateId: - example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 - type: string - templateLatestVerson: - example: v1.0.3 - type: string - templateName: - example: 레이블 요구 - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.ClusterResponse: properties: byoClusterEndpointHost: @@ -1391,6 +1369,15 @@ definitions: year: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus: + properties: + error: + type: integer + normal: + type: integer + warning: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain.DashboardResource: properties: cpu: @@ -1452,6 +1439,13 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest: + properties: + policyIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest: properties: adminPassword: @@ -1638,37 +1632,6 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterNode' type: array type: object - github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse: - properties: - affectedPolicies: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus' - type: array - templateCurrentVersion: - example: v1.0.1 - type: string - templateDescription: - example: 파라미터로 설정된 레이블 검사 - type: string - templateId: - example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 - type: string - templateLatestVerson: - example: v1.0.3 - type: string - templateLatestVersonReleaseDate: - format: date-time - type: string - templateMandatory: - type: boolean - templateName: - example: 레이블 요구 - type: string - updatedPolicyParameters: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter' - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.GetClusterResponse: properties: cluster: @@ -1695,6 +1658,11 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse: + properties: + statuses: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus' + type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse: properties: resources: @@ -1875,6 +1843,37 @@ definitions: kubeConfig: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse: + properties: + affectedPolicies: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyStatus' + type: array + templateCurrentVersion: + example: v1.0.1 + type: string + templateDescription: + example: 파라미터로 설정된 레이블 검사 + type: string + templateId: + example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 + type: string + templateLatestVerson: + example: v1.0.3 + type: string + templateLatestVersonReleaseDate: + format: date-time + type: string + templateMandatory: + type: boolean + templateName: + example: 레이블 요구 + type: string + updatedPolicyParameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdatedPolicyTemplateParameter' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetStackResponse: properties: stack: @@ -2064,13 +2063,6 @@ definitions: type: string type: array type: object - github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse: - properties: - polices: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterPolicyStatusResponse' - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse: properties: organizations: @@ -2116,6 +2108,13 @@ definitions: type: string type: array type: object + github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse: + properties: + polices: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.ListTksRoleResponse: properties: pagination: @@ -2920,6 +2919,35 @@ definitions: - tksInfraNode - tksUserNode type: object + github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse: + properties: + policyDescription: + example: org 레이블 설정 여부 검사 + type: string + policyId: + example: 0091fe9b-e44b-423d-9562-ac2b73089593 + type: string + policyMandatory: + type: boolean + policyName: + example: org 레이블 요구 + type: string + templateCurrentVersion: + example: v1.0.1 + type: string + templateDescription: + example: 파라미터로 설정된 레이블 검사 + type: string + templateId: + example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 + type: string + templateLatestVerson: + example: v1.0.3 + type: string + templateName: + example: 레이블 요구 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.StackResponse: properties: cloudAccount: @@ -3152,6 +3180,8 @@ definitions: type: string id: type: string + isSystem: + type: boolean messageActionProposal: type: string messageContent: @@ -3183,6 +3213,8 @@ definitions: type: string id: type: string + isSystem: + type: boolean metricParameters: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationMetricParameterResponse' @@ -3292,15 +3324,6 @@ definitions: description: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest: - properties: - templateCurrentVersion: - example: v1.0.1 - type: string - templateTargetVerson: - example: v1.0.3 - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest: properties: groupName: @@ -3509,6 +3532,15 @@ definitions: required: - name type: object + github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest: + properties: + templateCurrentVersion: + example: v1.0.1 + type: string + templateTargetVerson: + example: v1.0.3 + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.UpdateStackRequest: properties: description: @@ -3776,6 +3808,13 @@ definitions: startY: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest: + properties: + policyTemplateIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateReponse: properties: id: @@ -3864,6 +3903,13 @@ definitions: example: v1.1.1 type: string type: object + github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest: + properties: + policyTemplateIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateKindResponse: properties: existed: @@ -4201,6 +4247,62 @@ paths: summary: Create organization in Admin portal tags: - Organizations + /admin/organizations/{organizationId}/policyTemplates: + post: + consumes: + - application/json + description: 특정 조직에 대해 허용된 tks 템플릿 목록을 추가한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: update pemitted policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[Admin_AddPermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 tks + 템플릿 목록 추가' + tags: + - PolicyTemplate + put: + consumes: + - application/json + description: 특정 조직에 대해 허용된 tks 템플릿의 허용 상태를 해제(제거)한다. tks 우형 템플릿에 대해서만 동작하고 organization + 유형 템플릿에 대해서는 거부된다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: delete pemitted policy template request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.DeletePermittedPolicyTemplatesForOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[Admin_DeletePermittedPolicyTemplatesForOrganization] 특정 조직에 대해 허용된 + tks 템플릿 목록 제거' + tags: + - PolicyTemplate /admin/organizations/{organizationId}/projects: get: consumes: @@ -5562,111 +5664,6 @@ paths: summary: Get nodes information for BYOH tags: - Clusters - /clusters/{clusterId}/policy-status: - get: - consumes: - - application/json - description: 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. - parameters: - - description: 클러스터 식별자(uuid) - in: path - name: clusterId - required: true - type: string - - description: pageSize - in: query - name: pageSize - type: string - - description: pageNumber - in: query - name: pageNumber - type: string - - description: sortColumn - in: query - name: sortColumn - type: string - - description: sortOrder - in: query - name: sortOrder - type: string - - collectionFormat: csv - description: filters - in: query - items: - type: string - name: filters - type: array - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListClusterPolicyStatusResponse' - security: - - JWT: [] - summary: '[ListClusterPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회' - tags: - - ClusterPolicyStatus - /clusters/{clusterId}/policy-templates/{templateId}: - get: - consumes: - - application/json - description: 템플릿의 클러스터 버전 등 상태를 조회한다. - parameters: - - description: 클러스터 식별자(uuid) - in: path - name: clusterId - required: true - type: string - - description: 정책 템플릿 식별자(uuid) - in: path - name: templateId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetClusterPolicyTemplateStatusResponse' - security: - - JWT: [] - summary: '[GetClusterPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회' - tags: - - ClusterPolicyStatus - patch: - consumes: - - application/json - description: 해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다. - parameters: - - description: 클러스터 식별자(uuid) - in: path - name: clusterId - required: true - type: string - - description: 정책 템플릿 식별자(uuid) - in: path - name: templateId - required: true - type: string - - description: update cluster policy template status request - in: body - name: body - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateClusterPolicyTemplateStatusRequest' - produces: - - application/json - responses: - "200": - description: OK - security: - - JWT: [] - summary: '[UpdateClusterPolicyTemplateStatus] 템플릿 버전 업데이트' - tags: - - ClusterPolicyStatus /clusters/{clusterId}/site-values: get: consumes: @@ -6174,6 +6171,29 @@ paths: summary: Get chart data tags: - Dashboards + /organizations/{organizationId}/dashboard/policy-status: + get: + consumes: + - application/json + description: Get policy status + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse' + security: + - JWT: [] + summary: Get policy status + tags: + - Dashboards /organizations/{organizationId}/dashboard/resources: get: consumes: @@ -9175,6 +9195,187 @@ paths: summary: Get KubeConfig by stack tags: - Stacks + /organizations/{organizationId}/stacks/{stackId}/policies: + post: + consumes: + - application/json + description: 특정 스택의 정책 목록을 정책 식별자 리스트로 지정해서 추가한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: add policies for stack request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AddPoliciesForStackRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[AddPoliciesForStack] 특정 스택의 정책 목록 추가' + tags: + - Policy + put: + consumes: + - application/json + description: 특정 스택에서 정책 식별자로 지정된 정책을 제거한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: delete policies for stack request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeletePoliciesForStackRequest' + produces: + - application/json + responses: {} + security: + - JWT: [] + summary: '[DeletePoliciesForStack] 특정 스택의 정책 제거' + tags: + - Policy + /organizations/{organizationId}/stacks/{stackId}/policy-status: + get: + consumes: + - application/json + description: 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: pageSize + in: query + name: pageSize + type: string + - description: pageNumber + in: query + name: pageNumber + type: string + - description: sortColumn + in: query + name: sortColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse' + security: + - JWT: [] + summary: '[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회' + tags: + - StackPolicyStatus + /organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}: + get: + consumes: + - application/json + description: 템플릿의 클러스터 버전 등 상태를 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse' + security: + - JWT: [] + summary: '[GetStackPolicyTemplateStatus] 클러스터 템플릿 상태 상세 조회' + tags: + - StackPolicyStatus + patch: + consumes: + - application/json + description: 해당 템플릿의 버전 업데이트 및 연관된 정책의 새 기본값을 설정한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: 정책 템플릿 식별자(uuid) + in: path + name: policyTemplateId + required: true + type: string + - description: update stack policy template status request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateStackPolicyTemplateStatusRequest' + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: '[UpdateStackPolicyTemplateStatus] 템플릿 버전 업데이트' + tags: + - StackPolicyStatus /organizations/{organizationId}/stacks/{stackId}/status: get: consumes: From 937137939f3bc0f801c7438712c3e76248919fd6 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 9 Apr 2024 11:13:20 +0900 Subject: [PATCH 263/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EC=A4=91=EB=B3=B5=20=EA=B2=80=EC=82=AC=20api=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/route/route.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/route/route.go b/internal/route/route.go index 32dfac9b..3175eb04 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -351,7 +351,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.GetPolicy, http.HandlerFunc(policyHandler.GetPolicy))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.DeletePolicy, http.HandlerFunc(policyHandler.DeletePolicy))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.UpdatePolicy, http.HandlerFunc(policyHandler.UpdatePolicy))).Methods(http.MethodPatch) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyName, http.HandlerFunc(policyHandler.ExistsPolicyName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/name/{policyName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyName, http.HandlerFunc(policyHandler.ExistsPolicyName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.AddPoliciesForStack, http.HandlerFunc(policyHandler.AddPoliciesForStack))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.DeletePoliciesForStack, http.HandlerFunc(policyHandler.DeletePoliciesForStack))).Methods(http.MethodPut) From 9a496129d0078285eda460be8ac0dd6c856a60c9 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 9 Apr 2024 15:03:58 +0900 Subject: [PATCH 264/502] trivial. bugfix --- internal/pagination/pagination.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 390e20fa..84d93fe3 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -194,7 +194,7 @@ func NewPagination(urlParams *url.Values) *Pagination { pg.Page, _ = strconv.Atoi(value[0]) } case PAGE_SIZE: - if value[0] == "" { + if value[0] != "" { if limitNum, err := strconv.Atoi(value[0]); err == nil { pg.Limit = limitNum } From 2cd6f863e698af99de44ceb13e53ecdd0fcfa854 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 9 Apr 2024 15:22:35 +0900 Subject: [PATCH 265/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=EB=B0=8F=20?= =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EB=B2=84=EC=A0=84=EC=97=85=20?= =?UTF-8?q?=ED=86=B5=EA=B3=84=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 ++ internal/delivery/http/policy.go | 46 +++++++++++ internal/policy-template/tkspolicy.go | 4 + internal/policy-template/tkspolicytemplate.go | 45 +++++++++++ internal/route/route.go | 1 + internal/usecase/policy.go | 79 +++++++++++++++++++ pkg/domain/policy.go | 9 +++ pkg/httpErrors/errorCode.go | 2 +- 9 files changed, 194 insertions(+), 1 deletion(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index deb76d8e..2eca135f 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -258,6 +258,7 @@ const ( GetPolicyEdit AddPoliciesForStack DeletePoliciesForStack + StackPolicyStatistics // OrganizationPolicyTemplate ListPolicyTemplate diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index aa43c935..ba06253e 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -807,6 +807,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "DeletePoliciesForStack", Group: "Policy", }, + StackPolicyStatistics: { + Name: "StackPolicyStatistics", + Group: "Policy", + }, ListPolicyTemplate: { Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", @@ -1288,6 +1292,8 @@ func (e Endpoint) String() string { return "AddPoliciesForStack" case DeletePoliciesForStack: return "DeletePoliciesForStack" + case StackPolicyStatistics: + return "StackPolicyStatistics" case ListPolicyTemplate: return "ListPolicyTemplate" case CreatePolicyTemplate: @@ -1734,6 +1740,8 @@ func GetEndpoint(name string) Endpoint { return AddPoliciesForStack case "DeletePoliciesForStack": return DeletePoliciesForStack + case "StackPolicyStatistics": + return StackPolicyStatistics case "ListPolicyTemplate": return ListPolicyTemplate case "CreatePolicyTemplate": diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index c26d0ee5..ef8529a7 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -40,6 +40,7 @@ type IPolicyHandler interface { AddPoliciesForStack(w http.ResponseWriter, r *http.Request) UpdatePoliciesForStack(w http.ResponseWriter, r *http.Request) DeletePoliciesForStack(w http.ResponseWriter, r *http.Request) + StackPolicyStatistics(w http.ResponseWriter, r *http.Request) } func NewPolicyHandler(u usecase.Usecase) IPolicyHandler { @@ -646,6 +647,51 @@ func (h *PolicyHandler) ListStackPolicyStatus(w http.ResponseWriter, r *http.Req ResponseJSON(w, r, http.StatusOK, out) } +// StackPolicyStatistics godoc +// +// @Tags StackPolicyStatus +// @Summary [ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회 +// @Description 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param stackId path string true "스택 식별자" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" +// @Param sortColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.ListStackPolicyStatusResponse +// @Router /organizations/{organizationId}/stacks/{stackId}/statistics [get] +// @Security JWT +func (h *PolicyHandler) StackPolicyStatistics(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), + "C_INVALID_STACK_ID", "")) + return + } + + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid clusterId"), + "C_INVALID_STACK_ID", "")) + return + } + + stackPolicyStatistics, err := h.usecase.GetStackPolicyStatistics(r.Context(), + organizationId, domain.ClusterId(stackId)) + + if err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, stackPolicyStatistics) +} + // GetStackPolicyTemplateStatus godoc // // @Tags StackPolicyStatus diff --git a/internal/policy-template/tkspolicy.go b/internal/policy-template/tkspolicy.go index 11b50a94..c38e8f7a 100644 --- a/internal/policy-template/tkspolicy.go +++ b/internal/policy-template/tkspolicy.go @@ -71,6 +71,10 @@ func (tksPolicy *TKSPolicy) GetPolicyID() string { return tksPolicy.ObjectMeta.Labels[PolicyIDLabel] } +func (tksPolicy *TKSPolicy) GetTemplateID() string { + return tksPolicy.ObjectMeta.Labels[TemplateIDLabel] +} + func (tksPolicy *TKSPolicy) JSON() (string, error) { result, err := json.MarshalIndent(tksPolicy, "", " ") diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index 653952dd..9b32d303 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -149,6 +149,10 @@ func (tksPolicyTemplate *TKSPolicyTemplate) ToUnstructured() (*unstructured.Unst return tksPolicyTemplateUnstructured, nil } +func (tksPolicyTemplate *TKSPolicyTemplate) GetId() string { + return tksPolicyTemplate.ObjectMeta.Labels[TemplateIDLabel] +} + func ApplyTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tksPolicyTemplate *TKSPolicyTemplate) error { if syncToKubernetes() { dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) @@ -282,3 +286,44 @@ func UpdateTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tks return err } + +func ListTksPolicyTemplateCR(ctx context.Context, primaryClusterId string) ([]*TKSPolicyTemplate, error) { + if syncToKubernetes() { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + + if err != nil { + return nil, err + } + + results, err := dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). + List(ctx, metav1.ListOptions{}) + + if err != nil { + return nil, err + } + + tkspolicytemplates := make([]*TKSPolicyTemplate, len(results.Items)) + + for i, result := range results.Items { + jsonBytes, err := json.Marshal(result.Object) + + if err != nil { + return nil, err + } + + var tksPolicyTemplate TKSPolicyTemplate + err = json.Unmarshal(jsonBytes, &tksPolicyTemplate) + + if err != nil { + return nil, err + } + + tkspolicytemplates[i] = &tksPolicyTemplate + } + + return tkspolicytemplates, nil + } + + tkspolicytemplates := make([]*TKSPolicyTemplate, 0) + return tkspolicytemplates, nil +} diff --git a/internal/route/route.go b/internal/route/route.go index 32dfac9b..6c976bbd 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -354,6 +354,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyName, http.HandlerFunc(policyHandler.ExistsPolicyName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.AddPoliciesForStack, http.HandlerFunc(policyHandler.AddPoliciesForStack))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.DeletePoliciesForStack, http.HandlerFunc(policyHandler.DeletePoliciesForStack))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/statistics", customMiddleware.Handle(internalApi.StackPolicyStatistics, http.HandlerFunc(policyHandler.StackPolicyStatistics))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policy-status", customMiddleware.Handle(internalApi.ListStackPolicyStatus, http.HandlerFunc(policyHandler.ListStackPolicyStatus))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policy-templates/{policyTemplateId}", customMiddleware.Handle(internalApi.GetStackPolicyTemplateStatus, http.HandlerFunc(policyHandler.GetStackPolicyTemplateStatus))).Methods(http.MethodGet) diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 2a7eb41a..c07d62a2 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -43,6 +43,7 @@ type IPolicyUsecase interface { AddPoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) UpdatePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) DeletePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) + GetStackPolicyStatistics(ctx context.Context, organizationId string, clusterId domain.ClusterId) (statistics *domain.StackPolicyStatistics, err error) } type PolicyUsecase struct { @@ -939,6 +940,84 @@ func (u *PolicyUsecase) DeletePoliciesForClusterID(ctx context.Context, organiza return u.repo.DeletePoliciesForClusterID(ctx, organizationId, clusterId, policyIds) } +func (u *PolicyUsecase) GetStackPolicyStatistics(ctx context.Context, organizationId string, clusterId domain.ClusterId) (statistics *domain.StackPolicyStatistics, err error) { + organization, err := u.organizationRepo.Get(ctx, organizationId) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") + } + + primaryClusterId := organization.PrimaryClusterId + + templateList, err := policytemplate.ListTksPolicyTemplateCR(ctx, primaryClusterId) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return nil, httpErrors.NewInternalServerError(fmt.Errorf("fail to get template list from kubernetes"), "P_FAILED_TO_CALL_KUBERNETES", "") + } + + totalTemplateCount := len(templateList) + outdatedTemplateIds := []string{} + + for _, template := range templateList { + templateId := template.GetId() + + id, err := uuid.Parse(templateId) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + continue + } + + version, err := u.templateRepo.GetLatestTemplateVersion(ctx, id) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + continue + } + + if version != template.Spec.Version { + outdatedTemplateIds = append(outdatedTemplateIds, templateId) + } + } + + outdatedTemplateCount := len(outdatedTemplateIds) + uptodateTemplateCount := totalTemplateCount - outdatedTemplateCount + + policyList, err := policytemplate.ListTksPolicyCR(ctx, primaryClusterId) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return nil, httpErrors.NewInternalServerError(fmt.Errorf("fail to get policy list from kubernetes"), "P_FAILED_TO_CALL_KUBERNETES", "") + } + + outdatedPolicyCount := 0 + + for _, policy := range policyList { + templateId := policy.GetTemplateID() + + if slices.Contains(outdatedTemplateIds, templateId) { + outdatedPolicyCount++ + } + } + + tototalPolicyCount := len(policyList) + + uptodatePolicyCount := tototalPolicyCount - outdatedPolicyCount + + result := domain.StackPolicyStatistics{ + TotalTemplateCount: totalTemplateCount, + UptodateTemplateCount: uptodateTemplateCount, + OutofdateTemplateCount: outdatedTemplateCount, + TotalPolicyCount: tototalPolicyCount, + UptodatePolicyCount: uptodatePolicyCount, + OutofdatePolicyCount: outdatedPolicyCount, + } + + return &result, nil +} + func extractNewTemplateParameter(paramdefs []*domain.ParameterDef, newParamDefs []*domain.ParameterDef) (policyParameters []domain.UpdatedPolicyTemplateParameter, err error) { diffParamDef, err := policytemplate.GetNewParamDefs(paramdefs, newParamDefs) diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index 5416f828..cdf10c7f 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -205,3 +205,12 @@ type PolicyStatisticsResponse struct { Template TemplateCount `json:"templateCount"` Policy PolicyCount `json:"policyCount"` } + +type StackPolicyStatistics struct { + TotalTemplateCount int `json:"totalTemplateCount"` + UptodateTemplateCount int `json:"uptodateTemplateCount"` + OutofdateTemplateCount int `json:"outofdateTemplateCount"` + TotalPolicyCount int `json:"totalPolicyCount"` + UptodatePolicyCount int `json:"uptodatePolicyCount"` + OutofdatePolicyCount int `json:"outofdatePolicyCount"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 3b90a6a9..3e0e5457 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -136,7 +136,7 @@ var errorMap = map[ErrorCode]string{ "P_INVALID_MATCH": "유효하지 않은 match 설정입니다. match 설정을 확인하세요.", "P_FAILED_FETCH_POLICY": "정책 ID에 해당하는 정책을 가져오는데 실패했습니다.", "P_FAILED_FETCH_CLUSTER": "정책의 클러스터 정보를 가져오는데 실패했습니다.", - "P_FAILED_FETCH_TEMPLATE": "정책의 클러스터 정보를 가져오는데 실패했습니다.", + "P_FAILED_FETCH_TEMPLATE": "정책의 템플릿 정보를 가져오는데 실패했습니다.", "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", } From 030d040ed164681eb3882410937aa679b9b1e476 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 9 Apr 2024 15:40:38 +0900 Subject: [PATCH 266/502] add API for providing project_namespace's kubeconfig --- internal/delivery/http/project.go | 54 +++++++++++++++++++++++++++++++ internal/usecase/project.go | 48 +++++++++++++++++++++++++++ pkg/domain/project.go | 4 +++ 3 files changed, 106 insertions(+) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 2db13574..91d389b0 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -55,6 +55,7 @@ type IProjectHandler interface { GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) GetProjectNamespaceK8sResources(w http.ResponseWriter, r *http.Request) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, r *http.Request) + GetProjectNamespaceKubeconfig(w http.ResponseWriter, r *http.Request) } type ProjectHandler struct { @@ -1821,3 +1822,56 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, } ResponseJSON(w, r, http.StatusOK, out) } + +// GetProjectNamespaceKubeconfig godoc +// +// @Tags Projects +// @Summary Get project namespace kubeconfig +// @Description Get project namespace kubeconfig +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param stackId path string true "Stack ID" +// @Param projectNamespace path string true "Project Namespace" +// @Success 200 {object} domain.GetProjectNamespaceKubeConfigResponse +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig [get] +// @Security JWT +func (p ProjectHandler) GetProjectNamespaceKubeconfig(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found in path"), "C_INVALID_PROJECT_ID", "")) + return + } + + projectNamespace, ok := vars["projectNamespace"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid projectNamespace"), "C_INVALID_PROJECT_NAMESPACE", "")) + return + } + stackId, ok := vars["stackId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackId"), "C_INVALID_STACK_ID", "")) + return + } + + kubeconfig, err := p.usecase.GetProjectNamespaceKubeconfig(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) + if err != nil { + log.Error(r.Context(), "Failed to get project kubeconfig.", err) + ErrorJSON(w, r, err) + return + } + + out := domain.GetProjectNamespaceKubeConfigResponse{ + KubeConfig: kubeconfig, + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 6a02db3d..b38cd056 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -56,6 +56,7 @@ type IProjectUsecase interface { MayRemoveRequiredSetupForCluster(ctx context.Context, organizationId string, projectId string, stackId string) error CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error DeleteK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error + GetProjectNamespaceKubeconfig(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (string, error) GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) @@ -654,6 +655,53 @@ func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, return nil } +func (u *ProjectUsecase) GetProjectNamespaceKubeconfig(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (string, error) { + kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId.String(), kubernetes.KubeconfigForUser) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to get kubeconfig.") + } + + type kubeConfigType struct { + APIVersion string `yaml:"apiVersion"` + Kind string `yaml:"kind"` + Clusters []struct { + Name string `yaml:"name"` + Cluster struct { + Server string `yaml:"server"` + CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` + } `yaml:"cluster"` + } `yaml:"clusters"` + Contexts []struct { + Name string `yaml:"name"` + Context struct { + Cluster string `yaml:"cluster"` + User string `yaml:"user"` + Namespace string `yaml:"namespace,omitempty"` + } `yaml:"context"` + } `yaml:"contexts"` + + Users []interface{} `yaml:"users,omitempty"` + } + + var config kubeConfigType + err = yaml.Unmarshal(kubeconfig, &config) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to unmarshal kubeconfig.") + } + config.Contexts[0].Context.Namespace = namespace + + kubeconfig, err = yaml.Marshal(config) + if err != nil { + log.Error(ctx, err) + return "", errors.Wrap(err, "Failed to marshal kubeconfig.") + } + + return string(kubeconfig[:]), nil + +} + func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) { projectNamespaces, err := u.projectRepo.GetProjectNamespaces(ctx, organizationId, projectId, nil) if err != nil { diff --git a/pkg/domain/project.go b/pkg/domain/project.go index b63d6036..517c31b4 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -194,3 +194,7 @@ type ProjectNamespaceResourcesUsage struct { type GetProjectNamespaceResourcesUsageResponse struct { ResourcesUsage ProjectNamespaceResourcesUsage `json:"resourcesUsage"` } + +type GetProjectNamespaceKubeConfigResponse struct { + KubeConfig string `json:"kubeConfig"` +} From b6527933ca445730736b3c0bcb342adba918373a Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 9 Apr 2024 15:54:22 +0900 Subject: [PATCH 267/502] add API for providing project_namespace's kubeconfig. --- internal/delivery/api/endpoint.go | 1 + internal/route/route.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2eca135f..fc741f58 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -185,6 +185,7 @@ const ( UnSetFavoriteProjectNamespace GetProjectKubeconfig GetProjectNamespaceK8sResources + GetProjectNamespaceKubeconfig // Audit GetAudits diff --git a/internal/route/route.go b/internal/route/route.go index 06d8aca5..8f857aeb 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -278,6 +278,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateProjectNamespace, http.HandlerFunc(projectHandler.UpdateProjectNamespace))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectNamespaceKubeconfig, http.HandlerFunc(projectHandler.GetProjectNamespaceKubeconfig))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) auditHandler := delivery.NewAuditHandler(usecaseFactory) From 19bd434cf06a01f24ab9ace9c9722b552b2f8bf5 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 9 Apr 2024 15:56:19 +0900 Subject: [PATCH 268/502] trivial. remove invalid validation tag from organization --- pkg/domain/organization.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index ef19f12c..f128bf0d 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -75,7 +75,7 @@ type CreateOrganizationRequest struct { Description string `json:"description" validate:"omitempty,min=0,max=100"` AdminAccountId string `json:"adminAccountId" validate:"required"` AdminName string `json:"adminName" validate:"name"` - AdminEmail string `json:"adminEmail" validate:"required,email"` + AdminEmail string `json:"adminEmail" validate:"required"` } type CreateOrganizationResponse struct { From 8ecf51a3d7ebd9aad66160b6c68354ac7f63a7f2 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 9 Apr 2024 16:00:00 +0900 Subject: [PATCH 269/502] rollback. rollback to previous commit --- pkg/domain/organization.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index f128bf0d..ef19f12c 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -75,7 +75,7 @@ type CreateOrganizationRequest struct { Description string `json:"description" validate:"omitempty,min=0,max=100"` AdminAccountId string `json:"adminAccountId" validate:"required"` AdminName string `json:"adminName" validate:"name"` - AdminEmail string `json:"adminEmail" validate:"required"` + AdminEmail string `json:"adminEmail" validate:"required,email"` } type CreateOrganizationResponse struct { From 2754d651621dc8468bd2c4386c59b8feff078008 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 9 Apr 2024 16:46:05 +0900 Subject: [PATCH 270/502] =?UTF-8?q?StackPolicyStatistics=20API=EC=97=90=20?= =?UTF-8?q?tks=ED=85=9C=ED=94=8C=EB=A6=BF,=20org=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=EC=9C=BC=EB=A1=9C=20=EC=83=9D=EC=84=B1=EB=90=9C=20?= =?UTF-8?q?=EC=A0=95=EC=B1=85=20=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy.go | 2 +- internal/repository/policy-template.go | 29 +++++++++++++++----------- internal/usecase/policy.go | 15 +++++++++---- pkg/domain/policy.go | 10 +++++---- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index ef8529a7..412770d8 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -661,7 +661,7 @@ func (h *PolicyHandler) ListStackPolicyStatus(w http.ResponseWriter, r *http.Req // @Param sortColumn query string false "sortColumn" // @Param sortOrder query string false "sortOrder" // @Param filters query []string false "filters" -// @Success 200 {object} domain.ListStackPolicyStatusResponse +// @Success 200 {object} domain.StackPolicyStatistics // @Router /organizations/{organizationId}/stacks/{stackId}/statistics [get] // @Security JWT func (h *PolicyHandler) StackPolicyStatistics(w http.ResponseWriter, r *http.Request) { diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index f472a1cf..c075189b 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -36,6 +36,7 @@ type IPolicyTemplateRepository interface { GetLatestTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID) (version string, err error) CountTksTemplateByOrganization(ctx context.Context, organizationId string) (count int64, err error) CountOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) + CountPolicyFromOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) } type PolicyTemplateRepository struct { @@ -184,22 +185,26 @@ func (r *PolicyTemplateRepository) CountTksTemplateByOrganization(ctx context.Co } func (r *PolicyTemplateRepository) CountOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) { - subQueryAloowedAll := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id") - subQueryMatchId := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id"). + err = r.db.WithContext(ctx). + Model(&model.PolicyTemplate{}). + Where("type = ?", "organization"). + Where("organization_id = ?", organizationId). + Count(&count).Error + + return +} + +func (r *PolicyTemplateRepository) CountPolicyFromOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) { + subQuery := r.db.Table("policy_templates").Select("id"). + Where("type = ?", "organization"). Where("organization_id = ?", organizationId) err = r.db.WithContext(ctx). - Model(&model.PolicyTemplate{}). + Model(&model.Policy{}). Where( - // tks 템플릿인 경우 - r.db.Where("type = ?", "tks"). - Where( - // permitted_organizations이 비어있거나 - r.db.Where("id not in (?)", subQueryAloowedAll). - Or("id in (?)", subQueryMatchId), - // permitted_organization에 매칭되는 템플릿 아이디가 있거나 - ), - ).Count(&count).Error + r.db.Where("template_id in (?)", subQuery), + ). + Count(&count).Error return } diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index c07d62a2..f209bb86 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -752,11 +752,18 @@ func (u *PolicyUsecase) GetPolicyStatistics(ctx context.Context, organizationId Total: tksTemplateCount + orgTemplateCount, } + policyFromOrgTemplates, err := u.templateRepo.CountPolicyFromOrganizationTemplate(ctx, organizationId) + if err != nil { + return nil, err + } + result.Policy = domain.PolicyCount{ - Deny: deny, - Warn: warn, - Dryrun: dryrun, - Total: policyTotal, + Deny: deny, + Warn: warn, + Dryrun: dryrun, + FromOrgTemplate: policyFromOrgTemplates, + FromTksTemplate: policyTotal - policyFromOrgTemplates, + Total: policyTotal, } return &result, nil diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index cdf10c7f..8171ad03 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -195,10 +195,12 @@ type TemplateCount struct { } type PolicyCount struct { - Deny int64 `json:"deny"` - Warn int64 `json:"warn"` - Dryrun int64 `json:"dryrun"` - Total int64 `json:"total"` + Deny int64 `json:"deny"` + Warn int64 `json:"warn"` + Dryrun int64 `json:"dryrun"` + FromTksTemplate int64 `json:"fromTksTemplate"` + FromOrgTemplate int64 `json:"fromOrgTemplate"` + Total int64 `json:"total"` } type PolicyStatisticsResponse struct { From d2bf5139903cde8559cff379efd74152238af6b0 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 9 Apr 2024 16:56:36 +0900 Subject: [PATCH 271/502] policy update widget --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/dashboard.go | 48 ++++++++++ internal/policy-template/tkspolicy.go | 91 ++++++++++++------- internal/policy-template/tkspolicytemplate.go | 91 ++++++++++++------- internal/route/route.go | 1 + internal/usecase/dashboard.go | 47 ++++++++++ internal/usecase/policy.go | 18 ++-- pkg/domain/dashboard.go | 9 ++ 8 files changed, 227 insertions(+), 79 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 2eca135f..428e9afc 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -118,6 +118,7 @@ const ( GetStacksDashboard // 대시보드/대시보드/조회 GetResourcesDashboard // 대시보드/대시보드/조회 GetPolicyStatusDashboard + GetPolicyUpdateDashboard // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index f0294bfc..75c7a399 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -24,6 +24,7 @@ type IDashboardHandler interface { GetStacks(w http.ResponseWriter, r *http.Request) GetResources(w http.ResponseWriter, r *http.Request) GetPolicyStatus(w http.ResponseWriter, r *http.Request) + GetPolicyUpdate(w http.ResponseWriter, r *http.Request) } type DashboardHandler struct { @@ -471,3 +472,50 @@ func (h *DashboardHandler) GetPolicyStatus(w http.ResponseWriter, r *http.Reques out.PolicyStatus = policyStatus ResponseJSON(w, r, http.StatusOK, out) } + +// GetPolicyUpdate godoc +// +// @Tags Dashboards +// @Summary Get the number of policytemplates that need to be updated +// @Description Get the number of policytemplates that need to be updated +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetDashboardPolicyUpdateResponse +// @Router /organizations/{organizationId}/dashboard/policy-update [get] +// @Security JWT +func (h *DashboardHandler) GetPolicyUpdate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + organization, err := h.organizationUsecase.Get(r.Context(), organizationId) + if err != nil { + log.Error(r.Context(), "Failed to retrieve organization") + ErrorJSON(w, r, fmt.Errorf("failed to retrieve organization")) + return + } + + policyTemplates, err := policytemplate.GetTksPolicyTemplateCRs(r.Context(), organization.PrimaryClusterId) + if err != nil { + log.Error(r.Context(), "Failed to retrieve policytemplate list", err) + ErrorJSON(w, r, err) + return + } + policies, err := policytemplate.GetTksPolicyCRs(r.Context(), organization.PrimaryClusterId) + if err != nil { + log.Error(r.Context(), "Failed to retrieve policy list", err) + ErrorJSON(w, r, err) + return + } + + dpu, err := h.usecase.GetPolicyUpdate(r.Context(), policyTemplates, policies) + + var out domain.GetDashboardPolicyUpdateResponse + out.PolicyUpdate = dpu + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/policy-template/tkspolicy.go b/internal/policy-template/tkspolicy.go index c38e8f7a..aa1ef836 100644 --- a/internal/policy-template/tkspolicy.go +++ b/internal/policy-template/tkspolicy.go @@ -235,43 +235,64 @@ func ExistsTksPolicyCR(ctx context.Context, primaryClusterId string, name string return true, nil } -func ListTksPolicyCR(ctx context.Context, primaryClusterId string) ([]*TKSPolicy, error) { - if syncToKubernetes() { - dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) - - if err != nil { - return nil, err - } - - results, err := dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). - List(ctx, metav1.ListOptions{}) - - if err != nil { - return nil, err - } - - tkspolicies := make([]*TKSPolicy, len(results.Items)) - - for i, result := range results.Items { - jsonBytes, err := json.Marshal(result.Object) - - if err != nil { - return nil, err - } - - var tksPolicy TKSPolicy - err = json.Unmarshal(jsonBytes, &tksPolicy) - - if err != nil { - return nil, err - } +//func ListTksPolicyCR(ctx context.Context, primaryClusterId string) ([]TKSPolicy, error) { +// if syncToKubernetes() { +// dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) +// +// if err != nil { +// return nil, err +// } +// +// results, err := dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). +// List(ctx, metav1.ListOptions{}) +// +// if err != nil { +// return nil, err +// } +// +// tkspolicies := make([]TKSPolicy, len(results.Items)) +// +// for i, result := range results.Items { +// jsonBytes, err := json.Marshal(result.Object) +// +// if err != nil { +// return nil, err +// } +// +// var tksPolicy TKSPolicy +// err = json.Unmarshal(jsonBytes, &tksPolicy) +// +// if err != nil { +// return nil, err +// } +// +// tkspolicies[i] = tksPolicy +// } +// +// return tkspolicies, nil +// } +// +// tkspolicies := make([]TKSPolicy, 0) +// return tkspolicies, nil +//} + +func GetTksPolicyCRs(ctx context.Context, primaryClusterId string) (tksPolicies []TKSPolicy, err error) { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + if err != nil { + return nil, err + } - tkspolicies[i] = &tksPolicy - } + resources, err := dynamicClient.Resource(TKSPolicyGVR).Namespace(primaryClusterId). + List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return nil, err + } - return tkspolicies, nil + var tksPolicy TKSPolicy + for _, c := range resources.Items { + err = runtime.DefaultUnstructuredConverter.FromUnstructured(c.UnstructuredContent(), &tksPolicy) + tksPolicies = append(tksPolicies, tksPolicy) } - tkspolicies := make([]*TKSPolicy, 0) - return tkspolicies, nil + return tksPolicies, nil } diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index 9b32d303..08709581 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -287,43 +287,64 @@ func UpdateTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tks return err } -func ListTksPolicyTemplateCR(ctx context.Context, primaryClusterId string) ([]*TKSPolicyTemplate, error) { - if syncToKubernetes() { - dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) - - if err != nil { - return nil, err - } - - results, err := dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). - List(ctx, metav1.ListOptions{}) - - if err != nil { - return nil, err - } - - tkspolicytemplates := make([]*TKSPolicyTemplate, len(results.Items)) - - for i, result := range results.Items { - jsonBytes, err := json.Marshal(result.Object) - - if err != nil { - return nil, err - } - - var tksPolicyTemplate TKSPolicyTemplate - err = json.Unmarshal(jsonBytes, &tksPolicyTemplate) - - if err != nil { - return nil, err - } +//func ListTksPolicyTemplateCR(ctx context.Context, primaryClusterId string) ([]TKSPolicyTemplate, error) { +// if syncToKubernetes() { +// dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) +// +// if err != nil { +// return nil, err +// } +// +// results, err := dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). +// List(ctx, metav1.ListOptions{}) +// +// if err != nil { +// return nil, err +// } +// +// tkspolicytemplates := make([]TKSPolicyTemplate, len(results.Items)) +// +// for i, result := range results.Items { +// jsonBytes, err := json.Marshal(result.Object) +// +// if err != nil { +// return nil, err +// } +// +// var tksPolicyTemplate TKSPolicyTemplate +// err = json.Unmarshal(jsonBytes, &tksPolicyTemplate) +// +// if err != nil { +// return nil, err +// } +// +// tkspolicytemplates[i] = tksPolicyTemplate +// } +// +// return tkspolicytemplates, nil +// } +// +// tkspolicytemplates := make([]TKSPolicyTemplate, 0) +// return tkspolicytemplates, nil +//} + +func GetTksPolicyTemplateCRs(ctx context.Context, primaryClusterId string) (tksPolicyTemplates []TKSPolicyTemplate, err error) { + dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) + if err != nil { + return nil, err + } - tkspolicytemplates[i] = &tksPolicyTemplate - } + resources, err := dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). + List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return nil, err + } - return tkspolicytemplates, nil + var tksPolicyTemplate TKSPolicyTemplate + for _, c := range resources.Items { + err = runtime.DefaultUnstructuredConverter.FromUnstructured(c.UnstructuredContent(), &tksPolicyTemplate) + tksPolicyTemplates = append(tksPolicyTemplates, tksPolicyTemplate) } - tkspolicytemplates := make([]*TKSPolicyTemplate, 0) - return tkspolicytemplates, nil + return tksPolicyTemplates, nil } diff --git a/internal/route/route.go b/internal/route/route.go index 06d8aca5..34e391b6 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -206,6 +206,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/policy-status", customMiddleware.Handle(internalApi.GetPolicyStatusDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/policy-update", customMiddleware.Handle(internalApi.GetPolicyUpdateDashboard, http.HandlerFunc(dashboardHandler.GetPolicyUpdate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index e404e2f7..c8b628cc 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/model" + policytemplate "github.com/openinfradev/tks-api/internal/policy-template" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" @@ -33,6 +34,7 @@ type IDashboardUsecase interface { GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (res []domain.DashboardChart, err error) GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) GetResources(ctx context.Context, organizationId string) (out domain.DashboardResource, err error) + GetPolicyUpdate(ctx context.Context, policyTemplates []policytemplate.TKSPolicyTemplate, policies []policytemplate.TKSPolicy) (domain.DashboardPolicyUpdate, error) } type DashboardUsecase struct { @@ -41,6 +43,8 @@ type DashboardUsecase struct { clusterRepo repository.IClusterRepository appGroupRepo repository.IAppGroupRepository systemNotificationRepo repository.ISystemNotificationRepository + policyTemplateRepo repository.IPolicyTemplateRepository + policyRepo repository.IPolicyRepository cache *gcache.Cache } @@ -51,6 +55,8 @@ func NewDashboardUsecase(r repository.Repository, cache *gcache.Cache) IDashboar clusterRepo: r.Cluster, appGroupRepo: r.AppGroup, systemNotificationRepo: r.SystemNotification, + policyTemplateRepo: r.PolicyTemplate, + policyRepo: r.Policy, cache: cache, } } @@ -601,6 +607,47 @@ func (u *DashboardUsecase) getClusterNameFromId(ctx context.Context, clusterId s return } +func (u *DashboardUsecase) GetPolicyUpdate(ctx context.Context, policyTemplates []policytemplate.TKSPolicyTemplate, + policies []policytemplate.TKSPolicy) (domain.DashboardPolicyUpdate, error) { + + var outdatedTemplateIds []string + for _, tpt := range policyTemplates { + templateId := tpt.Labels[policytemplate.TemplateIDLabel] + id, err := uuid.Parse(templateId) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + continue + } + version, err := u.policyTemplateRepo.GetLatestTemplateVersion(ctx, id) + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + continue + } + + if version != tpt.Spec.Version { + outdatedTemplateIds = append(outdatedTemplateIds, templateId) + } + } + + outdatedTemplateCount := len(outdatedTemplateIds) + outdatedPolicyCount := 0 + + for _, policy := range policies { + templateId := policy.Labels[policytemplate.TemplateIDLabel] + + if slices.Contains(outdatedTemplateIds, templateId) { + outdatedPolicyCount++ + } + } + + dpu := domain.DashboardPolicyUpdate{ + PolicyTemplate: outdatedTemplateCount, + Policy: outdatedPolicyCount, + } + + return dpu, nil +} + func rangeDate(start, end time.Time) func() time.Time { y, m, d := start.Date() start = time.Date(y, m, d, 0, 0, 0, 0, time.UTC) diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index c07d62a2..6f950115 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -773,7 +773,7 @@ func (u *PolicyUsecase) AddPoliciesForClusterID(ctx context.Context, organizatio return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } - tkpolicies, err := policytemplate.ListTksPolicyCR(ctx, primaryClusterId) + tkpolicies, err := policytemplate.GetTksPolicyCRs(ctx, primaryClusterId) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) @@ -796,7 +796,7 @@ func (u *PolicyUsecase) AddPoliciesForClusterID(ctx context.Context, organizatio if !slices.Contains(tkspolicy.Spec.Clusters, string(clusterId)) { tkspolicy.Spec.Clusters = append(tkspolicy.Spec.Clusters, string(clusterId)) - err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, tkspolicy) + err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, &tkspolicy) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) } @@ -833,7 +833,7 @@ func (u *PolicyUsecase) UpdatePoliciesForClusterID(ctx context.Context, organiza return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } - tkpolicies, err := policytemplate.ListTksPolicyCR(ctx, primaryClusterId) + tkpolicies, err := policytemplate.GetTksPolicyCRs(ctx, primaryClusterId) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) @@ -856,7 +856,7 @@ func (u *PolicyUsecase) UpdatePoliciesForClusterID(ctx context.Context, organiza if !slices.Contains(tkspolicy.Spec.Clusters, string(clusterId)) { tkspolicy.Spec.Clusters = append(tkspolicy.Spec.Clusters, string(clusterId)) - err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, tkspolicy) + err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, &tkspolicy) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) } @@ -870,7 +870,7 @@ func (u *PolicyUsecase) UpdatePoliciesForClusterID(ctx context.Context, organiza tkspolicy.Spec.Clusters = slices.Filter(newClusters, tkspolicy.Spec.Clusters, func(s string) bool { return s != string(clusterId) }) - err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, tkspolicy) + err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, &tkspolicy) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) } @@ -906,7 +906,7 @@ func (u *PolicyUsecase) DeletePoliciesForClusterID(ctx context.Context, organiza return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } - tkpolicies, err := policytemplate.ListTksPolicyCR(ctx, primaryClusterId) + tkpolicies, err := policytemplate.GetTksPolicyCRs(ctx, primaryClusterId) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) @@ -928,7 +928,7 @@ func (u *PolicyUsecase) DeletePoliciesForClusterID(ctx context.Context, organiza tkspolicy.Spec.Clusters = slices.Filter(newClusters, tkspolicy.Spec.Clusters, func(s string) bool { return s != string(clusterId) }) - err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, tkspolicy) + err := policytemplate.ApplyTksPolicyCR(ctx, primaryClusterId, &tkspolicy) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) @@ -951,7 +951,7 @@ func (u *PolicyUsecase) GetStackPolicyStatistics(ctx context.Context, organizati primaryClusterId := organization.PrimaryClusterId - templateList, err := policytemplate.ListTksPolicyTemplateCR(ctx, primaryClusterId) + templateList, err := policytemplate.GetTksPolicyTemplateCRs(ctx, primaryClusterId) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) @@ -985,7 +985,7 @@ func (u *PolicyUsecase) GetStackPolicyStatistics(ctx context.Context, organizati outdatedTemplateCount := len(outdatedTemplateIds) uptodateTemplateCount := totalTemplateCount - outdatedTemplateCount - policyList, err := policytemplate.ListTksPolicyCR(ctx, primaryClusterId) + policyList, err := policytemplate.GetTksPolicyCRs(ctx, primaryClusterId) if err != nil { log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 6574c428..e8f52250 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -188,3 +188,12 @@ type DashboardPolicyStatus struct { type GetDashboardPolicyStatusResponse struct { PolicyStatus DashboardPolicyStatus `json:"statuses"` } + +type DashboardPolicyUpdate struct { + PolicyTemplate int `json:"policyTemplate"` + Policy int `json:"policy"` +} + +type GetDashboardPolicyUpdateResponse struct { + PolicyUpdate DashboardPolicyUpdate `json:"updatedResources"` +} From ff3f6a9e30c6f5a23e32930caef69d9bdf1efb59 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 9 Apr 2024 16:57:51 +0900 Subject: [PATCH 272/502] policy update widget\n endpoint generate --- internal/delivery/api/generated_endpoints.go.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index ba06253e..8f987908 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -359,6 +359,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyStatusDashboard", Group: "Dashboard", }, + GetPolicyUpdateDashboard: { + Name: "GetPolicyUpdateDashboard", + Group: "Dashboard", + }, Admin_CreateSystemNotificationTemplate: { Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", @@ -1068,6 +1072,8 @@ func (e Endpoint) String() string { return "GetResourcesDashboard" case GetPolicyStatusDashboard: return "GetPolicyStatusDashboard" + case GetPolicyUpdateDashboard: + return "GetPolicyUpdateDashboard" case Admin_CreateSystemNotificationTemplate: return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: @@ -1516,6 +1522,8 @@ func GetEndpoint(name string) Endpoint { return GetResourcesDashboard case "GetPolicyStatusDashboard": return GetPolicyStatusDashboard + case "GetPolicyUpdateDashboard": + return GetPolicyUpdateDashboard case "Admin_CreateSystemNotificationTemplate": return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": From b97ec60be42f7574fdf5aa58be620824e6a2571d Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 9 Apr 2024 16:58:50 +0900 Subject: [PATCH 273/502] policy update widget\n swag init --- api/swagger/docs.go | 134 +++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.json | 134 +++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 86 +++++++++++++++++++++++++ 3 files changed, 354 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 8f7c48dd..80bd7371 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3337,6 +3337,43 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/dashboard/policy-update": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get the number of policytemplates that need to be updated", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get the number of policytemplates that need to be updated", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboard/resources": { "get": { "security": [ @@ -8331,6 +8368,84 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/stacks/{stackId}/statistics": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks/{stackId}/status": { "get": { "security": [ @@ -11703,6 +11818,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate": { + "type": "object", + "properties": { + "policy": { + "type": "integer" + }, + "policyTemplate": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DashboardResource": { "type": "object", "properties": { @@ -12140,6 +12266,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse": { + "type": "object", + "properties": { + "updatedResources": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index ce2fd0c9..08116933 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3331,6 +3331,43 @@ } } }, + "/organizations/{organizationId}/dashboard/policy-update": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get the number of policytemplates that need to be updated", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get the number of policytemplates that need to be updated", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboard/resources": { "get": { "security": [ @@ -8325,6 +8362,84 @@ } } }, + "/organizations/{organizationId}/stacks/{stackId}/statistics": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackPolicyStatus" + ], + "summary": "[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "스택 식별자", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "sortColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks/{stackId}/status": { "get": { "security": [ @@ -11697,6 +11812,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate": { + "type": "object", + "properties": { + "policy": { + "type": "integer" + }, + "policyTemplate": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DashboardResource": { "type": "object", "properties": { @@ -12134,6 +12260,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse": { + "type": "object", + "properties": { + "updatedResources": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index f210e853..c61f885d 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1378,6 +1378,13 @@ definitions: warning: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate: + properties: + policy: + type: integer + policyTemplate: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain.DashboardResource: properties: cpu: @@ -1663,6 +1670,11 @@ definitions: statuses: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus' type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse: + properties: + updatedResources: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate' + type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse: properties: resources: @@ -6196,6 +6208,29 @@ paths: summary: Get policy status tags: - Dashboards + /organizations/{organizationId}/dashboard/policy-update: + get: + consumes: + - application/json + description: Get the number of policytemplates that need to be updated + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse' + security: + - JWT: [] + summary: Get the number of policytemplates that need to be updated + tags: + - Dashboards /organizations/{organizationId}/dashboard/resources: get: consumes: @@ -9378,6 +9413,57 @@ paths: summary: '[UpdateStackPolicyTemplateStatus] 템플릿 버전 업데이트' tags: - StackPolicyStatus + /organizations/{organizationId}/stacks/{stackId}/statistics: + get: + consumes: + - application/json + description: 클러스터의 정책과 정책 템플릿, 버전 등을 포함한 상태 목록을 조회한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 스택 식별자 + in: path + name: stackId + required: true + type: string + - description: pageSize + in: query + name: pageSize + type: string + - description: pageNumber + in: query + name: pageNumber + type: string + - description: sortColumn + in: query + name: sortColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse' + security: + - JWT: [] + summary: '[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회' + tags: + - StackPolicyStatus /organizations/{organizationId}/stacks/{stackId}/status: get: consumes: From 947a8a1d425201f07791cd1a04730dcd6692d4fa Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 9 Apr 2024 17:13:54 +0900 Subject: [PATCH 274/502] trivial. bugfix for mashaling --- internal/delivery/http/cluster.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 7f9d878e..bd49b31b 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" + "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -161,6 +162,10 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } + cId, err := uuid.Parse(input.CloudAccountId) + if err == nil { + dto.CloudAccountId = &cId + } dto.ClusterType = domain.ClusterType_USER dto.SetDefaultConf() From 3e0a87c5509e89c97f9530c2f1799645010e36b4 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 9 Apr 2024 17:26:44 +0900 Subject: [PATCH 275/502] fix lint error --- internal/delivery/http/dashboard.go | 5 +++++ internal/policy-template/tkspolicy.go | 4 +++- internal/policy-template/tkspolicytemplate.go | 4 +++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 75c7a399..3cabd03c 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -514,6 +514,11 @@ func (h *DashboardHandler) GetPolicyUpdate(w http.ResponseWriter, r *http.Reques } dpu, err := h.usecase.GetPolicyUpdate(r.Context(), policyTemplates, policies) + if err != nil { + log.Error(r.Context(), "Failed to make policy update status", err) + ErrorJSON(w, r, err) + return + } var out domain.GetDashboardPolicyUpdateResponse out.PolicyUpdate = dpu diff --git a/internal/policy-template/tkspolicy.go b/internal/policy-template/tkspolicy.go index aa1ef836..106f6ac4 100644 --- a/internal/policy-template/tkspolicy.go +++ b/internal/policy-template/tkspolicy.go @@ -290,7 +290,9 @@ func GetTksPolicyCRs(ctx context.Context, primaryClusterId string) (tksPolicies var tksPolicy TKSPolicy for _, c := range resources.Items { - err = runtime.DefaultUnstructuredConverter.FromUnstructured(c.UnstructuredContent(), &tksPolicy) + if err = runtime.DefaultUnstructuredConverter.FromUnstructured(c.UnstructuredContent(), &tksPolicy); err != nil { + return nil, err + } tksPolicies = append(tksPolicies, tksPolicy) } diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index 08709581..edbe3981 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -342,7 +342,9 @@ func GetTksPolicyTemplateCRs(ctx context.Context, primaryClusterId string) (tksP var tksPolicyTemplate TKSPolicyTemplate for _, c := range resources.Items { - err = runtime.DefaultUnstructuredConverter.FromUnstructured(c.UnstructuredContent(), &tksPolicyTemplate) + if err = runtime.DefaultUnstructuredConverter.FromUnstructured(c.UnstructuredContent(), &tksPolicyTemplate); err != nil { + return nil, err + } tksPolicyTemplates = append(tksPolicyTemplates, tksPolicyTemplate) } From a4d7fd34e8408d89c4aaff1f1c5537bbfec9ecda Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 9 Apr 2024 18:03:09 +0900 Subject: [PATCH 276/502] add grafanaUrl field in the body of the response of Project Namespace Get Methods --- internal/model/project.go | 1 + internal/usecase/project.go | 50 +++++++++++++++++++++++++++++++++++++ pkg/domain/project.go | 1 + 3 files changed, 52 insertions(+) diff --git a/internal/model/project.go b/internal/model/project.go index 7b69911f..50fe7d59 100644 --- a/internal/model/project.go +++ b/internal/model/project.go @@ -78,6 +78,7 @@ type ProjectNamespace struct { ProjectId string `gorm:"not null" json:"projectId"` Description string `json:"description,omitempty"` Status string `json:"status,omitempty"` + GrafanaUrl string `gorm:"-:all" json:"grafanaUrl,omitempty"` CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt"` UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` diff --git a/internal/usecase/project.go b/internal/usecase/project.go index b38cd056..a5f3bf0a 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -400,6 +400,33 @@ func (u *ProjectUsecase) GetProjectNamespaces(ctx context.Context, organizationI return nil, errors.Wrap(err, "Failed to retrieve project namespaces.") } + for _, pn := range pns { + o, err := u.organizationRepository.Get(ctx, organizationId) + if err != nil { + log.Error(ctx, err) + return nil, errors.Wrap(err, "Failed to get organization.") + } + + appGroupsInPrimaryCluster, err := u.appgroupRepository.Fetch(ctx, domain.ClusterId(o.PrimaryClusterId), nil) + if err != nil { + log.Error(ctx, err) + return nil, errors.Wrap(err, "Failed to get app groups.") + } + + for i, appGroup := range appGroupsInPrimaryCluster { + if appGroup.AppGroupType == domain.AppGroupType_LMA { + applications, err := u.appgroupRepository.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) + if err != nil { + log.Error(ctx, err) + return nil, errors.Wrap(err, "Failed to get applications.") + } + if len(applications) > 0 { + pns[i].GrafanaUrl = applications[0].Endpoint + "/d/tks_namespace_dashboard/tks-kubernetes-view-namespaces?orgId=" + organizationId + "&var-datasource=Prometheus&var-taco_cluster=" + pn.StackId + "&var-namespace=" + pn.Namespace + } + } + } + } + return pns, nil } @@ -409,7 +436,30 @@ func (u *ProjectUsecase) GetProjectNamespace(ctx context.Context, organizationId log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to retrieve project namespace.") } + o, err := u.organizationRepository.Get(ctx, organizationId) + if err != nil { + log.Error(ctx, err) + return nil, errors.Wrap(err, "Failed to get organization.") + } + + appGroupsInPrimaryCluster, err := u.appgroupRepository.Fetch(ctx, domain.ClusterId(o.PrimaryClusterId), nil) + if err != nil { + log.Error(ctx, err) + return nil, errors.Wrap(err, "Failed to get app groups.") + } + for _, appGroup := range appGroupsInPrimaryCluster { + if appGroup.AppGroupType == domain.AppGroupType_LMA { + applications, err := u.appgroupRepository.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) + if err != nil { + log.Error(ctx, err) + return nil, errors.Wrap(err, "Failed to get applications.") + } + if len(applications) > 0 { + pn.GrafanaUrl = applications[0].Endpoint + "/d/tks_namespace_dashboard/tks-kubernetes-view-namespaces?orgId=" + organizationId + "&var-datasource=Prometheus&var-taco_cluster=" + stackId + "&var-namespace=" + projectNamespace + } + } + } return pn, nil } diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 517c31b4..e5f45890 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -148,6 +148,7 @@ type ProjectNamespaceResponse struct { Description string `json:"description"` Status string `json:"status"` AppCount int `json:"appCount"` + GrafanaUrl string `json:"grafanaUrl"` CreatedAt time.Time `json:"createdAt"` UpdatedAt *time.Time `json:"updatedAt"` } From d8462aadf3a49c69373a59e995aa64397fa82210 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 9 Apr 2024 18:11:20 +0900 Subject: [PATCH 277/502] trivial. bugfix for creating stack --- internal/delivery/http/stack.go | 4 ++++ internal/model/stack.go | 1 + internal/usecase/stack.go | 22 +++++++++++----------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 9f74ace6..db949d64 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -56,6 +56,10 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } + if err = serializer.Map(r.Context(), input, &dto.Conf); err != nil { + log.Info(r.Context(), err) + } + dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) if err != nil { diff --git a/internal/model/stack.go b/internal/model/stack.go index ab287fc5..2f7b518b 100644 --- a/internal/model/stack.go +++ b/internal/model/stack.go @@ -31,6 +31,7 @@ type Stack = struct { ClusterEndpoint string Resource domain.DashboardStack PolicyIds []string + Conf StackConf } type StackConf struct { diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 32f6294e..08cf81e8 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -103,20 +103,20 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom } // Make stack nodes - var stackConf domain.StackConfResponse - if err = serializer.Map(ctx, dto, &stackConf); err != nil { - log.Info(ctx, err) - } + // [TODO] to be advanced feature + dto.Conf.TksCpNodeMax = dto.Conf.TksCpNode + dto.Conf.TksInfraNodeMax = dto.Conf.TksInfraNode + dto.Conf.TksUserNodeMax = dto.Conf.TksUserNode if stackTemplate.CloudService == "AWS" && stackTemplate.KubeType == "AWS" { - if stackConf.TksCpNode == 0 { - stackConf.TksCpNode = 3 - stackConf.TksCpNodeMax = 3 - stackConf.TksInfraNode = 3 - stackConf.TksInfraNodeMax = 3 + if dto.Conf.TksCpNode == 0 { + dto.Conf.TksCpNode = 3 + dto.Conf.TksCpNodeMax = 3 + dto.Conf.TksInfraNode = 3 + dto.Conf.TksInfraNodeMax = 3 } // user 노드는 MAX_AZ_NUM의 배수로 요청한다. - if stackConf.TksUserNode%domain.MAX_AZ_NUM != 0 { + if dto.Conf.TksUserNode%domain.MAX_AZ_NUM != 0 { return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Invalid node count"), "", "") } } @@ -132,7 +132,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom "stack_template_id=" + dto.StackTemplateId.String(), "creator=" + user.GetUserId().String(), "base_repo_branch=" + viper.GetString("revision"), - "infra_conf=" + strings.Replace(helper.ModelToJson(stackConf), "\"", "\\\"", -1), + "infra_conf=" + strings.Replace(helper.ModelToJson(dto.Conf), "\"", "\\\"", -1), "cloud_service=" + dto.CloudService, "cluster_endpoint=" + dto.ClusterEndpoint, "policy_ids=" + strings.Join(dto.PolicyIds, ","), From eebe2a2c5f301462b2a95d2aec77d50af90b61bd Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Wed, 10 Apr 2024 23:01:21 +0900 Subject: [PATCH 278/502] =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20=EB=93=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy-template.go | 2 +- .../policy-template/policy-template-rego.go | 94 ++++++++++++++++++- internal/policy-template/validation.go | 19 ++++ internal/usecase/policy-template.go | 74 ++++++++++----- pkg/domain/policy-template.go | 8 +- 5 files changed, 167 insertions(+), 30 deletions(-) create mode 100644 internal/policy-template/validation.go diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 1a98126b..cfb7a29e 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -1735,7 +1735,7 @@ func (h *PolicyTemplateHandler) ExtractParameters(w http.ResponseWriter, r *http return } - if err := serializer.Map(r.Context(), response, &out); err != nil { + if err := serializer.Map(r.Context(), *response, &out); err != nil { log.Info(r.Context(), err) } diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index 1a68c874..a0a7f652 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -1,6 +1,7 @@ package policytemplate import ( + "fmt" "regexp" "sort" "strings" @@ -14,7 +15,9 @@ const ( input_param_prefix = "input.parameters" input_extract_pattern = `input(\.parameters|\[\"parameters\"\])((\[\"[\w\-]+\"\])|(\[_\])|(\.\w+))*` //(\.\w+)*` // (\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))*` // input_extract_pattern = `input\.parameters((\[\".+\"\])?(\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))+` - obj_get_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+)\, \"*([^,\"]+)\"*, [^\)]+\)` + obj_get_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+)\, \"*([^,\"]+)\"*, [^\)]+\)` + package_name_regex = `package ([\w\.]+)[\n\r]+` + import_regex = `import ([\w\.]+)[\n\r]+` ) var ( @@ -268,6 +271,23 @@ func ExtractParameter(modules map[string]*ast.Module) []*domain.ParameterDef { return defStore.store } +func MergeRegoAndLibs(rego string, libs []string) string { + if len(libs) == 0 { + return rego + } + + var re = regexp.MustCompile(import_regex) + var re2 = regexp.MustCompile(package_name_regex) + + result := re.ReplaceAllString(rego, "") + + for _, lib := range libs { + result += re2.ReplaceAllString(lib, "") + } + + return result +} + type ParamDefStore struct { store []*domain.ParameterDef } @@ -346,3 +366,75 @@ func createKey(key string, isLast bool) *domain.ParameterDef { return newDef } + +func CompileRegoWithLibs(rego string, libs []string) (modules map[string]*ast.Module, compiler *ast.Compiler, err error) { + modules = map[string]*ast.Module{} + + regoPackage := GetPackageFromRegoCode(rego) + + regoModule, err := ast.ParseModuleWithOpts(regoPackage, rego, ast.ParserOptions{}) + if err != nil { + return modules, nil, err + } + + modules[regoPackage] = regoModule + + for i, lib := range libs { + // Lib이 공백이면 무시 + if len(strings.TrimSpace(lib)) == 0 { + continue + } + + libPackage := GetPackageFromRegoCode(lib) + + // Lib의 패키지 명이 공백이면 rego에서 import 될 수 없기 때문에 에러 처리 + // 패키지 명이 Parse할 때 비어있으면 에러가 나지만, rego인지 lib인지 정확히 알기 어려울 수 있으므로 알려 줌 + if len(strings.TrimSpace(libPackage)) == 0 { + return modules, nil, fmt.Errorf("lib[%d] is not valid, empty package name", i) + } + + libModule, err := ast.ParseModuleWithOpts(libPackage, lib, ast.ParserOptions{}) + if err != nil { + return modules, nil, err + } + + modules[libPackage] = libModule + } + + compiler = ast.NewCompiler() + compiler.Compile(modules) + + return modules, compiler, nil +} + +func MergeAndCompileRegoWithLibs(rego string, libs []string) (modules map[string]*ast.Module, err error) { + modules = map[string]*ast.Module{} + + regoPackage := GetPackageFromRegoCode(rego) + + merged := MergeRegoAndLibs(rego, libs) + + module, err := ast.ParseModuleWithOpts(regoPackage, merged, ast.ParserOptions{}) + if err != nil { + return modules, err + } + + modules[regoPackage] = module + + compiler := ast.NewCompiler() + compiler.Compile(modules) + + return modules, nil +} + +func GetPackageFromRegoCode(regoCode string) string { + packageRegex := regexp.MustCompile(package_name_regex) + + match := packageRegex.FindStringSubmatch(regoCode) + + if len(match) > 1 { + return match[1] + } + + return "" +} diff --git a/internal/policy-template/validation.go b/internal/policy-template/validation.go new file mode 100644 index 00000000..7ab6a4eb --- /dev/null +++ b/internal/policy-template/validation.go @@ -0,0 +1,19 @@ +package policytemplate + +import ( + "fmt" + "slices" + "strings" +) + +var VALID_PARAM_TYPES = []string{"string", "number", "integer", "object", "boolean", "null"} + +func ValidateParamDefType(paramType string) error { + baseType := strings.TrimSuffix(paramType, "[]") + + if slices.Contains(VALID_PARAM_TYPES, baseType) { + return nil + } + + return fmt.Errorf("%s is not valid type", paramType) +} diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 96f2c2ef..4434b2d5 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -10,7 +10,6 @@ import ( mapset "github.com/deckarep/golang-set/v2" "github.com/google/uuid" - "github.com/open-policy-agent/opa/ast" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -435,21 +434,19 @@ func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, } func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) { - modules := map[string]*ast.Module{} - response = &domain.RegoCompileResponse{} response.Errors = []domain.RegoCompieError{} - mod, err := ast.ParseModuleWithOpts("rego", request.Rego, ast.ParserOptions{}) - if err != nil { - return nil, err - } - modules["rego"] = mod - - compiler := ast.NewCompiler() - compiler.Compile(modules) + modules, compiler, err := policytemplate.CompileRegoWithLibs(request.Rego, request.Libs) - if compiler.Failed() { + if err != nil { + response.Errors = append(response.Errors, domain.RegoCompieError{ + Status: 400, + Code: "PT_FAILED_TO_LOAD_REGO_MODULE", + Message: "failed to load rego module", + Text: err.Error(), + }) + } else if compiler.Failed() { for _, compileError := range compiler.Errors { response.Errors = append(response.Errors, domain.RegoCompieError{ Status: 400, @@ -462,8 +459,23 @@ func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, } } + if len(response.Errors) > 0 { + return response, nil + } + if parseParameter { - response.ParametersSchema = policytemplate.ExtractParameter(modules) + // 효율적인 파라미터 추출을 위한 머지 + modules, err = policytemplate.MergeAndCompileRegoWithLibs(request.Rego, request.Libs) + if err != nil { + response.Errors = append(response.Errors, domain.RegoCompieError{ + Status: 400, + Code: "PT_FAILED_TO_LOAD_REGO_MODULE", + Message: "failed to load merged rego module", + Text: err.Error(), + }) + } else { + response.ParametersSchema = policytemplate.ExtractParameter(modules) + } } return response, nil @@ -549,21 +561,20 @@ func (u *PolicyTemplateUsecase) ExtractPolicyParameters(ctx context.Context, org } } - modules := map[string]*ast.Module{} - response = &domain.RegoCompileResponse{} response.Errors = []domain.RegoCompieError{} - mod, err := ast.ParseModuleWithOpts("rego", rego, ast.ParserOptions{}) - if err != nil { - return nil, err - } - modules["rego"] = mod + modules, compiler, err := policytemplate.CompileRegoWithLibs(rego, libs) - compiler := ast.NewCompiler() - compiler.Compile(modules) - - if compiler.Failed() { + if err != nil { + response.Errors = append(response.Errors, domain.RegoCompieError{ + Status: 400, + Code: "PT_FAILED_TO_LOAD_REGO_MODULE", + Message: "failed to load rego module", + Text: err.Error(), + }) + return response, nil + } else if compiler.Failed() { for _, compileError := range compiler.Errors { response.Errors = append(response.Errors, domain.RegoCompieError{ Status: 400, @@ -574,6 +585,21 @@ func (u *PolicyTemplateUsecase) ExtractPolicyParameters(ctx context.Context, org compileError.Message), }) } + return response, nil + } + + if len(response.Errors) > 0 { + return response, nil + } + + modules, err = policytemplate.MergeAndCompileRegoWithLibs(rego, libs) + if err != nil { + response.Errors = append(response.Errors, domain.RegoCompieError{ + Status: 400, + Code: "PT_FAILED_TO_LOAD_REGO_MODULE", + Message: "failed to load merged rego module", + Text: err.Error(), + }) } extractedParamDefs := policytemplate.ExtractParameter(modules) diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 536dbaf2..c24ba0df 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -182,8 +182,8 @@ type RegoCompieError struct { } type RegoCompileResponse struct { - ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` - Errors []RegoCompieError `json:"errors,omitempty"` + ParametersSchema []*ParameterDef `json:"parametersSchema"` + Errors []RegoCompieError `json:"errors"` } type ExtractParametersRequest struct { @@ -192,8 +192,8 @@ type ExtractParametersRequest struct { } type ExtractParametersResponse struct { - ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` - Errors []RegoCompieError `json:"errors,omitempty"` + ParametersSchema []*ParameterDef `json:"parametersSchema"` + Errors []RegoCompieError `json:"errors"` } type AddPoliciesForStackRequest struct { From f41b03e26da3c9371bebd617d605e28583155246 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 11 Apr 2024 01:02:40 +0900 Subject: [PATCH 279/502] ParameterSchema validation --- .../policy-template/policy-template-rego.go | 12 ++++---- internal/policy-template/validation.go | 28 ++++++++++++++++++- internal/usecase/policy-template.go | 16 ++++++++--- pkg/httpErrors/errorCode.go | 1 + 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index a0a7f652..867f36c3 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -367,14 +367,14 @@ func createKey(key string, isLast bool) *domain.ParameterDef { return newDef } -func CompileRegoWithLibs(rego string, libs []string) (modules map[string]*ast.Module, compiler *ast.Compiler, err error) { - modules = map[string]*ast.Module{} +func CompileRegoWithLibs(rego string, libs []string) (compiler *ast.Compiler, err error) { + modules := map[string]*ast.Module{} regoPackage := GetPackageFromRegoCode(rego) regoModule, err := ast.ParseModuleWithOpts(regoPackage, rego, ast.ParserOptions{}) if err != nil { - return modules, nil, err + return nil, err } modules[regoPackage] = regoModule @@ -390,12 +390,12 @@ func CompileRegoWithLibs(rego string, libs []string) (modules map[string]*ast.Mo // Lib의 패키지 명이 공백이면 rego에서 import 될 수 없기 때문에 에러 처리 // 패키지 명이 Parse할 때 비어있으면 에러가 나지만, rego인지 lib인지 정확히 알기 어려울 수 있으므로 알려 줌 if len(strings.TrimSpace(libPackage)) == 0 { - return modules, nil, fmt.Errorf("lib[%d] is not valid, empty package name", i) + return nil, fmt.Errorf("lib[%d] is not valid, empty package name", i) } libModule, err := ast.ParseModuleWithOpts(libPackage, lib, ast.ParserOptions{}) if err != nil { - return modules, nil, err + return nil, err } modules[libPackage] = libModule @@ -404,7 +404,7 @@ func CompileRegoWithLibs(rego string, libs []string) (modules map[string]*ast.Mo compiler = ast.NewCompiler() compiler.Compile(modules) - return modules, compiler, nil + return compiler, nil } func MergeAndCompileRegoWithLibs(rego string, libs []string) (modules map[string]*ast.Module, err error) { diff --git a/internal/policy-template/validation.go b/internal/policy-template/validation.go index 7ab6a4eb..673ec78b 100644 --- a/internal/policy-template/validation.go +++ b/internal/policy-template/validation.go @@ -4,16 +4,42 @@ import ( "fmt" "slices" "strings" + + "github.com/openinfradev/tks-api/pkg/domain" ) var VALID_PARAM_TYPES = []string{"string", "number", "integer", "object", "boolean", "null"} -func ValidateParamDefType(paramType string) error { +func ValidateParamDef(paramdef *domain.ParameterDef) error { + paramType := paramdef.Type + baseType := strings.TrimSuffix(paramType, "[]") + // 타입과 []를 제거한 타입이 같은데 배열이면 에러임 + if (baseType == paramType) != paramdef.IsArray { + return fmt.Errorf("type is '%s', but IsArray=%v", paramType, paramdef.IsArray) + } + if slices.Contains(VALID_PARAM_TYPES, baseType) { return nil } return fmt.Errorf("%s is not valid type", paramType) } + +func ValidateParamDefs(paramdefs []*domain.ParameterDef) error { + for _, paramdef := range paramdefs { + err := ValidateParamDef(paramdef) + if err != nil { + return err + } + + err = ValidateParamDefs(paramdef.Children) + + if err != nil { + return err + } + } + + return nil +} diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 4434b2d5..2291cc8f 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -94,6 +94,10 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp } } + if err := policytemplate.ValidateParamDefs(dto.ParametersSchema); err != nil { + return uuid.Nil, httpErrors.NewBadRequestError(err, "PT_INVALID_PARAMETER_SCHEMA", "") + } + if dto.IsTksTemplate() { // TKS 템블릿이면 dto.Mandatory = false @@ -430,6 +434,10 @@ func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE", "") } + if err := policytemplate.ValidateParamDefs(policyTemplate.ParametersSchema); err != nil { + return "", httpErrors.NewBadRequestError(err, "PT_INVALID_PARAMETER_SCHEMA", "") + } + return u.repo.CreatePolicyTemplateVersion(ctx, policyTemplateId, newVersion, schema, rego, libs) } @@ -437,7 +445,7 @@ func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, response = &domain.RegoCompileResponse{} response.Errors = []domain.RegoCompieError{} - modules, compiler, err := policytemplate.CompileRegoWithLibs(request.Rego, request.Libs) + compiler, err := policytemplate.CompileRegoWithLibs(request.Rego, request.Libs) if err != nil { response.Errors = append(response.Errors, domain.RegoCompieError{ @@ -465,7 +473,7 @@ func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, if parseParameter { // 효율적인 파라미터 추출을 위한 머지 - modules, err = policytemplate.MergeAndCompileRegoWithLibs(request.Rego, request.Libs) + modules, err := policytemplate.MergeAndCompileRegoWithLibs(request.Rego, request.Libs) if err != nil { response.Errors = append(response.Errors, domain.RegoCompieError{ Status: 400, @@ -564,7 +572,7 @@ func (u *PolicyTemplateUsecase) ExtractPolicyParameters(ctx context.Context, org response = &domain.RegoCompileResponse{} response.Errors = []domain.RegoCompieError{} - modules, compiler, err := policytemplate.CompileRegoWithLibs(rego, libs) + compiler, err := policytemplate.CompileRegoWithLibs(rego, libs) if err != nil { response.Errors = append(response.Errors, domain.RegoCompieError{ @@ -592,7 +600,7 @@ func (u *PolicyTemplateUsecase) ExtractPolicyParameters(ctx context.Context, org return response, nil } - modules, err = policytemplate.MergeAndCompileRegoWithLibs(rego, libs) + modules, err := policytemplate.MergeAndCompileRegoWithLibs(rego, libs) if err != nil { response.Errors = append(response.Errors, domain.RegoCompieError{ Status: 400, diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 3e0e5457..763ffc8e 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -127,6 +127,7 @@ var errorMap = map[ErrorCode]string{ "PT_INVALID_POLICY_TEMPLATE_KIND": "유효하지 않은 정책 템플릿 유형입니다. 정책 템플릿 유형을 확인하세요.", "PT_INVALID_REGO_PARSEPARAMETER": "유효하지 않은 Rego 파싱 설정입니다. Rego 파싱 설정을 확인하세요.", "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE": "tks 템플릿에 대해 해당 동작을 수행할 수 없습니다.", + "PT_INVALID_PARAMETER_SCHEMA": "파라미터 스키마에 잘못된 타입이 지정되었습니다.", // Policy "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", From 0c986e5bc5ac51d3b6ec382b88ec5e5d4a26316b Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 11 Apr 2024 11:22:29 +0900 Subject: [PATCH 280/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20validation=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 1 + internal/policy-template/paramdef-util.go | 6 ++- internal/policy-template/validation.go | 51 ++++++++++++++++++++++- internal/usecase/policy.go | 17 +++++++- pkg/httpErrors/errorCode.go | 1 + 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 92a6c021..d4c63026 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/swaggo/swag v1.16.3 github.com/thoas/go-funk v0.9.3 github.com/vmware-tanzu/cluster-api-provider-bringyourownhost v0.5.0 + github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/crypto v0.21.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/net v0.22.0 diff --git a/go.sum b/go.sum index 9a81524e..eb9fc3f4 100644 --- a/go.sum +++ b/go.sum @@ -323,6 +323,7 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMc github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go index b136b42c..56a1ab64 100644 --- a/internal/policy-template/paramdef-util.go +++ b/internal/policy-template/paramdef-util.go @@ -146,7 +146,11 @@ func ParamDefsToJSONSchemaProeprties(paramdefs []*domain.ParameterDef) *apiexten return nil } - result := apiextensionsv1.JSONSchemaProps{Type: "object", Properties: convert(paramdefs)} + result := apiextensionsv1.JSONSchemaProps{ + Type: "object", + Properties: convert(paramdefs), + AdditionalProperties: &apiextensionsv1.JSONSchemaPropsOrBool{Allows: false}, + } return &result } diff --git a/internal/policy-template/validation.go b/internal/policy-template/validation.go index 673ec78b..5cb01946 100644 --- a/internal/policy-template/validation.go +++ b/internal/policy-template/validation.go @@ -1,11 +1,13 @@ package policytemplate import ( + "encoding/json" "fmt" "slices" "strings" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/xeipuuv/gojsonschema" ) var VALID_PARAM_TYPES = []string{"string", "number", "integer", "object", "boolean", "null"} @@ -15,8 +17,8 @@ func ValidateParamDef(paramdef *domain.ParameterDef) error { baseType := strings.TrimSuffix(paramType, "[]") - // 타입과 []를 제거한 타입이 같은데 배열이면 에러임 - if (baseType == paramType) != paramdef.IsArray { + // 타입과 []를 제거한 타입이 다르면 array인데 이것과 isArray 속성이 다르면 에러임 + if (baseType != paramType) != paramdef.IsArray { return fmt.Errorf("type is '%s', but IsArray=%v", paramType, paramdef.IsArray) } @@ -43,3 +45,48 @@ func ValidateParamDefs(paramdefs []*domain.ParameterDef) error { return nil } + +func ValidateJSONusingParamdefs(paramdefs []*domain.ParameterDef, jsonStr string) error { + jsonSchema := ParamDefsToJSONSchemaProeprties(paramdefs) + + if jsonSchema == nil { + // 파라미터가 없는데 "{}" 이나 ""이면 에러가 아님 + if isEmptyValue(jsonStr) { + return nil + } else { + return fmt.Errorf("schema has no field but value '%v' specified", jsonStr) + } + } + + // Load JSON Schema + schemaLoader := gojsonschema.NewGoLoader(jsonSchema) + + // Load JSON data + documentLoader := gojsonschema.NewStringLoader(jsonStr) + + // Validate JSON against JSON Schema + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + if err != nil { + return err + } + + // Check if the result is valid + if result.Valid() { + return nil + } + + schemaBytes, _ := json.Marshal(paramdefs) + jsonSchemaBytes, _ := json.Marshal(jsonSchema) + + return fmt.Errorf("value '%s' is not valid against schemas:\njsonschema='%s',\nparamdefs='%s'", + jsonStr, string(jsonSchemaBytes), string(schemaBytes)) +} + +func isEmptyValue(value string) bool { + val := strings.TrimSpace(value) + val = strings.TrimPrefix(val, "{") + val = strings.TrimSuffix(val, "}") + val = strings.TrimSpace(val) + + return len(val) == 0 +} diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 5a2afac8..d2566032 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -137,6 +137,12 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } + if err := policytemplate.ValidateJSONusingParamdefs(policyTemplate.ParametersSchema, dto.Parameters); err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return uuid.Nil, httpErrors.NewBadRequestError(err, "P_INVALID_POLICY_PARAMETER", "") + } + primaryClusterId := organization.PrimaryClusterId // k8s에 label로 policyID를 기록해 주기 위해 DB 컬럼 생성 시 ID를 생성하지 않고 미리 생성 @@ -226,7 +232,7 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic return httpErrors.NewBadRequestError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } - _, err = u.repo.GetByID(ctx, organizationId, policyId) + policy, err := u.repo.GetByID(ctx, organizationId, policyId) if err != nil { return httpErrors.NewNotFoundError(err, "P_FAILED_FETCH_POLICY", "") } @@ -249,8 +255,11 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic updateMap["description"] = description } + schema := policy.PolicyTemplate.ParametersSchema + if templateId != nil { policyTemplate, err := u.templateRepo.GetByID(ctx, *templateId) + schema = policyTemplate.ParametersSchema if err != nil { return err @@ -271,6 +280,12 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic if parameters != nil { updateMap["parameters"] = parameters + + if err := policytemplate.ValidateJSONusingParamdefs(schema, *parameters); err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + + return httpErrors.NewBadRequestError(err, "P_INVALID_POLICY_PARAMETER", "") + } } if matchYaml != nil { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 763ffc8e..175518be 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -140,6 +140,7 @@ var errorMap = map[ErrorCode]string{ "P_FAILED_FETCH_TEMPLATE": "정책의 템플릿 정보를 가져오는데 실패했습니다.", "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", + "P_INVALID_POLICY_PARAMETER": "정책 파라미터가 템플릿의 파라미터 스키마에 유효하지 않습니다. 파라미터를 확인하세요.", } func (m ErrorCode) GetText() string { From 994fbc3b6098466d74aaca9cea25272e28267106 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 11 Apr 2024 14:32:01 +0900 Subject: [PATCH 281/502] feature. add email template for systemNotification --- api/swagger/docs.go | 106 +++++++++++++++++- api/swagger/swagger.json | 106 +++++++++++++++++- api/swagger/swagger.yaml | 70 +++++++++++- internal/mail/content.go | 32 ++++++ .../mail/contents/system_notification.html | 105 +++++++++++++++++ internal/usecase/system-notification.go | 12 ++ pkg/domain/system-notification-rule.go | 1 + pkg/domain/system-notification-template.go | 1 + 8 files changed, 430 insertions(+), 3 deletions(-) create mode 100644 internal/mail/contents/system_notification.html diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 80bd7371..b1c8289d 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -6960,6 +6960,64 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project namespace kubeconfig", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project namespace kubeconfig", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { "get": { "security": [ @@ -8440,7 +8498,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics" } } } @@ -12480,6 +12538,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse": { + "type": "object", + "properties": { + "kubeConfig": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse": { "type": "object", "properties": { @@ -13335,6 +13401,12 @@ const docTemplate = `{ "dryrun": { "type": "integer" }, + "fromOrgTemplate": { + "type": "integer" + }, + "fromTksTemplate": { + "type": "integer" + }, "total": { "type": "integer" }, @@ -13709,6 +13781,9 @@ const docTemplate = `{ "description": { "type": "string" }, + "grafanaUrl": { + "type": "string" + }, "namespace": { "type": "string" }, @@ -14172,6 +14247,29 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics": { + "type": "object", + "properties": { + "outofdatePolicyCount": { + "type": "integer" + }, + "outofdateTemplateCount": { + "type": "integer" + }, + "totalPolicyCount": { + "type": "integer" + }, + "totalTemplateCount": { + "type": "integer" + }, + "uptodatePolicyCount": { + "type": "integer" + }, + "uptodateTemplateCount": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse": { "type": "object", "properties": { @@ -14582,6 +14680,9 @@ const docTemplate = `{ "name": { "type": "string" }, + "notificationType": { + "type": "string" + }, "systemNotificationCondition": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" }, @@ -14635,6 +14736,9 @@ const docTemplate = `{ "name": { "type": "string" }, + "notificationType": { + "type": "string" + }, "organizations": { "type": "array", "items": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 08116933..c33a4906 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -6954,6 +6954,64 @@ } } }, + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get project namespace kubeconfig", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Projects" + ], + "summary": "Get project namespace kubeconfig", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Stack ID", + "name": "stackId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project Namespace", + "name": "projectNamespace", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage": { "get": { "security": [ @@ -8434,7 +8492,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics" } } } @@ -12474,6 +12532,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse": { + "type": "object", + "properties": { + "kubeConfig": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse": { "type": "object", "properties": { @@ -13329,6 +13395,12 @@ "dryrun": { "type": "integer" }, + "fromOrgTemplate": { + "type": "integer" + }, + "fromTksTemplate": { + "type": "integer" + }, "total": { "type": "integer" }, @@ -13703,6 +13775,9 @@ "description": { "type": "string" }, + "grafanaUrl": { + "type": "string" + }, "namespace": { "type": "string" }, @@ -14166,6 +14241,29 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics": { + "type": "object", + "properties": { + "outofdatePolicyCount": { + "type": "integer" + }, + "outofdateTemplateCount": { + "type": "integer" + }, + "totalPolicyCount": { + "type": "integer" + }, + "totalTemplateCount": { + "type": "integer" + }, + "uptodatePolicyCount": { + "type": "integer" + }, + "uptodateTemplateCount": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse": { "type": "object", "properties": { @@ -14576,6 +14674,9 @@ "name": { "type": "string" }, + "notificationType": { + "type": "string" + }, "systemNotificationCondition": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" }, @@ -14629,6 +14730,9 @@ "name": { "type": "string" }, + "notificationType": { + "type": "string" + }, "organizations": { "type": "array", "items": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index c61f885d..ce870a9e 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1807,6 +1807,11 @@ definitions: k8sResources: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources' type: object + github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse: + properties: + kubeConfig: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse: properties: resourcesUsage: @@ -2367,6 +2372,10 @@ definitions: type: integer dryrun: type: integer + fromOrgTemplate: + type: integer + fromTksTemplate: + type: integer total: type: integer warn: @@ -2625,6 +2634,8 @@ definitions: type: string description: type: string + grafanaUrl: + type: string namespace: type: string projectId: @@ -2931,6 +2942,21 @@ definitions: - tksInfraNode - tksUserNode type: object + github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics: + properties: + outofdatePolicyCount: + type: integer + outofdateTemplateCount: + type: integer + totalPolicyCount: + type: integer + totalTemplateCount: + type: integer + uptodatePolicyCount: + type: integer + uptodateTemplateCount: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatusResponse: properties: policyDescription: @@ -3204,6 +3230,8 @@ definitions: type: string name: type: string + notificationType: + type: string systemNotificationCondition: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse' systemNotificationTemplate: @@ -3237,6 +3265,8 @@ definitions: type: string name: type: string + notificationType: + type: string organizations: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse' @@ -8453,6 +8483,44 @@ paths: summary: Get k8s resources for project namespace tags: - Projects + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig: + get: + consumes: + - application/json + description: Get project namespace kubeconfig + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: Stack ID + in: path + name: stackId + required: true + type: string + - description: Project Namespace + in: path + name: projectNamespace + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse' + security: + - JWT: [] + summary: Get project namespace kubeconfig + tags: + - Projects /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/resources-usage: get: consumes: @@ -9458,7 +9526,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ListStackPolicyStatusResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics' security: - JWT: [] summary: '[ListStackPolicyStatus] 클러스터의 정책과 정책 템플릿, 버전 조회' diff --git a/internal/mail/content.go b/internal/mail/content.go index 77a4950d..9a7abbb3 100644 --- a/internal/mail/content.go +++ b/internal/mail/content.go @@ -97,3 +97,35 @@ func MakeGeneratingOrganizationMessage( return m, nil } + +func MakeSystemNotificationMessage( + ctx context.Context, + organizationId string, title string, + to string) (*MessageInfo, error) { + subject := "[TKS] 시스템 알림이 발생하였습니다." + + tmpl, err := template.ParseFS(templateFS, "contents/system_notification.html") + if err != nil { + log.Errorf(ctx, "failed to parse template, %v", err) + return nil, err + } + + data := map[string]string{ + "OrganizationId": organizationId, + } + + var tpl bytes.Buffer + if err := tmpl.Execute(&tpl, data); err != nil { + log.Errorf(ctx, "failed to execute template, %v", err) + return nil, err + } + + m := &MessageInfo{ + From: from, + To: to, + Subject: subject, + Body: tpl.String(), + } + + return m, nil +} diff --git a/internal/mail/contents/system_notification.html b/internal/mail/contents/system_notification.html new file mode 100644 index 00000000..105d3ef4 --- /dev/null +++ b/internal/mail/contents/system_notification.html @@ -0,0 +1,105 @@ + + + + + 시스템 알림 + + + +
+ + + + + + + + + + + + + + + +
SKT Enterprise
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 조직 생성 안내 +
안녕하세요.
항상 저희 TKS Cloud Service를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
+ 시스템 알림 +
테스트
로그인 정보
더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
감사합니다.
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
본 메일은 발신 전용 메일로, 회신 되지 않습니다.
우편번호: 04539 서울특별시중구을지로65 (을지로2가) SK T-타워 SK텔레콤㈜ 대표이사 : 유영상
COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED.
+
+
+ + + + \ No newline at end of file diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index eca9e6c2..09a1b688 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -119,6 +119,18 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre if err != nil { continue } + + /* + for _, user := range dto.System + message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, "test", dto.Users, user.AccountId, randomPassword) + if err != nil { + return nil, httpErrors.NewInternalServerError(err, "", "") + } + mailer := mail.New(message) + if err := mailer.SendMail(ctx); err != nil { + return nil, httpErrors.NewInternalServerError(err, "", "") + } + */ } return nil diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index dc4747ca..ed33b8b9 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -32,6 +32,7 @@ func (m SystemNotificationRuleStatus) FromString(s string) SystemNotificationRul type SystemNotificationRuleResponse struct { ID string `json:"id"` Name string `json:"name"` + NotificationType string `json:"notificationType"` Description string `json:"description"` MessageTitle string `json:"messageTitle"` MessageContent string `json:"messageContent"` diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index c28de31e..d8a87797 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -20,6 +20,7 @@ type SystemNotificationTemplateResponse struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` + NotificationType string `json:"notificationType"` MetricQuery string `json:"metricQuery" validate:"required"` MetricParameters []SystemNotificationMetricParameterResponse `json:"metricParameters,omitempty"` Organizations []SimpleOrganizationResponse `json:"organizations,omitempty"` From 057829ee04e53910b348383804f47d3df8a27a13 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 11 Apr 2024 16:58:26 +0900 Subject: [PATCH 282/502] feature. support sending email to multiple targets --- internal/mail/content.go | 11 ++--- internal/mail/ses.go | 2 +- internal/mail/smtp.go | 15 +++--- internal/usecase/app-group.go | 2 +- internal/usecase/system-notification.go | 61 +++++++++++++++++-------- pkg/domain/system-notification.go | 13 +++--- 6 files changed, 64 insertions(+), 40 deletions(-) diff --git a/internal/mail/content.go b/internal/mail/content.go index 9a7abbb3..417d00cf 100644 --- a/internal/mail/content.go +++ b/internal/mail/content.go @@ -27,7 +27,7 @@ func MakeVerityIdentityMessage(ctx context.Context, to, code string) (*MessageIn m := &MessageInfo{ From: from, - To: to, + To: []string{to}, Subject: subject, Body: tpl.String(), } @@ -54,7 +54,7 @@ func MakeTemporaryPasswordMessage(ctx context.Context, to, organizationId, accou m := &MessageInfo{ From: from, - To: to, + To: []string{to}, Subject: subject, Body: tpl.String(), } @@ -90,7 +90,7 @@ func MakeGeneratingOrganizationMessage( m := &MessageInfo{ From: from, - To: to, + To: []string{to}, Subject: subject, Body: tpl.String(), } @@ -98,10 +98,7 @@ func MakeGeneratingOrganizationMessage( return m, nil } -func MakeSystemNotificationMessage( - ctx context.Context, - organizationId string, title string, - to string) (*MessageInfo, error) { +func MakeSystemNotificationMessage(ctx context.Context, organizationId string, title string, to []string) (*MessageInfo, error) { subject := "[TKS] 시스템 알림이 발생하였습니다." tmpl, err := template.ParseFS(templateFS, "contents/system_notification.html") diff --git a/internal/mail/ses.go b/internal/mail/ses.go index eb7a4f0a..787e1324 100644 --- a/internal/mail/ses.go +++ b/internal/mail/ses.go @@ -23,7 +23,7 @@ type AwsMailer struct { func (a *AwsMailer) SendMail(ctx context.Context) error { input := &awsSes.SendEmailInput{ Destination: &types.Destination{ - ToAddresses: []string{a.message.To}, + ToAddresses: a.message.To, }, Message: &types.Message{ Subject: &types.Content{ diff --git a/internal/mail/smtp.go b/internal/mail/smtp.go index 62dc4578..ef673310 100644 --- a/internal/mail/smtp.go +++ b/internal/mail/smtp.go @@ -33,7 +33,7 @@ type Mailer interface { type MessageInfo struct { From string - To string + To []string Subject string Body string } @@ -50,14 +50,17 @@ type SmtpMailer struct { func (s *SmtpMailer) SendMail(ctx context.Context) error { s.client.SetHeader("From", s.message.From) - s.client.SetHeader("To", s.message.To) s.client.SetHeader("Subject", s.message.Subject) s.client.SetBody("text/html", s.message.Body) - d := NewDialer(s.Host, s.Port, s.Username, s.Password) - if err := d.DialAndSend(s.client); err != nil { - log.Errorf(ctx, "failed to send email, %v", err) - return err + + for _, to := range s.message.To { + s.client.SetHeader("To", to) + + if err := d.DialAndSend(s.client); err != nil { + log.Errorf(ctx, "failed to send email, %v", err) + continue + } } return nil diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index 39d7c8ac..37896b64 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -127,7 +127,7 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do "app_group_id=" + dto.ID.String(), "keycloak_url=" + strings.TrimSuffix(viper.GetString("keycloak-address"), "/auth"), "console_url=" + viper.GetString("console-address"), - "alert_tks=" + viper.GetString("external-address") + "/system-api/1.0/alerts", + "alert_tks=" + viper.GetString("external-address") + "/system-api/1.0/system-notifications", "alert_slack=" + viper.GetString("alert-slack"), "cloud_account_id=" + tksCloudAccountId, "object_store=" + tksObjectStore, diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 09a1b688..2543ab9e 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -8,6 +8,7 @@ import ( "time" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/mail" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -31,18 +32,20 @@ type ISystemNotificationUsecase interface { } type SystemNotificationUsecase struct { - repo repository.ISystemNotificationRepository - clusterRepo repository.IClusterRepository - organizationRepo repository.IOrganizationRepository - appGroupRepo repository.IAppGroupRepository + repo repository.ISystemNotificationRepository + clusterRepo repository.IClusterRepository + organizationRepo repository.IOrganizationRepository + appGroupRepo repository.IAppGroupRepository + systemNotificationRuleRepo repository.ISystemNotificationRuleRepository } func NewSystemNotificationUsecase(r repository.Repository) ISystemNotificationUsecase { return &SystemNotificationUsecase{ - repo: r.SystemNotification, - clusterRepo: r.Cluster, - appGroupRepo: r.AppGroup, - organizationRepo: r.Organization, + repo: r.SystemNotification, + clusterRepo: r.Cluster, + appGroupRepo: r.AppGroup, + organizationRepo: r.Organization, + systemNotificationRuleRepo: r.SystemNotificationRule, } } @@ -117,20 +120,40 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre _, err = u.repo.Create(ctx, dto) if err != nil { + log.Error(ctx, "Failed to create systemNotification ", err) continue } - /* - for _, user := range dto.System - message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, "test", dto.Users, user.AccountId, randomPassword) - if err != nil { - return nil, httpErrors.NewInternalServerError(err, "", "") - } - mailer := mail.New(message) - if err := mailer.SendMail(ctx); err != nil { - return nil, httpErrors.NewInternalServerError(err, "", "") - } - */ + if systemNotification.Annotations.SystemNotificationRuleId == "" { + log.Error(ctx, "Invalid systemNotificationRuleId ") + continue + } + + systemNotificationRuleId, err := uuid.Parse(systemNotification.Annotations.SystemNotificationRuleId) + if err != nil { + log.Error(ctx, "Failed to parse uuid ", err) + continue + } + rule, err := u.systemNotificationRuleRepo.Get(ctx, systemNotificationRuleId) + if err != nil { + log.Error(ctx, "Failed to get systemNotificationRule ", err) + continue + } + + to := []string{} + for _, user := range rule.TargetUsers { + to = append(to, user.Email) + } + message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, to) + if err != nil { + log.Error(ctx, fmt.Sprintf("Failed to make email content. err : %s", err.Error())) + continue + } + mailer := mail.New(message) + if err := mailer.SendMail(ctx); err != nil { + log.Error(ctx, fmt.Sprintf("Failed to send email to %s. err : %s", to, err.Error())) + continue + } } return nil diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 697f7968..f95868ef 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -53,12 +53,13 @@ type SystemNotificationRequest struct { TacoCluster string `json:"taco_cluster"` } `json:"labels"` Annotations struct { - Message string `json:"message"` - Summary string `json:"summary"` - Description string `json:"description"` - Checkpoint string `json:"Checkpoint"` - Discriminative string `json:"discriminative"` - AlertType string `json:"alertType"` + Message string `json:"message"` + Summary string `json:"summary"` + Description string `json:"description"` + Checkpoint string `json:"Checkpoint"` + Discriminative string `json:"discriminative"` + AlertType string `json:"alertType"` + SystemNotificationRuleId string `json:"systemNotificationRuleId"` } `json:"annotations"` } From f21d7fc991c85ba1501cd9ee574fde91ded9f362 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 11 Apr 2024 20:41:07 +0900 Subject: [PATCH 283/502] =?UTF-8?q?=EB=A6=AC=EC=86=8C=EC=8A=A4=EB=AA=85,?= =?UTF-8?q?=20kind,=20version=20=EB=93=B1=20=EA=B8=B0=ED=83=80=20validatio?= =?UTF-8?q?n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/validator/validator.go | 38 +++++++++++++++++++++- pkg/domain/admin/policy-template.go | 49 +++++------------------------ pkg/domain/policy-template.go | 45 +++++--------------------- pkg/domain/policy.go | 22 ++++++------- 4 files changed, 64 insertions(+), 90 deletions(-) diff --git a/internal/validator/validator.go b/internal/validator/validator.go index 212a6394..e977bf55 100644 --- a/internal/validator/validator.go +++ b/internal/validator/validator.go @@ -11,7 +11,13 @@ import ( "github.com/opentracing/opentracing-go/log" ) -const REGEX_RFC1123 = `^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$` +const ( + REGEX_RFC1123 = `^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$` + REGEX_SIMPLE_SEMVER = `^v\d+\.\d+\.\d+$` + REGEX_PASCAL_CASE = `^([A-Z][a-z\d]+)+$` // 대문자로 시작하는 camel case(pascal case or upper camel case)를 표현한 정규식 + REGEX_RFC1123_DNS_LABEL = "[a-z0-9]([-a-z0-9]*[a-z0-9])?" + REGEX_RFC1123_SUBDOMAIN = `^` + REGEX_RFC1123_DNS_LABEL + `(\.` + REGEX_RFC1123_DNS_LABEL + `)*$` +) func NewValidator() (*validator.Validate, *ut.UniversalTranslator) { en := en.New() @@ -27,6 +33,9 @@ func NewValidator() (*validator.Validate, *ut.UniversalTranslator) { // register custom validator _ = v.RegisterValidation("rfc1123", validateRfc1123) _ = v.RegisterValidation("name", validateName) + _ = v.RegisterValidation("version", validateVersion) + _ = v.RegisterValidation("pascalcase", validatePascalCase) + _ = v.RegisterValidation("resourcename", validateResourceName) // register custom error _ = v.RegisterTranslation("required", trans, func(ut ut.Translator) error { @@ -65,3 +74,30 @@ func validateName(fl validator.FieldLevel) bool { return utf8.RuneCountInString(fl.Field().String()) <= 30 } + +func validateVersion(fl validator.FieldLevel) bool { + if fl.Field().String() == "" { + return false + } + + r, _ := regexp.Compile(REGEX_SIMPLE_SEMVER) + return r.MatchString(fl.Field().String()) +} + +func validatePascalCase(fl validator.FieldLevel) bool { + if fl.Field().String() == "" { + return false + } + + r, _ := regexp.Compile(REGEX_PASCAL_CASE) + return r.MatchString(fl.Field().String()) +} + +func validateResourceName(fl validator.FieldLevel) bool { + if fl.Field().String() == "" { + return false + } + + r, _ := regexp.Compile(REGEX_RFC1123_SUBDOMAIN) + return r.MatchString(fl.Field().String()) +} diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index c60a8a35..df542606 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -3,7 +3,6 @@ package admin import ( "time" - "github.com/google/uuid" "github.com/openinfradev/tks-api/pkg/domain" ) @@ -43,9 +42,9 @@ type SimplePolicyTemplateResponse struct { } type CreatePolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` - Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + TemplateName string `json:"templateName" validate:"required,name" example:"필수 Label 검사" validate:"name"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required,pascalcase"` + Severity string `json:"severity" validate:"required,oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` Description string `json:"description,omitempty" example:"이 정책은 ..."` ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` @@ -65,46 +64,14 @@ type CreateOrganizationPolicyTemplateReponse struct { ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` } -type UpdateCommmonPolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사"` - Description string `json:"description,omitempty"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` - Deprecated bool `json:"deprecated" example:"false"` - // Tags []string `json:"tags,omitempty"` -} - -type UpdatePolicyTemplateUpdate struct { - ID uuid.UUID - Type string - UpdatorId uuid.UUID - TemplateName *string - Description *string - Severity *string - Deprecated *bool - PermittedOrganizationIds *[]string -} - -func (dto *UpdatePolicyTemplateUpdate) IsNothingToUpdate() bool { - return dto.TemplateName == nil && - dto.Description == nil && - dto.Severity == nil && - dto.Deprecated == nil && - dto.PermittedOrganizationIds == nil -} - type UpdatePolicyTemplateRequest struct { - TemplateName *string `json:"templateName,omitempty" example:"필수 Label 검사"` + TemplateName *string `json:"templateName,omitempty" validate:"required,name" example:"필수 Label 검사"` Description *string `json:"description,omitempty"` - Severity *string `json:"severity,omitempty" enums:"low,medium,high" example:"medium"` + Severity *string `json:"severity,omitempty" validate:"oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated *bool `json:"deprecated,omitempty" example:"false"` PermittedOrganizationIds *[]string `json:"permittedOrganizationIds,omitempty"` } -type UpdateOrganizationPolicyTemplateRequest struct { - UpdateCommmonPolicyTemplateRequest - Mandatory bool `json:"mandatory"` -} - type GetPolicyTemplateDeployResponse struct { DeployVersion map[string]string `json:"deployVersion"` } @@ -126,9 +93,9 @@ type GetPolicyTemplateVersionResponse struct { } type CreatePolicyTemplateVersionRequest struct { - VersionUpType string `json:"versionUpType" enums:"major,minor,patch" example:"minor" validate:"required"` - CurrentVersion string `json:"currentVersion" example:"v1.0.0" validate:"required"` - ExpectedVersion string `json:"expectedVersion" example:"v1.1.0" validate:"required"` + VersionUpType string `json:"versionUpType" validate:"required,oneof=major minor patch" enums:"major,minor,patch" example:"minor"` + CurrentVersion string `json:"currentVersion" validate:"required,version" example:"v1.0.0"` + ExpectedVersion string `json:"expectedVersion" validate:"required,version" example:"v1.1.0"` ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index c24ba0df..749bfd88 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -2,8 +2,6 @@ package domain import ( "time" - - "github.com/google/uuid" ) type PolicyTemplateResponse struct { @@ -34,9 +32,9 @@ type SimplePolicyTemplateResponse struct { } type CreatePolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사" validate:"name"` - Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + TemplateName string `json:"templateName" validate:"required,name" example:"필수 Label 검사" validate:"name"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required,pascalcase"` + Severity string `json:"severity" validate:"required,oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` Description string `json:"description,omitempty" example:"이 정책은 ..."` ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` @@ -52,37 +50,10 @@ type CreatePolicyTemplateReponse struct { ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` } -type UpdateCommmonPolicyTemplateRequest struct { - TemplateName string `json:"templateName" example:"필수 Label 검사"` - Description string `json:"description,omitempty"` - Severity string `json:"severity" enums:"low,medium,high" example:"medium"` - Deprecated bool `json:"deprecated" example:"false"` - // Tags []string `json:"tags,omitempty"` -} - -type UpdatePolicyTemplateUpdate struct { - ID uuid.UUID - Type string - UpdatorId uuid.UUID - TemplateName *string - Description *string - Severity *string - Deprecated *bool - PermittedOrganizationIds *[]string -} - -func (dto *UpdatePolicyTemplateUpdate) IsNothingToUpdate() bool { - return dto.TemplateName == nil && - dto.Description == nil && - dto.Severity == nil && - dto.Deprecated == nil && - dto.PermittedOrganizationIds == nil -} - type UpdatePolicyTemplateRequest struct { - TemplateName *string `json:"templateName,omitempty" example:"필수 Label 검사"` + TemplateName *string `json:"templateName,omitempty" validate:"required,name" example:"필수 Label 검사"` Description *string `json:"description,omitempty"` - Severity *string `json:"severity,omitempty" enums:"low,medium,high" example:"medium"` + Severity *string `json:"severity,omitempty" validate:"oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated *bool `json:"deprecated,omitempty" example:"false"` PermittedOrganizationIds *[]string `json:"permittedOrganizationIds,omitempty"` } @@ -100,9 +71,9 @@ type GetPolicyTemplateVersionResponse struct { } type CreatePolicyTemplateVersionRequest struct { - VersionUpType string `json:"versionUpType" enums:"major,minor,patch" example:"minor" validate:"required"` - CurrentVersion string `json:"currentVersion" example:"v1.0.0" validate:"required"` - ExpectedVersion string `json:"expectedVersion" example:"v1.1.0" validate:"required"` + VersionUpType string `json:"versionUpType" validate:"required,oneof=major minor patch" enums:"major,minor,patch" example:"minor"` + CurrentVersion string `json:"currentVersion" validate:"required,version" example:"v1.0.0"` + ExpectedVersion string `json:"expectedVersion" validate:"required,version" example:"v1.1.0"` ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index 8171ad03..ccaa4d47 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -54,11 +54,11 @@ type CreatePolicyRequest struct { TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` Mandatory bool `json:"mandatory"` - PolicyName string `json:"policyName" example:"label 정책"` - PolicyResourceName string `json:"policyResourceName,omitempty" example:"labelpolicy"` + PolicyName string `json:"policyName" validate:"required,name" example:"label 정책"` + PolicyResourceName string `json:"policyResourceName,omitempty" validate:"resourcename" example:"labelpolicy"` Description string `json:"description"` TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun" example:"deny"` + EnforcementAction string `json:"enforcementAction" validate:"required,oneof=deny dryrun warn" enum:"warn,deny,dryrun" example:"deny"` Parameters string `json:"parameters" example:"{\"key\":\"value\"}"` Match *Match `json:"match,omitempty"` MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` @@ -73,10 +73,10 @@ type UpdatePolicyRequest struct { TargetClusterIds *[]string `json:"targetClusterIds,omitempty" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` Mandatory *bool `json:"mandatory,omitempty"` - PolicyName *string `json:"policyName,omitempty" example:"label 정책"` + PolicyName *string `json:"policyName,omitempty" validate:"required,name" example:"label 정책"` Description *string `json:"description"` TemplateId *string `json:"templateId,omitempty" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - EnforcementAction *string `json:"enforcementAction,omitempty" enum:"warn,deny,dryrun"` + EnforcementAction *string `json:"enforcementAction" validate:"required,oneof=deny dryrun warn" enum:"warn,deny,dryrun" example:"deny"` Parameters *string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` Match *Match `json:"match,omitempty"` MatchYaml *string `json:"matchYaml,omitempty"` @@ -133,8 +133,8 @@ type StackPolicyStatusResponse struct { TemplateName string `json:"templateName" example:"레이블 요구"` TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` TemplateDescription string `json:"templateDescription" example:"파라미터로 설정된 레이블 검사"` - TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` - TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` + TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` + TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` } type ListStackPolicyStatusResponse struct { @@ -146,8 +146,8 @@ type GetStackPolicyTemplateStatusResponse struct { TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` TemplateDescription string `json:"templateDescription" example:"파라미터로 설정된 레이블 검사"` TemplateMandatory bool `json:"templateMandatory"` - TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` - TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` + TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` + TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` TemplateLatestVersonReleaseDate time.Time `json:"templateLatestVersonReleaseDate" format:"date-time"` UpdatedPolicyParameters []UpdatedPolicyTemplateParameter `json:"updatedPolicyParameters"` AffectedPolicies []PolicyStatus `json:"affectedPolicies"` @@ -183,8 +183,8 @@ type PolicyUpdate struct { } type UpdateStackPolicyTemplateStatusRequest struct { - TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` - TemplateTargetVerson string `json:"templateTargetVerson" example:"v1.0.3"` + TemplateCurrentVersion string `json:"templateCurrentVersion" validate:"version" example:"v1.0.1"` + TemplateTargetVerson string `json:"templateTargetVerson" validate:"version" example:"v1.0.3"` // PolicyUpdate []PolicyUpdate `json:"policyUpdate"` } From 62b5729ca8351601276b74c96b9409a2041dc44d Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 11 Apr 2024 20:47:20 +0900 Subject: [PATCH 284/502] =?UTF-8?q?lint=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/domain/admin/policy-template.go | 2 +- pkg/domain/policy-template.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index df542606..ab13594c 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -42,7 +42,7 @@ type SimplePolicyTemplateResponse struct { } type CreatePolicyTemplateRequest struct { - TemplateName string `json:"templateName" validate:"required,name" example:"필수 Label 검사" validate:"name"` + TemplateName string `json:"templateName" validate:"required,name" example:"필수 Label 검사"` Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required,pascalcase"` Severity string `json:"severity" validate:"required,oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 749bfd88..59311718 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -32,7 +32,7 @@ type SimplePolicyTemplateResponse struct { } type CreatePolicyTemplateRequest struct { - TemplateName string `json:"templateName" validate:"required,name" example:"필수 Label 검사" validate:"name"` + TemplateName string `json:"templateName" validate:"required,name" example:"필수 Label 검사"` Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required,pascalcase"` Severity string `json:"severity" validate:"required,oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` From 00b75e112d7d0a3eb14f827881454dd0e3e17383 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 12 Apr 2024 02:30:25 +0900 Subject: [PATCH 285/502] =?UTF-8?q?policy=20match=20validate=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/handler.go | 16 +++++ internal/delivery/http/policy.go | 10 +++ internal/validator/validator.go | 106 +++++++++++++++++++++++++++++- pkg/domain/policy.go | 8 +-- 4 files changed, 135 insertions(+), 5 deletions(-) diff --git a/internal/delivery/http/handler.go b/internal/delivery/http/handler.go index 2e053ae5..ffb133b5 100644 --- a/internal/delivery/http/handler.go +++ b/internal/delivery/http/handler.go @@ -71,6 +71,22 @@ func UnmarshalRequestInput(r *http.Request, in any) error { return nil } +// Http Request가 아닌 경우에도 domain 객체 validate가 필요한 경우 호출 +// 예를 들어 정책의 match를 RawYaml로 전달받았을 경우 이를 domain.Match 객체로 unmarshalling 한 후 domain.Match를 이용해서 validate 가능 +func ValidateDomainObject(in any) error { + err := validate.Struct(in) + if err != nil { + var valErrs validator_.ValidationErrors + if errors.As(err, &valErrs) { + for _, e := range valErrs { + return httpErrors.NewBadRequestError(err, "", e.Translate(trans)) + } + } + } + + return nil +} + /* func (h *APIHandler) GetClientFromClusterId(clusterId string) (*kubernetes.Clientset, error) { const prefix = "CACHE_KEY_KUBE_CLIENT_" diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 412770d8..9a45cd31 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -93,6 +93,11 @@ func (h *PolicyHandler) CreatePolicy(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match yaml error: %s", err), "P_INVALID_MATCH", "")) return } + + if err := ValidateDomainObject(match); err != nil { + ErrorJSON(w, r, err) + return + } } if len(input.PolicyResourceName) > 0 { @@ -180,6 +185,11 @@ func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match yaml error: %s", err), "P_INVALID_MATCH", "")) return } + + if err := ValidateDomainObject(match); err != nil { + ErrorJSON(w, r, err) + return + } } var templateId *uuid.UUID = nil diff --git a/internal/validator/validator.go b/internal/validator/validator.go index e977bf55..07b288da 100644 --- a/internal/validator/validator.go +++ b/internal/validator/validator.go @@ -2,12 +2,14 @@ package validator import ( "regexp" + "strings" "unicode/utf8" "github.com/go-playground/locales/en" ut "github.com/go-playground/universal-translator" validator "github.com/go-playground/validator/v10" en_translations "github.com/go-playground/validator/v10/translations/en" + "github.com/openinfradev/tks-api/pkg/domain" "github.com/opentracing/opentracing-go/log" ) @@ -16,6 +18,7 @@ const ( REGEX_SIMPLE_SEMVER = `^v\d+\.\d+\.\d+$` REGEX_PASCAL_CASE = `^([A-Z][a-z\d]+)+$` // 대문자로 시작하는 camel case(pascal case or upper camel case)를 표현한 정규식 REGEX_RFC1123_DNS_LABEL = "[a-z0-9]([-a-z0-9]*[a-z0-9])?" + REGEX_RESOURCE_NAME = `^` + REGEX_RFC1123_DNS_LABEL + "$" REGEX_RFC1123_SUBDOMAIN = `^` + REGEX_RFC1123_DNS_LABEL + `(\.` + REGEX_RFC1123_DNS_LABEL + `)*$` ) @@ -36,6 +39,8 @@ func NewValidator() (*validator.Validate, *ut.UniversalTranslator) { _ = v.RegisterValidation("version", validateVersion) _ = v.RegisterValidation("pascalcase", validatePascalCase) _ = v.RegisterValidation("resourcename", validateResourceName) + _ = v.RegisterValidation("matchnamespace", validateMatchNamespace) + _ = v.RegisterValidation("matchkinds", validateMatchKinds) // register custom error _ = v.RegisterTranslation("required", trans, func(ut ut.Translator) error { @@ -98,6 +103,105 @@ func validateResourceName(fl validator.FieldLevel) bool { return false } - r, _ := regexp.Compile(REGEX_RFC1123_SUBDOMAIN) + r, _ := regexp.Compile(REGEX_RESOURCE_NAME) return r.MatchString(fl.Field().String()) } + +func validateMatchKinds(fl validator.FieldLevel) bool { + kinds, ok := fl.Field().Interface().([]domain.Kinds) + if !ok { + return false + } + + for _, kind := range kinds { + if ok := validateMatchKindAPIGroup(kind.APIGroups) && validateMatchKindKind(kind.Kinds); !ok { + return false + } + } + + return true +} + +func validateMatchKindAPIGroup(apigroups []string) bool { + if len(apigroups) == 0 { + return true + } + + containsWildcard := false + + r, _ := regexp.Compile(REGEX_RFC1123_SUBDOMAIN) + + for _, apigroup := range apigroups { + if apigroup == "*" || apigroup == "" { + containsWildcard = true + } else { + if !r.MatchString(apigroup) { + return false + } + } + } + + if containsWildcard && len(apigroups) != 1 { + return false + } + + return true +} + +func validateMatchKindKind(kinds []string) bool { + if len(kinds) == 0 { + return true + } + + containsWildcard := false + + r, _ := regexp.Compile(REGEX_PASCAL_CASE) + + for _, kind := range kinds { + if kind == "*" || kind == "" { + containsWildcard = true + } else { + if !r.MatchString(kind) { + return false + } + } + } + + if containsWildcard && len(kinds) != 1 { + return false + } + + return true +} + +func validateMatchNamespace(fl validator.FieldLevel) bool { + namespaces, ok := fl.Field().Interface().([]string) + if !ok { + return false + } + + if len(namespaces) == 0 { + return true + } + + containsWildcard := false + + r, _ := regexp.Compile(REGEX_RESOURCE_NAME) + + for _, namespace := range namespaces { + if namespace == "*" || namespace == "" { + containsWildcard = true + } else { + trimmed := strings.TrimSuffix(strings.TrimPrefix(namespace, "*"), "*") + if !r.MatchString(trimmed) { + return false + } + } + } + + if containsWildcard && len(namespaces) != 1 { + return false + } + + return true +} diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index ccaa4d47..a147bfc4 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -6,14 +6,14 @@ import ( ) type Kinds struct { - APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,1,rep,name=apiGroups"` + APIGroups []string `json:"apiGroups,omitempty"` Kinds []string `json:"kinds,omitempty"` } type Match struct { - Namespaces []string `json:"namespaces,omitempty"` - ExcludedNamespaces []string `json:"excludedNamespaces,omitempty"` - Kinds []Kinds `json:"kinds,omitempty"` + Namespaces []string `json:"namespaces,omitempty" validate:"matchnamespace"` + ExcludedNamespaces []string `json:"excludedNamespaces,omitempty" validate:"matchnamespace"` + Kinds []Kinds `json:"kinds,omitempty" validate:"matchkinds"` } func (m *Match) JSON() string { From 4d212bf0c1b5eaf019f2cdc7f9cc4287bbcc07a8 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Sun, 14 Apr 2024 23:08:05 +0900 Subject: [PATCH 286/502] trivial. add checking logic snr email --- internal/usecase/system-notification.go | 30 +++++++++++++------------ 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 2543ab9e..8ca3130c 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -140,19 +140,21 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre continue } - to := []string{} - for _, user := range rule.TargetUsers { - to = append(to, user.Email) - } - message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, to) - if err != nil { - log.Error(ctx, fmt.Sprintf("Failed to make email content. err : %s", err.Error())) - continue - } - mailer := mail.New(message) - if err := mailer.SendMail(ctx); err != nil { - log.Error(ctx, fmt.Sprintf("Failed to send email to %s. err : %s", to, err.Error())) - continue + if rule.SystemNotificationCondition.EnableEmail { + to := []string{} + for _, user := range rule.TargetUsers { + to = append(to, user.Email) + } + message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, to) + if err != nil { + log.Error(ctx, fmt.Sprintf("Failed to make email content. err : %s", err.Error())) + continue + } + mailer := mail.New(message) + if err := mailer.SendMail(ctx); err != nil { + log.Error(ctx, fmt.Sprintf("Failed to send email to %s. err : %s", to, err.Error())) + continue + } } } @@ -308,7 +310,7 @@ func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryC case "pvc-full": url = primaryGrafanaEndpoint + "/d/tks_cluster_dashboard/tks-kubernetes-view-cluster-global?var-taco_cluster=" + clusterId.String() + "&kiosk" default: - url = "/d/tks_cluster_dashboard" + url = primaryGrafanaEndpoint + "/d/tks_cluster_dashboard" } return url From 9c8e650e975b9f994f5904bb34eccde9035a632b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 15 Apr 2024 11:04:32 +0900 Subject: [PATCH 287/502] feature. disable default snr rules --- api/swagger/docs.go | 35 +++++++++++++++++++++++--- api/swagger/swagger.json | 35 +++++++++++++++++++++++--- api/swagger/swagger.yaml | 23 +++++++++++++++++ internal/delivery/http/organization.go | 18 +++++++------ 4 files changed, 98 insertions(+), 13 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index b1c8289d..8f7319ef 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -11266,12 +11266,21 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest": { "type": "object", + "required": [ + "enforcementAction", + "policyName" + ], "properties": { "description": { "type": "string" }, "enforcementAction": { "type": "string", + "enum": [ + "deny", + "dryrun", + "warn" + ], "example": "deny" }, "mandatory": { @@ -11333,7 +11342,9 @@ const docTemplate = `{ "type": "object", "required": [ "kind", - "rego" + "rego", + "severity", + "templateName" ], "properties": { "deprecated": { @@ -15068,12 +15079,22 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { "type": "object", + "required": [ + "enforcementAction", + "policyName" + ], "properties": { "description": { "type": "string" }, "enforcementAction": { - "type": "string" + "type": "string", + "enum": [ + "deny", + "dryrun", + "warn" + ], + "example": "deny" }, "mandatory": { "type": "boolean" @@ -15110,6 +15131,9 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { "type": "object", + "required": [ + "templateName" + ], "properties": { "deprecated": { "type": "boolean", @@ -15633,7 +15657,9 @@ const docTemplate = `{ "type": "object", "required": [ "kind", - "rego" + "rego", + "severity", + "templateName" ], "properties": { "deprecated": { @@ -15987,6 +16013,9 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest": { "type": "object", + "required": [ + "templateName" + ], "properties": { "deprecated": { "type": "boolean", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index c33a4906..05a152bd 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -11260,12 +11260,21 @@ }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest": { "type": "object", + "required": [ + "enforcementAction", + "policyName" + ], "properties": { "description": { "type": "string" }, "enforcementAction": { "type": "string", + "enum": [ + "deny", + "dryrun", + "warn" + ], "example": "deny" }, "mandatory": { @@ -11327,7 +11336,9 @@ "type": "object", "required": [ "kind", - "rego" + "rego", + "severity", + "templateName" ], "properties": { "deprecated": { @@ -15062,12 +15073,22 @@ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { "type": "object", + "required": [ + "enforcementAction", + "policyName" + ], "properties": { "description": { "type": "string" }, "enforcementAction": { - "type": "string" + "type": "string", + "enum": [ + "deny", + "dryrun", + "warn" + ], + "example": "deny" }, "mandatory": { "type": "boolean" @@ -15104,6 +15125,9 @@ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { "type": "object", + "required": [ + "templateName" + ], "properties": { "deprecated": { "type": "boolean", @@ -15627,7 +15651,9 @@ "type": "object", "required": [ "kind", - "rego" + "rego", + "severity", + "templateName" ], "properties": { "deprecated": { @@ -15981,6 +16007,9 @@ }, "github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest": { "type": "object", + "required": [ + "templateName" + ], "properties": { "deprecated": { "type": "boolean", diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ce870a9e..17bb87b0 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -965,6 +965,10 @@ definitions: description: type: string enforcementAction: + enum: + - deny + - dryrun + - warn example: deny type: string mandatory: @@ -993,6 +997,9 @@ definitions: templateId: example: d98ef5f1-4a68-4047-a446-2207787ce3ff type: string + required: + - enforcementAction + - policyName type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse: properties: @@ -1046,6 +1053,8 @@ definitions: required: - kind - rego + - severity + - templateName type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest: properties: @@ -3492,6 +3501,11 @@ definitions: description: type: string enforcementAction: + enum: + - deny + - dryrun + - warn + example: deny type: string mandatory: type: boolean @@ -3515,6 +3529,9 @@ definitions: templateId: example: d98ef5f1-4a68-4047-a446-2207787ce3ff type: string + required: + - enforcementAction + - policyName type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest: properties: @@ -3537,6 +3554,8 @@ definitions: templateName: example: 필수 Label 검사 type: string + required: + - templateName type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest: properties: @@ -3906,6 +3925,8 @@ definitions: required: - kind - rego + - severity + - templateName type: object github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest: properties: @@ -4129,6 +4150,8 @@ definitions: templateName: example: 필수 Label 검사 type: string + required: + - templateName type: object github_com_openinfradev_tks-api_pkg_httpErrors.RestError: properties: diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 4821dbdd..65c5c545 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -148,13 +148,17 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r } organization.AdminId = &admin.ID - // Default systemNotificationRules 생성 - err = h.systemNotificationRuleUsecase.MakeDefaultSystemNotificationRules(r.Context(), organizationId, &organization) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } + /* + 0415 팀미팅의 결과, 기본 시스템 알림은 decapod 시스템을 사용한다. + + // Default systemNotificationRules 생성 + err = h.systemNotificationRuleUsecase.MakeDefaultSystemNotificationRules(r.Context(), organizationId, &organization) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + */ var out domain.CreateOrganizationResponse if err = serializer.Map(r.Context(), organization, &out); err != nil { From 9a98908c5f5211447af99efc203c56fb9c2c7fab Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 15 Apr 2024 14:39:58 +0900 Subject: [PATCH 288/502] feature. bug fix for stack_templates --- api/swagger/docs.go | 62 +++++++++++++++++++++--- api/swagger/swagger.json | 62 +++++++++++++++++++++--- api/swagger/swagger.yaml | 40 +++++++++++++++ internal/delivery/http/organization.go | 2 - internal/delivery/http/stack-template.go | 9 +++- internal/usecase/stack-template.go | 40 +++++++++------ internal/usecase/stack.go | 8 ++- pkg/domain/stack-template.go | 39 ++++++++------- 8 files changed, 211 insertions(+), 51 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index b1c8289d..dd929f03 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -11266,12 +11266,21 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest": { "type": "object", + "required": [ + "enforcementAction", + "policyName" + ], "properties": { "description": { "type": "string" }, "enforcementAction": { "type": "string", + "enum": [ + "deny", + "dryrun", + "warn" + ], "example": "deny" }, "mandatory": { @@ -11333,7 +11342,9 @@ const docTemplate = `{ "type": "object", "required": [ "kind", - "rego" + "rego", + "severity", + "templateName" ], "properties": { "deprecated": { @@ -15068,12 +15079,22 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { "type": "object", + "required": [ + "enforcementAction", + "policyName" + ], "properties": { "description": { "type": "string" }, "enforcementAction": { - "type": "string" + "type": "string", + "enum": [ + "deny", + "dryrun", + "warn" + ], + "example": "deny" }, "mandatory": { "type": "boolean" @@ -15110,6 +15131,9 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { "type": "object", + "required": [ + "templateName" + ], "properties": { "deprecated": { "type": "boolean", @@ -15237,11 +15261,22 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { "type": "object", "required": [ - "serviceIds" + "kubeType", + "kubeVersion", + "organizationIds", + "platform", + "serviceIds", + "template", + "version" ], "properties": { "cloudService": { - "type": "string" + "type": "string", + "enum": [ + "AWS", + "AZZURE", + "GCP" + ] }, "description": { "type": "string" @@ -15252,6 +15287,12 @@ const docTemplate = `{ "kubeVersion": { "type": "string" }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, "platform": { "type": "string" }, @@ -15265,7 +15306,11 @@ const docTemplate = `{ "type": "string" }, "templateType": { - "type": "string" + "type": "string", + "enum": [ + "STANDARD", + "MSA" + ] }, "version": { "type": "string" @@ -15633,7 +15678,9 @@ const docTemplate = `{ "type": "object", "required": [ "kind", - "rego" + "rego", + "severity", + "templateName" ], "properties": { "deprecated": { @@ -15987,6 +16034,9 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest": { "type": "object", + "required": [ + "templateName" + ], "properties": { "deprecated": { "type": "boolean", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index c33a4906..9169d042 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -11260,12 +11260,21 @@ }, "github_com_openinfradev_tks-api_pkg_domain.CreatePolicyRequest": { "type": "object", + "required": [ + "enforcementAction", + "policyName" + ], "properties": { "description": { "type": "string" }, "enforcementAction": { "type": "string", + "enum": [ + "deny", + "dryrun", + "warn" + ], "example": "deny" }, "mandatory": { @@ -11327,7 +11336,9 @@ "type": "object", "required": [ "kind", - "rego" + "rego", + "severity", + "templateName" ], "properties": { "deprecated": { @@ -15062,12 +15073,22 @@ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { "type": "object", + "required": [ + "enforcementAction", + "policyName" + ], "properties": { "description": { "type": "string" }, "enforcementAction": { - "type": "string" + "type": "string", + "enum": [ + "deny", + "dryrun", + "warn" + ], + "example": "deny" }, "mandatory": { "type": "boolean" @@ -15104,6 +15125,9 @@ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest": { "type": "object", + "required": [ + "templateName" + ], "properties": { "deprecated": { "type": "boolean", @@ -15231,11 +15255,22 @@ "github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest": { "type": "object", "required": [ - "serviceIds" + "kubeType", + "kubeVersion", + "organizationIds", + "platform", + "serviceIds", + "template", + "version" ], "properties": { "cloudService": { - "type": "string" + "type": "string", + "enum": [ + "AWS", + "AZZURE", + "GCP" + ] }, "description": { "type": "string" @@ -15246,6 +15281,12 @@ "kubeVersion": { "type": "string" }, + "organizationIds": { + "type": "array", + "items": { + "type": "string" + } + }, "platform": { "type": "string" }, @@ -15259,7 +15300,11 @@ "type": "string" }, "templateType": { - "type": "string" + "type": "string", + "enum": [ + "STANDARD", + "MSA" + ] }, "version": { "type": "string" @@ -15627,7 +15672,9 @@ "type": "object", "required": [ "kind", - "rego" + "rego", + "severity", + "templateName" ], "properties": { "deprecated": { @@ -15981,6 +16028,9 @@ }, "github_com_openinfradev_tks-api_pkg_domain_admin.UpdatePolicyTemplateRequest": { "type": "object", + "required": [ + "templateName" + ], "properties": { "deprecated": { "type": "boolean", diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ce870a9e..0d4d6e9a 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -965,6 +965,10 @@ definitions: description: type: string enforcementAction: + enum: + - deny + - dryrun + - warn example: deny type: string mandatory: @@ -993,6 +997,9 @@ definitions: templateId: example: d98ef5f1-4a68-4047-a446-2207787ce3ff type: string + required: + - enforcementAction + - policyName type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyResponse: properties: @@ -1046,6 +1053,8 @@ definitions: required: - kind - rego + - severity + - templateName type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest: properties: @@ -3492,6 +3501,11 @@ definitions: description: type: string enforcementAction: + enum: + - deny + - dryrun + - warn + example: deny type: string mandatory: type: boolean @@ -3515,6 +3529,9 @@ definitions: templateId: example: d98ef5f1-4a68-4047-a446-2207787ce3ff type: string + required: + - enforcementAction + - policyName type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest: properties: @@ -3537,6 +3554,8 @@ definitions: templateName: example: 필수 Label 검사 type: string + required: + - templateName type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePrimaryClusterRequest: properties: @@ -3602,6 +3621,10 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.UpdateStackTemplateRequest: properties: cloudService: + enum: + - AWS + - AZZURE + - GCP type: string description: type: string @@ -3609,6 +3632,10 @@ definitions: type: string kubeVersion: type: string + organizationIds: + items: + type: string + type: array platform: type: string serviceIds: @@ -3618,11 +3645,20 @@ definitions: template: type: string templateType: + enum: + - STANDARD + - MSA type: string version: type: string required: + - kubeType + - kubeVersion + - organizationIds + - platform - serviceIds + - template + - version type: object github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRequest: properties: @@ -3906,6 +3942,8 @@ definitions: required: - kind - rego + - severity + - templateName type: object github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest: properties: @@ -4129,6 +4167,8 @@ definitions: templateName: example: 필수 Label 검사 type: string + required: + - templateName type: object github_com_openinfradev_tks-api_pkg_httpErrors.RestError: properties: diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 4821dbdd..524e78ae 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -197,8 +197,6 @@ func (h *OrganizationHandler) GetOrganizations(w http.ResponseWriter, r *http.Re if err = serializer.Map(r.Context(), organization, &out.Organizations[i]); err != nil { log.Error(r.Context(), err) } - - log.Info(r.Context(), organization) } if out.Pagination, err = pg.Response(r.Context()); err != nil { diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 23815272..708c769f 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -193,8 +193,15 @@ func (h *StackTemplateHandler) UpdateStackTemplate(w http.ResponseWriter, r *htt return } + input := domain.UpdateStackTemplateRequest{} + err = UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + var dto model.StackTemplate - if err := serializer.Map(r.Context(), r, &dto); err != nil { + if err := serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } dto.ID = stackTemplateId diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 2eb0c715..403372c3 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -56,21 +56,7 @@ func (u *StackTemplateUsecase) Create(ctx context.Context, dto model.StackTempla return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate stackTemplate name"), "ST_CREATE_ALREADY_EXISTED_NAME", "") } - services := "[" - for i, serviceId := range dto.ServiceIds { - if i > 1 { - services = services + "," - } - switch serviceId { - case "LMA": - services = services + internal.SERVICE_LMA - case "SERVICE_MESH": - services = services + internal.SERVICE_SERVICE_MESH - } - } - services = services + "]" - dto.Services = []byte(services) - + dto.Services = servicesFromIds(dto.ServiceIds) stackTemplateId, err = u.repo.Create(ctx, dto) if err != nil { return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") @@ -92,10 +78,17 @@ func (u *StackTemplateUsecase) Update(ctx context.Context, dto model.StackTempla return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_STACK_TEMPLATE", "") } + dto.Services = servicesFromIds(dto.ServiceIds) err = u.repo.Update(ctx, dto) if err != nil { return err } + + err = u.UpdateOrganizations(ctx, dto) + if err != nil { + return err + } + return nil } @@ -233,3 +226,20 @@ func (u *StackTemplateUsecase) RemoveOrganizationStackTemplates(ctx context.Cont return nil } + +func servicesFromIds(serviceIds []string) []byte { + services := "[" + for i, serviceId := range serviceIds { + if i > 0 { + services = services + "," + } + switch serviceId { + case "LMA": + services = services + internal.SERVICE_LMA + case "SERVICE_MESH": + services = services + internal.SERVICE_SERVICE_MESH + } + } + services = services + "]" + return []byte(services) +} diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 08cf81e8..00f42648 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -121,6 +121,12 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom } } + var conf domain.StackConfResponse + if err := serializer.Map(ctx, dto.Conf, &conf); err != nil { + log.Error(ctx, err) + return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Invalid node conf"), "", "") + } + workflow := "tks-stack-create" workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ @@ -132,7 +138,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom "stack_template_id=" + dto.StackTemplateId.String(), "creator=" + user.GetUserId().String(), "base_repo_branch=" + viper.GetString("revision"), - "infra_conf=" + strings.Replace(helper.ModelToJson(dto.Conf), "\"", "\\\"", -1), + "infra_conf=" + strings.Replace(helper.ModelToJson(conf), "\"", "\\\"", -1), "cloud_service=" + dto.CloudService, "cluster_endpoint=" + dto.ClusterEndpoint, "policy_ids=" + strings.Join(dto.PolicyIds, ","), diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index e5bce152..b4287d7d 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -62,17 +62,15 @@ type GetStackTemplateResponse struct { } type CreateStackTemplateRequest struct { - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` - Version string `json:"version" validate:"required"` - - CloudService string `json:"cloudService" validate:"oneof=AWS AZZURE GCP"` - Platform string `json:"platform" validate:"required"` - TemplateType string `json:"templateType" validate:"oneof=STANDARD MSA"` - Template string `json:"template" validate:"required"` - KubeVersion string `json:"kubeVersion" validate:"required"` - KubeType string `json:"kubeType" validate:"required"` - + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + Version string `json:"version" validate:"required"` + CloudService string `json:"cloudService" validate:"oneof=AWS AZZURE GCP"` + Platform string `json:"platform" validate:"required"` + TemplateType string `json:"templateType" validate:"oneof=STANDARD MSA"` + Template string `json:"template" validate:"required"` + KubeVersion string `json:"kubeVersion" validate:"required"` + KubeType string `json:"kubeType" validate:"required"` OrganizationIds []string `json:"organizationIds" validate:"required"` ServiceIds []string `json:"serviceIds" validate:"required"` } @@ -82,15 +80,16 @@ type CreateStackTemplateResponse struct { } type UpdateStackTemplateRequest struct { - Description string `json:"description"` - Template string `json:"template"` - TemplateType string `json:"templateType"` - CloudService string `json:"cloudService"` - Version string `json:"version"` - Platform string `json:"platform"` - KubeVersion string `json:"kubeVersion"` - KubeType string `json:"kubeType"` - ServiceIds []string `json:"serviceIds" validate:"required"` + Description string `json:"description"` + Version string `json:"version" validate:"required"` + CloudService string `json:"cloudService" validate:"oneof=AWS AZZURE GCP"` + Platform string `json:"platform" validate:"required"` + TemplateType string `json:"templateType" validate:"oneof=STANDARD MSA"` + Template string `json:"template" validate:"required"` + KubeVersion string `json:"kubeVersion" validate:"required"` + KubeType string `json:"kubeType" validate:"required"` + OrganizationIds []string `json:"organizationIds" validate:"required"` + ServiceIds []string `json:"serviceIds" validate:"required"` } type GetStackTemplateServicesResponse struct { From af8435c7454024682c0409508d02429c07a1cb98 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 15 Apr 2024 14:52:27 +0900 Subject: [PATCH 289/502] =?UTF-8?q?policy=20resource=20name=20validation?= =?UTF-8?q?=20=EB=B2=84=EA=B7=B8=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/validator/validator.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/validator/validator.go b/internal/validator/validator.go index 07b288da..5d9fd3f7 100644 --- a/internal/validator/validator.go +++ b/internal/validator/validator.go @@ -99,8 +99,10 @@ func validatePascalCase(fl validator.FieldLevel) bool { } func validateResourceName(fl validator.FieldLevel) bool { + // 정책 리소스 이름을 지정하지 않으면 지정하기 때문에 유효함 + // 다른 리소스 이름을 처리할 때에는 분리 필요 if fl.Field().String() == "" { - return false + return true } r, _ := regexp.Compile(REGEX_RESOURCE_NAME) From e5280d8202f2ee7fbccc6180db9e582429361021 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 15 Apr 2024 15:36:41 +0900 Subject: [PATCH 290/502] =?UTF-8?q?tks=20=ED=85=9C=ED=94=8C=EB=A6=BF=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=8B=9C=20duplicate=20key=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/usecase/policy-template.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 2291cc8f..dbcd774e 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -103,17 +103,14 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp dto.Mandatory = false dto.OrganizationId = nil - dto.PermittedOrganizations = make([]model.Organization, len(dto.PermittedOrganizationIds)) - for i, organizationId := range dto.PermittedOrganizationIds { - - organization, err := u.organizationRepo.Get(ctx, organizationId) + for _, organizationId := range dto.PermittedOrganizationIds { + _, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } - dto.PermittedOrganizations[i] = organization } } else { - dto.PermittedOrganizations = make([]model.Organization, 0) + dto.PermittedOrganizationIds = make([]string, 0) } userId := user.GetUserId() From 6807629d45403ae2a373c4ec34b402d8d01c0516 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 15 Apr 2024 15:44:26 +0900 Subject: [PATCH 291/502] policy enforcement status --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/dashboard.go | 72 ++++++++++++++---- internal/route/route.go | 13 ++-- internal/usecase/dashboard.go | 110 ++++++++++++++++++++++++++++ pkg/domain/dashboard.go | 25 +++++++ 5 files changed, 202 insertions(+), 19 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index bddfbf67..b0dd8299 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -119,6 +119,7 @@ const ( GetResourcesDashboard // 대시보드/대시보드/조회 GetPolicyStatusDashboard GetPolicyUpdateDashboard + GetPolicyEnforcementDashboard // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 3cabd03c..f693b33d 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -13,6 +13,7 @@ import ( "github.com/openinfradev/tks-api/pkg/log" "net/http" "strings" + "time" ) type IDashboardHandler interface { @@ -25,6 +26,7 @@ type IDashboardHandler interface { GetResources(w http.ResponseWriter, r *http.Request) GetPolicyStatus(w http.ResponseWriter, r *http.Request) GetPolicyUpdate(w http.ResponseWriter, r *http.Request) + GetPolicyEnforcement(w http.ResponseWriter, r *http.Request) } type DashboardHandler struct { @@ -111,7 +113,7 @@ func (h *DashboardHandler) CreateDashboard(w http.ResponseWriter, r *http.Reques // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" -// @Success 200 {object} domain.GetDashboardResponse +// @Success 200 {array} domain.GetDashboardResponse // @Router /organizations/{organizationId}/dashboards [get] // @Security JWT func (h *DashboardHandler) GetDashboard(w http.ResponseWriter, r *http.Request) { @@ -207,7 +209,7 @@ func (h *DashboardHandler) UpdateDashboard(w http.ResponseWriter, r *http.Reques // GetCharts godoc // -// @Tags Dashboards +// @Tags Dashboard Widgets // @Summary Get charts data // @Description Get charts data // @Accept json @@ -217,7 +219,7 @@ func (h *DashboardHandler) UpdateDashboard(w http.ResponseWriter, r *http.Reques // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardChartsResponse -// @Router /organizations/{organizationId}/dashboard/charts [get] +// @Router /organizations/{organizationId}/dashboards/charts [get] // @Security JWT func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -267,7 +269,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { // GetChart godoc // -// @Tags Dashboards +// @Tags Dashboard Widgets // @Summary Get chart data // @Description Get chart data // @Accept json @@ -277,7 +279,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardChartResponse -// @Router /organizations/{organizationId}/dashboard/charts/{chartType} [get] +// @Router /organizations/{organizationId}/dashboards/charts/{chartType} [get] // @Security JWT func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -344,14 +346,14 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { // GetStacks godoc // -// @Tags Dashboards +// @Tags Dashboard Widgets // @Summary Get stacks // @Description Get stacks // @Accept json // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetDashboardStacksResponse -// @Router /organizations/{organizationId}/dashboard/stacks [get] +// @Router /organizations/{organizationId}/dashboards/stacks [get] // @Security JWT func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -386,14 +388,14 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { // GetResources godoc // -// @Tags Dashboards +// @Tags Dashboard Widgets // @Summary Get resources // @Description Get resources // @Accept json // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetDashboardResourcesResponse -// @Router /organizations/{organizationId}/dashboard/resources [get] +// @Router /organizations/{organizationId}/dashboards/resources [get] // @Security JWT func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -422,14 +424,14 @@ func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) // GetPolicyStatus godoc // -// @Tags Dashboards +// @Tags Dashboard Widgets // @Summary Get policy status // @Description Get policy status // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.GetDashboardPolicyStatusResponse -// @Router /organizations/{organizationId}/dashboard/policy-status [get] +// @Router /organizations/{organizationId}/dashboards/policy-status [get] // @Security JWT func (h *DashboardHandler) GetPolicyStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -475,14 +477,14 @@ func (h *DashboardHandler) GetPolicyStatus(w http.ResponseWriter, r *http.Reques // GetPolicyUpdate godoc // -// @Tags Dashboards +// @Tags Dashboard Widgets // @Summary Get the number of policytemplates that need to be updated // @Description Get the number of policytemplates that need to be updated // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.GetDashboardPolicyUpdateResponse -// @Router /organizations/{organizationId}/dashboard/policy-update [get] +// @Router /organizations/{organizationId}/dashboards/policy-update [get] // @Security JWT func (h *DashboardHandler) GetPolicyUpdate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -524,3 +526,47 @@ func (h *DashboardHandler) GetPolicyUpdate(w http.ResponseWriter, r *http.Reques out.PolicyUpdate = dpu ResponseJSON(w, r, http.StatusOK, out) } + +// GetPolicyEnforcement godoc +// +// @Tags Dashboard Widgets +// @Summary Get the number of policy enforcement +// @Description Get the number of policy enforcement +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetDashboardPolicyEnforcementResponse +// @Router /organizations/{organizationId}/dashboards/policy-enforcement [get] +// @Security JWT +func (h *DashboardHandler) GetPolicyEnforcement(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + organization, err := h.organizationUsecase.Get(r.Context(), organizationId) + if err != nil { + log.Error(r.Context(), "Failed to retrieve organization") + ErrorJSON(w, r, fmt.Errorf("failed to retrieve organization")) + return + } + + bcd, err := h.usecase.GetPolicyEnforcement(r.Context(), organizationId, organization.PrimaryClusterId) + if err != nil { + log.Error(r.Context(), "Failed to make policy bar chart data", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetDashboardPolicyEnforcementResponse + out.ChartType = "PolicyEnforcement" + out.OrganizationId = organizationId + out.Name = "정책 적용 현황" + out.Description = "정책 적용 현황 통계 데이터" + out.ChartData = *bcd + out.UpdatedAt = time.Now() + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/route/route.go b/internal/route/route.go index 0a4dd37f..03991257 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -201,12 +201,13 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.RemoveOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.RemoveOrganizationStackTemplates))).Methods(http.MethodPut) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/charts/{chartType}", customMiddleware.Handle(internalApi.GetChartDashboard, http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/policy-status", customMiddleware.Handle(internalApi.GetPolicyStatusDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatus))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboard/policy-update", customMiddleware.Handle(internalApi.GetPolicyUpdateDashboard, http.HandlerFunc(dashboardHandler.GetPolicyUpdate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/charts/{chartType}", customMiddleware.Handle(internalApi.GetChartDashboard, http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-status", customMiddleware.Handle(internalApi.GetPolicyStatusDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-update", customMiddleware.Handle(internalApi.GetPolicyUpdateDashboard, http.HandlerFunc(dashboardHandler.GetPolicyUpdate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-enforcement", customMiddleware.Handle(internalApi.GetPolicyEnforcementDashboard, http.HandlerFunc(dashboardHandler.GetPolicyEnforcement))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index c8b628cc..b3687664 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -35,6 +35,7 @@ type IDashboardUsecase interface { GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) GetResources(ctx context.Context, organizationId string) (out domain.DashboardResource, err error) GetPolicyUpdate(ctx context.Context, policyTemplates []policytemplate.TKSPolicyTemplate, policies []policytemplate.TKSPolicy) (domain.DashboardPolicyUpdate, error) + GetPolicyEnforcement(ctx context.Context, organizationId string, primaryClusterId string) (*domain.BarChartData, error) } type DashboardUsecase struct { @@ -648,6 +649,115 @@ func (u *DashboardUsecase) GetPolicyUpdate(ctx context.Context, policyTemplates return dpu, nil } +func (u *DashboardUsecase) GetPolicyEnforcement(ctx context.Context, organizationId string, primaryClusterId string) (*domain.BarChartData, error) { + type DashboardPolicyTemplate struct { + ClusterId string + PolicyTemplate map[string]map[string]int + } + + clusters, err := policytemplate.GetTksClusterCRs(ctx, primaryClusterId) + if err != nil { + log.Error(ctx, "Failed to retrieve policytemplate list ", err) + return nil, err + } + + dashboardPolicyTemplates := make([]DashboardPolicyTemplate, 0) + for _, cluster := range clusters { + // If the cluster does not have a policytemplate, skip ahead + // cluster.Status.Templates = {"K8sAllowedRepos": ["members"]} + if cluster.Status.Templates == nil { + continue + } + // policyTemplates = {"K8sAllowedRepos": {"members": 1}} + policyTemplates := make(map[string]map[string]int) + for templateName, policies := range cluster.Status.Templates { + for _, policy := range policies { + policyTemplates[templateName] = make(map[string]int) + policyTemplates[templateName][policy] = 1 + } + } + dashboardPolicyTemplates = append(dashboardPolicyTemplates, + DashboardPolicyTemplate{ClusterId: cluster.Name, PolicyTemplate: policyTemplates}) + } + + // fetch policies from db + dbPolicies, err := u.policyRepo.Fetch(ctx, organizationId, nil) + if err != nil { + return nil, err + } + + type TotalPolicyCount struct { + PolicyName string + OptionalPolicyCount int + RequiredPolicyCount int + } + + // totalTemplate = {"template name": TotalPolicyCount} + totalTemplate := make(map[string]*TotalPolicyCount) + for _, dpt := range dashboardPolicyTemplates { + for templateName, policies := range dpt.PolicyTemplate { + if _, ok := totalTemplate[templateName]; !ok { + totalTemplate[templateName] = &TotalPolicyCount{"", 0, 0} + } + // check if policy is required or optional + for policy, count := range policies { + for _, dbPolicy := range *dbPolicies { + if policy == dbPolicy.PolicyResourceName { + temp := totalTemplate[templateName] + temp.PolicyName = policy + if dbPolicy.Mandatory { + temp.RequiredPolicyCount += count + } else { + temp.OptionalPolicyCount += count + } + } + } + } + } + } + + // Y축 + var series []domain.UnitNumber + var yRequiredData []int + var yOptionalData []int + + // X축 + var xAxis *domain.Axis + var xData []string + + for key, val := range totalTemplate { + // X axis Data + xData = append(xData, key) + + // Y axis Data + yOptionalData = append(yOptionalData, val.OptionalPolicyCount) + yRequiredData = append(yRequiredData, val.RequiredPolicyCount) + } + + xAxis = &domain.Axis{ + Data: xData, + } + + optionalUnit := domain.UnitNumber{ + Name: "선택", + Data: yOptionalData, + } + series = append(series, optionalUnit) + + requiredUnit := domain.UnitNumber{ + Name: "필수", + Data: yRequiredData, + } + series = append(series, requiredUnit) + + bcd := &domain.BarChartData{ + XAxis: xAxis, + Series: series, + } + + return bcd, nil +} + func rangeDate(start, end time.Time) func() time.Time { y, m, d := start.Date() start = time.Date(y, m, d, 0, 0, 0, 0, time.UTC) diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index e8f52250..ea64bc6a 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -197,3 +197,28 @@ type DashboardPolicyUpdate struct { type GetDashboardPolicyUpdateResponse struct { PolicyUpdate DashboardPolicyUpdate `json:"updatedResources"` } + +type GetDashboardPolicyEnforcementResponse struct { + BarChart + ChartData BarChartData `json:"chartData"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type BarChart struct { + ChartType string `json:"chartType"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + Duration string `json:"duration"` + Interval string `json:"interval"` +} + +type BarChartData struct { + XAxis *Axis `json:"xAxis,omitempty"` + Series []UnitNumber `json:"series,omitempty"` +} + +type UnitNumber struct { + Name string `json:"name"` + Data []int `json:"data"` +} From 3cc3490e712bbaffe5120a72a462d14bb88882d3 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 15 Apr 2024 15:46:02 +0900 Subject: [PATCH 292/502] policy enforcement status\n endpoint generate --- internal/delivery/api/generated_endpoints.go.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 8f987908..c593692a 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -363,6 +363,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyUpdateDashboard", Group: "Dashboard", }, + GetPolicyEnforcementDashboard: { + Name: "GetPolicyEnforcementDashboard", + Group: "Dashboard", + }, Admin_CreateSystemNotificationTemplate: { Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", @@ -591,6 +595,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetProjectNamespaceK8sResources", Group: "Project", }, + GetProjectNamespaceKubeconfig: { + Name: "GetProjectNamespaceKubeconfig", + Group: "Project", + }, GetAudits: { Name: "GetAudits", Group: "Audit", @@ -1074,6 +1082,8 @@ func (e Endpoint) String() string { return "GetPolicyStatusDashboard" case GetPolicyUpdateDashboard: return "GetPolicyUpdateDashboard" + case GetPolicyEnforcementDashboard: + return "GetPolicyEnforcementDashboard" case Admin_CreateSystemNotificationTemplate: return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: @@ -1188,6 +1198,8 @@ func (e Endpoint) String() string { return "GetProjectKubeconfig" case GetProjectNamespaceK8sResources: return "GetProjectNamespaceK8sResources" + case GetProjectNamespaceKubeconfig: + return "GetProjectNamespaceKubeconfig" case GetAudits: return "GetAudits" case GetAudit: @@ -1524,6 +1536,8 @@ func GetEndpoint(name string) Endpoint { return GetPolicyStatusDashboard case "GetPolicyUpdateDashboard": return GetPolicyUpdateDashboard + case "GetPolicyEnforcementDashboard": + return GetPolicyEnforcementDashboard case "Admin_CreateSystemNotificationTemplate": return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": @@ -1638,6 +1652,8 @@ func GetEndpoint(name string) Endpoint { return GetProjectKubeconfig case "GetProjectNamespaceK8sResources": return GetProjectNamespaceK8sResources + case "GetProjectNamespaceKubeconfig": + return GetProjectNamespaceKubeconfig case "GetAudits": return GetAudits case "GetAudit": From 13cb474eefad0a109be3024b6341c8a862088a5a Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 15 Apr 2024 15:47:56 +0900 Subject: [PATCH 293/502] policy enforcement status\n swagger generate --- api/swagger/docs.go | 311 ++++++++++++++++++---------- api/swagger/swagger.json | 311 ++++++++++++++++++---------- api/swagger/swagger.yaml | 236 +++++++++++++-------- internal/delivery/http/dashboard.go | 2 +- 4 files changed, 558 insertions(+), 302 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index dd929f03..507e0c42 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3185,14 +3185,14 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboard/charts": { + "/organizations/{organizationId}/dashboards": { "get": { "security": [ { "JWT": [] } ], - "description": "Get charts data", + "description": "Get dashboard", "consumes": [ "application/json" ], @@ -3202,54 +3202,79 @@ const docTemplate = `{ "tags": [ "Dashboards" ], - "summary": "Get charts data", + "summary": "Get dashboard", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true - }, + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" + } + } + } + } + }, + "put": { + "security": [ { - "type": "string", - "description": "chartType", - "name": "chartType", - "in": "query" - }, + "JWT": [] + } + ], + "description": "Update dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Update dashboard", + "parameters": [ { "type": "string", - "description": "duration", - "name": "duration", - "in": "query", + "description": "Organization ID", + "name": "organizationId", + "in": "path", "required": true }, { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true + "description": "Request body to update dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" } } } - } - }, - "/organizations/{organizationId}/dashboard/charts/{chartType}": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get chart data", + "description": "Create new dashboard", "consumes": [ "application/json" ], @@ -3259,55 +3284,43 @@ const docTemplate = `{ "tags": [ "Dashboards" ], - "summary": "Get chart data", + "summary": "Create new dashboard", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { - "type": "string", - "description": "chartType", - "name": "chartType", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "duration", - "name": "duration", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true + "description": "Request body to create dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse" } } } } }, - "/organizations/{organizationId}/dashboard/policy-status": { + "/organizations/{organizationId}/dashboards/charts": { "get": { "security": [ { "JWT": [] } ], - "description": "Get policy status", + "description": "Get charts data", "consumes": [ "application/json" ], @@ -3315,36 +3328,56 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get policy status", + "summary": "Get charts data", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "chartType", + "name": "chartType", + "in": "query" + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse" } } } } }, - "/organizations/{organizationId}/dashboard/policy-update": { + "/organizations/{organizationId}/dashboards/charts/{chartType}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get the number of policytemplates that need to be updated", + "description": "Get chart data", "consumes": [ "application/json" ], @@ -3352,36 +3385,57 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get the number of policytemplates that need to be updated", + "summary": "Get chart data", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "chartType", + "name": "chartType", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse" } } } } }, - "/organizations/{organizationId}/dashboard/resources": { + "/organizations/{organizationId}/dashboards/policy-enforcement": { "get": { "security": [ { "JWT": [] } ], - "description": "Get resources", + "description": "Get the number of policy enforcement", "consumes": [ "application/json" ], @@ -3389,13 +3443,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get resources", + "summary": "Get the number of policy enforcement", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true @@ -3405,20 +3459,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse" } } } } }, - "/organizations/{organizationId}/dashboard/stacks": { + "/organizations/{organizationId}/dashboards/policy-status": { "get": { "security": [ { "JWT": [] } ], - "description": "Get stacks", + "description": "Get policy status", "consumes": [ "application/json" ], @@ -3426,13 +3480,13 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get stacks", + "summary": "Get policy status", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true @@ -3442,20 +3496,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse" } } } } }, - "/organizations/{organizationId}/dashboards": { + "/organizations/{organizationId}/dashboards/policy-update": { "get": { "security": [ { "JWT": [] } ], - "description": "Get dashboard", + "description": "Get the number of policytemplates that need to be updated", "consumes": [ "application/json" ], @@ -3463,9 +3517,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get dashboard", + "summary": "Get the number of policytemplates that need to be updated", "parameters": [ { "type": "string", @@ -3479,18 +3533,20 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse" } } } - }, - "put": { + } + }, + "/organizations/{organizationId}/dashboards/resources": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update dashboard", + "description": "Get resources", "consumes": [ "application/json" ], @@ -3498,43 +3554,36 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Update dashboard", + "summary": "Get resources", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true - }, - { - "description": "Request body to update dashboard", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/dashboards/stacks": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create new dashboard", + "description": "Get stacks", "consumes": [ "application/json" ], @@ -3542,32 +3591,23 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Create new dashboard", + "summary": "Get stacks", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true - }, - { - "description": "Request body to create dashboard", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse" } } } @@ -10598,6 +10638,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.BarChartData": { + "type": "object", + "properties": { + "series": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UnitNumber" + } + }, + "xAxis": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig": { "type": "object", "properties": { @@ -12327,6 +12381,35 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse": { + "type": "object", + "properties": { + "chartData": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData" + }, + "chartType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "string" + }, + "interval": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse": { "type": "object", "properties": { @@ -14812,6 +14895,20 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UnitNumber": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest": { "type": "object", "required": [ diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 9169d042..b0f2f0ee 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3179,14 +3179,14 @@ } } }, - "/organizations/{organizationId}/dashboard/charts": { + "/organizations/{organizationId}/dashboards": { "get": { "security": [ { "JWT": [] } ], - "description": "Get charts data", + "description": "Get dashboard", "consumes": [ "application/json" ], @@ -3196,54 +3196,79 @@ "tags": [ "Dashboards" ], - "summary": "Get charts data", + "summary": "Get dashboard", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true - }, + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" + } + } + } + } + }, + "put": { + "security": [ { - "type": "string", - "description": "chartType", - "name": "chartType", - "in": "query" - }, + "JWT": [] + } + ], + "description": "Update dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Update dashboard", + "parameters": [ { "type": "string", - "description": "duration", - "name": "duration", - "in": "query", + "description": "Organization ID", + "name": "organizationId", + "in": "path", "required": true }, { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true + "description": "Request body to update dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" } } } - } - }, - "/organizations/{organizationId}/dashboard/charts/{chartType}": { - "get": { + }, + "post": { "security": [ { "JWT": [] } ], - "description": "Get chart data", + "description": "Create new dashboard", "consumes": [ "application/json" ], @@ -3253,55 +3278,43 @@ "tags": [ "Dashboards" ], - "summary": "Get chart data", + "summary": "Create new dashboard", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true }, { - "type": "string", - "description": "chartType", - "name": "chartType", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "duration", - "name": "duration", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true + "description": "Request body to create dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest" + } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse" } } } } }, - "/organizations/{organizationId}/dashboard/policy-status": { + "/organizations/{organizationId}/dashboards/charts": { "get": { "security": [ { "JWT": [] } ], - "description": "Get policy status", + "description": "Get charts data", "consumes": [ "application/json" ], @@ -3309,36 +3322,56 @@ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get policy status", + "summary": "Get charts data", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "chartType", + "name": "chartType", + "in": "query" + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartsResponse" } } } } }, - "/organizations/{organizationId}/dashboard/policy-update": { + "/organizations/{organizationId}/dashboards/charts/{chartType}": { "get": { "security": [ { "JWT": [] } ], - "description": "Get the number of policytemplates that need to be updated", + "description": "Get chart data", "consumes": [ "application/json" ], @@ -3346,36 +3379,57 @@ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get the number of policytemplates that need to be updated", + "summary": "Get chart data", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "chartType", + "name": "chartType", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardChartResponse" } } } } }, - "/organizations/{organizationId}/dashboard/resources": { + "/organizations/{organizationId}/dashboards/policy-enforcement": { "get": { "security": [ { "JWT": [] } ], - "description": "Get resources", + "description": "Get the number of policy enforcement", "consumes": [ "application/json" ], @@ -3383,13 +3437,13 @@ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get resources", + "summary": "Get the number of policy enforcement", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true @@ -3399,20 +3453,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse" } } } } }, - "/organizations/{organizationId}/dashboard/stacks": { + "/organizations/{organizationId}/dashboards/policy-status": { "get": { "security": [ { "JWT": [] } ], - "description": "Get stacks", + "description": "Get policy status", "consumes": [ "application/json" ], @@ -3420,13 +3474,13 @@ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get stacks", + "summary": "Get policy status", "parameters": [ { "type": "string", - "description": "organizationId", + "description": "Organization ID", "name": "organizationId", "in": "path", "required": true @@ -3436,20 +3490,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse" } } } } }, - "/organizations/{organizationId}/dashboards": { + "/organizations/{organizationId}/dashboards/policy-update": { "get": { "security": [ { "JWT": [] } ], - "description": "Get dashboard", + "description": "Get the number of policytemplates that need to be updated", "consumes": [ "application/json" ], @@ -3457,9 +3511,9 @@ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Get dashboard", + "summary": "Get the number of policytemplates that need to be updated", "parameters": [ { "type": "string", @@ -3473,18 +3527,20 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse" } } } - }, - "put": { + } + }, + "/organizations/{organizationId}/dashboards/resources": { + "get": { "security": [ { "JWT": [] } ], - "description": "Update dashboard", + "description": "Get resources", "consumes": [ "application/json" ], @@ -3492,43 +3548,36 @@ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Update dashboard", + "summary": "Get resources", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true - }, - { - "description": "Request body to update dashboard", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse" } } } - }, - "post": { + } + }, + "/organizations/{organizationId}/dashboards/stacks": { + "get": { "security": [ { "JWT": [] } ], - "description": "Create new dashboard", + "description": "Get stacks", "consumes": [ "application/json" ], @@ -3536,32 +3585,23 @@ "application/json" ], "tags": [ - "Dashboards" + "Dashboard Widgets" ], - "summary": "Create new dashboard", + "summary": "Get stacks", "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true - }, - { - "description": "Request body to create dashboard", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse" } } } @@ -10592,6 +10632,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.BarChartData": { + "type": "object", + "properties": { + "series": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UnitNumber" + } + }, + "xAxis": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig": { "type": "object", "properties": { @@ -12321,6 +12375,35 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse": { + "type": "object", + "properties": { + "chartData": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData" + }, + "chartType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "string" + }, + "interval": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse": { "type": "object", "properties": { @@ -14806,6 +14889,20 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.UnitNumber": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "integer" + } + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest": { "type": "object", "required": [ diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 0d4d6e9a..be01be37 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -516,6 +516,15 @@ definitions: type: string type: array type: object + github_com_openinfradev_tks-api_pkg_domain.BarChartData: + properties: + series: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UnitNumber' + type: array + xAxis: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Axis' + type: object github_com_openinfradev_tks-api_pkg_domain.BootstrapKubeconfig: properties: expiration: @@ -1674,6 +1683,25 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardChartResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse: + properties: + chartData: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData' + chartType: + type: string + description: + type: string + duration: + type: string + interval: + type: string + name: + type: string + organizationId: + type: string + updatedAt: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse: properties: statuses: @@ -3318,6 +3346,15 @@ definitions: name: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.UnitNumber: + properties: + data: + items: + type: integer + type: array + name: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.UpdateAppServeAppEndpointRequest: properties: endpointUrl: @@ -6180,7 +6217,88 @@ paths: summary: Check name for cloudAccount tags: - CloudAccounts - /organizations/{organizationId}/dashboard/charts: + /organizations/{organizationId}/dashboards: + get: + consumes: + - application/json + description: Get dashboard + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse' + type: array + security: + - JWT: [] + summary: Get dashboard + tags: + - Dashboards + post: + consumes: + - application/json + description: Create new dashboard + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Request body to create dashboard + in: body + name: request + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse' + security: + - JWT: [] + summary: Create new dashboard + tags: + - Dashboards + put: + consumes: + - application/json + description: Update dashboard + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Request body to update dashboard + in: body + name: request + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse' + security: + - JWT: [] + summary: Update dashboard + tags: + - Dashboards + /organizations/{organizationId}/dashboards/charts: get: consumes: - application/json @@ -6216,8 +6334,8 @@ paths: - JWT: [] summary: Get charts data tags: - - Dashboards - /organizations/{organizationId}/dashboard/charts/{chartType}: + - Dashboard Widgets + /organizations/{organizationId}/dashboards/charts/{chartType}: get: consumes: - application/json @@ -6254,12 +6372,12 @@ paths: - JWT: [] summary: Get chart data tags: - - Dashboards - /organizations/{organizationId}/dashboard/policy-status: + - Dashboard Widgets + /organizations/{organizationId}/dashboards/policy-enforcement: get: consumes: - application/json - description: Get policy status + description: Get the number of policy enforcement parameters: - description: Organization ID in: path @@ -6272,17 +6390,17 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse' security: - JWT: [] - summary: Get policy status + summary: Get the number of policy enforcement tags: - - Dashboards - /organizations/{organizationId}/dashboard/policy-update: + - Dashboard Widgets + /organizations/{organizationId}/dashboards/policy-status: get: consumes: - application/json - description: Get the number of policytemplates that need to be updated + description: Get policy status parameters: - description: Organization ID in: path @@ -6295,19 +6413,19 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse' security: - JWT: [] - summary: Get the number of policytemplates that need to be updated + summary: Get policy status tags: - - Dashboards - /organizations/{organizationId}/dashboard/resources: + - Dashboard Widgets + /organizations/{organizationId}/dashboards/policy-update: get: consumes: - application/json - description: Get resources + description: Get the number of policytemplates that need to be updated parameters: - - description: organizationId + - description: Organization ID in: path name: organizationId required: true @@ -6318,17 +6436,17 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyUpdateResponse' security: - JWT: [] - summary: Get resources + summary: Get the number of policytemplates that need to be updated tags: - - Dashboards - /organizations/{organizationId}/dashboard/stacks: + - Dashboard Widgets + /organizations/{organizationId}/dashboards/resources: get: consumes: - application/json - description: Get stacks + description: Get resources parameters: - description: organizationId in: path @@ -6341,91 +6459,35 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse' security: - JWT: [] - summary: Get stacks + summary: Get resources tags: - - Dashboards - /organizations/{organizationId}/dashboards: + - Dashboard Widgets + /organizations/{organizationId}/dashboards/stacks: get: consumes: - application/json - description: Get dashboard - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse' - security: - - JWT: [] - summary: Get dashboard - tags: - - Dashboards - post: - consumes: - - application/json - description: Create new dashboard - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: Request body to create dashboard - in: body - name: request - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse' - security: - - JWT: [] - summary: Create new dashboard - tags: - - Dashboards - put: - consumes: - - application/json - description: Update dashboard + description: Get stacks parameters: - - description: Organization ID + - description: organizationId in: path name: organizationId required: true type: string - - description: Request body to update dashboard - in: body - name: request - required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardStacksResponse' security: - JWT: [] - summary: Update dashboard + summary: Get stacks tags: - - Dashboards + - Dashboard Widgets /organizations/{organizationId}/mandatory-policies: get: consumes: diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index f693b33d..ae1e41c2 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -112,7 +112,7 @@ func (h *DashboardHandler) CreateDashboard(w http.ResponseWriter, r *http.Reques // @Description Get dashboard // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" +// @Param organizationId path string true "Organization ID" // @Success 200 {array} domain.GetDashboardResponse // @Router /organizations/{organizationId}/dashboards [get] // @Security JWT From 8094e87c689706d8fec369a1df5642302dce997f Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 20 Feb 2024 15:45:06 +0900 Subject: [PATCH 294/502] app-serving: validate project param --- internal/delivery/http/app-serve-app.go | 39 ++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 04fd8e95..cf587bd6 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -70,7 +70,8 @@ var ( ) type AppServeAppHandler struct { - usecase usecase.IAppServeAppUsecase + usecase usecase.IAppServeAppUsecase + prjUsecase usecase.IProjectUsecase } func NewAppServeAppHandler(h usecase.Usecase) *AppServeAppHandler { @@ -125,6 +126,18 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re log.Infof(r.Context(), "Processing CREATE request for app '%s'...", app.Name) + // Namespace validation + exist, err := h.prjUsecase.IsProjectNamespaceExist(organizationId, projectId, app.TargetClusterId, app.Namespace) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("Error while checking namespace record: %s", err), "", "")) + return + } + + if !exist { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("Namespace '%s' doesn't exist", app.Namespace), "", "")) + return + } + now := time.Now() app.OrganizationId = organizationId app.ProjectId = projectId @@ -459,6 +472,12 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r return } + projectId, ok := vars["projectId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid projectId: %s", projectId), "C_INVALID_PROJECT_ID", "")) + return + } + appId, ok := vars["appId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid appId: %s", appId), "C_INVALID_ASA_ID", "")) @@ -468,6 +487,15 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) + // Check if projectId exists + prj, err := h.prjUsecase.GetProject(r.Context(), organizationId, projectId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("Error while checking project record: %v", err), "", "")) + return + } else if prj == nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found: %s", projectId), "C_INVALID_PROJECT_ID", "")) + } + tasks, err := h.usecase.GetAppServeAppTasks(r.Context(), appId, pg) if err != nil { log.Error(r.Context(), "Failed to get app-serve-app-tasks ", err) @@ -536,6 +564,15 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * return } + // Check if projectId exists + prj, err := h.prjUsecase.GetProject(organizationId, projectId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("Error while checking project record: %s", err), "", "")) + return + } else if prj == nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found: %s", projectId), "C_INVALID_PROJECT_ID", "")) + } + task, app, err := h.usecase.GetAppServeAppTaskById(r.Context(), taskId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) From 8e1e738a803b4e573d4102c86091605a3d760718 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 20 Feb 2024 16:16:07 +0900 Subject: [PATCH 295/502] leave TODO comment --- internal/delivery/http/app-serve-app.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index cf587bd6..e1a218da 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -487,6 +487,7 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) + // TODO: Fix runtime error here! // Check if projectId exists prj, err := h.prjUsecase.GetProject(r.Context(), organizationId, projectId) if err != nil { From 29d67d34923d41570d497ebed61c9d071f9d2309 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 9 Apr 2024 16:33:35 +0900 Subject: [PATCH 296/502] app-serving: filter apps by project instead of org --- go.mod | 2 +- internal/delivery/http/app-serve-app.go | 25 +++++++++++++++++-------- internal/repository/app-serve-app.go | 12 ++++++++---- internal/usecase/app-serve-app.go | 8 ++++---- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index d4c63026..0ee31202 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/openinfradev/tks-api -go 1.21 +go 1.22 require ( github.com/Masterminds/semver/v3 v3.2.0 diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index e1a218da..13d18263 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -74,9 +74,10 @@ type AppServeAppHandler struct { prjUsecase usecase.IProjectUsecase } -func NewAppServeAppHandler(h usecase.Usecase) *AppServeAppHandler { +func NewAppServeAppHandler(u usecase.Usecase) *AppServeAppHandler { return &AppServeAppHandler{ - usecase: h.AppServeApp, + usecase: u.AppServeApp, + prjUsecase: u.Project, } } @@ -127,7 +128,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re log.Infof(r.Context(), "Processing CREATE request for app '%s'...", app.Name) // Namespace validation - exist, err := h.prjUsecase.IsProjectNamespaceExist(organizationId, projectId, app.TargetClusterId, app.Namespace) + exist, err := h.prjUsecase.IsProjectNamespaceExist(r.Context(), organizationId, projectId, app.TargetClusterId, app.Namespace) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("Error while checking namespace record: %s", err), "", "")) return @@ -166,7 +167,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re return } - exist, err := h.usecase.IsAppServeAppNameExist(r.Context(), organizationId, app.Name) + exist, err = h.usecase.IsAppServeAppNameExist(r.Context(), organizationId, app.Name) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -250,13 +251,21 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re // @Security JWT func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] - fmt.Printf("organizationId = [%v]\n", organizationId) + log.Debugf(r.Context(), "organizationId = [%v]\n", organizationId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) return } + projectId, ok := vars["projectId"] + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid projectId"), "C_INVALID_PROJECT_ID", "")) + return + } + urlParams := r.URL.Query() showAllParam := urlParams.Get("showAll") @@ -270,8 +279,9 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ ErrorJSON(w, r, err) return } + pg := pagination.NewPagination(&urlParams) - apps, err := h.usecase.GetAppServeApps(r.Context(), organizationId, showAll, pg) + apps, err := h.usecase.GetAppServeApps(r.Context(), organizationId, projectId, showAll, pg) if err != nil { log.Error(r.Context(), "Failed to get Failed to get app-serve-apps ", err) ErrorJSON(w, r, err) @@ -487,7 +497,6 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - // TODO: Fix runtime error here! // Check if projectId exists prj, err := h.prjUsecase.GetProject(r.Context(), organizationId, projectId) if err != nil { @@ -566,7 +575,7 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * } // Check if projectId exists - prj, err := h.prjUsecase.GetProject(organizationId, projectId) + prj, err := h.prjUsecase.GetProject(r.Context(), organizationId, projectId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("Error while checking project record: %s", err), "", "")) return diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index a37559ca..175fec41 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -15,7 +15,7 @@ import ( type IAppServeAppRepository interface { CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(ctx context.Context, organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) + GetAppServeApps(ctx context.Context, organizationId string, projectId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) GetAppServeAppTasksByAppId(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) @@ -63,7 +63,7 @@ func (r *AppServeAppRepository) CreateTask(ctx context.Context, task *model.AppS return task.ID, nil } -func (r *AppServeAppRepository) GetAppServeApps(ctx context.Context, organizationId string, showAll bool, pg *pagination.Pagination) (apps []model.AppServeApp, err error) { +func (r *AppServeAppRepository) GetAppServeApps(ctx context.Context, organizationId string, projectId string, showAll bool, pg *pagination.Pagination) (apps []model.AppServeApp, err error) { var clusters []model.Cluster if pg == nil { pg = pagination.NewPagination(nil) @@ -71,9 +71,9 @@ func (r *AppServeAppRepository) GetAppServeApps(ctx context.Context, organizatio // TODO: should return different records based on showAll param _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.AppServeApp{}). - Where("app_serve_apps.organization_id = ? AND status <> 'DELETE_SUCCESS'", organizationId), &apps) + Where("app_serve_apps.project_id = ? AND status <> 'DELETE_SUCCESS'", projectId), &apps) if res.Error != nil { - return nil, fmt.Errorf("error while finding appServeApps with organizationId: %s", organizationId) + return nil, fmt.Errorf("error while finding appServeApps with projectId: %s", projectId) } // If no record is found, just return empty array. @@ -100,6 +100,10 @@ func (r *AppServeAppRepository) GetAppServeApps(ctx context.Context, organizatio return } +// //////////////////////////////////////////////////////////////////////////////////////// +// TODO: this API will'be deprecated soon once the new task-related API's are verified. +// Until then, this is available (except for stage info) just for backward compatibility. +// //////////////////////////////////////////////////////////////////////////////////////// func (r *AppServeAppRepository) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) { var app model.AppServeApp var cluster model.Cluster diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 28e76385..9c62f902 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -25,7 +25,7 @@ import ( type IAppServeAppUsecase interface { CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) - GetAppServeApps(ctx context.Context, organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) + GetAppServeApps(ctx context.Context, organizationId string, projectId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) @@ -180,10 +180,10 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A return appId, app.Name, nil } -func (u *AppServeAppUsecase) GetAppServeApps(ctx context.Context, organizationId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) { - apps, err := u.repo.GetAppServeApps(ctx, organizationId, showAll, pg) +func (u *AppServeAppUsecase) GetAppServeApps(ctx context.Context, organizationId string, projectId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) { + apps, err := u.repo.GetAppServeApps(ctx, organizationId, projectId, showAll, pg) if err != nil { - fmt.Println(apps) + log.Debugf(ctx, "Apps: [%v]", apps) } return apps, nil From cbd1d720bf40559f9a0a6c19f70b747c3754b7ae Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Thu, 11 Apr 2024 11:32:28 +0900 Subject: [PATCH 297/502] adjust indent with gofmt --- .../delivery/api/generated_endpoints.go.go | 871 +++++++++--------- 1 file changed, 436 insertions(+), 435 deletions(-) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index c593692a..363c80c1 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -1,362 +1,362 @@ - // This is generated code. DO NOT EDIT. +// This is generated code. DO NOT EDIT. package api var ApiMap = map[Endpoint]EndpointInfo{ - Login: { - Name: "Login", + Login: { + Name: "Login", Group: "Auth", }, - Logout: { - Name: "Logout", + Logout: { + Name: "Logout", Group: "Auth", }, - RefreshToken: { - Name: "RefreshToken", + RefreshToken: { + Name: "RefreshToken", Group: "Auth", }, - FindId: { - Name: "FindId", + FindId: { + Name: "FindId", Group: "Auth", }, - FindPassword: { - Name: "FindPassword", + FindPassword: { + Name: "FindPassword", Group: "Auth", }, - VerifyIdentityForLostId: { - Name: "VerifyIdentityForLostId", + VerifyIdentityForLostId: { + Name: "VerifyIdentityForLostId", Group: "Auth", }, - VerifyIdentityForLostPassword: { - Name: "VerifyIdentityForLostPassword", + VerifyIdentityForLostPassword: { + Name: "VerifyIdentityForLostPassword", Group: "Auth", }, - VerifyToken: { - Name: "VerifyToken", + VerifyToken: { + Name: "VerifyToken", Group: "Auth", }, - CreateUser: { - Name: "CreateUser", + CreateUser: { + Name: "CreateUser", Group: "User", }, - ListUser: { - Name: "ListUser", + ListUser: { + Name: "ListUser", Group: "User", }, - GetUser: { - Name: "GetUser", + GetUser: { + Name: "GetUser", Group: "User", }, - DeleteUser: { - Name: "DeleteUser", + DeleteUser: { + Name: "DeleteUser", Group: "User", }, - UpdateUsers: { - Name: "UpdateUsers", + UpdateUsers: { + Name: "UpdateUsers", Group: "User", }, - UpdateUser: { - Name: "UpdateUser", + UpdateUser: { + Name: "UpdateUser", Group: "User", }, - ResetPassword: { - Name: "ResetPassword", + ResetPassword: { + Name: "ResetPassword", Group: "User", }, - CheckId: { - Name: "CheckId", + CheckId: { + Name: "CheckId", Group: "User", }, - CheckEmail: { - Name: "CheckEmail", + CheckEmail: { + Name: "CheckEmail", Group: "User", }, - GetPermissionsByAccountId: { - Name: "GetPermissionsByAccountId", + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", Group: "User", }, - GetMyProfile: { - Name: "GetMyProfile", + GetMyProfile: { + Name: "GetMyProfile", Group: "MyProfile", }, - UpdateMyProfile: { - Name: "UpdateMyProfile", + UpdateMyProfile: { + Name: "UpdateMyProfile", Group: "MyProfile", }, - UpdateMyPassword: { - Name: "UpdateMyPassword", + UpdateMyPassword: { + Name: "UpdateMyPassword", Group: "MyProfile", }, - RenewPasswordExpiredDate: { - Name: "RenewPasswordExpiredDate", + RenewPasswordExpiredDate: { + Name: "RenewPasswordExpiredDate", Group: "MyProfile", }, - DeleteMyProfile: { - Name: "DeleteMyProfile", + DeleteMyProfile: { + Name: "DeleteMyProfile", Group: "MyProfile", }, - Admin_CreateOrganization: { - Name: "Admin_CreateOrganization", + Admin_CreateOrganization: { + Name: "Admin_CreateOrganization", Group: "Organization", }, - Admin_DeleteOrganization: { - Name: "Admin_DeleteOrganization", + Admin_DeleteOrganization: { + Name: "Admin_DeleteOrganization", Group: "Organization", }, - GetOrganizations: { - Name: "GetOrganizations", + GetOrganizations: { + Name: "GetOrganizations", Group: "Organization", }, - GetOrganization: { - Name: "GetOrganization", + GetOrganization: { + Name: "GetOrganization", Group: "Organization", }, - CheckOrganizationName: { - Name: "CheckOrganizationName", + CheckOrganizationName: { + Name: "CheckOrganizationName", Group: "Organization", }, - UpdateOrganization: { - Name: "UpdateOrganization", + UpdateOrganization: { + Name: "UpdateOrganization", Group: "Organization", }, - UpdatePrimaryCluster: { - Name: "UpdatePrimaryCluster", + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", Group: "Organization", }, - CreateCluster: { - Name: "CreateCluster", + CreateCluster: { + Name: "CreateCluster", Group: "Cluster", }, - GetClusters: { - Name: "GetClusters", + GetClusters: { + Name: "GetClusters", Group: "Cluster", }, - ImportCluster: { - Name: "ImportCluster", + ImportCluster: { + Name: "ImportCluster", Group: "Cluster", }, - GetCluster: { - Name: "GetCluster", + GetCluster: { + Name: "GetCluster", Group: "Cluster", }, - DeleteCluster: { - Name: "DeleteCluster", + DeleteCluster: { + Name: "DeleteCluster", Group: "Cluster", }, - GetClusterSiteValues: { - Name: "GetClusterSiteValues", + GetClusterSiteValues: { + Name: "GetClusterSiteValues", Group: "Cluster", }, - InstallCluster: { - Name: "InstallCluster", + InstallCluster: { + Name: "InstallCluster", Group: "Cluster", }, - CreateBootstrapKubeconfig: { - Name: "CreateBootstrapKubeconfig", + CreateBootstrapKubeconfig: { + Name: "CreateBootstrapKubeconfig", Group: "Cluster", }, - GetBootstrapKubeconfig: { - Name: "GetBootstrapKubeconfig", + GetBootstrapKubeconfig: { + Name: "GetBootstrapKubeconfig", Group: "Cluster", }, - GetNodes: { - Name: "GetNodes", + GetNodes: { + Name: "GetNodes", Group: "Cluster", }, - CreateAppgroup: { - Name: "CreateAppgroup", + CreateAppgroup: { + Name: "CreateAppgroup", Group: "Appgroup", }, - GetAppgroups: { - Name: "GetAppgroups", + GetAppgroups: { + Name: "GetAppgroups", Group: "Appgroup", }, - GetAppgroup: { - Name: "GetAppgroup", + GetAppgroup: { + Name: "GetAppgroup", Group: "Appgroup", }, - DeleteAppgroup: { - Name: "DeleteAppgroup", + DeleteAppgroup: { + Name: "DeleteAppgroup", Group: "Appgroup", }, - GetApplications: { - Name: "GetApplications", + GetApplications: { + Name: "GetApplications", Group: "Appgroup", }, - CreateApplication: { - Name: "CreateApplication", + CreateApplication: { + Name: "CreateApplication", Group: "Appgroup", }, - GetAppServeAppTasksByAppId: { - Name: "GetAppServeAppTasksByAppId", + GetAppServeAppTasksByAppId: { + Name: "GetAppServeAppTasksByAppId", Group: "AppServeApp", }, - GetAppServeAppTaskDetail: { - Name: "GetAppServeAppTaskDetail", + GetAppServeAppTaskDetail: { + Name: "GetAppServeAppTaskDetail", Group: "AppServeApp", }, - CreateAppServeApp: { - Name: "CreateAppServeApp", + CreateAppServeApp: { + Name: "CreateAppServeApp", Group: "AppServeApp", }, - GetAppServeApps: { - Name: "GetAppServeApps", + GetAppServeApps: { + Name: "GetAppServeApps", Group: "AppServeApp", }, - GetNumOfAppsOnStack: { - Name: "GetNumOfAppsOnStack", + GetNumOfAppsOnStack: { + Name: "GetNumOfAppsOnStack", Group: "AppServeApp", }, - GetAppServeApp: { - Name: "GetAppServeApp", + GetAppServeApp: { + Name: "GetAppServeApp", Group: "AppServeApp", }, - GetAppServeAppLatestTask: { - Name: "GetAppServeAppLatestTask", + GetAppServeAppLatestTask: { + Name: "GetAppServeAppLatestTask", Group: "AppServeApp", }, - IsAppServeAppExist: { - Name: "IsAppServeAppExist", + IsAppServeAppExist: { + Name: "IsAppServeAppExist", Group: "AppServeApp", }, - IsAppServeAppNameExist: { - Name: "IsAppServeAppNameExist", + IsAppServeAppNameExist: { + Name: "IsAppServeAppNameExist", Group: "AppServeApp", }, - DeleteAppServeApp: { - Name: "DeleteAppServeApp", + DeleteAppServeApp: { + Name: "DeleteAppServeApp", Group: "AppServeApp", }, - UpdateAppServeApp: { - Name: "UpdateAppServeApp", + UpdateAppServeApp: { + Name: "UpdateAppServeApp", Group: "AppServeApp", }, - UpdateAppServeAppStatus: { - Name: "UpdateAppServeAppStatus", + UpdateAppServeAppStatus: { + Name: "UpdateAppServeAppStatus", Group: "AppServeApp", }, - UpdateAppServeAppEndpoint: { - Name: "UpdateAppServeAppEndpoint", + UpdateAppServeAppEndpoint: { + Name: "UpdateAppServeAppEndpoint", Group: "AppServeApp", }, - RollbackAppServeApp: { - Name: "RollbackAppServeApp", + RollbackAppServeApp: { + Name: "RollbackAppServeApp", Group: "AppServeApp", }, - GetCloudAccounts: { - Name: "GetCloudAccounts", + GetCloudAccounts: { + Name: "GetCloudAccounts", Group: "CloudAccount", }, - CreateCloudAccount: { - Name: "CreateCloudAccount", + CreateCloudAccount: { + Name: "CreateCloudAccount", Group: "CloudAccount", }, - CheckCloudAccountName: { - Name: "CheckCloudAccountName", + CheckCloudAccountName: { + Name: "CheckCloudAccountName", Group: "CloudAccount", }, - CheckAwsAccountId: { - Name: "CheckAwsAccountId", + CheckAwsAccountId: { + Name: "CheckAwsAccountId", Group: "CloudAccount", }, - GetCloudAccount: { - Name: "GetCloudAccount", + GetCloudAccount: { + Name: "GetCloudAccount", Group: "CloudAccount", }, - UpdateCloudAccount: { - Name: "UpdateCloudAccount", + UpdateCloudAccount: { + Name: "UpdateCloudAccount", Group: "CloudAccount", }, - DeleteCloudAccount: { - Name: "DeleteCloudAccount", + DeleteCloudAccount: { + Name: "DeleteCloudAccount", Group: "CloudAccount", }, - DeleteForceCloudAccount: { - Name: "DeleteForceCloudAccount", + DeleteForceCloudAccount: { + Name: "DeleteForceCloudAccount", Group: "CloudAccount", }, - GetResourceQuota: { - Name: "GetResourceQuota", + GetResourceQuota: { + Name: "GetResourceQuota", Group: "CloudAccount", }, - Admin_GetStackTemplates: { - Name: "Admin_GetStackTemplates", + Admin_GetStackTemplates: { + Name: "Admin_GetStackTemplates", Group: "StackTemplate", }, - Admin_GetStackTemplate: { - Name: "Admin_GetStackTemplate", + Admin_GetStackTemplate: { + Name: "Admin_GetStackTemplate", Group: "StackTemplate", }, - Admin_GetStackTemplateServices: { - Name: "Admin_GetStackTemplateServices", + Admin_GetStackTemplateServices: { + Name: "Admin_GetStackTemplateServices", Group: "StackTemplate", }, - Admin_CreateStackTemplate: { - Name: "Admin_CreateStackTemplate", + Admin_CreateStackTemplate: { + Name: "Admin_CreateStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplate: { - Name: "Admin_UpdateStackTemplate", + Admin_UpdateStackTemplate: { + Name: "Admin_UpdateStackTemplate", Group: "StackTemplate", }, - Admin_DeleteStackTemplate: { - Name: "Admin_DeleteStackTemplate", + Admin_DeleteStackTemplate: { + Name: "Admin_DeleteStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplateOrganizations: { - Name: "Admin_UpdateStackTemplateOrganizations", + Admin_UpdateStackTemplateOrganizations: { + Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, - Admin_CheckStackTemplateName: { - Name: "Admin_CheckStackTemplateName", + Admin_CheckStackTemplateName: { + Name: "Admin_CheckStackTemplateName", Group: "StackTemplate", }, - GetOrganizationStackTemplates: { - Name: "GetOrganizationStackTemplates", + GetOrganizationStackTemplates: { + Name: "GetOrganizationStackTemplates", Group: "StackTemplate", }, - GetOrganizationStackTemplate: { - Name: "GetOrganizationStackTemplate", + GetOrganizationStackTemplate: { + Name: "GetOrganizationStackTemplate", Group: "StackTemplate", }, - AddOrganizationStackTemplates: { - Name: "AddOrganizationStackTemplates", + AddOrganizationStackTemplates: { + Name: "AddOrganizationStackTemplates", Group: "StackTemplate", }, - RemoveOrganizationStackTemplates: { - Name: "RemoveOrganizationStackTemplates", + RemoveOrganizationStackTemplates: { + Name: "RemoveOrganizationStackTemplates", Group: "StackTemplate", }, - CreateDashboard: { - Name: "CreateDashboard", + CreateDashboard: { + Name: "CreateDashboard", Group: "Dashboard", }, - GetDashboard: { - Name: "GetDashboard", + GetDashboard: { + Name: "GetDashboard", Group: "Dashboard", }, - UpdateDashboard: { - Name: "UpdateDashboard", + UpdateDashboard: { + Name: "UpdateDashboard", Group: "Dashboard", }, - GetChartsDashboard: { - Name: "GetChartsDashboard", + GetChartsDashboard: { + Name: "GetChartsDashboard", Group: "Dashboard", }, - GetChartDashboard: { - Name: "GetChartDashboard", + GetChartDashboard: { + Name: "GetChartDashboard", Group: "Dashboard", }, - GetStacksDashboard: { - Name: "GetStacksDashboard", + GetStacksDashboard: { + Name: "GetStacksDashboard", Group: "Dashboard", }, - GetResourcesDashboard: { - Name: "GetResourcesDashboard", + GetResourcesDashboard: { + Name: "GetResourcesDashboard", Group: "Dashboard", }, - GetPolicyStatusDashboard: { - Name: "GetPolicyStatusDashboard", + GetPolicyStatusDashboard: { + Name: "GetPolicyStatusDashboard", Group: "Dashboard", }, GetPolicyUpdateDashboard: { @@ -371,228 +371,228 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_UpdateSystemNotificationTemplate: { - Name: "Admin_UpdateSystemNotificationTemplate", + Admin_UpdateSystemNotificationTemplate: { + Name: "Admin_UpdateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_DeleteSystemNotificationTemplate: { - Name: "Admin_DeleteSystemNotificationTemplate", + Admin_DeleteSystemNotificationTemplate: { + Name: "Admin_DeleteSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplates: { - Name: "Admin_GetSystemNotificationTemplates", + Admin_GetSystemNotificationTemplates: { + Name: "Admin_GetSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplate: { - Name: "Admin_GetSystemNotificationTemplate", + Admin_GetSystemNotificationTemplate: { + Name: "Admin_GetSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_CheckSystemNotificationTemplateName: { - Name: "Admin_CheckSystemNotificationTemplateName", + Admin_CheckSystemNotificationTemplateName: { + Name: "Admin_CheckSystemNotificationTemplateName", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplates: { - Name: "GetOrganizationSystemNotificationTemplates", + GetOrganizationSystemNotificationTemplates: { + Name: "GetOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplate: { - Name: "GetOrganizationSystemNotificationTemplate", + GetOrganizationSystemNotificationTemplate: { + Name: "GetOrganizationSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - AddOrganizationSystemNotificationTemplates: { - Name: "AddOrganizationSystemNotificationTemplates", + AddOrganizationSystemNotificationTemplates: { + Name: "AddOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - RemoveOrganizationSystemNotificationTemplates: { - Name: "RemoveOrganizationSystemNotificationTemplates", + RemoveOrganizationSystemNotificationTemplates: { + Name: "RemoveOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - CreateSystemNotificationRule: { - Name: "CreateSystemNotificationRule", + CreateSystemNotificationRule: { + Name: "CreateSystemNotificationRule", Group: "SystemNotificationRule", }, - GetSystemNotificationRules: { - Name: "GetSystemNotificationRules", + GetSystemNotificationRules: { + Name: "GetSystemNotificationRules", Group: "SystemNotificationRule", }, - GetSystemNotificationRule: { - Name: "GetSystemNotificationRule", + GetSystemNotificationRule: { + Name: "GetSystemNotificationRule", Group: "SystemNotificationRule", }, - CheckSystemNotificationRuleName: { - Name: "CheckSystemNotificationRuleName", + CheckSystemNotificationRuleName: { + Name: "CheckSystemNotificationRuleName", Group: "SystemNotificationRule", }, - DeleteSystemNotificationRule: { - Name: "DeleteSystemNotificationRule", + DeleteSystemNotificationRule: { + Name: "DeleteSystemNotificationRule", Group: "SystemNotificationRule", }, - UpdateSystemNotificationRule: { - Name: "UpdateSystemNotificationRule", + UpdateSystemNotificationRule: { + Name: "UpdateSystemNotificationRule", Group: "SystemNotificationRule", }, - MakeDefaultSystemNotificationRules: { - Name: "MakeDefaultSystemNotificationRules", + MakeDefaultSystemNotificationRules: { + Name: "MakeDefaultSystemNotificationRules", Group: "SystemNotificationRule", }, - CreateSystemNotification: { - Name: "CreateSystemNotification", + CreateSystemNotification: { + Name: "CreateSystemNotification", Group: "SystemNotification", }, - GetSystemNotifications: { - Name: "GetSystemNotifications", + GetSystemNotifications: { + Name: "GetSystemNotifications", Group: "SystemNotification", }, - GetSystemNotification: { - Name: "GetSystemNotification", + GetSystemNotification: { + Name: "GetSystemNotification", Group: "SystemNotification", }, - DeleteSystemNotification: { - Name: "DeleteSystemNotification", + DeleteSystemNotification: { + Name: "DeleteSystemNotification", Group: "SystemNotification", }, - UpdateSystemNotification: { - Name: "UpdateSystemNotification", + UpdateSystemNotification: { + Name: "UpdateSystemNotification", Group: "SystemNotification", }, - CreateSystemNotificationAction: { - Name: "CreateSystemNotificationAction", + CreateSystemNotificationAction: { + Name: "CreateSystemNotificationAction", Group: "SystemNotification", }, - GetStacks: { - Name: "GetStacks", + GetStacks: { + Name: "GetStacks", Group: "Stack", }, - CreateStack: { - Name: "CreateStack", + CreateStack: { + Name: "CreateStack", Group: "Stack", }, - CheckStackName: { - Name: "CheckStackName", + CheckStackName: { + Name: "CheckStackName", Group: "Stack", }, - GetStack: { - Name: "GetStack", + GetStack: { + Name: "GetStack", Group: "Stack", }, - UpdateStack: { - Name: "UpdateStack", + UpdateStack: { + Name: "UpdateStack", Group: "Stack", }, - DeleteStack: { - Name: "DeleteStack", + DeleteStack: { + Name: "DeleteStack", Group: "Stack", }, - GetStackKubeConfig: { - Name: "GetStackKubeConfig", + GetStackKubeConfig: { + Name: "GetStackKubeConfig", Group: "Stack", }, - GetStackStatus: { - Name: "GetStackStatus", + GetStackStatus: { + Name: "GetStackStatus", Group: "Stack", }, - SetFavoriteStack: { - Name: "SetFavoriteStack", + SetFavoriteStack: { + Name: "SetFavoriteStack", Group: "Stack", }, - DeleteFavoriteStack: { - Name: "DeleteFavoriteStack", + DeleteFavoriteStack: { + Name: "DeleteFavoriteStack", Group: "Stack", }, - InstallStack: { - Name: "InstallStack", + InstallStack: { + Name: "InstallStack", Group: "Stack", }, - CreateProject: { - Name: "CreateProject", + CreateProject: { + Name: "CreateProject", Group: "Project", }, - GetProjectRoles: { - Name: "GetProjectRoles", + GetProjectRoles: { + Name: "GetProjectRoles", Group: "Project", }, - GetProjectRole: { - Name: "GetProjectRole", + GetProjectRole: { + Name: "GetProjectRole", Group: "Project", }, - GetProjects: { - Name: "GetProjects", + GetProjects: { + Name: "GetProjects", Group: "Project", }, - GetProject: { - Name: "GetProject", + GetProject: { + Name: "GetProject", Group: "Project", }, - UpdateProject: { - Name: "UpdateProject", + UpdateProject: { + Name: "UpdateProject", Group: "Project", }, - DeleteProject: { - Name: "DeleteProject", + DeleteProject: { + Name: "DeleteProject", Group: "Project", }, - AddProjectMember: { - Name: "AddProjectMember", + AddProjectMember: { + Name: "AddProjectMember", Group: "Project", }, - GetProjectMember: { - Name: "GetProjectMember", + GetProjectMember: { + Name: "GetProjectMember", Group: "Project", }, - GetProjectMembers: { - Name: "GetProjectMembers", + GetProjectMembers: { + Name: "GetProjectMembers", Group: "Project", }, - RemoveProjectMember: { - Name: "RemoveProjectMember", + RemoveProjectMember: { + Name: "RemoveProjectMember", Group: "Project", }, - UpdateProjectMemberRole: { - Name: "UpdateProjectMemberRole", + UpdateProjectMemberRole: { + Name: "UpdateProjectMemberRole", Group: "Project", }, - CreateProjectNamespace: { - Name: "CreateProjectNamespace", + CreateProjectNamespace: { + Name: "CreateProjectNamespace", Group: "Project", }, - GetProjectNamespaces: { - Name: "GetProjectNamespaces", + GetProjectNamespaces: { + Name: "GetProjectNamespaces", Group: "Project", }, - GetProjectNamespace: { - Name: "GetProjectNamespace", + GetProjectNamespace: { + Name: "GetProjectNamespace", Group: "Project", }, - UpdateProjectNamespace: { - Name: "UpdateProjectNamespace", + UpdateProjectNamespace: { + Name: "UpdateProjectNamespace", Group: "Project", }, - DeleteProjectNamespace: { - Name: "DeleteProjectNamespace", + DeleteProjectNamespace: { + Name: "DeleteProjectNamespace", Group: "Project", }, - SetFavoriteProject: { - Name: "SetFavoriteProject", + SetFavoriteProject: { + Name: "SetFavoriteProject", Group: "Project", }, - SetFavoriteProjectNamespace: { - Name: "SetFavoriteProjectNamespace", + SetFavoriteProjectNamespace: { + Name: "SetFavoriteProjectNamespace", Group: "Project", }, - UnSetFavoriteProject: { - Name: "UnSetFavoriteProject", + UnSetFavoriteProject: { + Name: "UnSetFavoriteProject", Group: "Project", }, - UnSetFavoriteProjectNamespace: { - Name: "UnSetFavoriteProjectNamespace", + UnSetFavoriteProjectNamespace: { + Name: "UnSetFavoriteProjectNamespace", Group: "Project", }, - GetProjectKubeconfig: { - Name: "GetProjectKubeconfig", + GetProjectKubeconfig: { + Name: "GetProjectKubeconfig", Group: "Project", }, - GetProjectNamespaceK8sResources: { - Name: "GetProjectNamespaceK8sResources", + GetProjectNamespaceK8sResources: { + Name: "GetProjectNamespaceK8sResources", Group: "Project", }, GetProjectNamespaceKubeconfig: { @@ -603,220 +603,220 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetAudits", Group: "Audit", }, - GetAudit: { - Name: "GetAudit", + GetAudit: { + Name: "GetAudit", Group: "Audit", }, - DeleteAudit: { - Name: "DeleteAudit", + DeleteAudit: { + Name: "DeleteAudit", Group: "Audit", }, - CreateTksRole: { - Name: "CreateTksRole", + CreateTksRole: { + Name: "CreateTksRole", Group: "Role", }, - ListTksRoles: { - Name: "ListTksRoles", + ListTksRoles: { + Name: "ListTksRoles", Group: "Role", }, - GetTksRole: { - Name: "GetTksRole", + GetTksRole: { + Name: "GetTksRole", Group: "Role", }, - DeleteTksRole: { - Name: "DeleteTksRole", + DeleteTksRole: { + Name: "DeleteTksRole", Group: "Role", }, - UpdateTksRole: { - Name: "UpdateTksRole", + UpdateTksRole: { + Name: "UpdateTksRole", Group: "Role", }, - GetPermissionsByRoleId: { - Name: "GetPermissionsByRoleId", + GetPermissionsByRoleId: { + Name: "GetPermissionsByRoleId", Group: "Role", }, - UpdatePermissionsByRoleId: { - Name: "UpdatePermissionsByRoleId", + UpdatePermissionsByRoleId: { + Name: "UpdatePermissionsByRoleId", Group: "Role", }, - IsRoleNameExisted: { - Name: "IsRoleNameExisted", + IsRoleNameExisted: { + Name: "IsRoleNameExisted", Group: "Role", }, - AppendUsersToRole: { - Name: "AppendUsersToRole", + AppendUsersToRole: { + Name: "AppendUsersToRole", Group: "Role", }, - GetUsersInRoleId: { - Name: "GetUsersInRoleId", + GetUsersInRoleId: { + Name: "GetUsersInRoleId", Group: "Role", }, - RemoveUsersFromRole: { - Name: "RemoveUsersFromRole", + RemoveUsersFromRole: { + Name: "RemoveUsersFromRole", Group: "Role", }, - GetPermissionTemplates: { - Name: "GetPermissionTemplates", + GetPermissionTemplates: { + Name: "GetPermissionTemplates", Group: "Permission", }, - Admin_CreateUser: { - Name: "Admin_CreateUser", + Admin_CreateUser: { + Name: "Admin_CreateUser", Group: "Admin_User", }, - Admin_ListUser: { - Name: "Admin_ListUser", + Admin_ListUser: { + Name: "Admin_ListUser", Group: "Admin_User", }, - Admin_GetUser: { - Name: "Admin_GetUser", + Admin_GetUser: { + Name: "Admin_GetUser", Group: "Admin_User", }, - Admin_DeleteUser: { - Name: "Admin_DeleteUser", + Admin_DeleteUser: { + Name: "Admin_DeleteUser", Group: "Admin_User", }, - Admin_UpdateUser: { - Name: "Admin_UpdateUser", + Admin_UpdateUser: { + Name: "Admin_UpdateUser", Group: "Admin_User", }, - Admin_ListTksRoles: { - Name: "Admin_ListTksRoles", + Admin_ListTksRoles: { + Name: "Admin_ListTksRoles", Group: "Admin Role", }, - Admin_GetTksRole: { - Name: "Admin_GetTksRole", + Admin_GetTksRole: { + Name: "Admin_GetTksRole", Group: "Admin Role", }, - Admin_GetProjects: { - Name: "Admin_GetProjects", + Admin_GetProjects: { + Name: "Admin_GetProjects", Group: "Admin Project", }, - Admin_ListPolicyTemplate: { - Name: "Admin_ListPolicyTemplate", + Admin_ListPolicyTemplate: { + Name: "Admin_ListPolicyTemplate", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplate: { - Name: "Admin_CreatePolicyTemplate", + Admin_CreatePolicyTemplate: { + Name: "Admin_CreatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplate: { - Name: "Admin_DeletePolicyTemplate", + Admin_DeletePolicyTemplate: { + Name: "Admin_DeletePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplate: { - Name: "Admin_GetPolicyTemplate", + Admin_GetPolicyTemplate: { + Name: "Admin_GetPolicyTemplate", Group: "PolicyTemplate", }, - Admin_UpdatePolicyTemplate: { - Name: "Admin_UpdatePolicyTemplate", + Admin_UpdatePolicyTemplate: { + Name: "Admin_UpdatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateDeploy: { - Name: "Admin_GetPolicyTemplateDeploy", + Admin_GetPolicyTemplateDeploy: { + Name: "Admin_GetPolicyTemplateDeploy", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateStatistics: { - Name: "Admin_ListPolicyTemplateStatistics", + Admin_ListPolicyTemplateStatistics: { + Name: "Admin_ListPolicyTemplateStatistics", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateVersions: { - Name: "Admin_ListPolicyTemplateVersions", + Admin_ListPolicyTemplateVersions: { + Name: "Admin_ListPolicyTemplateVersions", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplateVersion: { - Name: "Admin_CreatePolicyTemplateVersion", + Admin_CreatePolicyTemplateVersion: { + Name: "Admin_CreatePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplateVersion: { - Name: "Admin_DeletePolicyTemplateVersion", + Admin_DeletePolicyTemplateVersion: { + Name: "Admin_DeletePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateVersion: { - Name: "Admin_GetPolicyTemplateVersion", + Admin_GetPolicyTemplateVersion: { + Name: "Admin_GetPolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateKind: { - Name: "Admin_ExistsPolicyTemplateKind", + Admin_ExistsPolicyTemplateKind: { + Name: "Admin_ExistsPolicyTemplateKind", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateName: { - Name: "Admin_ExistsPolicyTemplateName", + Admin_ExistsPolicyTemplateName: { + Name: "Admin_ExistsPolicyTemplateName", Group: "PolicyTemplate", }, - Admin_ExtractParameters: { - Name: "Admin_ExtractParameters", + Admin_ExtractParameters: { + Name: "Admin_ExtractParameters", Group: "PolicyTemplate", }, - Admin_AddPermittedPolicyTemplatesForOrganization: { - Name: "Admin_AddPermittedPolicyTemplatesForOrganization", + Admin_AddPermittedPolicyTemplatesForOrganization: { + Name: "Admin_AddPermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - Admin_DeletePermittedPolicyTemplatesForOrganization: { - Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", + Admin_DeletePermittedPolicyTemplatesForOrganization: { + Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - ListStackPolicyStatus: { - Name: "ListStackPolicyStatus", + ListStackPolicyStatus: { + Name: "ListStackPolicyStatus", Group: "StackPolicyStatus", }, - GetStackPolicyTemplateStatus: { - Name: "GetStackPolicyTemplateStatus", + GetStackPolicyTemplateStatus: { + Name: "GetStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - UpdateStackPolicyTemplateStatus: { - Name: "UpdateStackPolicyTemplateStatus", + UpdateStackPolicyTemplateStatus: { + Name: "UpdateStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - GetMandatoryPolicies: { - Name: "GetMandatoryPolicies", + GetMandatoryPolicies: { + Name: "GetMandatoryPolicies", Group: "Policy", }, - SetMandatoryPolicies: { - Name: "SetMandatoryPolicies", + SetMandatoryPolicies: { + Name: "SetMandatoryPolicies", Group: "Policy", }, - GetPolicyStatistics: { - Name: "GetPolicyStatistics", + GetPolicyStatistics: { + Name: "GetPolicyStatistics", Group: "Policy", }, - ListPolicy: { - Name: "ListPolicy", + ListPolicy: { + Name: "ListPolicy", Group: "Policy", }, - CreatePolicy: { - Name: "CreatePolicy", + CreatePolicy: { + Name: "CreatePolicy", Group: "Policy", }, - DeletePolicy: { - Name: "DeletePolicy", + DeletePolicy: { + Name: "DeletePolicy", Group: "Policy", }, - GetPolicy: { - Name: "GetPolicy", + GetPolicy: { + Name: "GetPolicy", Group: "Policy", }, - UpdatePolicy: { - Name: "UpdatePolicy", + UpdatePolicy: { + Name: "UpdatePolicy", Group: "Policy", }, - UpdatePolicyTargetClusters: { - Name: "UpdatePolicyTargetClusters", + UpdatePolicyTargetClusters: { + Name: "UpdatePolicyTargetClusters", Group: "Policy", }, - ExistsPolicyName: { - Name: "ExistsPolicyName", + ExistsPolicyName: { + Name: "ExistsPolicyName", Group: "Policy", }, - GetPolicyEdit: { - Name: "GetPolicyEdit", + GetPolicyEdit: { + Name: "GetPolicyEdit", Group: "Policy", }, - AddPoliciesForStack: { - Name: "AddPoliciesForStack", + AddPoliciesForStack: { + Name: "AddPoliciesForStack", Group: "Policy", }, - DeletePoliciesForStack: { - Name: "DeletePoliciesForStack", + DeletePoliciesForStack: { + Name: "DeletePoliciesForStack", Group: "Policy", }, StackPolicyStatistics: { @@ -827,79 +827,80 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplate: { - Name: "CreatePolicyTemplate", + CreatePolicyTemplate: { + Name: "CreatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplate: { - Name: "DeletePolicyTemplate", + DeletePolicyTemplate: { + Name: "DeletePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplate: { - Name: "GetPolicyTemplate", + GetPolicyTemplate: { + Name: "GetPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - UpdatePolicyTemplate: { - Name: "UpdatePolicyTemplate", + UpdatePolicyTemplate: { + Name: "UpdatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateDeploy: { - Name: "GetPolicyTemplateDeploy", + GetPolicyTemplateDeploy: { + Name: "GetPolicyTemplateDeploy", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateStatistics: { - Name: "ListPolicyTemplateStatistics", + ListPolicyTemplateStatistics: { + Name: "ListPolicyTemplateStatistics", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateVersions: { - Name: "ListPolicyTemplateVersions", + ListPolicyTemplateVersions: { + Name: "ListPolicyTemplateVersions", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplateVersion: { - Name: "CreatePolicyTemplateVersion", + CreatePolicyTemplateVersion: { + Name: "CreatePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplateVersion: { - Name: "DeletePolicyTemplateVersion", + DeletePolicyTemplateVersion: { + Name: "DeletePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateVersion: { - Name: "GetPolicyTemplateVersion", + GetPolicyTemplateVersion: { + Name: "GetPolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateKind: { - Name: "ExistsPolicyTemplateKind", + ExistsPolicyTemplateKind: { + Name: "ExistsPolicyTemplateKind", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateName: { - Name: "ExistsPolicyTemplateName", + ExistsPolicyTemplateName: { + Name: "ExistsPolicyTemplateName", Group: "OrganizationPolicyTemplate", }, - ExtractParameters: { - Name: "ExtractParameters", + ExtractParameters: { + Name: "ExtractParameters", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateExample: { - Name: "ListPolicyTemplateExample", + ListPolicyTemplateExample: { + Name: "ListPolicyTemplateExample", Group: "PolicyTemplateExample", }, - GetPolicyTemplateExample: { - Name: "GetPolicyTemplateExample", + GetPolicyTemplateExample: { + Name: "GetPolicyTemplateExample", Group: "PolicyTemplateExample", }, - UpdatePolicyTemplateExample: { - Name: "UpdatePolicyTemplateExample", + UpdatePolicyTemplateExample: { + Name: "UpdatePolicyTemplateExample", Group: "PolicyTemplateExample", }, - DeletePolicyTemplateExample: { - Name: "DeletePolicyTemplateExample", + DeletePolicyTemplateExample: { + Name: "DeletePolicyTemplateExample", Group: "PolicyTemplateExample", }, - CompileRego: { - Name: "CompileRego", + CompileRego: { + Name: "CompileRego", Group: "Utility", }, } + func (e Endpoint) String() string { switch e { case Login: From 59b79746e7c93f88f51a99919448c0bd1a8644a7 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Thu, 11 Apr 2024 18:20:06 +0900 Subject: [PATCH 298/502] trivial: modify err msg --- internal/delivery/http/app-serve-app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 13d18263..cd9536d5 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -113,7 +113,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re appReq := domain.CreateAppServeAppRequest{} err := UnmarshalRequestInput(r, &appReq) if err != nil { - ErrorJSON(w, r, err) + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Error while unmarshalling request"), "C_INTERNAL_ERROR", "")) return } From 4bfc59f21232388ba92ad542d2cae916b1a78a8f Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Mon, 15 Apr 2024 11:47:26 +0900 Subject: [PATCH 299/502] add missing param 'project_id' --- internal/usecase/app-serve-app.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 9c62f902..fa6efe24 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -144,6 +144,7 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A "strategy=" + app.AppServeAppTasks[0].Strategy, "app_type=" + app.AppType, "organization_id=" + app.OrganizationId, + "project_id=" + app.ProjectId, "target_cluster_id=" + app.TargetClusterId, "app_name=" + app.Name, "namespace=" + app.Namespace, @@ -398,6 +399,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(ctx context.Context, appId string "asa_id=" + app.ID, "asa_task_id=" + taskId, "organization_id=" + app.OrganizationId, + "project_id=" + app.ProjectId, "tks_api_url=" + viper.GetString("external-address"), }, }) @@ -505,6 +507,7 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, app *model.A "strategy=" + appTask.Strategy, "app_type=" + app.AppType, "organization_id=" + app.OrganizationId, + "project_id=" + app.ProjectId, "target_cluster_id=" + app.TargetClusterId, "app_name=" + app.Name, "namespace=" + app.Namespace, @@ -578,6 +581,7 @@ func (u *AppServeAppUsecase) PromoteAppServeApp(ctx context.Context, appId strin workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ "organization_id=" + app.OrganizationId, + "project_id=" + app.ProjectId, "target_cluster_id=" + app.TargetClusterId, "app_name=" + app.Name, "namespace=" + app.Namespace, @@ -609,10 +613,7 @@ func (u *AppServeAppUsecase) AbortAppServeApp(ctx context.Context, appId string) // Get the latest task ID so that the task status can be modified inside workflow once the abort process is done. latestTaskId := app.AppServeAppTasks[0].ID - strategy := app.AppServeAppTasks[0].Strategy log.Info(ctx, "latestTaskId = ", latestTaskId) - log.Info(ctx, "strategy = ", strategy) - log.Info(ctx, "Updating app status to 'ABORTING'..") err = u.repo.UpdateStatus(ctx, appId, latestTaskId, "ABORTING", "") @@ -631,12 +632,12 @@ func (u *AppServeAppUsecase) AbortAppServeApp(ctx context.Context, appId string) workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ "organization_id=" + app.OrganizationId, + "project_id=" + app.ProjectId, "target_cluster_id=" + app.TargetClusterId, "app_name=" + app.Name, "namespace=" + app.Namespace, "asa_id=" + app.ID, "asa_task_id=" + latestTaskId, - "strategy=" + strategy, "tks_api_url=" + viper.GetString("external-address"), }, }) From e6fab0acfdf7cd47647ac509427c368a72313c30 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Mon, 15 Apr 2024 15:29:21 +0900 Subject: [PATCH 300/502] app-serving: auto-create task UUID --- internal/model/app-serve-app.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go index 4a9b2186..5291cd7c 100644 --- a/internal/model/app-serve-app.go +++ b/internal/model/app-serve-app.go @@ -2,6 +2,8 @@ package model import ( "time" + "github.com/google/uuid" + "gorm.io/gorm" ) type AppServeApp struct { @@ -52,3 +54,8 @@ type AppServeAppTask struct { UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` } + +func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { + t.ID = uuid.New().String() + return nil +} From 4b622b936a113331de0568cdc43c01b9c244889d Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 16 Apr 2024 10:32:37 +0900 Subject: [PATCH 301/502] revert go version --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0ee31202..d4c63026 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/openinfradev/tks-api -go 1.22 +go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.0 From ad41454f24f9e4cc8bf3f7a1acfc8be43325c599 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 16 Apr 2024 10:55:47 +0900 Subject: [PATCH 302/502] modify default harbor url --- cmd/server/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 1d2cc060..d5e62bde 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -44,7 +44,7 @@ func init() { flag.String("console-address", "https://tks-console-dev.taco-cat.xyz", "service address for console") // app-serve-apps - flag.String("image-registry-url", "harbor-dev.taco-cat.xyz/appserving", "URL of image registry") + flag.String("image-registry-url", "harbor.taco-cat.xyz/appserving", "URL of image registry") flag.String("harbor-pw-secret", "harbor-core", "name of harbor password secret") flag.String("git-repository-url", "github.com/openinfradev", "URL of git repository") From b802ec5b51c378c185699e2655434c2344dc08ad Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 16 Apr 2024 13:14:24 +0900 Subject: [PATCH 303/502] =?UTF-8?q?spec.clusters:=20Required=20value=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/policy-operator.go | 8 +++++++- internal/usecase/policy.go | 18 +++++++++--------- pkg/domain/policy.go | 20 ++++++++++---------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 84831e1f..ad192c00 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -50,6 +50,12 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { } } + targetClusterIds := make([]string, 0) + + if policy.TargetClusterIds != nil { + targetClusterIds = policy.TargetClusterIds + } + return &TKSPolicy{ TypeMeta: metav1.TypeMeta{ APIVersion: "tkspolicy.openinfradev.github.io/v1", @@ -63,7 +69,7 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { Spec: TKSPolicySpec{ EnforcementAction: policy.EnforcementAction, - Clusters: policy.TargetClusterIds, + Clusters: targetClusterIds, Template: policy.PolicyTemplate.Kind, Match: policy.Match, Params: params, diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index d2566032..c417d67d 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -572,7 +572,7 @@ func (u *PolicyUsecase) ListStackPolicyStatus(ctx context.Context, clusterId str // result[i].TemplateCurrentVersion = version // } - result[i].TemplateLatestVerson = latestVersion + result[i].TemplateLatestVersion = latestVersion result[i].TemplateDescription = policy.PolicyTemplate.Description } @@ -711,14 +711,14 @@ func (u *PolicyUsecase) GetStackPolicyTemplateStatus(ctx context.Context, cluste } result := domain.GetStackPolicyTemplateStatusResponse{ - TemplateName: currentTemplate.TemplateName, - TemplateId: policyTemplateId.String(), - TemplateDescription: currentTemplate.Description, - TemplateLatestVerson: latestTemplate.Version, - TemplateCurrentVersion: currentTemplate.Version, - TemplateLatestVersonReleaseDate: latestTemplate.CreatedAt, - AffectedPolicies: affectedPolicies, - UpdatedPolicyParameters: updatedPolicyParameters, + TemplateName: currentTemplate.TemplateName, + TemplateId: policyTemplateId.String(), + TemplateDescription: currentTemplate.Description, + TemplateLatestVersion: latestTemplate.Version, + TemplateCurrentVersion: currentTemplate.Version, + TemplateLatestVersionReleaseDate: latestTemplate.CreatedAt, + AffectedPolicies: affectedPolicies, + UpdatedPolicyParameters: updatedPolicyParameters, } return &result, nil diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index a147bfc4..411da352 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -134,7 +134,7 @@ type StackPolicyStatusResponse struct { TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` TemplateDescription string `json:"templateDescription" example:"파라미터로 설정된 레이블 검사"` TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` - TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` + TemplateLatestVersion string `json:"templateLatestVersion" example:"v1.0.3"` } type ListStackPolicyStatusResponse struct { @@ -142,15 +142,15 @@ type ListStackPolicyStatusResponse struct { } type GetStackPolicyTemplateStatusResponse struct { - TemplateName string `json:"templateName" example:"레이블 요구"` - TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` - TemplateDescription string `json:"templateDescription" example:"파라미터로 설정된 레이블 검사"` - TemplateMandatory bool `json:"templateMandatory"` - TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` - TemplateLatestVerson string `json:"templateLatestVerson" example:"v1.0.3"` - TemplateLatestVersonReleaseDate time.Time `json:"templateLatestVersonReleaseDate" format:"date-time"` - UpdatedPolicyParameters []UpdatedPolicyTemplateParameter `json:"updatedPolicyParameters"` - AffectedPolicies []PolicyStatus `json:"affectedPolicies"` + TemplateName string `json:"templateName" example:"레이블 요구"` + TemplateId string `json:"templateId" example:"708d1e5b-4e6f-40e9-87a3-329e2fd051a5"` + TemplateDescription string `json:"templateDescription" example:"파라미터로 설정된 레이블 검사"` + TemplateMandatory bool `json:"templateMandatory"` + TemplateCurrentVersion string `json:"templateCurrentVersion" example:"v1.0.1"` + TemplateLatestVersion string `json:"templateLatestVersion" example:"v1.0.3"` + TemplateLatestVersionReleaseDate time.Time `json:"templateLatestVersionReleaseDate" format:"date-time"` + UpdatedPolicyParameters []UpdatedPolicyTemplateParameter `json:"updatedPolicyParameters"` + AffectedPolicies []PolicyStatus `json:"affectedPolicies"` } type PolicyStatus struct { From ed161c06ab1e8f001d6abf0d6247d291c5f8fdc9 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 16 Apr 2024 13:35:13 +0900 Subject: [PATCH 304/502] trivial. fix update systemNotificationRUle --- internal/usecase/system-notification-rule.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index e133fca6..5f5cdaf6 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -79,7 +79,7 @@ func (u *SystemNotificationRuleUsecase) Create(ctx context.Context, dto model.Sy } func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.SystemNotificationRule) error { - _, err := u.repo.Get(ctx, dto.ID) + rule, err := u.repo.Get(ctx, dto.ID) if err != nil { return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") } @@ -96,6 +96,10 @@ func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.Sy } } + // Make parameters + dto.SystemNotificationCondition.Parameter = []byte(helper.ModelToJson(dto.SystemNotificationCondition.Parameters)) + dto.SystemNotificationCondition.ID = rule.SystemNotificationCondition.ID + err = u.repo.Update(ctx, dto) if err != nil { return err From 84c8cfc178586a637ea212deeef1aa7ad383c35b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 16 Apr 2024 14:50:55 +0900 Subject: [PATCH 305/502] trivial. support array filter on users --- api/swagger/docs.go | 6 +-- api/swagger/swagger.json | 6 +-- api/swagger/swagger.yaml | 6 +-- internal/repository/user.go | 15 +++++++- internal/usecase/system-notification.go | 51 ++++++++++++------------- 5 files changed, 48 insertions(+), 36 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 507e0c42..5cbd0a84 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -12737,11 +12737,11 @@ const docTemplate = `{ "type": "string", "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" }, - "templateLatestVerson": { + "templateLatestVersion": { "type": "string", "example": "v1.0.3" }, - "templateLatestVersonReleaseDate": { + "templateLatestVersionReleaseDate": { "type": "string", "format": "date-time" }, @@ -14394,7 +14394,7 @@ const docTemplate = `{ "type": "string", "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" }, - "templateLatestVerson": { + "templateLatestVersion": { "type": "string", "example": "v1.0.3" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index b0f2f0ee..fc187166 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -12731,11 +12731,11 @@ "type": "string", "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" }, - "templateLatestVerson": { + "templateLatestVersion": { "type": "string", "example": "v1.0.3" }, - "templateLatestVersonReleaseDate": { + "templateLatestVersionReleaseDate": { "type": "string", "format": "date-time" }, @@ -14388,7 +14388,7 @@ "type": "string", "example": "708d1e5b-4e6f-40e9-87a3-329e2fd051a5" }, - "templateLatestVerson": { + "templateLatestVersion": { "type": "string", "example": "v1.0.3" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index be01be37..4b0abe43 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1912,10 +1912,10 @@ definitions: templateId: example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 type: string - templateLatestVerson: + templateLatestVersion: example: v1.0.3 type: string - templateLatestVersonReleaseDate: + templateLatestVersionReleaseDate: format: date-time type: string templateMandatory: @@ -3016,7 +3016,7 @@ definitions: templateId: example: 708d1e5b-4e6f-40e9-87a3-329e2fd051a5 type: string - templateLatestVerson: + templateLatestVersion: example: v1.0.3 type: string templateName: diff --git a/internal/repository/user.go b/internal/repository/user.go index fdbae67c..839f9b37 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -10,6 +10,7 @@ import ( "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" "gorm.io/gorm" + "gorm.io/gorm/clause" ) // Interface @@ -120,7 +121,19 @@ func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination. pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.WithContext(ctx).Preload("Organization").Preload("Roles").Model(&model.User{}).Where("users.organization_id = ?", organizationId), &users) + db := r.db.WithContext(ctx).Preload(clause.Associations).Model(&model.User{}). + Where("users.organization_id = ?", organizationId) + + // [TODO] more pretty! + for _, filter := range pg.Filters { + log.Info(ctx, "KTKFREE ", filter.Relation) + if filter.Relation == "Roles" { + db = db.Where("id IN (SELECT user_id FROM user_roles WHERE name IN ?)", filter.Values) + break + } + } + + _, res := pg.Fetch(db, &users) if res.Error != nil { log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return nil, res.Error diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 8ca3130c..0d3f984e 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -124,38 +124,37 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre continue } - if systemNotification.Annotations.SystemNotificationRuleId == "" { - log.Error(ctx, "Invalid systemNotificationRuleId ") - continue - } - - systemNotificationRuleId, err := uuid.Parse(systemNotification.Annotations.SystemNotificationRuleId) - if err != nil { - log.Error(ctx, "Failed to parse uuid ", err) - continue - } - rule, err := u.systemNotificationRuleRepo.Get(ctx, systemNotificationRuleId) - if err != nil { - log.Error(ctx, "Failed to get systemNotificationRule ", err) - continue - } - - if rule.SystemNotificationCondition.EnableEmail { - to := []string{} - for _, user := range rule.TargetUsers { - to = append(to, user.Email) - } - message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, to) + // 사용자가 생성한 알림 + if systemNotification.Annotations.SystemNotificationRuleId != "" { + systemNotificationRuleId, err := uuid.Parse(systemNotification.Annotations.SystemNotificationRuleId) if err != nil { - log.Error(ctx, fmt.Sprintf("Failed to make email content. err : %s", err.Error())) + log.Error(ctx, "Failed to parse uuid ", err) continue } - mailer := mail.New(message) - if err := mailer.SendMail(ctx); err != nil { - log.Error(ctx, fmt.Sprintf("Failed to send email to %s. err : %s", to, err.Error())) + rule, err := u.systemNotificationRuleRepo.Get(ctx, systemNotificationRuleId) + if err != nil { + log.Error(ctx, "Failed to get systemNotificationRule ", err) continue } + + if rule.SystemNotificationCondition.EnableEmail { + to := []string{} + for _, user := range rule.TargetUsers { + to = append(to, user.Email) + } + message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, to) + if err != nil { + log.Error(ctx, fmt.Sprintf("Failed to make email content. err : %s", err.Error())) + continue + } + mailer := mail.New(message) + if err := mailer.SendMail(ctx); err != nil { + log.Error(ctx, fmt.Sprintf("Failed to send email to %s. err : %s", to, err.Error())) + continue + } + } } + } return nil From bc33c420ad50edcbf165470663991fdbb436e202 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 16 Apr 2024 15:28:12 +0900 Subject: [PATCH 306/502] bugfix: pass value to serializer --- internal/delivery/http/app-serve-app.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index cd9536d5..e667e4e6 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -599,10 +599,10 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * } var out domain.GetAppServeAppTaskResponse - if err := serializer.Map(r.Context(), app, &out.AppServeApp); err != nil { + if err := serializer.Map(r.Context(), *app, &out.AppServeApp); err != nil { log.Info(r.Context(), err) } - if err := serializer.Map(r.Context(), task, &out.AppServeAppTask); err != nil { + if err := serializer.Map(r.Context(), *task, &out.AppServeAppTask); err != nil { log.Info(r.Context(), err) } From 1ca466e19a7f79c961ec54f45fae65ab57dfb3ce Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 16 Apr 2024 17:03:04 +0900 Subject: [PATCH 307/502] policy violation widget --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/dashboard.go | 51 ++++++++++ internal/route/route.go | 1 + internal/usecase/dashboard.go | 146 ++++++++++++++++++++++++++++ pkg/domain/dashboard.go | 6 ++ pkg/thanos-client/client.go | 36 +++++++ pkg/thanos-client/types.go | 22 +++++ 7 files changed, 263 insertions(+) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index b0dd8299..9fb9f17b 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -120,6 +120,7 @@ const ( GetPolicyStatusDashboard GetPolicyUpdateDashboard GetPolicyEnforcementDashboard + GetPolicyViolationDashboard // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index ae1e41c2..5676f14a 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -27,6 +27,7 @@ type IDashboardHandler interface { GetPolicyStatus(w http.ResponseWriter, r *http.Request) GetPolicyUpdate(w http.ResponseWriter, r *http.Request) GetPolicyEnforcement(w http.ResponseWriter, r *http.Request) + GetPolicyViolation(w http.ResponseWriter, r *http.Request) } type DashboardHandler struct { @@ -570,3 +571,53 @@ func (h *DashboardHandler) GetPolicyEnforcement(w http.ResponseWriter, r *http.R out.UpdatedAt = time.Now() ResponseJSON(w, r, http.StatusOK, out) } + +// GetPolicyViolation godoc +// +// @Tags Dashboard Widgets +// @Summary Get the number of policy violation +// @Description Get the number of policy violation +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param duration query string true "duration" +// @Param interval query string true "interval" +// @Success 200 {object} domain.GetDashboardPolicyViolationResponse +// @Router /organizations/{organizationId}/dashboards/policy-enforcement [get] +// @Security JWT +func (h *DashboardHandler) GetPolicyViolation(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + query := r.URL.Query() + duration := query.Get("duration") + if duration == "" { + duration = "1d" // default + } + + interval := query.Get("interval") + if interval == "" { + interval = "1d" // default + } + + bcd, err := h.usecase.GetPolicyViolation(r.Context(), organizationId, duration, interval) + if err != nil { + log.Error(r.Context(), "Failed to make policy bar chart data", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetDashboardPolicyViolationResponse + out.ChartType = "PolicyViolation" + out.OrganizationId = organizationId + out.Name = "정책 위반 현황" + out.Description = "정책 위반 현황 통계 데이터" + out.ChartData = *bcd + out.UpdatedAt = time.Now() + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/route/route.go b/internal/route/route.go index 03991257..2ae34fd1 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -208,6 +208,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-status", customMiddleware.Handle(internalApi.GetPolicyStatusDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatus))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-update", customMiddleware.Handle(internalApi.GetPolicyUpdateDashboard, http.HandlerFunc(dashboardHandler.GetPolicyUpdate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-enforcement", customMiddleware.Handle(internalApi.GetPolicyEnforcementDashboard, http.HandlerFunc(dashboardHandler.GetPolicyEnforcement))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-violation", customMiddleware.Handle(internalApi.GetPolicyViolationDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolation))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index b3687664..4c5494ba 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -6,6 +6,7 @@ import ( "math" "sort" "strconv" + "strings" "time" "github.com/google/uuid" @@ -36,6 +37,7 @@ type IDashboardUsecase interface { GetResources(ctx context.Context, organizationId string) (out domain.DashboardResource, err error) GetPolicyUpdate(ctx context.Context, policyTemplates []policytemplate.TKSPolicyTemplate, policies []policytemplate.TKSPolicy) (domain.DashboardPolicyUpdate, error) GetPolicyEnforcement(ctx context.Context, organizationId string, primaryClusterId string) (*domain.BarChartData, error) + GetPolicyViolation(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) } type DashboardUsecase struct { @@ -758,6 +760,126 @@ func (u *DashboardUsecase) GetPolicyEnforcement(ctx context.Context, organizatio return bcd, nil } +func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) { + thanosClient, err := u.GetThanosClient(ctx, organizationId) + if err != nil { + return nil, errors.Wrap(err, "failed to create thanos client") + } + + durationSec, intervalSec := getDurationAndIntervalSec(duration, interval) + + clusterIdStr, err := u.GetFlatClusterIds(ctx, organizationId) + if err != nil { + return nil, err + } + query := fmt.Sprintf("sum by(kind,name,violation_enforcement)(opa_scorecard_constraint_violations{taco_cluster=~\"%s\"})", clusterIdStr) + + now := time.Now() + pm, err := thanosClient.FetchPolicyRange(ctx, query, int(now.Unix())-durationSec, int(now.Unix()), intervalSec) + if err != nil { + return nil, err + } + + // totalViolation: {"K8sRequiredLabels": {"violation_enforcement": 2}} + totalViolation := make(map[string]map[string]int) + + // Y축 + var series []domain.UnitNumber + var yDenyData []int + var yWarnData []int + var yDryrunData []int + + // X축 + var xAxis *domain.Axis + var xData []string + + for _, res := range pm.Data.Result { + policyTemplate := res.Metric.Kind + if len(res.Metric.Violation) == 0 { + continue + } + if !slices.Contains(xData, policyTemplate) { + xData = append(xData, policyTemplate) + } + + count, err := strconv.Atoi(res.Value[1].(string)) + if err != nil { + count = 0 + } + violation := res.Metric.Violation + if val, ok := totalViolation[policyTemplate][violation]; !ok { + totalViolation[policyTemplate] = make(map[string]int) + totalViolation[policyTemplate][violation] = count + } else { + totalViolation[policyTemplate][violation] = val + count + } + } + + for _, violations := range totalViolation { + yDenyData = append(yDenyData, violations["deny"]) + yWarnData = append(yWarnData, violations["warn"]) + yDryrunData = append(yDryrunData, violations["dryrun"]) + } + + xAxis = &domain.Axis{ + Data: xData, + } + + denyUnit := domain.UnitNumber{ + Name: "거부", + Data: yDenyData, + } + series = append(series, denyUnit) + + warnUnit := domain.UnitNumber{ + Name: "경고", + Data: yWarnData, + } + series = append(series, warnUnit) + + dryrunUnit := domain.UnitNumber{ + Name: "감사", + Data: yDryrunData, + } + series = append(series, dryrunUnit) + + bcd := &domain.BarChartData{ + XAxis: xAxis, + Series: series, + } + + return bcd, nil + +} + +func (u *DashboardUsecase) GetThanosClient(ctx context.Context, organizationId string) (thanos.ThanosClient, error) { + thanosUrl, err := u.getThanosUrl(ctx, organizationId) + if err != nil { + log.Error(ctx, err) + return nil, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") + } + address, port := helper.SplitAddress(ctx, thanosUrl) + client, err := thanos.New(address, port, false, "") + if err != nil { + return nil, errors.Wrap(err, "failed to create thanos client") + } + return client, nil +} + +func (u *DashboardUsecase) GetFlatClusterIds(ctx context.Context, organizationId string) (string, error) { + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, uuid.Nil, nil) + if err != nil { + log.Error(ctx, err) + return "", err + } + var clusterIds []string + for _, cluster := range clusters { + clusterIds = append(clusterIds, cluster.ID.String()) + } + clusterIdStr := strings.Join(clusterIds, "|") + return clusterIdStr, nil +} + func rangeDate(start, end time.Time) func() time.Time { y, m, d := start.Date() start = time.Date(y, m, d, 0, 0, 0, 0, time.UTC) @@ -773,3 +895,27 @@ func rangeDate(start, end time.Time) func() time.Time { return date } } + +func getDurationAndIntervalSec(duration string, interval string) (int, int) { + durationSec := 60 * 60 * 24 + switch duration { + case "1h": + durationSec = 60 * 60 + case "1d": + durationSec = 60 * 60 * 24 + case "7d": + durationSec = 60 * 60 * 24 * 7 + case "30d": + durationSec = 60 * 60 * 24 * 30 + } + + intervalSec := 60 * 60 // default 1h + switch interval { + case "1h": + intervalSec = 60 * 60 + case "1d": + intervalSec = 60 * 60 * 24 + } + + return durationSec, intervalSec +} diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index ea64bc6a..f9a2ac34 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -204,6 +204,12 @@ type GetDashboardPolicyEnforcementResponse struct { UpdatedAt time.Time `json:"updatedAt"` } +type GetDashboardPolicyViolationResponse struct { + BarChart + ChartData BarChartData `json:"chartData"` + UpdatedAt time.Time `json:"updatedAt"` +} + type BarChart struct { ChartType string `json:"chartType"` OrganizationId string `json:"organizationId"` diff --git a/pkg/thanos-client/client.go b/pkg/thanos-client/client.go index bb9e360c..db18ea19 100644 --- a/pkg/thanos-client/client.go +++ b/pkg/thanos-client/client.go @@ -16,6 +16,7 @@ import ( type ThanosClient interface { Get(ctx context.Context, query string) (Metric, error) FetchRange(ctx context.Context, query string, start int, end int, step int) (out Metric, err error) + FetchPolicyRange(ctx context.Context, query string, start int, end int, step int) (*PolicyMetric, error) } type ThanosClientImpl struct { @@ -124,3 +125,38 @@ func (c *ThanosClientImpl) FetchRange(ctx context.Context, query string, start i return } + +func (c *ThanosClientImpl) FetchPolicyRange(ctx context.Context, query string, start int, end int, step int) (pm *PolicyMetric, err error) { + rangeParam := fmt.Sprintf("&dedup=true&partial_response=false&start=%d&end=%d&step=%d&max_source_resolution=0s", start, end, step) + query = url.QueryEscape(query) + rangeParam + requestUrl := c.url + "/api/v1/query_range?query=" + query + + res, err := c.client.Get(requestUrl) + if err != nil { + return nil, err + } + if res == nil { + return nil, fmt.Errorf("failed to call thanos") + } + if res.StatusCode != 200 { + return nil, fmt.Errorf("invalid http status. return code: %d", res.StatusCode) + } + + defer func() { + if err := res.Body.Close(); err != nil { + log.Error(ctx, "error closing http body") + } + }() + + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + err = json.Unmarshal(body, &pm) + if err != nil { + return nil, err + } + + return pm, nil +} diff --git a/pkg/thanos-client/types.go b/pkg/thanos-client/types.go index 6f41cbe3..b01c14f3 100644 --- a/pkg/thanos-client/types.go +++ b/pkg/thanos-client/types.go @@ -20,3 +20,25 @@ type MetricDataResultMetric struct { Name string `json:"__name__"` TacoCluster string `json:"taco_cluster"` } + +// PolicyMetric dedicated policy metric struct +type PolicyMetric struct { + Data PolicyMetricData `json:"data"` + Status string `json:"status"` +} + +type PolicyMetricData struct { + Result []PolicyMetricResult `json:"result"` + ResultType string `json:"resultType"` +} + +type PolicyMetricResult struct { + Metric PolicyMetricDataResultMetric `json:"metric"` + Value []interface{} `json:"value"` +} + +type PolicyMetricDataResultMetric struct { + Kind string `json:"kind"` + Name string `json:"name"` + Violation string `json:"violation_enforcement"` +} From ff6822a960b24869cbc749b792e396ae9698b1a0 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 16 Apr 2024 17:03:40 +0900 Subject: [PATCH 308/502] policy violation widget\n endpoint generation --- internal/delivery/api/generated_endpoints.go.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index c593692a..f1cfb374 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -367,6 +367,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyEnforcementDashboard", Group: "Dashboard", }, + GetPolicyViolationDashboard: { + Name: "GetPolicyViolationDashboard", + Group: "Dashboard", + }, Admin_CreateSystemNotificationTemplate: { Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", @@ -1084,6 +1088,8 @@ func (e Endpoint) String() string { return "GetPolicyUpdateDashboard" case GetPolicyEnforcementDashboard: return "GetPolicyEnforcementDashboard" + case GetPolicyViolationDashboard: + return "GetPolicyViolationDashboard" case Admin_CreateSystemNotificationTemplate: return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: @@ -1538,6 +1544,8 @@ func GetEndpoint(name string) Endpoint { return GetPolicyUpdateDashboard case "GetPolicyEnforcementDashboard": return GetPolicyEnforcementDashboard + case "GetPolicyViolationDashboard": + return GetPolicyViolationDashboard case "Admin_CreateSystemNotificationTemplate": return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": From 092d61a5a6f0c5e5319629cc0adb6da1be46574f Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Tue, 16 Apr 2024 17:04:10 +0900 Subject: [PATCH 309/502] policy violation widget\n swagger generation --- api/swagger/docs.go | 49 +++++++++++++++++++++++++++++++++++++--- api/swagger/swagger.json | 49 +++++++++++++++++++++++++++++++++++++--- api/swagger/swagger.yaml | 35 +++++++++++++++++++++++++--- 3 files changed, 124 insertions(+), 9 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 507e0c42..f53cd7ca 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3435,7 +3435,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Get the number of policy enforcement", + "description": "Get the number of policy violation", "consumes": [ "application/json" ], @@ -3445,7 +3445,7 @@ const docTemplate = `{ "tags": [ "Dashboard Widgets" ], - "summary": "Get the number of policy enforcement", + "summary": "Get the number of policy violation", "parameters": [ { "type": "string", @@ -3453,13 +3453,27 @@ const docTemplate = `{ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse" } } } @@ -12426,6 +12440,35 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse": { + "type": "object", + "properties": { + "chartData": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData" + }, + "chartType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "string" + }, + "interval": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index b0f2f0ee..75a650f1 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3429,7 +3429,7 @@ "JWT": [] } ], - "description": "Get the number of policy enforcement", + "description": "Get the number of policy violation", "consumes": [ "application/json" ], @@ -3439,7 +3439,7 @@ "tags": [ "Dashboard Widgets" ], - "summary": "Get the number of policy enforcement", + "summary": "Get the number of policy violation", "parameters": [ { "type": "string", @@ -3447,13 +3447,27 @@ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse" } } } @@ -12420,6 +12434,35 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse": { + "type": "object", + "properties": { + "chartData": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData" + }, + "chartType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "string" + }, + "interval": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index be01be37..2aecfa27 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1712,6 +1712,25 @@ definitions: updatedResources: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate' type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse: + properties: + chartData: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData' + chartType: + type: string + description: + type: string + duration: + type: string + interval: + type: string + name: + type: string + organizationId: + type: string + updatedAt: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse: properties: resources: @@ -6377,23 +6396,33 @@ paths: get: consumes: - application/json - description: Get the number of policy enforcement + description: Get the number of policy violation parameters: - description: Organization ID in: path name: organizationId required: true type: string + - description: duration + in: query + name: duration + required: true + type: string + - description: interval + in: query + name: interval + required: true + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse' security: - JWT: [] - summary: Get the number of policy enforcement + summary: Get the number of policy violation tags: - Dashboard Widgets /organizations/{organizationId}/dashboards/policy-status: From ce8c6e143d1187f0e67b836e7bb925b9df608057 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 16 Apr 2024 17:12:15 +0900 Subject: [PATCH 310/502] =?UTF-8?q?GetPolicyForEdit=20fill=20parameter=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/paramdef-util.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go index 56a1ab64..e87ffbb2 100644 --- a/internal/policy-template/paramdef-util.go +++ b/internal/policy-template/paramdef-util.go @@ -251,13 +251,13 @@ func FillParamDefFromJson(paramdefs []*domain.ParameterDef, parameters *map[stri } else if nestedMapArray, ok := value.([]map[string]interface{}); ok { jsonByte, err := json.Marshal(nestedMapArray) - if err != nil { + if err == nil { paramdef.DefaultValue = string(jsonByte) } } else if value != nil { jsonByte, err := json.Marshal(value) - if err != nil { + if err == nil { paramdef.DefaultValue = string(jsonByte) } } From df23102b0922edd0b74c0d7ab3054004c974c3ec Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 16 Apr 2024 17:28:36 +0900 Subject: [PATCH 311/502] trivial. add user roles to audit --- internal/delivery/http/audit.go | 6 ++++++ internal/repository/audit.go | 3 ++- pkg/domain/audit.go | 20 ++++++++++---------- pkg/domain/user.go | 9 +++++++++ 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 520521c1..58fda3fb 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -71,6 +71,12 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { if err := serializer.Map(r.Context(), audit, &out.Audits[i]); err != nil { log.Info(r.Context(), err) } + out.Audits[i].User.Roles = make([]domain.SimpleRoleResponse, len(audit.User.Roles)) + for j, role := range audit.User.Roles { + if err := serializer.Map(r.Context(), role, &out.Audits[i].User.Roles[j]); err != nil { + log.Info(r.Context(), err) + } + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { diff --git a/internal/repository/audit.go b/internal/repository/audit.go index c0ac2010..2b35467d 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -44,7 +44,8 @@ func (r *AuditRepository) Fetch(ctx context.Context, pg *pagination.Pagination) pg = pagination.NewPagination(nil) } - db := r.db.WithContext(ctx).Model(&model.Audit{}).Preload(clause.Associations) + db := r.db.WithContext(ctx).Model(&model.Audit{}).Preload(clause.Associations).Preload("User.Roles") + _, res := pg.Fetch(db, &out) if res.Error != nil { return nil, res.Error diff --git a/pkg/domain/audit.go b/pkg/domain/audit.go index 6622aa40..2353b2bb 100644 --- a/pkg/domain/audit.go +++ b/pkg/domain/audit.go @@ -5,16 +5,16 @@ import ( ) type AuditResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Organization SimpleOrganizationResponse `json:"organization"` - Description string `json:"description"` - Group string `json:"group"` - Message string `json:"message"` - ClientIP string `json:"clientIP"` - User SimpleUserResponse `json:"user"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Organization SimpleOrganizationResponse `json:"organization"` + Description string `json:"description"` + Group string `json:"group"` + Message string `json:"message"` + ClientIP string `json:"clientIP"` + User SimpleUserResponseWithRoles `json:"user"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type CreateAuditRequest struct { diff --git a/pkg/domain/user.go b/pkg/domain/user.go index cdf30644..1258f1f4 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -49,6 +49,15 @@ type SimpleUserResponse struct { Email string `json:"email"` } +type SimpleUserResponseWithRoles struct { + ID string `json:"id"` + AccountId string `json:"accountId"` + Name string `json:"name"` + Department string `json:"department"` + Email string `json:"email"` + Roles []SimpleRoleResponse `json:"roles"` +} + type CreateUserResponse struct { User struct { ID string `json:"id"` From 458c880ea75d9124ad6632d0b7f22b4e9f6ab2a2 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 16 Apr 2024 17:58:19 +0900 Subject: [PATCH 312/502] trivial. bugfix for stack node count --- internal/repository/audit.go | 2 +- internal/usecase/stack.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/repository/audit.go b/internal/repository/audit.go index 2b35467d..094a2424 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -32,7 +32,7 @@ func NewAuditRepository(db *gorm.DB) IAuditRepository { // Logics func (r *AuditRepository) Get(ctx context.Context, auditId uuid.UUID) (out model.Audit, err error) { - res := r.db.WithContext(ctx).Preload(clause.Associations).First(&out, "id = ?", auditId) + res := r.db.WithContext(ctx).Preload(clause.Associations).Preload("User.Roles").First(&out, "id = ?", auditId) if res.Error != nil { return } diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 00f42648..0410bd3d 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -630,6 +630,10 @@ func reflectClusterToStack(ctx context.Context, cluster model.Cluster, appGroups log.Error(ctx, err) } + if err := serializer.Map(ctx, cluster, &out.Conf); err != nil { + log.Error(ctx, err) + } + status, statusDesc := getStackStatus(cluster, appGroups) out.ID = domain.StackId(cluster.ID) From cdb7ce9dcb10033637389bd3baf9ba1751eae024 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Wed, 17 Apr 2024 10:32:17 +0900 Subject: [PATCH 313/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EB=B2=84=EA=B7=B8=20=ED=94=BD=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/usecase/policy.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index c417d67d..6ce39010 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -244,11 +244,20 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic } if policyName != nil { - exists, err := u.repo.ExistByName(ctx, organizationId, *policyName) - if err == nil && exists { - return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY__NAME", "policy template name already exists") + policy, err := u.repo.GetByName(ctx, organizationId, *policyName) + if err != nil { + return err + } + + // 이름이 같은 정책이 존재하지만 아이디가 서로 다른 경우, 즉 다른 정책이 해당 이름 사용 중임 + if policy != nil && policyId != policy.ID { + return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_NAME", "policy name already exists") + } + + // 해당 이름 사용중인 정책이 없으면 업데이트, 있으면 동일 정책이므로 업데이트 안 함 + if policy == nil { + updateMap["policy_name"] = policyName } - updateMap["policy_name"] = policyName } if description != nil { @@ -323,7 +332,7 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic return err } - if policyName != nil || templateId != nil || enforcementAction != nil || + if templateId != nil || enforcementAction != nil || parameters != nil || match != nil || targetClusterIds != nil { organization, err := u.organizationRepo.Get(ctx, organizationId) @@ -332,16 +341,6 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic return httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } - if policyName != nil { - err = policytemplate.DeleteTksPolicyCR(ctx, organization.PrimaryClusterId, *policyName) - - if err != nil { - log.Errorf(ctx, "failed to delete TksPolicyCR: %v", err) - return httpErrors.NewInternalServerError(err, "P_FAILED_TO_APPLY_KUBERNETES", "") - - } - } - policy, err := u.repo.GetByID(ctx, organizationId, policyId) if err != nil { return httpErrors.NewBadRequestError(fmt.Errorf("invalid policyId"), "C_INVALID_POLICY_ID", "") From aad38c25452d26f52bb093155a61bc6972e542fc Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 17 Apr 2024 14:25:16 +0900 Subject: [PATCH 314/502] trivial. add status to systemNotificationRule --- pkg/domain/system-notification-rule.go | 2 ++ scripts/init_postgres.sql | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index ed33b8b9..c8026d38 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -41,6 +41,7 @@ type SystemNotificationRuleResponse struct { SystemNotificationTemplate SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplate"` SystemNotificationCondition SystemNotificationConditionResponse `json:"systemNotificationCondition"` IsSystem bool `json:"isSystem"` + Status string `json:"status"` Creator SimpleUserResponse `json:"creator"` Updator SimpleUserResponse `json:"updator"` CreatedAt time.Time `json:"createdAt"` @@ -66,6 +67,7 @@ type SimpleSystemNotificationRuleResponse struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` + Status string `json:"status"` } type GetSystemNotificationRulesResponse struct { diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index 6b3fab26..6f2ba46d 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -105,4 +105,3 @@ insert into system_notification_metric_parameters ( "order", system_notification values ( 5, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'VIOLATING_NAME', '$labels.violating_name', now(), now() ); insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) values ( 6, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'VIOLATION_MSG', '$labels.violation_msg', now(), now() ); -insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) From 8a9c3ff8291e0f65323675b8480ab9c5356f4508 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 17 Apr 2024 15:24:34 +0900 Subject: [PATCH 315/502] policy violation log skeleton code --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/dashboard.go | 33 ++++++++++++++++++++++++++++- internal/route/route.go | 1 + internal/usecase/dashboard.go | 6 ++++++ pkg/domain/dashboard.go | 4 ++++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 9fb9f17b..f8ddc546 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -121,6 +121,7 @@ const ( GetPolicyUpdateDashboard GetPolicyEnforcementDashboard GetPolicyViolationDashboard + GetPolicyViolationLogDashboard // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 5676f14a..370368b5 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -28,6 +28,7 @@ type IDashboardHandler interface { GetPolicyUpdate(w http.ResponseWriter, r *http.Request) GetPolicyEnforcement(w http.ResponseWriter, r *http.Request) GetPolicyViolation(w http.ResponseWriter, r *http.Request) + GetPolicyViolationLog(w http.ResponseWriter, r *http.Request) } type DashboardHandler struct { @@ -583,7 +584,7 @@ func (h *DashboardHandler) GetPolicyEnforcement(w http.ResponseWriter, r *http.R // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardPolicyViolationResponse -// @Router /organizations/{organizationId}/dashboards/policy-enforcement [get] +// @Router /organizations/{organizationId}/dashboards/policy-violation [get] // @Security JWT func (h *DashboardHandler) GetPolicyViolation(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -621,3 +622,33 @@ func (h *DashboardHandler) GetPolicyViolation(w http.ResponseWriter, r *http.Req out.UpdatedAt = time.Now() ResponseJSON(w, r, http.StatusOK, out) } + +// GetPolicyViolationLog godoc +// +// @Tags Dashboard Widgets +// @Summary Get policy violation log +// @Description Get policy violation log +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetDashboardPolicyViolationLogResponse +// @Router /organizations/{organizationId}/dashboards/policy-violation-log [get] +// @Security JWT +func (h *DashboardHandler) GetPolicyViolationLog(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + out, err := h.usecase.GetPolicyViolationLog(r.Context(), organizationId) + if err != nil { + log.Error(r.Context(), "Failed to make policy violation log", err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/route/route.go b/internal/route/route.go index 2ae34fd1..4ac45ede 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -209,6 +209,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-update", customMiddleware.Handle(internalApi.GetPolicyUpdateDashboard, http.HandlerFunc(dashboardHandler.GetPolicyUpdate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-enforcement", customMiddleware.Handle(internalApi.GetPolicyEnforcementDashboard, http.HandlerFunc(dashboardHandler.GetPolicyEnforcement))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-violation", customMiddleware.Handle(internalApi.GetPolicyViolationDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolation))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-violation-log", customMiddleware.Handle(internalApi.GetPolicyViolationLogDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolationLog))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 4c5494ba..25853cc9 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -38,6 +38,7 @@ type IDashboardUsecase interface { GetPolicyUpdate(ctx context.Context, policyTemplates []policytemplate.TKSPolicyTemplate, policies []policytemplate.TKSPolicy) (domain.DashboardPolicyUpdate, error) GetPolicyEnforcement(ctx context.Context, organizationId string, primaryClusterId string) (*domain.BarChartData, error) GetPolicyViolation(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) + GetPolicyViolationLog(ctx context.Context, organizationId string) (*domain.GetDashboardPolicyViolationLogResponse, error) } type DashboardUsecase struct { @@ -852,6 +853,11 @@ func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationI } +func (u *DashboardUsecase) GetPolicyViolationLog(ctx context.Context, organizationId string) (*domain.GetDashboardPolicyViolationLogResponse, error) { + // TODO Implement me + return nil, nil +} + func (u *DashboardUsecase) GetThanosClient(ctx context.Context, organizationId string) (thanos.ThanosClient, error) { thanosUrl, err := u.getThanosUrl(ctx, organizationId) if err != nil { diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index f9a2ac34..abd8c152 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -210,6 +210,10 @@ type GetDashboardPolicyViolationResponse struct { UpdatedAt time.Time `json:"updatedAt"` } +type GetDashboardPolicyViolationLogResponse struct { + // TODO implement me +} + type BarChart struct { ChartType string `json:"chartType"` OrganizationId string `json:"organizationId"` From 1c001bdfe208e9ebebdfbf69b3b8d28fb975c665 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 17 Apr 2024 15:24:59 +0900 Subject: [PATCH 316/502] policy violation log skeleton code\n endpoint generation --- .../delivery/api/generated_endpoints.go.go | 879 +++++++++--------- 1 file changed, 443 insertions(+), 436 deletions(-) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index f4b0cde2..3d9408fe 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -1,362 +1,362 @@ -// This is generated code. DO NOT EDIT. + // This is generated code. DO NOT EDIT. package api var ApiMap = map[Endpoint]EndpointInfo{ - Login: { - Name: "Login", + Login: { + Name: "Login", Group: "Auth", }, - Logout: { - Name: "Logout", + Logout: { + Name: "Logout", Group: "Auth", }, - RefreshToken: { - Name: "RefreshToken", + RefreshToken: { + Name: "RefreshToken", Group: "Auth", }, - FindId: { - Name: "FindId", + FindId: { + Name: "FindId", Group: "Auth", }, - FindPassword: { - Name: "FindPassword", + FindPassword: { + Name: "FindPassword", Group: "Auth", }, - VerifyIdentityForLostId: { - Name: "VerifyIdentityForLostId", + VerifyIdentityForLostId: { + Name: "VerifyIdentityForLostId", Group: "Auth", }, - VerifyIdentityForLostPassword: { - Name: "VerifyIdentityForLostPassword", + VerifyIdentityForLostPassword: { + Name: "VerifyIdentityForLostPassword", Group: "Auth", }, - VerifyToken: { - Name: "VerifyToken", + VerifyToken: { + Name: "VerifyToken", Group: "Auth", }, - CreateUser: { - Name: "CreateUser", + CreateUser: { + Name: "CreateUser", Group: "User", }, - ListUser: { - Name: "ListUser", + ListUser: { + Name: "ListUser", Group: "User", }, - GetUser: { - Name: "GetUser", + GetUser: { + Name: "GetUser", Group: "User", }, - DeleteUser: { - Name: "DeleteUser", + DeleteUser: { + Name: "DeleteUser", Group: "User", }, - UpdateUsers: { - Name: "UpdateUsers", + UpdateUsers: { + Name: "UpdateUsers", Group: "User", }, - UpdateUser: { - Name: "UpdateUser", + UpdateUser: { + Name: "UpdateUser", Group: "User", }, - ResetPassword: { - Name: "ResetPassword", + ResetPassword: { + Name: "ResetPassword", Group: "User", }, - CheckId: { - Name: "CheckId", + CheckId: { + Name: "CheckId", Group: "User", }, - CheckEmail: { - Name: "CheckEmail", + CheckEmail: { + Name: "CheckEmail", Group: "User", }, - GetPermissionsByAccountId: { - Name: "GetPermissionsByAccountId", + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", Group: "User", }, - GetMyProfile: { - Name: "GetMyProfile", + GetMyProfile: { + Name: "GetMyProfile", Group: "MyProfile", }, - UpdateMyProfile: { - Name: "UpdateMyProfile", + UpdateMyProfile: { + Name: "UpdateMyProfile", Group: "MyProfile", }, - UpdateMyPassword: { - Name: "UpdateMyPassword", + UpdateMyPassword: { + Name: "UpdateMyPassword", Group: "MyProfile", }, - RenewPasswordExpiredDate: { - Name: "RenewPasswordExpiredDate", + RenewPasswordExpiredDate: { + Name: "RenewPasswordExpiredDate", Group: "MyProfile", }, - DeleteMyProfile: { - Name: "DeleteMyProfile", + DeleteMyProfile: { + Name: "DeleteMyProfile", Group: "MyProfile", }, - Admin_CreateOrganization: { - Name: "Admin_CreateOrganization", + Admin_CreateOrganization: { + Name: "Admin_CreateOrganization", Group: "Organization", }, - Admin_DeleteOrganization: { - Name: "Admin_DeleteOrganization", + Admin_DeleteOrganization: { + Name: "Admin_DeleteOrganization", Group: "Organization", }, - GetOrganizations: { - Name: "GetOrganizations", + GetOrganizations: { + Name: "GetOrganizations", Group: "Organization", }, - GetOrganization: { - Name: "GetOrganization", + GetOrganization: { + Name: "GetOrganization", Group: "Organization", }, - CheckOrganizationName: { - Name: "CheckOrganizationName", + CheckOrganizationName: { + Name: "CheckOrganizationName", Group: "Organization", }, - UpdateOrganization: { - Name: "UpdateOrganization", + UpdateOrganization: { + Name: "UpdateOrganization", Group: "Organization", }, - UpdatePrimaryCluster: { - Name: "UpdatePrimaryCluster", + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", Group: "Organization", }, - CreateCluster: { - Name: "CreateCluster", + CreateCluster: { + Name: "CreateCluster", Group: "Cluster", }, - GetClusters: { - Name: "GetClusters", + GetClusters: { + Name: "GetClusters", Group: "Cluster", }, - ImportCluster: { - Name: "ImportCluster", + ImportCluster: { + Name: "ImportCluster", Group: "Cluster", }, - GetCluster: { - Name: "GetCluster", + GetCluster: { + Name: "GetCluster", Group: "Cluster", }, - DeleteCluster: { - Name: "DeleteCluster", + DeleteCluster: { + Name: "DeleteCluster", Group: "Cluster", }, - GetClusterSiteValues: { - Name: "GetClusterSiteValues", + GetClusterSiteValues: { + Name: "GetClusterSiteValues", Group: "Cluster", }, - InstallCluster: { - Name: "InstallCluster", + InstallCluster: { + Name: "InstallCluster", Group: "Cluster", }, - CreateBootstrapKubeconfig: { - Name: "CreateBootstrapKubeconfig", + CreateBootstrapKubeconfig: { + Name: "CreateBootstrapKubeconfig", Group: "Cluster", }, - GetBootstrapKubeconfig: { - Name: "GetBootstrapKubeconfig", + GetBootstrapKubeconfig: { + Name: "GetBootstrapKubeconfig", Group: "Cluster", }, - GetNodes: { - Name: "GetNodes", + GetNodes: { + Name: "GetNodes", Group: "Cluster", }, - CreateAppgroup: { - Name: "CreateAppgroup", + CreateAppgroup: { + Name: "CreateAppgroup", Group: "Appgroup", }, - GetAppgroups: { - Name: "GetAppgroups", + GetAppgroups: { + Name: "GetAppgroups", Group: "Appgroup", }, - GetAppgroup: { - Name: "GetAppgroup", + GetAppgroup: { + Name: "GetAppgroup", Group: "Appgroup", }, - DeleteAppgroup: { - Name: "DeleteAppgroup", + DeleteAppgroup: { + Name: "DeleteAppgroup", Group: "Appgroup", }, - GetApplications: { - Name: "GetApplications", + GetApplications: { + Name: "GetApplications", Group: "Appgroup", }, - CreateApplication: { - Name: "CreateApplication", + CreateApplication: { + Name: "CreateApplication", Group: "Appgroup", }, - GetAppServeAppTasksByAppId: { - Name: "GetAppServeAppTasksByAppId", + GetAppServeAppTasksByAppId: { + Name: "GetAppServeAppTasksByAppId", Group: "AppServeApp", }, - GetAppServeAppTaskDetail: { - Name: "GetAppServeAppTaskDetail", + GetAppServeAppTaskDetail: { + Name: "GetAppServeAppTaskDetail", Group: "AppServeApp", }, - CreateAppServeApp: { - Name: "CreateAppServeApp", + CreateAppServeApp: { + Name: "CreateAppServeApp", Group: "AppServeApp", }, - GetAppServeApps: { - Name: "GetAppServeApps", + GetAppServeApps: { + Name: "GetAppServeApps", Group: "AppServeApp", }, - GetNumOfAppsOnStack: { - Name: "GetNumOfAppsOnStack", + GetNumOfAppsOnStack: { + Name: "GetNumOfAppsOnStack", Group: "AppServeApp", }, - GetAppServeApp: { - Name: "GetAppServeApp", + GetAppServeApp: { + Name: "GetAppServeApp", Group: "AppServeApp", }, - GetAppServeAppLatestTask: { - Name: "GetAppServeAppLatestTask", + GetAppServeAppLatestTask: { + Name: "GetAppServeAppLatestTask", Group: "AppServeApp", }, - IsAppServeAppExist: { - Name: "IsAppServeAppExist", + IsAppServeAppExist: { + Name: "IsAppServeAppExist", Group: "AppServeApp", }, - IsAppServeAppNameExist: { - Name: "IsAppServeAppNameExist", + IsAppServeAppNameExist: { + Name: "IsAppServeAppNameExist", Group: "AppServeApp", }, - DeleteAppServeApp: { - Name: "DeleteAppServeApp", + DeleteAppServeApp: { + Name: "DeleteAppServeApp", Group: "AppServeApp", }, - UpdateAppServeApp: { - Name: "UpdateAppServeApp", + UpdateAppServeApp: { + Name: "UpdateAppServeApp", Group: "AppServeApp", }, - UpdateAppServeAppStatus: { - Name: "UpdateAppServeAppStatus", + UpdateAppServeAppStatus: { + Name: "UpdateAppServeAppStatus", Group: "AppServeApp", }, - UpdateAppServeAppEndpoint: { - Name: "UpdateAppServeAppEndpoint", + UpdateAppServeAppEndpoint: { + Name: "UpdateAppServeAppEndpoint", Group: "AppServeApp", }, - RollbackAppServeApp: { - Name: "RollbackAppServeApp", + RollbackAppServeApp: { + Name: "RollbackAppServeApp", Group: "AppServeApp", }, - GetCloudAccounts: { - Name: "GetCloudAccounts", + GetCloudAccounts: { + Name: "GetCloudAccounts", Group: "CloudAccount", }, - CreateCloudAccount: { - Name: "CreateCloudAccount", + CreateCloudAccount: { + Name: "CreateCloudAccount", Group: "CloudAccount", }, - CheckCloudAccountName: { - Name: "CheckCloudAccountName", + CheckCloudAccountName: { + Name: "CheckCloudAccountName", Group: "CloudAccount", }, - CheckAwsAccountId: { - Name: "CheckAwsAccountId", + CheckAwsAccountId: { + Name: "CheckAwsAccountId", Group: "CloudAccount", }, - GetCloudAccount: { - Name: "GetCloudAccount", + GetCloudAccount: { + Name: "GetCloudAccount", Group: "CloudAccount", }, - UpdateCloudAccount: { - Name: "UpdateCloudAccount", + UpdateCloudAccount: { + Name: "UpdateCloudAccount", Group: "CloudAccount", }, - DeleteCloudAccount: { - Name: "DeleteCloudAccount", + DeleteCloudAccount: { + Name: "DeleteCloudAccount", Group: "CloudAccount", }, - DeleteForceCloudAccount: { - Name: "DeleteForceCloudAccount", + DeleteForceCloudAccount: { + Name: "DeleteForceCloudAccount", Group: "CloudAccount", }, - GetResourceQuota: { - Name: "GetResourceQuota", + GetResourceQuota: { + Name: "GetResourceQuota", Group: "CloudAccount", }, - Admin_GetStackTemplates: { - Name: "Admin_GetStackTemplates", + Admin_GetStackTemplates: { + Name: "Admin_GetStackTemplates", Group: "StackTemplate", }, - Admin_GetStackTemplate: { - Name: "Admin_GetStackTemplate", + Admin_GetStackTemplate: { + Name: "Admin_GetStackTemplate", Group: "StackTemplate", }, - Admin_GetStackTemplateServices: { - Name: "Admin_GetStackTemplateServices", + Admin_GetStackTemplateServices: { + Name: "Admin_GetStackTemplateServices", Group: "StackTemplate", }, - Admin_CreateStackTemplate: { - Name: "Admin_CreateStackTemplate", + Admin_CreateStackTemplate: { + Name: "Admin_CreateStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplate: { - Name: "Admin_UpdateStackTemplate", + Admin_UpdateStackTemplate: { + Name: "Admin_UpdateStackTemplate", Group: "StackTemplate", }, - Admin_DeleteStackTemplate: { - Name: "Admin_DeleteStackTemplate", + Admin_DeleteStackTemplate: { + Name: "Admin_DeleteStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplateOrganizations: { - Name: "Admin_UpdateStackTemplateOrganizations", + Admin_UpdateStackTemplateOrganizations: { + Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, - Admin_CheckStackTemplateName: { - Name: "Admin_CheckStackTemplateName", + Admin_CheckStackTemplateName: { + Name: "Admin_CheckStackTemplateName", Group: "StackTemplate", }, - GetOrganizationStackTemplates: { - Name: "GetOrganizationStackTemplates", + GetOrganizationStackTemplates: { + Name: "GetOrganizationStackTemplates", Group: "StackTemplate", }, - GetOrganizationStackTemplate: { - Name: "GetOrganizationStackTemplate", + GetOrganizationStackTemplate: { + Name: "GetOrganizationStackTemplate", Group: "StackTemplate", }, - AddOrganizationStackTemplates: { - Name: "AddOrganizationStackTemplates", + AddOrganizationStackTemplates: { + Name: "AddOrganizationStackTemplates", Group: "StackTemplate", }, - RemoveOrganizationStackTemplates: { - Name: "RemoveOrganizationStackTemplates", + RemoveOrganizationStackTemplates: { + Name: "RemoveOrganizationStackTemplates", Group: "StackTemplate", }, - CreateDashboard: { - Name: "CreateDashboard", + CreateDashboard: { + Name: "CreateDashboard", Group: "Dashboard", }, - GetDashboard: { - Name: "GetDashboard", + GetDashboard: { + Name: "GetDashboard", Group: "Dashboard", }, - UpdateDashboard: { - Name: "UpdateDashboard", + UpdateDashboard: { + Name: "UpdateDashboard", Group: "Dashboard", }, - GetChartsDashboard: { - Name: "GetChartsDashboard", + GetChartsDashboard: { + Name: "GetChartsDashboard", Group: "Dashboard", }, - GetChartDashboard: { - Name: "GetChartDashboard", + GetChartDashboard: { + Name: "GetChartDashboard", Group: "Dashboard", }, - GetStacksDashboard: { - Name: "GetStacksDashboard", + GetStacksDashboard: { + Name: "GetStacksDashboard", Group: "Dashboard", }, - GetResourcesDashboard: { - Name: "GetResourcesDashboard", + GetResourcesDashboard: { + Name: "GetResourcesDashboard", Group: "Dashboard", }, - GetPolicyStatusDashboard: { - Name: "GetPolicyStatusDashboard", + GetPolicyStatusDashboard: { + Name: "GetPolicyStatusDashboard", Group: "Dashboard", }, GetPolicyUpdateDashboard: { @@ -371,232 +371,236 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyViolationDashboard", Group: "Dashboard", }, + GetPolicyViolationLogDashboard: { + Name: "GetPolicyViolationLogDashboard", + Group: "Dashboard", + }, Admin_CreateSystemNotificationTemplate: { Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_UpdateSystemNotificationTemplate: { - Name: "Admin_UpdateSystemNotificationTemplate", + Admin_UpdateSystemNotificationTemplate: { + Name: "Admin_UpdateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_DeleteSystemNotificationTemplate: { - Name: "Admin_DeleteSystemNotificationTemplate", + Admin_DeleteSystemNotificationTemplate: { + Name: "Admin_DeleteSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplates: { - Name: "Admin_GetSystemNotificationTemplates", + Admin_GetSystemNotificationTemplates: { + Name: "Admin_GetSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplate: { - Name: "Admin_GetSystemNotificationTemplate", + Admin_GetSystemNotificationTemplate: { + Name: "Admin_GetSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_CheckSystemNotificationTemplateName: { - Name: "Admin_CheckSystemNotificationTemplateName", + Admin_CheckSystemNotificationTemplateName: { + Name: "Admin_CheckSystemNotificationTemplateName", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplates: { - Name: "GetOrganizationSystemNotificationTemplates", + GetOrganizationSystemNotificationTemplates: { + Name: "GetOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplate: { - Name: "GetOrganizationSystemNotificationTemplate", + GetOrganizationSystemNotificationTemplate: { + Name: "GetOrganizationSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - AddOrganizationSystemNotificationTemplates: { - Name: "AddOrganizationSystemNotificationTemplates", + AddOrganizationSystemNotificationTemplates: { + Name: "AddOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - RemoveOrganizationSystemNotificationTemplates: { - Name: "RemoveOrganizationSystemNotificationTemplates", + RemoveOrganizationSystemNotificationTemplates: { + Name: "RemoveOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - CreateSystemNotificationRule: { - Name: "CreateSystemNotificationRule", + CreateSystemNotificationRule: { + Name: "CreateSystemNotificationRule", Group: "SystemNotificationRule", }, - GetSystemNotificationRules: { - Name: "GetSystemNotificationRules", + GetSystemNotificationRules: { + Name: "GetSystemNotificationRules", Group: "SystemNotificationRule", }, - GetSystemNotificationRule: { - Name: "GetSystemNotificationRule", + GetSystemNotificationRule: { + Name: "GetSystemNotificationRule", Group: "SystemNotificationRule", }, - CheckSystemNotificationRuleName: { - Name: "CheckSystemNotificationRuleName", + CheckSystemNotificationRuleName: { + Name: "CheckSystemNotificationRuleName", Group: "SystemNotificationRule", }, - DeleteSystemNotificationRule: { - Name: "DeleteSystemNotificationRule", + DeleteSystemNotificationRule: { + Name: "DeleteSystemNotificationRule", Group: "SystemNotificationRule", }, - UpdateSystemNotificationRule: { - Name: "UpdateSystemNotificationRule", + UpdateSystemNotificationRule: { + Name: "UpdateSystemNotificationRule", Group: "SystemNotificationRule", }, - MakeDefaultSystemNotificationRules: { - Name: "MakeDefaultSystemNotificationRules", + MakeDefaultSystemNotificationRules: { + Name: "MakeDefaultSystemNotificationRules", Group: "SystemNotificationRule", }, - CreateSystemNotification: { - Name: "CreateSystemNotification", + CreateSystemNotification: { + Name: "CreateSystemNotification", Group: "SystemNotification", }, - GetSystemNotifications: { - Name: "GetSystemNotifications", + GetSystemNotifications: { + Name: "GetSystemNotifications", Group: "SystemNotification", }, - GetSystemNotification: { - Name: "GetSystemNotification", + GetSystemNotification: { + Name: "GetSystemNotification", Group: "SystemNotification", }, - DeleteSystemNotification: { - Name: "DeleteSystemNotification", + DeleteSystemNotification: { + Name: "DeleteSystemNotification", Group: "SystemNotification", }, - UpdateSystemNotification: { - Name: "UpdateSystemNotification", + UpdateSystemNotification: { + Name: "UpdateSystemNotification", Group: "SystemNotification", }, - CreateSystemNotificationAction: { - Name: "CreateSystemNotificationAction", + CreateSystemNotificationAction: { + Name: "CreateSystemNotificationAction", Group: "SystemNotification", }, - GetStacks: { - Name: "GetStacks", + GetStacks: { + Name: "GetStacks", Group: "Stack", }, - CreateStack: { - Name: "CreateStack", + CreateStack: { + Name: "CreateStack", Group: "Stack", }, - CheckStackName: { - Name: "CheckStackName", + CheckStackName: { + Name: "CheckStackName", Group: "Stack", }, - GetStack: { - Name: "GetStack", + GetStack: { + Name: "GetStack", Group: "Stack", }, - UpdateStack: { - Name: "UpdateStack", + UpdateStack: { + Name: "UpdateStack", Group: "Stack", }, - DeleteStack: { - Name: "DeleteStack", + DeleteStack: { + Name: "DeleteStack", Group: "Stack", }, - GetStackKubeConfig: { - Name: "GetStackKubeConfig", + GetStackKubeConfig: { + Name: "GetStackKubeConfig", Group: "Stack", }, - GetStackStatus: { - Name: "GetStackStatus", + GetStackStatus: { + Name: "GetStackStatus", Group: "Stack", }, - SetFavoriteStack: { - Name: "SetFavoriteStack", + SetFavoriteStack: { + Name: "SetFavoriteStack", Group: "Stack", }, - DeleteFavoriteStack: { - Name: "DeleteFavoriteStack", + DeleteFavoriteStack: { + Name: "DeleteFavoriteStack", Group: "Stack", }, - InstallStack: { - Name: "InstallStack", + InstallStack: { + Name: "InstallStack", Group: "Stack", }, - CreateProject: { - Name: "CreateProject", + CreateProject: { + Name: "CreateProject", Group: "Project", }, - GetProjectRoles: { - Name: "GetProjectRoles", + GetProjectRoles: { + Name: "GetProjectRoles", Group: "Project", }, - GetProjectRole: { - Name: "GetProjectRole", + GetProjectRole: { + Name: "GetProjectRole", Group: "Project", }, - GetProjects: { - Name: "GetProjects", + GetProjects: { + Name: "GetProjects", Group: "Project", }, - GetProject: { - Name: "GetProject", + GetProject: { + Name: "GetProject", Group: "Project", }, - UpdateProject: { - Name: "UpdateProject", + UpdateProject: { + Name: "UpdateProject", Group: "Project", }, - DeleteProject: { - Name: "DeleteProject", + DeleteProject: { + Name: "DeleteProject", Group: "Project", }, - AddProjectMember: { - Name: "AddProjectMember", + AddProjectMember: { + Name: "AddProjectMember", Group: "Project", }, - GetProjectMember: { - Name: "GetProjectMember", + GetProjectMember: { + Name: "GetProjectMember", Group: "Project", }, - GetProjectMembers: { - Name: "GetProjectMembers", + GetProjectMembers: { + Name: "GetProjectMembers", Group: "Project", }, - RemoveProjectMember: { - Name: "RemoveProjectMember", + RemoveProjectMember: { + Name: "RemoveProjectMember", Group: "Project", }, - UpdateProjectMemberRole: { - Name: "UpdateProjectMemberRole", + UpdateProjectMemberRole: { + Name: "UpdateProjectMemberRole", Group: "Project", }, - CreateProjectNamespace: { - Name: "CreateProjectNamespace", + CreateProjectNamespace: { + Name: "CreateProjectNamespace", Group: "Project", }, - GetProjectNamespaces: { - Name: "GetProjectNamespaces", + GetProjectNamespaces: { + Name: "GetProjectNamespaces", Group: "Project", }, - GetProjectNamespace: { - Name: "GetProjectNamespace", + GetProjectNamespace: { + Name: "GetProjectNamespace", Group: "Project", }, - UpdateProjectNamespace: { - Name: "UpdateProjectNamespace", + UpdateProjectNamespace: { + Name: "UpdateProjectNamespace", Group: "Project", }, - DeleteProjectNamespace: { - Name: "DeleteProjectNamespace", + DeleteProjectNamespace: { + Name: "DeleteProjectNamespace", Group: "Project", }, - SetFavoriteProject: { - Name: "SetFavoriteProject", + SetFavoriteProject: { + Name: "SetFavoriteProject", Group: "Project", }, - SetFavoriteProjectNamespace: { - Name: "SetFavoriteProjectNamespace", + SetFavoriteProjectNamespace: { + Name: "SetFavoriteProjectNamespace", Group: "Project", }, - UnSetFavoriteProject: { - Name: "UnSetFavoriteProject", + UnSetFavoriteProject: { + Name: "UnSetFavoriteProject", Group: "Project", }, - UnSetFavoriteProjectNamespace: { - Name: "UnSetFavoriteProjectNamespace", + UnSetFavoriteProjectNamespace: { + Name: "UnSetFavoriteProjectNamespace", Group: "Project", }, - GetProjectKubeconfig: { - Name: "GetProjectKubeconfig", + GetProjectKubeconfig: { + Name: "GetProjectKubeconfig", Group: "Project", }, - GetProjectNamespaceK8sResources: { - Name: "GetProjectNamespaceK8sResources", + GetProjectNamespaceK8sResources: { + Name: "GetProjectNamespaceK8sResources", Group: "Project", }, GetProjectNamespaceKubeconfig: { @@ -607,220 +611,220 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetAudits", Group: "Audit", }, - GetAudit: { - Name: "GetAudit", + GetAudit: { + Name: "GetAudit", Group: "Audit", }, - DeleteAudit: { - Name: "DeleteAudit", + DeleteAudit: { + Name: "DeleteAudit", Group: "Audit", }, - CreateTksRole: { - Name: "CreateTksRole", + CreateTksRole: { + Name: "CreateTksRole", Group: "Role", }, - ListTksRoles: { - Name: "ListTksRoles", + ListTksRoles: { + Name: "ListTksRoles", Group: "Role", }, - GetTksRole: { - Name: "GetTksRole", + GetTksRole: { + Name: "GetTksRole", Group: "Role", }, - DeleteTksRole: { - Name: "DeleteTksRole", + DeleteTksRole: { + Name: "DeleteTksRole", Group: "Role", }, - UpdateTksRole: { - Name: "UpdateTksRole", + UpdateTksRole: { + Name: "UpdateTksRole", Group: "Role", }, - GetPermissionsByRoleId: { - Name: "GetPermissionsByRoleId", + GetPermissionsByRoleId: { + Name: "GetPermissionsByRoleId", Group: "Role", }, - UpdatePermissionsByRoleId: { - Name: "UpdatePermissionsByRoleId", + UpdatePermissionsByRoleId: { + Name: "UpdatePermissionsByRoleId", Group: "Role", }, - IsRoleNameExisted: { - Name: "IsRoleNameExisted", + IsRoleNameExisted: { + Name: "IsRoleNameExisted", Group: "Role", }, - AppendUsersToRole: { - Name: "AppendUsersToRole", + AppendUsersToRole: { + Name: "AppendUsersToRole", Group: "Role", }, - GetUsersInRoleId: { - Name: "GetUsersInRoleId", + GetUsersInRoleId: { + Name: "GetUsersInRoleId", Group: "Role", }, - RemoveUsersFromRole: { - Name: "RemoveUsersFromRole", + RemoveUsersFromRole: { + Name: "RemoveUsersFromRole", Group: "Role", }, - GetPermissionTemplates: { - Name: "GetPermissionTemplates", + GetPermissionTemplates: { + Name: "GetPermissionTemplates", Group: "Permission", }, - Admin_CreateUser: { - Name: "Admin_CreateUser", + Admin_CreateUser: { + Name: "Admin_CreateUser", Group: "Admin_User", }, - Admin_ListUser: { - Name: "Admin_ListUser", + Admin_ListUser: { + Name: "Admin_ListUser", Group: "Admin_User", }, - Admin_GetUser: { - Name: "Admin_GetUser", + Admin_GetUser: { + Name: "Admin_GetUser", Group: "Admin_User", }, - Admin_DeleteUser: { - Name: "Admin_DeleteUser", + Admin_DeleteUser: { + Name: "Admin_DeleteUser", Group: "Admin_User", }, - Admin_UpdateUser: { - Name: "Admin_UpdateUser", + Admin_UpdateUser: { + Name: "Admin_UpdateUser", Group: "Admin_User", }, - Admin_ListTksRoles: { - Name: "Admin_ListTksRoles", + Admin_ListTksRoles: { + Name: "Admin_ListTksRoles", Group: "Admin Role", }, - Admin_GetTksRole: { - Name: "Admin_GetTksRole", + Admin_GetTksRole: { + Name: "Admin_GetTksRole", Group: "Admin Role", }, - Admin_GetProjects: { - Name: "Admin_GetProjects", + Admin_GetProjects: { + Name: "Admin_GetProjects", Group: "Admin Project", }, - Admin_ListPolicyTemplate: { - Name: "Admin_ListPolicyTemplate", + Admin_ListPolicyTemplate: { + Name: "Admin_ListPolicyTemplate", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplate: { - Name: "Admin_CreatePolicyTemplate", + Admin_CreatePolicyTemplate: { + Name: "Admin_CreatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplate: { - Name: "Admin_DeletePolicyTemplate", + Admin_DeletePolicyTemplate: { + Name: "Admin_DeletePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplate: { - Name: "Admin_GetPolicyTemplate", + Admin_GetPolicyTemplate: { + Name: "Admin_GetPolicyTemplate", Group: "PolicyTemplate", }, - Admin_UpdatePolicyTemplate: { - Name: "Admin_UpdatePolicyTemplate", + Admin_UpdatePolicyTemplate: { + Name: "Admin_UpdatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateDeploy: { - Name: "Admin_GetPolicyTemplateDeploy", + Admin_GetPolicyTemplateDeploy: { + Name: "Admin_GetPolicyTemplateDeploy", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateStatistics: { - Name: "Admin_ListPolicyTemplateStatistics", + Admin_ListPolicyTemplateStatistics: { + Name: "Admin_ListPolicyTemplateStatistics", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateVersions: { - Name: "Admin_ListPolicyTemplateVersions", + Admin_ListPolicyTemplateVersions: { + Name: "Admin_ListPolicyTemplateVersions", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplateVersion: { - Name: "Admin_CreatePolicyTemplateVersion", + Admin_CreatePolicyTemplateVersion: { + Name: "Admin_CreatePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplateVersion: { - Name: "Admin_DeletePolicyTemplateVersion", + Admin_DeletePolicyTemplateVersion: { + Name: "Admin_DeletePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateVersion: { - Name: "Admin_GetPolicyTemplateVersion", + Admin_GetPolicyTemplateVersion: { + Name: "Admin_GetPolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateKind: { - Name: "Admin_ExistsPolicyTemplateKind", + Admin_ExistsPolicyTemplateKind: { + Name: "Admin_ExistsPolicyTemplateKind", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateName: { - Name: "Admin_ExistsPolicyTemplateName", + Admin_ExistsPolicyTemplateName: { + Name: "Admin_ExistsPolicyTemplateName", Group: "PolicyTemplate", }, - Admin_ExtractParameters: { - Name: "Admin_ExtractParameters", + Admin_ExtractParameters: { + Name: "Admin_ExtractParameters", Group: "PolicyTemplate", }, - Admin_AddPermittedPolicyTemplatesForOrganization: { - Name: "Admin_AddPermittedPolicyTemplatesForOrganization", + Admin_AddPermittedPolicyTemplatesForOrganization: { + Name: "Admin_AddPermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - Admin_DeletePermittedPolicyTemplatesForOrganization: { - Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", + Admin_DeletePermittedPolicyTemplatesForOrganization: { + Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - ListStackPolicyStatus: { - Name: "ListStackPolicyStatus", + ListStackPolicyStatus: { + Name: "ListStackPolicyStatus", Group: "StackPolicyStatus", }, - GetStackPolicyTemplateStatus: { - Name: "GetStackPolicyTemplateStatus", + GetStackPolicyTemplateStatus: { + Name: "GetStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - UpdateStackPolicyTemplateStatus: { - Name: "UpdateStackPolicyTemplateStatus", + UpdateStackPolicyTemplateStatus: { + Name: "UpdateStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - GetMandatoryPolicies: { - Name: "GetMandatoryPolicies", + GetMandatoryPolicies: { + Name: "GetMandatoryPolicies", Group: "Policy", }, - SetMandatoryPolicies: { - Name: "SetMandatoryPolicies", + SetMandatoryPolicies: { + Name: "SetMandatoryPolicies", Group: "Policy", }, - GetPolicyStatistics: { - Name: "GetPolicyStatistics", + GetPolicyStatistics: { + Name: "GetPolicyStatistics", Group: "Policy", }, - ListPolicy: { - Name: "ListPolicy", + ListPolicy: { + Name: "ListPolicy", Group: "Policy", }, - CreatePolicy: { - Name: "CreatePolicy", + CreatePolicy: { + Name: "CreatePolicy", Group: "Policy", }, - DeletePolicy: { - Name: "DeletePolicy", + DeletePolicy: { + Name: "DeletePolicy", Group: "Policy", }, - GetPolicy: { - Name: "GetPolicy", + GetPolicy: { + Name: "GetPolicy", Group: "Policy", }, - UpdatePolicy: { - Name: "UpdatePolicy", + UpdatePolicy: { + Name: "UpdatePolicy", Group: "Policy", }, - UpdatePolicyTargetClusters: { - Name: "UpdatePolicyTargetClusters", + UpdatePolicyTargetClusters: { + Name: "UpdatePolicyTargetClusters", Group: "Policy", }, - ExistsPolicyName: { - Name: "ExistsPolicyName", + ExistsPolicyName: { + Name: "ExistsPolicyName", Group: "Policy", }, - GetPolicyEdit: { - Name: "GetPolicyEdit", + GetPolicyEdit: { + Name: "GetPolicyEdit", Group: "Policy", }, - AddPoliciesForStack: { - Name: "AddPoliciesForStack", + AddPoliciesForStack: { + Name: "AddPoliciesForStack", Group: "Policy", }, - DeletePoliciesForStack: { - Name: "DeletePoliciesForStack", + DeletePoliciesForStack: { + Name: "DeletePoliciesForStack", Group: "Policy", }, StackPolicyStatistics: { @@ -831,80 +835,79 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplate: { - Name: "CreatePolicyTemplate", + CreatePolicyTemplate: { + Name: "CreatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplate: { - Name: "DeletePolicyTemplate", + DeletePolicyTemplate: { + Name: "DeletePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplate: { - Name: "GetPolicyTemplate", + GetPolicyTemplate: { + Name: "GetPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - UpdatePolicyTemplate: { - Name: "UpdatePolicyTemplate", + UpdatePolicyTemplate: { + Name: "UpdatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateDeploy: { - Name: "GetPolicyTemplateDeploy", + GetPolicyTemplateDeploy: { + Name: "GetPolicyTemplateDeploy", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateStatistics: { - Name: "ListPolicyTemplateStatistics", + ListPolicyTemplateStatistics: { + Name: "ListPolicyTemplateStatistics", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateVersions: { - Name: "ListPolicyTemplateVersions", + ListPolicyTemplateVersions: { + Name: "ListPolicyTemplateVersions", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplateVersion: { - Name: "CreatePolicyTemplateVersion", + CreatePolicyTemplateVersion: { + Name: "CreatePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplateVersion: { - Name: "DeletePolicyTemplateVersion", + DeletePolicyTemplateVersion: { + Name: "DeletePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateVersion: { - Name: "GetPolicyTemplateVersion", + GetPolicyTemplateVersion: { + Name: "GetPolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateKind: { - Name: "ExistsPolicyTemplateKind", + ExistsPolicyTemplateKind: { + Name: "ExistsPolicyTemplateKind", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateName: { - Name: "ExistsPolicyTemplateName", + ExistsPolicyTemplateName: { + Name: "ExistsPolicyTemplateName", Group: "OrganizationPolicyTemplate", }, - ExtractParameters: { - Name: "ExtractParameters", + ExtractParameters: { + Name: "ExtractParameters", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateExample: { - Name: "ListPolicyTemplateExample", + ListPolicyTemplateExample: { + Name: "ListPolicyTemplateExample", Group: "PolicyTemplateExample", }, - GetPolicyTemplateExample: { - Name: "GetPolicyTemplateExample", + GetPolicyTemplateExample: { + Name: "GetPolicyTemplateExample", Group: "PolicyTemplateExample", }, - UpdatePolicyTemplateExample: { - Name: "UpdatePolicyTemplateExample", + UpdatePolicyTemplateExample: { + Name: "UpdatePolicyTemplateExample", Group: "PolicyTemplateExample", }, - DeletePolicyTemplateExample: { - Name: "DeletePolicyTemplateExample", + DeletePolicyTemplateExample: { + Name: "DeletePolicyTemplateExample", Group: "PolicyTemplateExample", }, - CompileRego: { - Name: "CompileRego", + CompileRego: { + Name: "CompileRego", Group: "Utility", }, } - func (e Endpoint) String() string { switch e { case Login: @@ -1091,6 +1094,8 @@ func (e Endpoint) String() string { return "GetPolicyEnforcementDashboard" case GetPolicyViolationDashboard: return "GetPolicyViolationDashboard" + case GetPolicyViolationLogDashboard: + return "GetPolicyViolationLogDashboard" case Admin_CreateSystemNotificationTemplate: return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: @@ -1547,6 +1552,8 @@ func GetEndpoint(name string) Endpoint { return GetPolicyEnforcementDashboard case "GetPolicyViolationDashboard": return GetPolicyViolationDashboard + case "GetPolicyViolationLogDashboard": + return GetPolicyViolationLogDashboard case "Admin_CreateSystemNotificationTemplate": return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": From b63b8fa23d3c2c9f669316191ae4bbaad9fa8472 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Wed, 17 Apr 2024 15:25:41 +0900 Subject: [PATCH 317/502] policy violation log skeleton code\n swagger generation --- api/swagger/docs.go | 142 ++++++++++++++++++++++++++++++++++----- api/swagger/swagger.json | 142 ++++++++++++++++++++++++++++++++++----- api/swagger/swagger.yaml | 95 ++++++++++++++++++++++---- 3 files changed, 329 insertions(+), 50 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 7284a6f2..417ada03 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3435,7 +3435,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Get the number of policy violation", + "description": "Get the number of policy enforcement", "consumes": [ "application/json" ], @@ -3445,7 +3445,7 @@ const docTemplate = `{ "tags": [ "Dashboard Widgets" ], - "summary": "Get the number of policy violation", + "summary": "Get the number of policy enforcement", "parameters": [ { "type": "string", @@ -3453,27 +3453,13 @@ const docTemplate = `{ "name": "organizationId", "in": "path", "required": true - }, - { - "type": "string", - "description": "duration", - "name": "duration", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse" } } } @@ -3553,6 +3539,94 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/dashboards/policy-violation": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get the number of policy violation", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get the number of policy violation", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboards/policy-violation-log": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get policy violation log", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get policy violation log", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboards/resources": { "get": { "security": [ @@ -10637,7 +10711,7 @@ const docTemplate = `{ "type": "string" }, "user": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles" } } }, @@ -12440,6 +12514,9 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse": { + "type": "object" + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse": { "type": "object", "properties": { @@ -14344,6 +14421,32 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackConfResponse": { "type": "object", "required": [ @@ -14820,6 +14923,9 @@ const docTemplate = `{ "notificationType": { "type": "string" }, + "status": { + "type": "string" + }, "systemNotificationCondition": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 246aed8f..562ac8b3 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3429,7 +3429,7 @@ "JWT": [] } ], - "description": "Get the number of policy violation", + "description": "Get the number of policy enforcement", "consumes": [ "application/json" ], @@ -3439,7 +3439,7 @@ "tags": [ "Dashboard Widgets" ], - "summary": "Get the number of policy violation", + "summary": "Get the number of policy enforcement", "parameters": [ { "type": "string", @@ -3447,27 +3447,13 @@ "name": "organizationId", "in": "path", "required": true - }, - { - "type": "string", - "description": "duration", - "name": "duration", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "interval", - "name": "interval", - "in": "query", - "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse" } } } @@ -3547,6 +3533,94 @@ } } }, + "/organizations/{organizationId}/dashboards/policy-violation": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get the number of policy violation", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get the number of policy violation", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse" + } + } + } + } + }, + "/organizations/{organizationId}/dashboards/policy-violation-log": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get policy violation log", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get policy violation log", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboards/resources": { "get": { "security": [ @@ -10631,7 +10705,7 @@ "type": "string" }, "user": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles" } } }, @@ -12434,6 +12508,9 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse": { + "type": "object" + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse": { "type": "object", "properties": { @@ -14338,6 +14415,32 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + }, + "department": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackConfResponse": { "type": "object", "required": [ @@ -14814,6 +14917,9 @@ "notificationType": { "type": "string" }, + "status": { + "type": "string" + }, "systemNotificationCondition": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 81edc270..a287656b 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -507,7 +507,7 @@ definitions: updatedAt: type: string user: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles' type: object github_com_openinfradev_tks-api_pkg_domain.Axis: properties: @@ -1712,6 +1712,8 @@ definitions: updatedResources: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate' type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse: + type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse: properties: chartData: @@ -2970,6 +2972,23 @@ definitions: name: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles: + properties: + accountId: + type: string + department: + type: string + email: + type: string + id: + type: string + name: + type: string + roles: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.StackConfResponse: properties: tksCpNode: @@ -3288,6 +3307,8 @@ definitions: type: string notificationType: type: string + status: + type: string systemNotificationCondition: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse' systemNotificationTemplate: @@ -6396,33 +6417,23 @@ paths: get: consumes: - application/json - description: Get the number of policy violation + description: Get the number of policy enforcement parameters: - description: Organization ID in: path name: organizationId required: true type: string - - description: duration - in: query - name: duration - required: true - type: string - - description: interval - in: query - name: interval - required: true - type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyEnforcementResponse' security: - JWT: [] - summary: Get the number of policy violation + summary: Get the number of policy enforcement tags: - Dashboard Widgets /organizations/{organizationId}/dashboards/policy-status: @@ -6471,6 +6482,62 @@ paths: summary: Get the number of policytemplates that need to be updated tags: - Dashboard Widgets + /organizations/{organizationId}/dashboards/policy-violation: + get: + consumes: + - application/json + description: Get the number of policy violation + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: duration + in: query + name: duration + required: true + type: string + - description: interval + in: query + name: interval + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse' + security: + - JWT: [] + summary: Get the number of policy violation + tags: + - Dashboard Widgets + /organizations/{organizationId}/dashboards/policy-violation-log: + get: + consumes: + - application/json + description: Get policy violation log + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse' + security: + - JWT: [] + summary: Get policy violation log + tags: + - Dashboard Widgets /organizations/{organizationId}/dashboards/resources: get: consumes: From c9c70ec137382a0f0ae4acd935807f7a8850d15d Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 17 Apr 2024 17:24:44 +0900 Subject: [PATCH 318/502] trivial. fix filters --- go.mod | 3 ++- go.sum | 2 ++ internal/pagination/pagination.go | 5 ++--- internal/repository/organization.go | 13 ++++++++++++- internal/repository/policy.go | 2 +- .../repository/system-notification-rule.go | 18 ++++++++++++++---- internal/repository/user.go | 1 - 7 files changed, 33 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index d4c63026..1b0c3724 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/gorilla/handlers v1.5.2 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 + github.com/iancoleman/strcase v0.3.0 github.com/open-policy-agent/opa v0.62.1 github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible @@ -41,7 +42,6 @@ require ( golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/net v0.22.0 golang.org/x/oauth2 v0.17.0 - golang.org/x/text v0.14.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v3 v3.0.1 gorm.io/datatypes v1.2.0 @@ -130,6 +130,7 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.15.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect diff --git a/go.sum b/go.sum index eb9fc3f4..ba79e3e7 100644 --- a/go.sum +++ b/go.sum @@ -188,6 +188,8 @@ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZH github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 84d93fe3..43feb12f 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -6,13 +6,12 @@ import ( "strconv" "strings" + "github.com/iancoleman/strcase" filter "github.com/openinfradev/tks-api/internal/filter" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/log" - "golang.org/x/text/cases" - "golang.org/x/text/language" "gorm.io/gorm" "goyave.dev/goyave/v4" @@ -210,7 +209,7 @@ func NewPagination(urlParams *url.Values) *Pagination { releation := "" arrColumns := strings.Split(column, ".") if len(arrColumns) > 1 { - releation = cases.Title(language.English, cases.Compact).String(arrColumns[0]) + releation = strcase.ToCamel(arrColumns[0]) column = arrColumns[1] } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 7949bd35..146227fd 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -85,7 +85,18 @@ func (r *OrganizationRepository) Fetch(ctx context.Context, pg *pagination.Pagin pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations), &out) + db := r.db.WithContext(ctx).Preload(clause.Associations).Model(&model.Organization{}) + + // [TODO] more pretty! + for _, filter := range pg.Filters { + if filter.Relation == "Admin" { + db = db.Joins("left outer join users on users.id::text = organizations.admin_id::text"). + Where("users.name like ?", "%"+filter.Values[0]+"%") + break + } + } + + _, res := pg.Fetch(db, &out) if res.Error != nil { return nil, res.Error } diff --git a/internal/repository/policy.go b/internal/repository/policy.go index ca0e3cd1..966ab5b8 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -94,7 +94,7 @@ func (r *PolicyRepository) Fetch(ctx context.Context, organizationId string, pg } _, res := pg.Fetch(r.db.WithContext(ctx).Preload(clause.Associations). - Where("organization_id = ?", organizationId), &out) + Where("policies.organization_id = ?", organizationId), &out) if res.Error != nil { return nil, res.Error diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index ce29f0d3..209c29d9 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -69,10 +69,20 @@ func (r *SystemNotificationRuleRepository) FetchWithOrganization(ctx context.Con pg = pagination.NewPagination(nil) } - _, res := pg.Fetch( - r.db.WithContext(ctx).Preload(clause.Associations). - Where("organization_id = ?", organizationId), - &out) + db := r.db.WithContext(ctx).Preload(clause.Associations).Model(&model.SystemNotificationRule{}). + Where("system_notification_rules.organization_id = ?", organizationId) + + // [TODO] more pretty! + for _, filter := range pg.Filters { + if filter.Relation == "TargetUsers" { + db = db.Joins("left outer join system_notification_rule_users on system_notification_rules.id = system_notification_rule_users.system_notification_rule_id"). + Joins("left outer join users on system_notification_rule_users.user_id = users.id"). + Where("users.name like ?", "%"+filter.Values[0]+"%") + break + } + } + + _, res := pg.Fetch(db, &out) if res.Error != nil { return nil, res.Error } diff --git a/internal/repository/user.go b/internal/repository/user.go index 839f9b37..72a129df 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -126,7 +126,6 @@ func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination. // [TODO] more pretty! for _, filter := range pg.Filters { - log.Info(ctx, "KTKFREE ", filter.Relation) if filter.Relation == "Roles" { db = db.Where("id IN (SELECT user_id FROM user_roles WHERE name IN ?)", filter.Values) break From 8da2a68d35feb345bc90e977607c11b7c01159f1 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Wed, 17 Apr 2024 18:27:57 +0900 Subject: [PATCH 319/502] app-serving: add cluster name to app response --- internal/repository/app-serve-app.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 175fec41..090df5f6 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -153,6 +153,7 @@ func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(ctx context.Context, func (r *AppServeAppRepository) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { var task model.AppServeAppTask var app model.AppServeApp + var cluster model.Cluster // Retrieve task info res := r.db.WithContext(ctx).Where("id = ?", taskId).First(&task) @@ -174,6 +175,10 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(ctx context.Context, task return nil, nil, fmt.Errorf("Couldn't find app with ID %s associated with task %s", app.ID, taskId) } + // Add cluster name to app object + r.db.WithContext(ctx).Select("name").Where("id = ?", app.TargetClusterId).First(&cluster) + app.TargetClusterName = cluster.Name + return &task, &app, nil } From 47356b60af7da0253910caec6325ebd662ed9301 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 18 Apr 2024 09:36:11 +0900 Subject: [PATCH 320/502] policy statistics widget --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/dashboard.go | 39 +++++++++++++++++++++++++++++ internal/route/route.go | 1 + pkg/domain/dashboard.go | 4 +++ 4 files changed, 45 insertions(+) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index f8ddc546..d5993f19 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -122,6 +122,7 @@ const ( GetPolicyEnforcementDashboard GetPolicyViolationDashboard GetPolicyViolationLogDashboard + GetPolicyStatisticsDashboard // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 370368b5..c4502458 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -29,17 +29,20 @@ type IDashboardHandler interface { GetPolicyEnforcement(w http.ResponseWriter, r *http.Request) GetPolicyViolation(w http.ResponseWriter, r *http.Request) GetPolicyViolationLog(w http.ResponseWriter, r *http.Request) + GetPolicyStatistics(w http.ResponseWriter, r *http.Request) } type DashboardHandler struct { usecase usecase.IDashboardUsecase organizationUsecase usecase.IOrganizationUsecase + policyUsecase usecase.IPolicyUsecase } func NewDashboardHandler(h usecase.Usecase) IDashboardHandler { return &DashboardHandler{ usecase: h.Dashboard, organizationUsecase: h.Organization, + policyUsecase: h.Policy, } } @@ -652,3 +655,39 @@ func (h *DashboardHandler) GetPolicyViolationLog(w http.ResponseWriter, r *http. ResponseJSON(w, r, http.StatusOK, out) } + +// GetPolicyStatistics godoc +// +// @Tags Dashboard Widgets +// @Summary Get policy violation log +// @Description Get policy violation log +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetDashboardPolicyStatisticsResponse +// @Router /organizations/{organizationId}/dashboards/policy-statistics [get] +// @Security JWT +func (h *DashboardHandler) GetPolicyStatistics(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + psr, err := h.policyUsecase.GetPolicyStatistics(r.Context(), organizationId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) + return + } + + ErrorJSON(w, r, err) + return + } + out := domain.GetDashboardPolicyStatisticsResponse{PolicyStatisticsResponse: *psr} + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/route/route.go b/internal/route/route.go index 4ac45ede..b7aa0014 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -210,6 +210,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-enforcement", customMiddleware.Handle(internalApi.GetPolicyEnforcementDashboard, http.HandlerFunc(dashboardHandler.GetPolicyEnforcement))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-violation", customMiddleware.Handle(internalApi.GetPolicyViolationDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolation))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-violation-log", customMiddleware.Handle(internalApi.GetPolicyViolationLogDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolationLog))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-statistics", customMiddleware.Handle(internalApi.GetPolicyStatisticsDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatistics))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index abd8c152..52571d9a 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -214,6 +214,10 @@ type GetDashboardPolicyViolationLogResponse struct { // TODO implement me } +type GetDashboardPolicyStatisticsResponse struct { + PolicyStatisticsResponse +} + type BarChart struct { ChartType string `json:"chartType"` OrganizationId string `json:"organizationId"` From c4fd13f2b0eab9b8c36ce61b9979901e6e569f1d Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 18 Apr 2024 09:36:39 +0900 Subject: [PATCH 321/502] policy statistics widget\n endpoint generate --- internal/delivery/api/generated_endpoints.go.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 3d9408fe..210b5f5f 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -375,6 +375,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyViolationLogDashboard", Group: "Dashboard", }, + GetPolicyStatisticsDashboard: { + Name: "GetPolicyStatisticsDashboard", + Group: "Dashboard", + }, Admin_CreateSystemNotificationTemplate: { Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", @@ -1096,6 +1100,8 @@ func (e Endpoint) String() string { return "GetPolicyViolationDashboard" case GetPolicyViolationLogDashboard: return "GetPolicyViolationLogDashboard" + case GetPolicyStatisticsDashboard: + return "GetPolicyStatisticsDashboard" case Admin_CreateSystemNotificationTemplate: return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: @@ -1554,6 +1560,8 @@ func GetEndpoint(name string) Endpoint { return GetPolicyViolationDashboard case "GetPolicyViolationLogDashboard": return GetPolicyViolationLogDashboard + case "GetPolicyStatisticsDashboard": + return GetPolicyStatisticsDashboard case "Admin_CreateSystemNotificationTemplate": return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": From a37e475987dfb62f43d7c3a59d23a6635ffed4e7 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 18 Apr 2024 09:37:27 +0900 Subject: [PATCH 322/502] policy statistics widget\n swagger generate --- api/swagger/docs.go | 48 ++++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.json | 48 ++++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 30 +++++++++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 417ada03..76083cf8 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3465,6 +3465,43 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/dashboards/policy-statistics": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get policy violation log", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get policy violation log", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatisticsResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboards/policy-status": { "get": { "security": [ @@ -12498,6 +12535,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatisticsResponse": { + "type": "object", + "properties": { + "policyCount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyCount" + }, + "templateCount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateCount" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 562ac8b3..571fc537 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3459,6 +3459,43 @@ } } }, + "/organizations/{organizationId}/dashboards/policy-statistics": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get policy violation log", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get policy violation log", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatisticsResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboards/policy-status": { "get": { "security": [ @@ -12492,6 +12529,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatisticsResponse": { + "type": "object", + "properties": { + "policyCount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyCount" + }, + "templateCount": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateCount" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index a287656b..ce6b4b7f 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1702,6 +1702,13 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatisticsResponse: + properties: + policyCount: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyCount' + templateCount: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.TemplateCount' + type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatusResponse: properties: statuses: @@ -6436,6 +6443,29 @@ paths: summary: Get the number of policy enforcement tags: - Dashboard Widgets + /organizations/{organizationId}/dashboards/policy-statistics: + get: + consumes: + - application/json + description: Get policy violation log + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyStatisticsResponse' + security: + - JWT: [] + summary: Get policy violation log + tags: + - Dashboard Widgets /organizations/{organizationId}/dashboards/policy-status: get: consumes: From 30e17ec023d5fdda479cf4b8ec42e768bb987907 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 18 Apr 2024 11:03:02 +0900 Subject: [PATCH 323/502] trivial. fix validation --- api/swagger/docs.go | 6 ++---- api/swagger/swagger.json | 6 ++---- api/swagger/swagger.yaml | 6 ++---- pkg/domain/stack-template.go | 4 ++-- pkg/domain/stack.go | 2 +- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 417ada03..007bc934 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -11729,8 +11729,7 @@ const docTemplate = `{ "type": "string", "enum": [ "AWS", - "AZZURE", - "GCP" + "BYOH" ] }, "description": { @@ -15520,8 +15519,7 @@ const docTemplate = `{ "type": "string", "enum": [ "AWS", - "AZZURE", - "GCP" + "BYOH" ] }, "description": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 562ac8b3..88a7691d 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -11723,8 +11723,7 @@ "type": "string", "enum": [ "AWS", - "AZZURE", - "GCP" + "BYOH" ] }, "description": { @@ -15514,8 +15513,7 @@ "type": "string", "enum": [ "AWS", - "AZZURE", - "GCP" + "BYOH" ] }, "description": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index a287656b..1310db49 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1186,8 +1186,7 @@ definitions: cloudService: enum: - AWS - - AZZURE - - GCP + - BYOH type: string description: type: string @@ -3700,8 +3699,7 @@ definitions: cloudService: enum: - AWS - - AZZURE - - GCP + - BYOH type: string description: type: string diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index b4287d7d..ae1cb4da 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -65,7 +65,7 @@ type CreateStackTemplateRequest struct { Name string `json:"name" validate:"required,name"` Description string `json:"description"` Version string `json:"version" validate:"required"` - CloudService string `json:"cloudService" validate:"oneof=AWS AZZURE GCP"` + CloudService string `json:"cloudService" validate:"oneof=AWS BYOH"` Platform string `json:"platform" validate:"required"` TemplateType string `json:"templateType" validate:"oneof=STANDARD MSA"` Template string `json:"template" validate:"required"` @@ -82,7 +82,7 @@ type CreateStackTemplateResponse struct { type UpdateStackTemplateRequest struct { Description string `json:"description"` Version string `json:"version" validate:"required"` - CloudService string `json:"cloudService" validate:"oneof=AWS AZZURE GCP"` + CloudService string `json:"cloudService" validate:"oneof=AWS BYOH"` Platform string `json:"platform" validate:"required"` TemplateType string `json:"templateType" validate:"oneof=STANDARD MSA"` Template string `json:"template" validate:"required"` diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 82cb8e66..37f9de81 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -65,7 +65,7 @@ func (m StackStatus) FromString(s string) StackStatus { return StackStatus_PENDING } -const MAX_STEP_CLUSTER_CREATE = 24 +const MAX_STEP_CLUSTER_CREATE = 26 const MAX_STEP_CLUSTER_REMOVE = 14 const MAX_STEP_LMA_CREATE_PRIMARY = 39 const MAX_STEP_LMA_CREATE_MEMBER = 29 From 0bdc93b96917be3f865f0d41d2bb2e41b106fab9 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 18 Apr 2024 13:32:11 +0900 Subject: [PATCH 324/502] change dashboard and widget path --- internal/delivery/http/dashboard.go | 51 +++++++++++++++++++---------- internal/model/dashboard.go | 1 + internal/repository/dashboard.go | 6 ++-- internal/route/route.go | 24 +++++++------- internal/usecase/dashboard.go | 6 ++-- pkg/domain/dashboard.go | 11 +++++-- 6 files changed, 60 insertions(+), 39 deletions(-) diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index c4502458..66a5d670 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -67,12 +67,12 @@ func (h *DashboardHandler) CreateDashboard(w http.ResponseWriter, r *http.Reques return } - var dashboardReq []domain.CreateDashboardRequest + var dashboardReq domain.CreateDashboardRequest if err := UnmarshalRequestInput(r, &dashboardReq); err != nil { ErrorJSON(w, r, err) return } - content, err := MarshalToString(r.Context(), dashboardReq) + content, err := MarshalToString(r.Context(), dashboardReq.Contents) if err != nil { ErrorJSON(w, r, err) return @@ -85,7 +85,7 @@ func (h *DashboardHandler) CreateDashboard(w http.ResponseWriter, r *http.Reques } userId := requestUserInfo.GetUserId() - dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId.String()) + dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId.String(), dashboardReq.DashboardKey) if err == nil && dashboard != nil { log.Error(r.Context(), "Dashboard already exists") ResponseJSON(w, r, http.StatusInternalServerError, "Dashboard already exists") @@ -95,6 +95,7 @@ func (h *DashboardHandler) CreateDashboard(w http.ResponseWriter, r *http.Reques dashboard = &model.Dashboard{ OrganizationId: organizationId, UserId: userId, + Key: dashboardReq.DashboardKey, Content: content, IsAdmin: false, } @@ -118,8 +119,9 @@ func (h *DashboardHandler) CreateDashboard(w http.ResponseWriter, r *http.Reques // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param dashboardKey path string true "Dashboard Key" // @Success 200 {array} domain.GetDashboardResponse -// @Router /organizations/{organizationId}/dashboards [get] +// @Router /organizations/{organizationId}/dashboards/{dashboardKey} [get] // @Security JWT func (h *DashboardHandler) GetDashboard(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -129,6 +131,13 @@ func (h *DashboardHandler) GetDashboard(w http.ResponseWriter, r *http.Request) "C_INVALID_ORGANIZATION_ID", "")) return } + dashboardKey, ok := vars["dashboardKey"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid dashboardKey", dashboardKey), + "", "")) + return + } + requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { log.Error(r.Context(), "Failed to retrieve user info from request") @@ -136,7 +145,7 @@ func (h *DashboardHandler) GetDashboard(w http.ResponseWriter, r *http.Request) } userId := requestUserInfo.GetUserId().String() - dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId) + dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId, dashboardKey) if err != nil { log.Error(r.Context(), "Failed to retrieve dashboard", err) ErrorJSON(w, r, err) @@ -168,7 +177,7 @@ func (h *DashboardHandler) GetDashboard(w http.ResponseWriter, r *http.Request) // @Param organizationId path string true "Organization ID" // @Param request body domain.UpdateDashboardRequest true "Request body to update dashboard" // @Success 200 {object} domain.CommonDashboardResponse -// @Router /organizations/{organizationId}/dashboards [put] +// @Router /organizations/{organizationId}/dashboards/{dashboardKey} [put] // @Security JWT func (h *DashboardHandler) UpdateDashboard(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -178,8 +187,14 @@ func (h *DashboardHandler) UpdateDashboard(w http.ResponseWriter, r *http.Reques "C_INVALID_ORGANIZATION_ID", "")) return } + dashboardKey, ok := vars["dashboardKey"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid dashboardKey", dashboardKey), + "", "")) + return + } - var dashboardReq []domain.CreateDashboardRequest + var dashboardReq []domain.UpdateDashboardRequest if err := UnmarshalRequestInput(r, &dashboardReq); err != nil { ErrorJSON(w, r, err) return @@ -197,7 +212,7 @@ func (h *DashboardHandler) UpdateDashboard(w http.ResponseWriter, r *http.Reques } userId := requestUserInfo.GetUserId().String() - dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId) + dashboard, err := h.usecase.GetDashboard(r.Context(), organizationId, userId, dashboardKey) if err != nil || dashboard == nil { log.Error(r.Context(), "Failed to retrieve dashboard", err) ErrorJSON(w, r, err) @@ -224,7 +239,7 @@ func (h *DashboardHandler) UpdateDashboard(w http.ResponseWriter, r *http.Reques // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardChartsResponse -// @Router /organizations/{organizationId}/dashboards/charts [get] +// @Router /organizations/{organizationId}/dashboards/widgets/charts [get] // @Security JWT func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -284,7 +299,7 @@ func (h *DashboardHandler) GetCharts(w http.ResponseWriter, r *http.Request) { // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardChartResponse -// @Router /organizations/{organizationId}/dashboards/charts/{chartType} [get] +// @Router /organizations/{organizationId}/dashboards/widgets/charts/{chartType} [get] // @Security JWT func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -358,7 +373,7 @@ func (h *DashboardHandler) GetChart(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetDashboardStacksResponse -// @Router /organizations/{organizationId}/dashboards/stacks [get] +// @Router /organizations/{organizationId}/dashboards/widgets/stacks [get] // @Security JWT func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -400,7 +415,7 @@ func (h *DashboardHandler) GetStacks(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "organizationId" // @Success 200 {object} domain.GetDashboardResourcesResponse -// @Router /organizations/{organizationId}/dashboards/resources [get] +// @Router /organizations/{organizationId}/dashboards/widgets/resources [get] // @Security JWT func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -436,7 +451,7 @@ func (h *DashboardHandler) GetResources(w http.ResponseWriter, r *http.Request) // @Produce json // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.GetDashboardPolicyStatusResponse -// @Router /organizations/{organizationId}/dashboards/policy-status [get] +// @Router /organizations/{organizationId}/dashboards/widgets/policy-status [get] // @Security JWT func (h *DashboardHandler) GetPolicyStatus(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -489,7 +504,7 @@ func (h *DashboardHandler) GetPolicyStatus(w http.ResponseWriter, r *http.Reques // @Produce json // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.GetDashboardPolicyUpdateResponse -// @Router /organizations/{organizationId}/dashboards/policy-update [get] +// @Router /organizations/{organizationId}/dashboards/widgets/policy-update [get] // @Security JWT func (h *DashboardHandler) GetPolicyUpdate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -541,7 +556,7 @@ func (h *DashboardHandler) GetPolicyUpdate(w http.ResponseWriter, r *http.Reques // @Produce json // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.GetDashboardPolicyEnforcementResponse -// @Router /organizations/{organizationId}/dashboards/policy-enforcement [get] +// @Router /organizations/{organizationId}/dashboards/widgets/policy-enforcement [get] // @Security JWT func (h *DashboardHandler) GetPolicyEnforcement(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -587,7 +602,7 @@ func (h *DashboardHandler) GetPolicyEnforcement(w http.ResponseWriter, r *http.R // @Param duration query string true "duration" // @Param interval query string true "interval" // @Success 200 {object} domain.GetDashboardPolicyViolationResponse -// @Router /organizations/{organizationId}/dashboards/policy-violation [get] +// @Router /organizations/{organizationId}/dashboards/widgets/policy-violation [get] // @Security JWT func (h *DashboardHandler) GetPolicyViolation(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -635,7 +650,7 @@ func (h *DashboardHandler) GetPolicyViolation(w http.ResponseWriter, r *http.Req // @Produce json // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.GetDashboardPolicyViolationLogResponse -// @Router /organizations/{organizationId}/dashboards/policy-violation-log [get] +// @Router /organizations/{organizationId}/dashboards/widgets/policy-violation-log [get] // @Security JWT func (h *DashboardHandler) GetPolicyViolationLog(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -665,7 +680,7 @@ func (h *DashboardHandler) GetPolicyViolationLog(w http.ResponseWriter, r *http. // @Produce json // @Param organizationId path string true "Organization ID" // @Success 200 {object} domain.GetDashboardPolicyStatisticsResponse -// @Router /organizations/{organizationId}/dashboards/policy-statistics [get] +// @Router /organizations/{organizationId}/dashboards/widgets/policy-statistics [get] // @Security JWT func (h *DashboardHandler) GetPolicyStatistics(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/model/dashboard.go b/internal/model/dashboard.go index f4781338..cb60fac8 100644 --- a/internal/model/dashboard.go +++ b/internal/model/dashboard.go @@ -10,6 +10,7 @@ type Dashboard struct { ID uuid.UUID `gorm:"primarykey;type:uuid"` OrganizationId string `gorm:"type:varchar(36)"` UserId uuid.UUID + Key string Content string IsAdmin bool `gorm:"default:false"` } diff --git a/internal/repository/dashboard.go b/internal/repository/dashboard.go index e5a078e1..3b2b5713 100644 --- a/internal/repository/dashboard.go +++ b/internal/repository/dashboard.go @@ -11,7 +11,7 @@ import ( type IDashboardRepository interface { CreateDashboard(ctx context.Context, d *model.Dashboard) (string, error) GetDashboardById(ctx context.Context, organizationId string, dashboardId string) (*model.Dashboard, error) - GetDashboardByUserId(ctx context.Context, organizationId string, userId string) (*model.Dashboard, error) + GetDashboardByUserId(ctx context.Context, organizationId string, userId string, dashboardKey string) (*model.Dashboard, error) UpdateDashboard(ctx context.Context, d *model.Dashboard) error } @@ -51,9 +51,9 @@ func (dr DashboardRepository) GetDashboardById(ctx context.Context, organization return d, nil } -func (dr DashboardRepository) GetDashboardByUserId(ctx context.Context, organizationId string, userId string) (d *model.Dashboard, err error) { +func (dr DashboardRepository) GetDashboardByUserId(ctx context.Context, organizationId string, userId string, dashboardKey string) (d *model.Dashboard, err error) { res := dr.db.WithContext(ctx).Limit(1). - Where("organization_id = ? and user_id = ?", organizationId, userId). + Where("organization_id = ? and user_id = ? and key = ?", organizationId, userId, dashboardKey). First(&d) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { diff --git a/internal/route/route.go b/internal/route/route.go index b7aa0014..30783517 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -201,19 +201,19 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.RemoveOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.RemoveOrganizationStackTemplates))).Methods(http.MethodPut) dashboardHandler := delivery.NewDashboardHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/charts/{chartType}", customMiddleware.Handle(internalApi.GetChartDashboard, http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-status", customMiddleware.Handle(internalApi.GetPolicyStatusDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatus))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-update", customMiddleware.Handle(internalApi.GetPolicyUpdateDashboard, http.HandlerFunc(dashboardHandler.GetPolicyUpdate))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-enforcement", customMiddleware.Handle(internalApi.GetPolicyEnforcementDashboard, http.HandlerFunc(dashboardHandler.GetPolicyEnforcement))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-violation", customMiddleware.Handle(internalApi.GetPolicyViolationDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolation))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-violation-log", customMiddleware.Handle(internalApi.GetPolicyViolationLogDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolationLog))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/policy-statistics", customMiddleware.Handle(internalApi.GetPolicyStatisticsDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatistics))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/charts", customMiddleware.Handle(internalApi.GetChartsDashboard, http.HandlerFunc(dashboardHandler.GetCharts))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/charts/{chartType}", customMiddleware.Handle(internalApi.GetChartDashboard, http.HandlerFunc(dashboardHandler.GetChart))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/stacks", customMiddleware.Handle(internalApi.GetStacksDashboard, http.HandlerFunc(dashboardHandler.GetStacks))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/resources", customMiddleware.Handle(internalApi.GetResourcesDashboard, http.HandlerFunc(dashboardHandler.GetResources))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-status", customMiddleware.Handle(internalApi.GetPolicyStatusDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatus))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-update", customMiddleware.Handle(internalApi.GetPolicyUpdateDashboard, http.HandlerFunc(dashboardHandler.GetPolicyUpdate))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-enforcement", customMiddleware.Handle(internalApi.GetPolicyEnforcementDashboard, http.HandlerFunc(dashboardHandler.GetPolicyEnforcement))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-violation", customMiddleware.Handle(internalApi.GetPolicyViolationDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolation))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-violation-log", customMiddleware.Handle(internalApi.GetPolicyViolationLogDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolationLog))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-statistics", customMiddleware.Handle(internalApi.GetPolicyStatisticsDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatistics))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/{dashboardKey}", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/{dashboardKey}", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) systemNotificationHandler := delivery.NewSystemNotificationHandler(usecaseFactory) r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/system-notifications", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 25853cc9..bcd630ab 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -30,7 +30,7 @@ import ( type IDashboardUsecase interface { CreateDashboard(ctx context.Context, dashboard *model.Dashboard) (string, error) - GetDashboard(ctx context.Context, organizationId string, userId string) (*model.Dashboard, error) + GetDashboard(ctx context.Context, organizationId string, userId string, dashboardKey string) (*model.Dashboard, error) UpdateDashboard(ctx context.Context, dashboard *model.Dashboard) error GetCharts(ctx context.Context, organizationId string, chartType domain.ChartType, duration string, interval string, year string, month string) (res []domain.DashboardChart, err error) GetStacks(ctx context.Context, organizationId string) (out []domain.DashboardStack, err error) @@ -74,8 +74,8 @@ func (u *DashboardUsecase) CreateDashboard(ctx context.Context, dashboard *model return dashboardId, nil } -func (u *DashboardUsecase) GetDashboard(ctx context.Context, organizationId string, userId string) (*model.Dashboard, error) { - dashboard, err := u.dashboardRepo.GetDashboardByUserId(ctx, organizationId, userId) +func (u *DashboardUsecase) GetDashboard(ctx context.Context, organizationId string, userId string, dashboardKey string) (*model.Dashboard, error) { + dashboard, err := u.dashboardRepo.GetDashboardByUserId(ctx, organizationId, userId, dashboardKey) if err != nil { return nil, errors.Wrap(err, "Failed to get dashboard.") } diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 52571d9a..62443a1c 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -146,20 +146,25 @@ type GetDashboardStacksResponse struct { } type WidgetResponse struct { - Key string `json:"key"` + Key string `json:"widgetKey"` StartX int `json:"startX"` StartY int `json:"startY"` SizeX int `json:"sizeX"` SizeY int `json:"sizeY"` } -type CreateDashboardRequest struct { +type DashboardContents struct { GroupName string `json:"groupName"` SizeX int `json:"sizeX"` SizeY int `json:"sizeY"` Widgets []WidgetResponse `json:"widgets"` } +type CreateDashboardRequest struct { + DashboardKey string `json:"dashboardKey"` + Contents []DashboardContents `json:"contents"` +} + type CreateDashboardResponse struct { DashboardId string `json:"dashboardId"` } @@ -172,7 +177,7 @@ type GetDashboardResponse struct { } type UpdateDashboardRequest struct { - CreateDashboardRequest + DashboardContents } type CommonDashboardResponse struct { From 6b55c6eb06782ec85181941d5f49db804fc069df Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 18 Apr 2024 13:32:45 +0900 Subject: [PATCH 325/502] change dashboard and widget path\n swagger generate --- api/swagger/docs.go | 235 +++++++++++++++++++++------------------ api/swagger/swagger.json | 235 +++++++++++++++++++++------------------ api/swagger/swagger.yaml | 85 ++++++++------ 3 files changed, 308 insertions(+), 247 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 76083cf8..4cb5fbbb 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3186,88 +3186,6 @@ const docTemplate = `{ } }, "/organizations/{organizationId}/dashboards": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get dashboard", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get dashboard", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" - } - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update dashboard", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Update dashboard", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Request body to update dashboard", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" - } - } - } - }, "post": { "security": [ { @@ -3313,7 +3231,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/charts": { + "/organizations/{organizationId}/dashboards/widgets/charts": { "get": { "security": [ { @@ -3370,7 +3288,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/charts/{chartType}": { + "/organizations/{organizationId}/dashboards/widgets/charts/{chartType}": { "get": { "security": [ { @@ -3428,7 +3346,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/policy-enforcement": { + "/organizations/{organizationId}/dashboards/widgets/policy-enforcement": { "get": { "security": [ { @@ -3465,7 +3383,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/policy-statistics": { + "/organizations/{organizationId}/dashboards/widgets/policy-statistics": { "get": { "security": [ { @@ -3502,7 +3420,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/policy-status": { + "/organizations/{organizationId}/dashboards/widgets/policy-status": { "get": { "security": [ { @@ -3539,7 +3457,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/policy-update": { + "/organizations/{organizationId}/dashboards/widgets/policy-update": { "get": { "security": [ { @@ -3576,7 +3494,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/policy-violation": { + "/organizations/{organizationId}/dashboards/widgets/policy-violation": { "get": { "security": [ { @@ -3627,7 +3545,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/policy-violation-log": { + "/organizations/{organizationId}/dashboards/widgets/policy-violation-log": { "get": { "security": [ { @@ -3664,7 +3582,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/resources": { + "/organizations/{organizationId}/dashboards/widgets/resources": { "get": { "security": [ { @@ -3701,7 +3619,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/dashboards/stacks": { + "/organizations/{organizationId}/dashboards/widgets/stacks": { "get": { "security": [ { @@ -3738,6 +3656,97 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/dashboards/{dashboardKey}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Dashboard Key", + "name": "dashboardKey", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" + } + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Update dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to update dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" + } + } + } + } + }, "/organizations/{organizationId}/mandatory-policies": { "get": { "security": [ @@ -11391,20 +11400,14 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest": { "type": "object", "properties": { - "groupName": { - "type": "string" - }, - "sizeX": { - "type": "integer" - }, - "sizeY": { - "type": "integer" - }, - "widgets": { + "contents": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardContents" } + }, + "dashboardKey": { + "type": "string" } } }, @@ -12052,6 +12055,26 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DashboardContents": { + "type": "object", + "properties": { + "groupName": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "widgets": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus": { "type": "object", "properties": { @@ -15931,9 +15954,6 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.WidgetResponse": { "type": "object", "properties": { - "key": { - "type": "string" - }, "sizeX": { "type": "integer" }, @@ -15945,6 +15965,9 @@ const docTemplate = `{ }, "startY": { "type": "integer" + }, + "widgetKey": { + "type": "string" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 571fc537..50e7a5e9 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3180,88 +3180,6 @@ } }, "/organizations/{organizationId}/dashboards": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get dashboard", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Get dashboard", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" - } - } - } - } - }, - "put": { - "security": [ - { - "JWT": [] - } - ], - "description": "Update dashboard", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Dashboards" - ], - "summary": "Update dashboard", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "description": "Request body to update dashboard", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" - } - } - } - }, "post": { "security": [ { @@ -3307,7 +3225,7 @@ } } }, - "/organizations/{organizationId}/dashboards/charts": { + "/organizations/{organizationId}/dashboards/widgets/charts": { "get": { "security": [ { @@ -3364,7 +3282,7 @@ } } }, - "/organizations/{organizationId}/dashboards/charts/{chartType}": { + "/organizations/{organizationId}/dashboards/widgets/charts/{chartType}": { "get": { "security": [ { @@ -3422,7 +3340,7 @@ } } }, - "/organizations/{organizationId}/dashboards/policy-enforcement": { + "/organizations/{organizationId}/dashboards/widgets/policy-enforcement": { "get": { "security": [ { @@ -3459,7 +3377,7 @@ } } }, - "/organizations/{organizationId}/dashboards/policy-statistics": { + "/organizations/{organizationId}/dashboards/widgets/policy-statistics": { "get": { "security": [ { @@ -3496,7 +3414,7 @@ } } }, - "/organizations/{organizationId}/dashboards/policy-status": { + "/organizations/{organizationId}/dashboards/widgets/policy-status": { "get": { "security": [ { @@ -3533,7 +3451,7 @@ } } }, - "/organizations/{organizationId}/dashboards/policy-update": { + "/organizations/{organizationId}/dashboards/widgets/policy-update": { "get": { "security": [ { @@ -3570,7 +3488,7 @@ } } }, - "/organizations/{organizationId}/dashboards/policy-violation": { + "/organizations/{organizationId}/dashboards/widgets/policy-violation": { "get": { "security": [ { @@ -3621,7 +3539,7 @@ } } }, - "/organizations/{organizationId}/dashboards/policy-violation-log": { + "/organizations/{organizationId}/dashboards/widgets/policy-violation-log": { "get": { "security": [ { @@ -3658,7 +3576,7 @@ } } }, - "/organizations/{organizationId}/dashboards/resources": { + "/organizations/{organizationId}/dashboards/widgets/resources": { "get": { "security": [ { @@ -3695,7 +3613,7 @@ } } }, - "/organizations/{organizationId}/dashboards/stacks": { + "/organizations/{organizationId}/dashboards/widgets/stacks": { "get": { "security": [ { @@ -3732,6 +3650,97 @@ } } }, + "/organizations/{organizationId}/dashboards/{dashboardKey}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Get dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Dashboard Key", + "name": "dashboardKey", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse" + } + } + } + } + }, + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update dashboard", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboards" + ], + "summary": "Update dashboard", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "Request body to update dashboard", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.UpdateDashboardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CommonDashboardResponse" + } + } + } + } + }, "/organizations/{organizationId}/mandatory-policies": { "get": { "security": [ @@ -11385,20 +11394,14 @@ "github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest": { "type": "object", "properties": { - "groupName": { - "type": "string" - }, - "sizeX": { - "type": "integer" - }, - "sizeY": { - "type": "integer" - }, - "widgets": { + "contents": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardContents" } + }, + "dashboardKey": { + "type": "string" } } }, @@ -12046,6 +12049,26 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DashboardContents": { + "type": "object", + "properties": { + "groupName": { + "type": "string" + }, + "sizeX": { + "type": "integer" + }, + "sizeY": { + "type": "integer" + }, + "widgets": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus": { "type": "object", "properties": { @@ -15925,9 +15948,6 @@ "github_com_openinfradev_tks-api_pkg_domain.WidgetResponse": { "type": "object", "properties": { - "key": { - "type": "string" - }, "sizeX": { "type": "integer" }, @@ -15939,6 +15959,9 @@ }, "startY": { "type": "integer" + }, + "widgetKey": { + "type": "string" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index ce6b4b7f..1debb0e7 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -934,16 +934,12 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest: properties: - groupName: - type: string - sizeX: - type: integer - sizeY: - type: integer - widgets: + contents: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardContents' type: array + dashboardKey: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse: properties: @@ -1387,6 +1383,19 @@ definitions: year: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.DashboardContents: + properties: + groupName: + type: string + sizeX: + type: integer + sizeY: + type: integer + widgets: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.WidgetResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyStatus: properties: error: @@ -3961,8 +3970,6 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.WidgetResponse: properties: - key: - type: string sizeX: type: integer sizeY: @@ -3971,6 +3978,8 @@ definitions: type: integer startY: type: integer + widgetKey: + type: string type: object github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest: properties: @@ -6265,56 +6274,62 @@ paths: tags: - CloudAccounts /organizations/{organizationId}/dashboards: - get: + post: consumes: - application/json - description: Get dashboard + description: Create new dashboard parameters: - description: Organization ID in: path name: organizationId required: true type: string + - description: Request body to create dashboard + in: body + name: request + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest' produces: - application/json responses: "200": description: OK schema: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse' - type: array + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse' security: - JWT: [] - summary: Get dashboard + summary: Create new dashboard tags: - Dashboards - post: + /organizations/{organizationId}/dashboards/{dashboardKey}: + get: consumes: - application/json - description: Create new dashboard + description: Get dashboard parameters: - description: Organization ID in: path name: organizationId required: true type: string - - description: Request body to create dashboard - in: body - name: request + - description: Dashboard Key + in: path + name: dashboardKey required: true - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardRequest' + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CreateDashboardResponse' + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardResponse' + type: array security: - JWT: [] - summary: Create new dashboard + summary: Get dashboard tags: - Dashboards put: @@ -6345,7 +6360,7 @@ paths: summary: Update dashboard tags: - Dashboards - /organizations/{organizationId}/dashboards/charts: + /organizations/{organizationId}/dashboards/widgets/charts: get: consumes: - application/json @@ -6382,7 +6397,7 @@ paths: summary: Get charts data tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/charts/{chartType}: + /organizations/{organizationId}/dashboards/widgets/charts/{chartType}: get: consumes: - application/json @@ -6420,7 +6435,7 @@ paths: summary: Get chart data tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/policy-enforcement: + /organizations/{organizationId}/dashboards/widgets/policy-enforcement: get: consumes: - application/json @@ -6443,7 +6458,7 @@ paths: summary: Get the number of policy enforcement tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/policy-statistics: + /organizations/{organizationId}/dashboards/widgets/policy-statistics: get: consumes: - application/json @@ -6466,7 +6481,7 @@ paths: summary: Get policy violation log tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/policy-status: + /organizations/{organizationId}/dashboards/widgets/policy-status: get: consumes: - application/json @@ -6489,7 +6504,7 @@ paths: summary: Get policy status tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/policy-update: + /organizations/{organizationId}/dashboards/widgets/policy-update: get: consumes: - application/json @@ -6512,7 +6527,7 @@ paths: summary: Get the number of policytemplates that need to be updated tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/policy-violation: + /organizations/{organizationId}/dashboards/widgets/policy-violation: get: consumes: - application/json @@ -6545,7 +6560,7 @@ paths: summary: Get the number of policy violation tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/policy-violation-log: + /organizations/{organizationId}/dashboards/widgets/policy-violation-log: get: consumes: - application/json @@ -6568,7 +6583,7 @@ paths: summary: Get policy violation log tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/resources: + /organizations/{organizationId}/dashboards/widgets/resources: get: consumes: - application/json @@ -6591,7 +6606,7 @@ paths: summary: Get resources tags: - Dashboard Widgets - /organizations/{organizationId}/dashboards/stacks: + /organizations/{organizationId}/dashboards/widgets/stacks: get: consumes: - application/json From ac400639339f47427ff1593f1380af164a7bbd54 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 18 Apr 2024 17:11:07 +0900 Subject: [PATCH 326/502] =?UTF-8?q?PolicyTemplate=20permittedOrganizations?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy-template.go | 40 ++++-- internal/repository/policy-template.go | 18 ++- internal/repository/policy.go | 14 ++- internal/usecase/policy-template.go | 143 ++++++++++++++-------- pkg/domain/admin/policy-template.go | 12 +- 5 files changed, 160 insertions(+), 67 deletions(-) diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index cfb7a29e..caf54f5c 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -261,10 +261,18 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplate(w http.ResponseWriter, r log.Error(r.Context(), err) } - if err = h.usecase.FillPermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { - log.Error(r.Context(), err) + out.PolicyTemplate.PermittedOrganizations = make([]domain.SimpleOrganizationResponse, len(policyTemplate.PermittedOrganizations)) + for i, organization := range policyTemplate.PermittedOrganizations { + if err := serializer.Map(r.Context(), organization, &out.PolicyTemplate.PermittedOrganizations[i]); err != nil { + log.Info(r.Context(), err) + continue + } } + // if err = h.usecase.FillPermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { + // log.Error(r.Context(), err) + // } + ResponseJSON(w, r, http.StatusOK, out) } @@ -301,12 +309,21 @@ func (h *PolicyTemplateHandler) Admin_ListPolicyTemplate(w http.ResponseWriter, log.Info(r.Context(), err) continue } - } - if err = h.usecase.FillPermittedOrganizationsForList(r.Context(), &policyTemplates, &out.PolicyTemplates); err != nil { - log.Error(r.Context(), err) + out.PolicyTemplates[i].PermittedOrganizations = make([]domain.SimpleOrganizationResponse, len(policyTemplate.PermittedOrganizations)) + for j, organization := range policyTemplate.PermittedOrganizations { + if err := serializer.Map(r.Context(), organization, &out.PolicyTemplates[i].PermittedOrganizations[j]); err != nil { + log.Info(r.Context(), err) + continue + } + } + } + // if err = h.usecase.FillPermittedOrganizationsForList(r.Context(), &policyTemplates, &out.PolicyTemplates); err != nil { + // log.Error(r.Context(), err) + // } + if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } @@ -554,10 +571,19 @@ func (h *PolicyTemplateHandler) Admin_GetPolicyTemplateVersion(w http.ResponseWr log.Error(r.Context(), err) } - if err = h.usecase.FillPermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { - log.Error(r.Context(), err) + out.PolicyTemplate.PermittedOrganizations = make([]domain.SimpleOrganizationResponse, len(policyTemplate.PermittedOrganizations)) + + for i, organization := range policyTemplate.PermittedOrganizations { + if err := serializer.Map(r.Context(), organization, &out.PolicyTemplate.PermittedOrganizations[i]); err != nil { + log.Info(r.Context(), err) + continue + } } + // if err = h.usecase.FillPermittedOrganizations(r.Context(), policyTemplate, &out.PolicyTemplate); err != nil { + // log.Error(r.Context(), err) + // } + ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index c075189b..c06a7cae 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -50,7 +50,19 @@ func NewPolicyTemplateRepository(db *gorm.DB) IPolicyTemplateRepository { } func (r *PolicyTemplateRepository) Create(ctx context.Context, dto model.PolicyTemplate) (policyTemplateId uuid.UUID, err error) { - err = r.db.WithContext(ctx).Create(&dto).Error + err = r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + // 이미 org가 존재하므로 many2many 레코드를 추가하지 않고 관계만 업데이트하도록 보장 + if err := tx.Omit("PermittedOrganizations").Create(&dto).Error; err != nil { + return err + } + + if err := tx.Model(&dto).Association("PermittedOrganizations"). + Append(dto.PermittedOrganizations); err != nil { + return err + } + + return nil + }) if err != nil { return uuid.Nil, err @@ -67,7 +79,7 @@ func (r *PolicyTemplateRepository) Update(ctx context.Context, policyTemplateId return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { if permittedOrganizations != nil { - err = r.db.WithContext(ctx).Model(&policyTemplate).Limit(1). + err = tx.WithContext(ctx).Model(&policyTemplate).Limit(1). Association("PermittedOrganizations").Replace(permittedOrganizations) if err != nil { @@ -76,7 +88,7 @@ func (r *PolicyTemplateRepository) Update(ctx context.Context, policyTemplateId } if len(updateMap) > 0 { - err = r.db.WithContext(ctx).Model(&policyTemplate).Limit(1). + err = tx.WithContext(ctx).Model(&policyTemplate).Limit(1). Where("id = ?", policyTemplateId).Where("type = ?", "tks"). Updates(updateMap).Error diff --git a/internal/repository/policy.go b/internal/repository/policy.go index ca0e3cd1..2f6cc3c0 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -48,7 +48,19 @@ func NewPolicyRepository(db *gorm.DB) IPolicyRepository { } func (r *PolicyRepository) Create(ctx context.Context, dto model.Policy) (policyId uuid.UUID, err error) { - err = r.db.WithContext(ctx).Create(&dto).Error + err = r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + // 이미 org가 존재하므로 many2many 레코드를 추가하지 않고 관계만 업데이트하도록 보장 + if err := tx.Omit("TargetClusters").Create(&dto).Error; err != nil { + return err + } + + if err := tx.Model(&dto).Association("TargetClusters"). + Append(dto.TargetClusters); err != nil { + return err + } + + return nil + }) if err != nil { return uuid.Nil, err diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index dbcd774e..b235e781 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -5,10 +5,8 @@ import ( "fmt" "strings" - admin_domain "github.com/openinfradev/tks-api/pkg/domain/admin" "github.com/openinfradev/tks-api/pkg/log" - mapset "github.com/deckarep/golang-set/v2" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" @@ -35,10 +33,10 @@ type IPolicyTemplateUsecase interface { RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) - FillPermittedOrganizations(ctx context.Context, - policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) error - FillPermittedOrganizationsForList(ctx context.Context, - policyTemplates *[]model.PolicyTemplate, outs *[]admin_domain.PolicyTemplateResponse) error + // FillPermittedOrganizations(ctx context.Context, + // policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) error + // FillPermittedOrganizationsForList(ctx context.Context, + // policyTemplates *[]model.PolicyTemplate, outs *[]admin_domain.PolicyTemplateResponse) error ListPolicyTemplateStatistics(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (statistics []model.UsageCount, err error) GetPolicyTemplateDeploy(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (deployInfo domain.GetPolicyTemplateDeployResponse, err error) @@ -102,15 +100,18 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp // TKS 템블릿이면 dto.Mandatory = false dto.OrganizationId = nil + dto.PermittedOrganizations = make([]model.Organization, len(dto.PermittedOrganizationIds)) - for _, organizationId := range dto.PermittedOrganizationIds { - _, err := u.organizationRepo.Get(ctx, organizationId) + for i, organizationId := range dto.PermittedOrganizationIds { + organization, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "") } + dto.PermittedOrganizations[i] = organization } } else { dto.PermittedOrganizationIds = make([]string, 0) + dto.PermittedOrganizations = make([]model.Organization, 0) } userId := user.GetUserId() @@ -127,71 +128,93 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, organizationId *string, pg *pagination.Pagination) (policyTemplates []model.PolicyTemplate, err error) { if organizationId == nil { - return u.repo.Fetch(ctx, pg) + policyTemplates, err = u.repo.Fetch(ctx, pg) + } else { + policyTemplates, err = u.repo.FetchForOrganization(ctx, *organizationId, pg) } - return u.repo.FetchForOrganization(ctx, *organizationId, pg) -} + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } -func (u *PolicyTemplateUsecase) FillPermittedOrganizations(ctx context.Context, - policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) error { organizations, err := u.organizationRepo.Fetch(ctx, nil) if err != nil { - return err + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) } - u.fillPermittedOrganizations(ctx, organizations, policyTemplate, out) + for i := range policyTemplates { + // 단순히 참조하면 업데이트가 안되므로 pointer derefrencing + policyTemplate := &policyTemplates[i] + if policyTemplate.IsTksTemplate() && len(policyTemplate.PermittedOrganizations) == 0 { + if organizations != nil { + (*policyTemplate).PermittedOrganizations = *organizations + } + } + } - return nil + return policyTemplates, err } -func (u *PolicyTemplateUsecase) FillPermittedOrganizationsForList(ctx context.Context, - policyTemplates *[]model.PolicyTemplate, outs *[]admin_domain.PolicyTemplateResponse) error { +// func (u *PolicyTemplateUsecase) FillPermittedOrganizations(ctx context.Context, +// policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) error { +// organizations, err := u.organizationRepo.Fetch(ctx, nil) - organizations, err := u.organizationRepo.Fetch(ctx, nil) +// if err != nil { +// return err +// } - if err != nil { - return err - } +// u.fillPermittedOrganizations(ctx, organizations, policyTemplate, out) - results := *outs +// return nil +// } - for i, policyTemplate := range *policyTemplates { - u.fillPermittedOrganizations(ctx, organizations, &policyTemplate, &results[i]) - } +// func (u *PolicyTemplateUsecase) FillPermittedOrganizationsForList(ctx context.Context, +// policyTemplates *[]model.PolicyTemplate, outs *[]admin_domain.PolicyTemplateResponse) error { - return nil -} +// organizations, err := u.organizationRepo.Fetch(ctx, nil) -// 모든 조직 목록에 대해 허용 여부 업데이트 -func (u *PolicyTemplateUsecase) fillPermittedOrganizations(_ context.Context, organizations *[]model.Organization, policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) { - if policyTemplate == nil || organizations == nil || out == nil { - return - } +// if err != nil { +// return err +// } - if policyTemplate.IsOrganizationTemplate() { - return - } +// results := *outs - // 정책 템플릿에서 허용된 조직 목록이 없다는 것은 모든 조직이 사용할 수 있음을 의미함 - allPermitted := len(policyTemplate.PermittedOrganizationIds) == 0 +// for i, policyTemplate := range *policyTemplates { +// u.fillPermittedOrganizations(ctx, organizations, &policyTemplate, &results[i]) +// } - // 허용된 조직 포함 여부를 효율적으로 처리하기 위해 ID 리스트를 셋으로 변환 - permittedOrganizationIdSet := mapset.NewSet(policyTemplate.PermittedOrganizationIds...) +// return nil +// } - out.PermittedOrganizations = make([]admin_domain.PermittedOrganization, len(*organizations)) +// // 모든 조직 목록에 대해 허용 여부 업데이트 +// func (u *PolicyTemplateUsecase) fillPermittedOrganizations(_ context.Context, organizations *[]model.Organization, policyTemplate *model.PolicyTemplate, out *admin_domain.PolicyTemplateResponse) { +// if policyTemplate == nil || organizations == nil || out == nil { +// return +// } - for i, organization := range *organizations { - permitted := allPermitted || permittedOrganizationIdSet.ContainsOne(organization.ID) +// if policyTemplate.IsOrganizationTemplate() { +// return +// } - out.PermittedOrganizations[i] = admin_domain.PermittedOrganization{ - OrganizationId: organization.ID, - OrganizationName: organization.Name, - Permitted: permitted, - } - } -} +// // 정책 템플릿에서 허용된 조직 목록이 없다는 것은 모든 조직이 사용할 수 있음을 의미함 +// allPermitted := len(policyTemplate.PermittedOrganizationIds) == 0 + +// // 허용된 조직 포함 여부를 효율적으로 처리하기 위해 ID 리스트를 셋으로 변환 +// permittedOrganizationIdSet := mapset.NewSet(policyTemplate.PermittedOrganizationIds...) + +// out.PermittedOrganizations = make([]admin_domain.PermittedOrganization, len(*organizations)) + +// for i, organization := range *organizations { +// permitted := allPermitted || permittedOrganizationIdSet.ContainsOne(organization.ID) + +// out.PermittedOrganizations[i] = admin_domain.PermittedOrganization{ +// OrganizationId: organization.ID, +// OrganizationName: organization.Name, +// Permitted: permitted, +// } +// } +// } func (u *PolicyTemplateUsecase) Get(ctx context.Context, organizationId *string, policyTemplateID uuid.UUID) (policyTemplates *model.PolicyTemplate, err error) { policyTemplate, err := u.repo.GetByID(ctx, policyTemplateID) @@ -206,6 +229,16 @@ func (u *PolicyTemplateUsecase) Get(ctx context.Context, organizationId *string, "PT_NOT_FOUND_POLICY_TEMPLATE", "") } + if policyTemplate.IsTksTemplate() && len(policyTemplate.PermittedOrganizations) == 0 { + organizations, err := u.organizationRepo.Fetch(ctx, nil) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } else if organizations != nil { + policyTemplate.PermittedOrganizations = *organizations + } + } + return policyTemplate, nil } @@ -357,6 +390,16 @@ func (u *PolicyTemplateUsecase) GetPolicyTemplateVersion(ctx context.Context, or "PT_NOT_FOUND_POLICY_TEMPLATE", "") } + if policyTemplate.IsTksTemplate() && len(policyTemplate.PermittedOrganizations) == 0 { + organizations, err := u.organizationRepo.Fetch(ctx, nil) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } else if organizations != nil { + policyTemplate.PermittedOrganizations = *organizations + } + } + return policyTemplate, nil } diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index ab13594c..413609a3 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -6,11 +6,11 @@ import ( "github.com/openinfradev/tks-api/pkg/domain" ) -type PermittedOrganization struct { - OrganizationId string `json:"organizationId"` - OrganizationName string `json:"organizationName"` - Permitted bool `json:"permitted"` -} +// type PermittedOrganization struct { +// OrganizationId string `json:"organizationId"` +// OrganizationName string `json:"organizationName"` +// Permitted bool `json:"permitted"` +// } type PolicyTemplateResponse struct { ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` @@ -30,7 +30,7 @@ type PolicyTemplateResponse struct { Rego string `json:"rego" example:"rego 코드"` Libs []string `json:"libs" example:"rego 코드"` - PermittedOrganizations []PermittedOrganization `json:"permittedOrganizations"` + PermittedOrganizations []domain.SimpleOrganizationResponse `json:"permittedOrganizations"` } type SimplePolicyTemplateResponse struct { From f8b567c2c0fcc4f80066d3ebc63bd30330cce79b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 18 Apr 2024 18:45:37 +0900 Subject: [PATCH 327/502] trivial. bugfix for application type --- pkg/domain/app-group.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/domain/app-group.go b/pkg/domain/app-group.go index 36dff144..87ed1bbe 100644 --- a/pkg/domain/app-group.go +++ b/pkg/domain/app-group.go @@ -130,13 +130,13 @@ type AppGroupResponse = struct { } type ApplicationResponse = struct { - ID uuid.UUID `json:"id"` - AppGroupId AppGroupId `json:"appGroupId"` - Endpoint string `json:"endpoint"` - Metadata string `json:"metadata"` - ApplicationType ApplicationType `json:"applicationType"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID uuid.UUID `json:"id"` + AppGroupId AppGroupId `json:"appGroupId"` + Endpoint string `json:"endpoint"` + Metadata string `json:"metadata"` + Type ApplicationType `json:"applicationType"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type CreateAppGroupRequest struct { @@ -151,9 +151,9 @@ type CreateAppGroupResponse struct { } type CreateApplicationRequest struct { - ApplicationType string `json:"applicationType"` - Endpoint string `json:"endpoint"` - Metadata string `json:"metadata"` + Type string `json:"applicationType"` + Endpoint string `json:"endpoint"` + Metadata string `json:"metadata"` } type GetAppGroupsResponse struct { From 27faa78455eb58685123846d54ec3bd97a4d26f8 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 19 Apr 2024 00:10:48 +0900 Subject: [PATCH 328/502] =?UTF-8?q?=EB=8B=A4=EC=A4=91=20libs=EB=A5=BC=20--?= =?UTF-8?q?-\n=EB=A1=9C=20=EB=B3=91=ED=95=A9=ED=95=B4=EC=84=9C=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/policy-template-rego.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index 867f36c3..e5f83937 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/open-policy-agent/opa/ast" + "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/pkg/domain" "golang.org/x/exp/maps" ) @@ -281,7 +282,7 @@ func MergeRegoAndLibs(rego string, libs []string) string { result := re.ReplaceAllString(rego, "") - for _, lib := range libs { + for _, lib := range processLibs(libs) { result += re2.ReplaceAllString(lib, "") } @@ -367,6 +368,16 @@ func createKey(key string, isLast bool) *domain.ParameterDef { return newDef } +func processLibs(libs []string) []string { + // libs 에 --- 로 코딩되어 여러 개가 한 번에 들어온 경우 분할 + newLibs := []string{} + for _, lib := range libs { + newLibs = append(newLibs, strings.Split(stripCarriageReturn(lib), model.FILE_DELIMETER)...) + } + + return newLibs +} + func CompileRegoWithLibs(rego string, libs []string) (compiler *ast.Compiler, err error) { modules := map[string]*ast.Module{} @@ -379,7 +390,7 @@ func CompileRegoWithLibs(rego string, libs []string) (compiler *ast.Compiler, er modules[regoPackage] = regoModule - for i, lib := range libs { + for i, lib := range processLibs(libs) { // Lib이 공백이면 무시 if len(strings.TrimSpace(lib)) == 0 { continue From 3339972f05332ddd890feb4ee3821747cbfa7d27 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 19 Apr 2024 11:25:18 +0900 Subject: [PATCH 329/502] =?UTF-8?q?clusterId=EB=A1=9C=20policyId=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/repository/policy.go | 27 +++++++++++++++++++++++++++ internal/usecase/policy.go | 5 +++++ 2 files changed, 32 insertions(+) diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 7b1be877..75dc7a90 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -35,6 +35,7 @@ type IPolicyRepository interface { AddPoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policies []model.Policy) (err error) UpdatePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policies []model.Policy) (err error) DeletePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) + GetPolicyIDsByClusterID(ctx context.Context, clusterId domain.ClusterId) (out *[]uuid.UUID, err error) } type PolicyRepository struct { @@ -339,3 +340,29 @@ func (r *PolicyRepository) DeletePoliciesForClusterID(ctx context.Context, organ Where("policy_id in ?", policyIds). Delete(&model.PolicyTargetCluster{}).Error } + +func (r *PolicyRepository) GetPolicyIDsByClusterID(ctx context.Context, clusterId domain.ClusterId) (*[]uuid.UUID, error) { + var policyTargetClusters []model.PolicyTargetCluster + + err := r.db.WithContext(ctx). + Where("cluster_id = ?", clusterId). + Find(&policyTargetClusters).Error + + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Infof(ctx, "Not found policices for clusterId '%v'", clusterId) + return nil, nil + } else { + log.Error(ctx, err) + return nil, err + } + } + + result := make([]uuid.UUID, len(policyTargetClusters)) + + for i, policyTargetCluster := range policyTargetClusters { + result[i] = policyTargetCluster.PolicyId + } + + return &result, nil +} diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 6ce39010..5f28f28e 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -44,6 +44,7 @@ type IPolicyUsecase interface { UpdatePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) DeletePoliciesForClusterID(ctx context.Context, organizationId string, clusterId domain.ClusterId, policyIds []uuid.UUID) (err error) GetStackPolicyStatistics(ctx context.Context, organizationId string, clusterId domain.ClusterId) (statistics *domain.StackPolicyStatistics, err error) + GetPolicyIDsByClusterID(ctx context.Context, clusterId domain.ClusterId) (out *[]uuid.UUID, err error) } type PolicyUsecase struct { @@ -1039,6 +1040,10 @@ func (u *PolicyUsecase) GetStackPolicyStatistics(ctx context.Context, organizati return &result, nil } +func (u *PolicyUsecase) GetPolicyIDsByClusterID(ctx context.Context, clusterId domain.ClusterId) (out *[]uuid.UUID, err error) { + return u.repo.GetPolicyIDsByClusterID(ctx, clusterId) +} + func extractNewTemplateParameter(paramdefs []*domain.ParameterDef, newParamDefs []*domain.ParameterDef) (policyParameters []domain.UpdatedPolicyTemplateParameter, err error) { diffParamDef, err := policytemplate.GetNewParamDefs(paramdefs, newParamDefs) From 8ccaab2ec7fc2e3effecd74a3231906b136cec28 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 19 Apr 2024 13:20:55 +0900 Subject: [PATCH 330/502] Workload widget --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/dashboard.go | 31 +++++++ internal/route/route.go | 1 + internal/usecase/dashboard.go | 138 ++++++++++++++++++++++++++++ pkg/domain/dashboard.go | 25 +++++ 5 files changed, 196 insertions(+) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index d5993f19..b58f2ace 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -123,6 +123,7 @@ const ( GetPolicyViolationDashboard GetPolicyViolationLogDashboard GetPolicyStatisticsDashboard + GetWorkloadDashboard // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 66a5d670..4d91ed3b 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -30,6 +30,7 @@ type IDashboardHandler interface { GetPolicyViolation(w http.ResponseWriter, r *http.Request) GetPolicyViolationLog(w http.ResponseWriter, r *http.Request) GetPolicyStatistics(w http.ResponseWriter, r *http.Request) + GetWorkload(w http.ResponseWriter, r *http.Request) } type DashboardHandler struct { @@ -706,3 +707,33 @@ func (h *DashboardHandler) GetPolicyStatistics(w http.ResponseWriter, r *http.Re ResponseJSON(w, r, http.StatusOK, out) } + +// GetWorkload godoc +// +// @Tags Dashboard Widgets +// @Summary Get workloads +// @Description Get workloads +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Success 200 {object} domain.GetDashboardWorkloadResponse +// @Router /organizations/{organizationId}/dashboards/widgets/workload [get] +// @Security JWT +func (h *DashboardHandler) GetWorkload(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + dwr, err := h.usecase.GetWorkload(r.Context(), organizationId) + if err != nil { + log.Error(r.Context(), "Failed to make workload", err) + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, dwr) +} diff --git a/internal/route/route.go b/internal/route/route.go index 30783517..4a0f47d9 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -211,6 +211,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-violation", customMiddleware.Handle(internalApi.GetPolicyViolationDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolation))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-violation-log", customMiddleware.Handle(internalApi.GetPolicyViolationLogDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolationLog))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-statistics", customMiddleware.Handle(internalApi.GetPolicyStatisticsDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatistics))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/workload", customMiddleware.Handle(internalApi.GetWorkloadDashboard, http.HandlerFunc(dashboardHandler.GetWorkload))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/{dashboardKey}", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/{dashboardKey}", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index bcd630ab..515936b7 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -39,6 +39,7 @@ type IDashboardUsecase interface { GetPolicyEnforcement(ctx context.Context, organizationId string, primaryClusterId string) (*domain.BarChartData, error) GetPolicyViolation(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) GetPolicyViolationLog(ctx context.Context, organizationId string) (*domain.GetDashboardPolicyViolationLogResponse, error) + GetWorkload(ctx context.Context, organizationId string) (*domain.GetDashboardWorkloadResponse, error) } type DashboardUsecase struct { @@ -858,6 +859,143 @@ func (u *DashboardUsecase) GetPolicyViolationLog(ctx context.Context, organizati return nil, nil } +func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId string) (*domain.GetDashboardWorkloadResponse, error) { + thanosClient, err := u.GetThanosClient(ctx, organizationId) + if err != nil { + return nil, errors.Wrap(err, "failed to create thanos client") + } + + clusterIdStr, err := u.GetFlatClusterIds(ctx, organizationId) + if err != nil { + return nil, err + } + + dwr := &domain.GetDashboardWorkloadResponse{} + + // Deployment count + query := fmt.Sprintf("count (kube_deployment_status_replicas_available{taco_cluster=~'%s'} != 0)", clusterIdStr) + wm, err := thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err := strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.DeploymentCount = count + + // Deployment pod count + query = fmt.Sprintf("sum (kube_deployment_status_replicas_available{taco_cluster=~'%s'} )", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.DeploymentPodCount = count + + // StatefulSet count + query = fmt.Sprintf("count (kube_statefulset_status_replicas_available{taco_cluster=~'%s'} != 0)", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.StatefulSetCount = count + + // StatefulSet pod count + query = fmt.Sprintf("sum (kube_statefulset_status_replicas_available{taco_cluster=~'%s'} )", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.StatefulSetPodCount = count + + // DaemonSet count + query = fmt.Sprintf("count (kube_daemonset_status_number_available{taco_cluster=~'%s'} != 0)", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.DaemonSetCount = count + + // DaemonSet pod count + query = fmt.Sprintf("sum (kube_daemonset_status_number_available{taco_cluster=~'%s'} )", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.DaemonSetPodCount = count + + // CronJob count + query = fmt.Sprintf("count (kube_cronjob_status_active{taco_cluster=~'%s'} != 0)", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.CronJobCount = count + + // CronJob pod count + query = fmt.Sprintf("sum (kube_cronjob_status_active{taco_cluster=~'%s'} )", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.CronJobPodCount = count + + // Job count + query = fmt.Sprintf("count (kube_job_status_active{taco_cluster=~'%s'} != 0)", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.JobCount = count + + // Job pod count + query = fmt.Sprintf("sum (kube_job_status_active{taco_cluster=~'%s'} )", clusterIdStr) + wm, err = thanosClient.Get(ctx, query) + if err != nil { + return nil, err + } + count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) + if err != nil { + count = 0 + } + dwr.JobPodCount = count + + return dwr, nil + +} + func (u *DashboardUsecase) GetThanosClient(ctx context.Context, organizationId string) (thanos.ThanosClient, error) { thanosUrl, err := u.getThanosUrl(ctx, organizationId) if err != nil { diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 62443a1c..b1df588c 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -223,6 +223,31 @@ type GetDashboardPolicyStatisticsResponse struct { PolicyStatisticsResponse } +type GetDashboardWorkloadResponse struct { + DeploymentCount int `json:"deploymentCount"` + DeploymentPodCount int `json:"deploymentPodCount"` + StatefulSetCount int `json:"statefulSetCount"` + StatefulSetPodCount int `json:"statefulSetPodCount"` + DaemonSetCount int `json:"daemonSetCount"` + DaemonSetPodCount int `json:"daemonSetPodCount"` + CronJobCount int `json:"cronJobCount"` + CronJobPodCount int `json:"cronJobPodCount"` + JobCount int `json:"jobCount"` + JobPodCount int `json:"jobPodCount"` +} + +type WorkloadMetric struct { + Status string `json:"status"` + Data struct { + ResultType string `json:"resultType"` + Result []struct { + Metric struct { + } `json:"metric"` + Value []interface{} `json:"value"` + } `json:"result"` + } `json:"data"` +} + type BarChart struct { ChartType string `json:"chartType"` OrganizationId string `json:"organizationId"` From 14d5d356717e06ac6c5aac1f557e18336f72d1d4 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 19 Apr 2024 13:21:27 +0900 Subject: [PATCH 331/502] Workload widget\n endpoint generation --- internal/delivery/api/generated_endpoints.go.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 210b5f5f..8b457221 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -379,6 +379,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyStatisticsDashboard", Group: "Dashboard", }, + GetWorkloadDashboard: { + Name: "GetWorkloadDashboard", + Group: "Dashboard", + }, Admin_CreateSystemNotificationTemplate: { Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", @@ -1102,6 +1106,8 @@ func (e Endpoint) String() string { return "GetPolicyViolationLogDashboard" case GetPolicyStatisticsDashboard: return "GetPolicyStatisticsDashboard" + case GetWorkloadDashboard: + return "GetWorkloadDashboard" case Admin_CreateSystemNotificationTemplate: return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: @@ -1562,6 +1568,8 @@ func GetEndpoint(name string) Endpoint { return GetPolicyViolationLogDashboard case "GetPolicyStatisticsDashboard": return GetPolicyStatisticsDashboard + case "GetWorkloadDashboard": + return GetWorkloadDashboard case "Admin_CreateSystemNotificationTemplate": return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": From a4cdd39c46f01e02123a5dcd5cb4a48a47e3f02f Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 19 Apr 2024 13:22:08 +0900 Subject: [PATCH 332/502] Workload widget\n swagger generation --- api/swagger/docs.go | 72 ++++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.json | 72 ++++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 46 +++++++++++++++++++++++++ 3 files changed, 190 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 4ee6c5c7..eb24ce6f 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3656,6 +3656,43 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/dashboards/widgets/workload": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get workloads", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get workloads", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboards/{dashboardKey}": { "get": { "security": [ @@ -12655,6 +12692,41 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse": { + "type": "object", + "properties": { + "cronJobCount": { + "type": "integer" + }, + "cronJobPodCount": { + "type": "integer" + }, + "daemonSetCount": { + "type": "integer" + }, + "daemonSetPodCount": { + "type": "integer" + }, + "deploymentCount": { + "type": "integer" + }, + "deploymentPodCount": { + "type": "integer" + }, + "jobCount": { + "type": "integer" + }, + "jobPodCount": { + "type": "integer" + }, + "statefulSetCount": { + "type": "integer" + }, + "statefulSetPodCount": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 2f517282..7179dec1 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3650,6 +3650,43 @@ } } }, + "/organizations/{organizationId}/dashboards/widgets/workload": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get workloads", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get workloads", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse" + } + } + } + } + }, "/organizations/{organizationId}/dashboards/{dashboardKey}": { "get": { "security": [ @@ -12649,6 +12686,41 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse": { + "type": "object", + "properties": { + "cronJobCount": { + "type": "integer" + }, + "cronJobPodCount": { + "type": "integer" + }, + "daemonSetCount": { + "type": "integer" + }, + "daemonSetPodCount": { + "type": "integer" + }, + "deploymentCount": { + "type": "integer" + }, + "deploymentPodCount": { + "type": "integer" + }, + "jobCount": { + "type": "integer" + }, + "jobPodCount": { + "type": "integer" + }, + "statefulSetCount": { + "type": "integer" + }, + "statefulSetPodCount": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index e9031ad5..f89af619 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1773,6 +1773,29 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardStackResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse: + properties: + cronJobCount: + type: integer + cronJobPodCount: + type: integer + daemonSetCount: + type: integer + daemonSetPodCount: + type: integer + deploymentCount: + type: integer + deploymentPodCount: + type: integer + jobCount: + type: integer + jobPodCount: + type: integer + statefulSetCount: + type: integer + statefulSetPodCount: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse: properties: templates: @@ -6627,6 +6650,29 @@ paths: summary: Get stacks tags: - Dashboard Widgets + /organizations/{organizationId}/dashboards/widgets/workload: + get: + consumes: + - application/json + description: Get workloads + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse' + security: + - JWT: [] + summary: Get workloads + tags: + - Dashboard Widgets /organizations/{organizationId}/mandatory-policies: get: consumes: From 3081cd356d2c5e45f4623a7bf16b9e16d7f878c0 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 19 Apr 2024 13:59:44 +0900 Subject: [PATCH 333/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=20K8s=20=EC=97=B0=EB=8F=99=20=EC=97=90=EB=9F=AC=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/tkspolicytemplate.go | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index edbe3981..45c2f2a3 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/openinfradev/tks-api/pkg/kubernetes" + "github.com/openinfradev/tks-api/pkg/log" "gopkg.in/yaml.v3" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -158,12 +159,16 @@ func ApplyTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tksP dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, tksPolicyTemplate.Name) return err } policyTemplate, err := GetTksPolicyTemplateCR(ctx, primaryClusterId, strings.ToLower(tksPolicyTemplate.Kind)) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, tksPolicyTemplate.Name) if errors.IsNotFound(err) { tksPolicyTemplateUnstructured, err := tksPolicyTemplate.ToUnstructured() @@ -183,12 +188,19 @@ func ApplyTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tksP tksPolicyTemplateUnstructured, err := policyTemplate.ToUnstructured() if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, tksPolicyTemplate.Name) return err } _, err = dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). Update(ctx, tksPolicyTemplateUnstructured, metav1.UpdateOptions{}) + if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, tksPolicyTemplate.Name) + } + return err } return nil @@ -198,6 +210,8 @@ func DeleteTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, nam dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, name) return err } @@ -216,6 +230,8 @@ func ExistsTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, nam dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, name) return false, err } @@ -223,6 +239,9 @@ func ExistsTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, nam Get(ctx, name, metav1.GetOptions{}) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, name) + if errors.IsNotFound(err) { return false, nil } else { @@ -237,6 +256,8 @@ func GetTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, name s dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, name) return nil, err } @@ -244,6 +265,8 @@ func GetTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, name s Get(ctx, name, metav1.GetOptions{}) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, name) return nil, err } @@ -251,6 +274,8 @@ func GetTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, name s jsonBytes, err := json.Marshal(result.Object) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, name) return nil, err } @@ -258,6 +283,8 @@ func GetTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, name s err = json.Unmarshal(jsonBytes, &tksPolicyTemplate) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, name) return nil, err } @@ -268,12 +295,17 @@ func UpdateTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tks dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, tksPolicyTemplate.Name) + return err } obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tksPolicyTemplate) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, tksPolicyTemplate.Name) return err } @@ -284,6 +316,12 @@ func UpdateTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tks _, err = dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). Update(ctx, tksPolicyUnstructured, metav1.UpdateOptions{}) + if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, tksPolicyTemplate.Name) + return err + } + return err } @@ -331,18 +369,27 @@ func UpdateTksPolicyTemplateCR(ctx context.Context, primaryClusterId string, tks func GetTksPolicyTemplateCRs(ctx context.Context, primaryClusterId string) (tksPolicyTemplates []TKSPolicyTemplate, err error) { dynamicClient, err := kubernetes.GetDynamicClientAdminCluster(ctx) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s'", + err.Error(), err, primaryClusterId) + return nil, err } resources, err := dynamicClient.Resource(TKSPolicyTemplateGVR).Namespace(primaryClusterId). List(context.TODO(), metav1.ListOptions{}) if err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s'", + err.Error(), err, primaryClusterId) + return nil, err } var tksPolicyTemplate TKSPolicyTemplate for _, c := range resources.Items { if err = runtime.DefaultUnstructuredConverter.FromUnstructured(c.UnstructuredContent(), &tksPolicyTemplate); err != nil { + log.Errorf(ctx, "error is :%s(%T), primaryClusterId='%s', policyTemplateName='%+v'", + err.Error(), err, primaryClusterId, tksPolicyTemplate.Name) + return nil, err } tksPolicyTemplates = append(tksPolicyTemplates, tksPolicyTemplate) From 6424780fdc631b07dea202aba26ef43f34fd6329 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 19 Apr 2024 14:07:00 +0900 Subject: [PATCH 334/502] feature. delete policies before stack deletion --- api/swagger/docs.go | 16 +--------------- api/swagger/swagger.json | 16 +--------------- api/swagger/swagger.yaml | 11 +---------- internal/delivery/http/stack.go | 23 ++++++++++++++++++++--- internal/usecase/stack.go | 5 +++-- pkg/httpErrors/errorCode.go | 1 + 6 files changed, 27 insertions(+), 45 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index eb24ce6f..5557423c 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -16308,20 +16308,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization": { - "type": "object", - "properties": { - "organizationId": { - "type": "string" - }, - "organizationName": { - "type": "string" - }, - "permitted": { - "type": "boolean" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse": { "type": "object", "properties": { @@ -16365,7 +16351,7 @@ const docTemplate = `{ "permittedOrganizations": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" } }, "rego": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 7179dec1..807132e8 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -16302,20 +16302,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization": { - "type": "object", - "properties": { - "organizationId": { - "type": "string" - }, - "organizationName": { - "type": "string" - }, - "permitted": { - "type": "boolean" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse": { "type": "object", "properties": { @@ -16359,7 +16345,7 @@ "permittedOrganizations": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" } }, "rego": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index f89af619..fb81bda2 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -4183,15 +4183,6 @@ definitions: type: string type: array type: object - github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization: - properties: - organizationId: - type: string - organizationName: - type: string - permitted: - type: boolean - type: object github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse: properties: createdAt: @@ -4222,7 +4213,7 @@ definitions: type: array permittedOrganizations: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.PermittedOrganization' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse' type: array rego: example: rego 코드 diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index db949d64..1692669f 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -16,12 +16,14 @@ import ( ) type StackHandler struct { - usecase usecase.IStackUsecase + usecase usecase.IStackUsecase + usecasePolicy usecase.IPolicyUsecase } func NewStackHandler(h usecase.Usecase) *StackHandler { return &StackHandler{ - usecase: h.Stack, + usecase: h.Stack, + usecasePolicy: h.Policy, } } @@ -310,7 +312,22 @@ func (h *StackHandler) DeleteStack(w http.ResponseWriter, r *http.Request) { dto.ID = domain.StackId(strId) dto.OrganizationId = organizationId - err := h.usecase.Delete(r.Context(), dto) + // Delete Policies + policyIds, err := h.usecasePolicy.GetPolicyIDsByClusterID(r.Context(), domain.ClusterId(dto.ID)) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "S_FAILED_DELETE_POLICIES", "")) + return + } + + if policyIds != nil && len(*policyIds) > 0 { + err = h.usecasePolicy.DeletePoliciesForClusterID(r.Context(), organizationId, domain.ClusterId(dto.ID), *policyIds) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "S_FAILED_DELETE_POLICIES", "")) + return + } + } + + err = h.usecase.Delete(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) return diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 0410bd3d..13bb6635 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -248,13 +248,13 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod return out, err } - stackResources, _ := u.dashbordUsecase.GetStacks(ctx, cluster.OrganizationId) out = reflectClusterToStack(ctx, cluster, appGroups) if organization.PrimaryClusterId == cluster.ID.String() { out.PrimaryCluster = true } + stackResources, _ := u.dashbordUsecase.GetStacks(ctx, cluster.OrganizationId) for _, resource := range stackResources { if resource.ID == domain.StackId(cluster.ID) { if err := serializer.Map(ctx, resource, &out.Resource); err != nil { @@ -433,6 +433,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) } } + // Check AppServing appsCnt, err := u.appServeAppRepo.GetNumOfAppsOnStack(ctx, dto.OrganizationId, dto.ID.String()) if err != nil { return errors.Wrap(err, "Failed to get numOfAppsOnStack") @@ -441,7 +442,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) return httpErrors.NewBadRequestError(fmt.Errorf("existed appServeApps in %s", dto.OrganizationId), "S_FAILED_DELETE_EXISTED_ASA", "") } - // [TODO] BYOH 삭제는 어떻게 처리하는게 좋은가? + // Policy 삭제 workflow := "tks-stack-delete" workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 175518be..ff17fbef 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -79,6 +79,7 @@ var errorMap = map[ErrorCode]string{ "S_INVALID_CLUSTER_URL": "BYOH 타입의 클러스터 생성은 반드시 userClusterEndpoint 값이 필요합니다.", "S_INVALID_CLUSTER_ID": "BYOH 타입의 클러스터 생성은 반드시 clusterId 값이 필요합니다.", "S_INVALID_CLOUD_SERVICE": "클라우드 서비스 타입이 잘못되었습니다.", + "S_FAILED_DELETE_POLICIES": "스택의 폴리시들을 삭제하는 실패하였습니다", // Alert "AL_NOT_FOUND_ALERT": "지정한 앨럿이 존재하지 않습니다.", From 1811366878240fd92abcca8526ce94603453de71 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 19 Apr 2024 14:59:30 +0900 Subject: [PATCH 335/502] tirivial. add policy_ids to createCluster workflow --- internal/usecase/cluster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index 2300b8dc..ce7574e8 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -198,7 +198,7 @@ func (u *ClusterUsecase) Create(ctx context.Context, dto model.Cluster) (cluster "cloud_account_id=" + tksCloudAccountId, "base_repo_branch=" + viper.GetString("revision"), "keycloak_url=" + viper.GetString("keycloak-address"), - //"manifest_repo_url=" + viper.GetString("git-base-url") + "/" + viper.GetString("git-account") + "/" + clusterId + "-manifests", + "policy_ids=" + strings.Join(dto.PolicyIds, ","), }, }) if err != nil { From 06d17ff1f8747c97eedb86eb92a77095c97e18b6 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 19 Apr 2024 15:46:32 +0900 Subject: [PATCH 336/502] fix workload widget panic --- internal/usecase/dashboard.go | 76 +++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 515936b7..b33cb47f 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -196,7 +196,7 @@ func (u *DashboardUsecase) GetResources(ctx context.Context, organizationId stri } filteredClusters := funk.Filter(clusters, func(x model.Cluster) bool { - return x.Status != domain.ClusterStatus_DELETED + return x.Status == domain.ClusterStatus_RUNNING }) var normal, abnormal int @@ -722,12 +722,12 @@ func (u *DashboardUsecase) GetPolicyEnforcement(ctx context.Context, organizatio // Y축 var series []domain.UnitNumber - var yRequiredData []int - var yOptionalData []int + yRequiredData := make([]int, 0) + yOptionalData := make([]int, 0) // X축 var xAxis *domain.Axis - var xData []string + xData := make([]string, 0) for key, val := range totalTemplate { // X axis Data @@ -787,13 +787,13 @@ func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationI // Y축 var series []domain.UnitNumber - var yDenyData []int - var yWarnData []int - var yDryrunData []int + yDenyData := make([]int, 0) + yWarnData := make([]int, 0) + yDryrunData := make([]int, 0) // X축 var xAxis *domain.Axis - var xData []string + xData := make([]string, 0) for _, res := range pm.Data.Result { policyTemplate := res.Metric.Kind @@ -873,122 +873,122 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin dwr := &domain.GetDashboardWorkloadResponse{} // Deployment count + var count int query := fmt.Sprintf("count (kube_deployment_status_replicas_available{taco_cluster=~'%s'} != 0)", clusterIdStr) wm, err := thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err := strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.DeploymentCount = count // Deployment pod count + count = 0 query = fmt.Sprintf("sum (kube_deployment_status_replicas_available{taco_cluster=~'%s'} )", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.DeploymentPodCount = count // StatefulSet count + count = 0 query = fmt.Sprintf("count (kube_statefulset_status_replicas_available{taco_cluster=~'%s'} != 0)", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.StatefulSetCount = count // StatefulSet pod count + count = 0 query = fmt.Sprintf("sum (kube_statefulset_status_replicas_available{taco_cluster=~'%s'} )", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.StatefulSetPodCount = count // DaemonSet count + count = 0 query = fmt.Sprintf("count (kube_daemonset_status_number_available{taco_cluster=~'%s'} != 0)", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.DaemonSetCount = count // DaemonSet pod count + count = 0 query = fmt.Sprintf("sum (kube_daemonset_status_number_available{taco_cluster=~'%s'} )", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.DaemonSetPodCount = count // CronJob count + count = 0 query = fmt.Sprintf("count (kube_cronjob_status_active{taco_cluster=~'%s'} != 0)", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.CronJobCount = count // CronJob pod count + count = 0 query = fmt.Sprintf("sum (kube_cronjob_status_active{taco_cluster=~'%s'} )", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.CronJobPodCount = count // Job count + count = 0 query = fmt.Sprintf("count (kube_job_status_active{taco_cluster=~'%s'} != 0)", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.JobCount = count // Job pod count + count = 0 query = fmt.Sprintf("sum (kube_job_status_active{taco_cluster=~'%s'} )", clusterIdStr) wm, err = thanosClient.Get(ctx, query) if err != nil { return nil, err } - count, err = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - if err != nil { - count = 0 + if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { + count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } dwr.JobPodCount = count From 5665311fb371e2f00f3ef4ca01d2c99ce3e1edb9 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 19 Apr 2024 18:04:06 +0900 Subject: [PATCH 337/502] bugfix. wrong constant value --- pkg/kubernetes/kubernetes.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index e54b2790..34cc90fc 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -394,9 +394,9 @@ func RemoveRoleBinding(ctx context.Context, kubeconfig []byte, projectName strin } const ( - leaderRole = "leader" - memberRole = "member" - viewerRole = "viewer" + leaderRole = "project-leader" + memberRole = "project-member" + viewerRole = "project-viewer" ) func getClusterRole(role, objName string) *rbacV1.ClusterRole { From a51341fb4f6d5abcadfc7db394f150be2813475a Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 19 Apr 2024 18:43:58 +0900 Subject: [PATCH 338/502] policy violation top5 --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/dashboard.go | 51 +++++++++++++ internal/route/route.go | 1 + internal/usecase/dashboard.go | 114 +++++++++++++++++++++++++--- pkg/domain/dashboard.go | 12 +-- pkg/thanos-client/client.go | 111 ++++++++++++++++++++------- pkg/thanos-client/types.go | 38 ++++++++++ 7 files changed, 278 insertions(+), 50 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index b58f2ace..3d21b9ec 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -124,6 +124,7 @@ const ( GetPolicyViolationLogDashboard GetPolicyStatisticsDashboard GetWorkloadDashboard + GetPolicyViolationTop5Dashboard // SystemNotificationTemplate Admin_CreateSystemNotificationTemplate diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index 4d91ed3b..f978f281 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -31,6 +31,7 @@ type IDashboardHandler interface { GetPolicyViolationLog(w http.ResponseWriter, r *http.Request) GetPolicyStatistics(w http.ResponseWriter, r *http.Request) GetWorkload(w http.ResponseWriter, r *http.Request) + GetPolicyViolationTop5(w http.ResponseWriter, r *http.Request) } type DashboardHandler struct { @@ -737,3 +738,53 @@ func (h *DashboardHandler) GetWorkload(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, dwr) } + +// GetPolicyViolationTop5 godoc +// +// @Tags Dashboard Widgets +// @Summary Get policy violation top5 +// @Description Get policy violation top5 +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param duration query string true "duration" +// @Param interval query string true "interval" +// @Success 200 {object} domain.GetDashboardPolicyViolationTop5Response +// @Router /organizations/{organizationId}/dashboards/widgets/policy-violation-top5 [get] +// @Security JWT +func (h *DashboardHandler) GetPolicyViolationTop5(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("%s: invalid organizationId", organizationId), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + query := r.URL.Query() + duration := query.Get("duration") + if duration == "" { + duration = "1d" // default + } + + interval := query.Get("interval") + if interval == "" { + interval = "1d" // default + } + + bcd, err := h.usecase.GetPolicyViolationTop5(r.Context(), organizationId, duration, interval) + if err != nil { + log.Error(r.Context(), "Failed to make policy bar chart data", err) + ErrorJSON(w, r, err) + return + } + + var out domain.GetDashboardPolicyViolationTop5Response + out.ChartType = "PolicyViolationTop5" + out.OrganizationId = organizationId + out.Name = "정책 위반 Top5" + out.Description = "정책 위반 Top5 데이터" + out.ChartData = *bcd + out.UpdatedAt = time.Now() + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/route/route.go b/internal/route/route.go index 4a0f47d9..63aab31f 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -212,6 +212,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-violation-log", customMiddleware.Handle(internalApi.GetPolicyViolationLogDashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolationLog))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-statistics", customMiddleware.Handle(internalApi.GetPolicyStatisticsDashboard, http.HandlerFunc(dashboardHandler.GetPolicyStatistics))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/workload", customMiddleware.Handle(internalApi.GetWorkloadDashboard, http.HandlerFunc(dashboardHandler.GetWorkload))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/widgets/policy-violation-top5", customMiddleware.Handle(internalApi.GetPolicyViolationTop5Dashboard, http.HandlerFunc(dashboardHandler.GetPolicyViolationTop5))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards", customMiddleware.Handle(internalApi.CreateDashboard, http.HandlerFunc(dashboardHandler.CreateDashboard))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/{dashboardKey}", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/{dashboardKey}", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index b33cb47f..def36d71 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -40,6 +40,7 @@ type IDashboardUsecase interface { GetPolicyViolation(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) GetPolicyViolationLog(ctx context.Context, organizationId string) (*domain.GetDashboardPolicyViolationLogResponse, error) GetWorkload(ctx context.Context, organizationId string) (*domain.GetDashboardWorkloadResponse, error) + GetPolicyViolationTop5(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) } type DashboardUsecase struct { @@ -851,7 +852,6 @@ func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationI } return bcd, nil - } func (u *DashboardUsecase) GetPolicyViolationLog(ctx context.Context, organizationId string) (*domain.GetDashboardPolicyViolationLogResponse, error) { @@ -875,7 +875,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // Deployment count var count int query := fmt.Sprintf("count (kube_deployment_status_replicas_available{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err := thanosClient.Get(ctx, query) + wm, err := thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -887,7 +887,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // Deployment pod count count = 0 query = fmt.Sprintf("sum (kube_deployment_status_replicas_available{taco_cluster=~'%s'} )", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -899,7 +899,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // StatefulSet count count = 0 query = fmt.Sprintf("count (kube_statefulset_status_replicas_available{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -911,7 +911,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // StatefulSet pod count count = 0 query = fmt.Sprintf("sum (kube_statefulset_status_replicas_available{taco_cluster=~'%s'} )", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -923,7 +923,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // DaemonSet count count = 0 query = fmt.Sprintf("count (kube_daemonset_status_number_available{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -935,7 +935,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // DaemonSet pod count count = 0 query = fmt.Sprintf("sum (kube_daemonset_status_number_available{taco_cluster=~'%s'} )", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -947,7 +947,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // CronJob count count = 0 query = fmt.Sprintf("count (kube_cronjob_status_active{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -959,7 +959,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // CronJob pod count count = 0 query = fmt.Sprintf("sum (kube_cronjob_status_active{taco_cluster=~'%s'} )", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -971,7 +971,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // Job count count = 0 query = fmt.Sprintf("count (kube_job_status_active{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -983,7 +983,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin // Job pod count count = 0 query = fmt.Sprintf("sum (kube_job_status_active{taco_cluster=~'%s'} )", clusterIdStr) - wm, err = thanosClient.Get(ctx, query) + wm, err = thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err } @@ -993,7 +993,99 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin dwr.JobPodCount = count return dwr, nil +} + +func (u *DashboardUsecase) GetPolicyViolationTop5(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) { + thanosClient, err := u.GetThanosClient(ctx, organizationId) + if err != nil { + return nil, errors.Wrap(err, "failed to create thanos client") + } + + durationSec, intervalSec := getDurationAndIntervalSec(duration, interval) + + clusterIdStr, err := u.GetFlatClusterIds(ctx, organizationId) + if err != nil { + return nil, err + } + + now := time.Now() + query := fmt.Sprintf("topk (5, sum by (kind) (opa_scorecard_constraint_violations{taco_cluster=~'%s'}))", clusterIdStr) + ptm, err := thanosClient.FetchPolicyTemplateRange(ctx, query, int(now.Unix())-durationSec, int(now.Unix()), intervalSec) + if err != nil { + return nil, err + } + + templateNames := make([]string, 0) + for _, result := range ptm.Data.Result { + templateNames = append(templateNames, result.Metric.Kind) + } + + // X축 + var xAxis *domain.Axis + xData := make([]string, 0) + + // Y축 + var series []domain.UnitNumber + yDenyData := make([]int, 0) + yWarnData := make([]int, 0) + yDryrunData := make([]int, 0) + + for _, templateName := range templateNames { + xData = append(xData, templateName) + + query = fmt.Sprintf("sum by (violation_enforcement) "+ + "(opa_scorecard_constraint_violations{taco_cluster='%s', kind='%s'})", clusterIdStr, templateName) + pvcm, err := thanosClient.FetchPolicyViolationCountRange(ctx, query, int(now.Unix())-durationSec, int(now.Unix()), intervalSec) + if err != nil { + return nil, err + } + + denyCount := 0 + warnCount := 0 + dryrunCount := 0 + for _, result := range pvcm.Data.Result { + switch policy := result.Metric.ViolationEnforcement; policy { + case "": + denyCount, _ = strconv.Atoi(result.Value[1].(string)) + case "warn": + warnCount, _ = strconv.Atoi(result.Value[1].(string)) + case "dryrun": + dryrunCount, _ = strconv.Atoi(result.Value[1].(string)) + } + } + yDenyData = append(yDenyData, denyCount) + yWarnData = append(yWarnData, warnCount) + yDryrunData = append(yDryrunData, dryrunCount) + } + + xAxis = &domain.Axis{ + Data: xData, + } + + denyUnit := domain.UnitNumber{ + Name: "거부", + Data: yDenyData, + } + series = append(series, denyUnit) + + warnUnit := domain.UnitNumber{ + Name: "경고", + Data: yWarnData, + } + series = append(series, warnUnit) + dryrunUnit := domain.UnitNumber{ + Name: "감사", + Data: yDryrunData, + } + series = append(series, dryrunUnit) + + bcd := &domain.BarChartData{ + XAxis: xAxis, + Series: series, + } + + return bcd, nil } func (u *DashboardUsecase) GetThanosClient(ctx context.Context, organizationId string) (thanos.ThanosClient, error) { diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index b1df588c..0f1c9a37 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -236,16 +236,8 @@ type GetDashboardWorkloadResponse struct { JobPodCount int `json:"jobPodCount"` } -type WorkloadMetric struct { - Status string `json:"status"` - Data struct { - ResultType string `json:"resultType"` - Result []struct { - Metric struct { - } `json:"metric"` - Value []interface{} `json:"value"` - } `json:"result"` - } `json:"data"` +type GetDashboardPolicyViolationTop5Response struct { + GetDashboardPolicyViolationResponse } type BarChart struct { diff --git a/pkg/thanos-client/client.go b/pkg/thanos-client/client.go index db18ea19..4dcf93e5 100644 --- a/pkg/thanos-client/client.go +++ b/pkg/thanos-client/client.go @@ -16,7 +16,10 @@ import ( type ThanosClient interface { Get(ctx context.Context, query string) (Metric, error) FetchRange(ctx context.Context, query string, start int, end int, step int) (out Metric, err error) + GetWorkload(ctx context.Context, query string) (WorkloadMetric, error) FetchPolicyRange(ctx context.Context, query string, start int, end int, step int) (*PolicyMetric, error) + FetchPolicyTemplateRange(ctx context.Context, query string, start int, end int, step int) (*PolicyTemplateMetric, error) + FetchPolicyViolationCountRange(ctx context.Context, query string, start int, end int, step int) (pvcm *PolicyViolationCountMetric, err error) } type ThanosClientImpl struct { @@ -24,12 +27,12 @@ type ThanosClientImpl struct { url string } -// New +// New function func New(host string, port int, ssl bool, token string) (ThanosClient, error) { var baseUrl string if ssl { if token == "" { - return nil, fmt.Errorf("thanos ssl enabled but token is empty.") + return nil, fmt.Errorf("thanos ssl enabled but token is empty") } baseUrl = fmt.Sprintf("%s:%d", host, port) } else { @@ -47,18 +50,18 @@ func New(host string, port int, ssl bool, token string) (ThanosClient, error) { } func (c *ThanosClientImpl) Get(ctx context.Context, query string) (out Metric, err error) { - url := c.url + "/api/v1/query?query=" + url.QueryEscape(query) + reqUrl := c.url + "/api/v1/query?query=" + url.QueryEscape(query) - log.Info(ctx, "url : ", url) - res, err := c.client.Get(url) + log.Info(ctx, "url : ", reqUrl) + res, err := c.client.Get(reqUrl) if err != nil { return out, err } if res == nil { - return out, fmt.Errorf("Failed to call thanos.") + return out, fmt.Errorf("failed to call thanos") } if res.StatusCode != 200 { - return out, fmt.Errorf("Invalid http status. return code: %d", res.StatusCode) + return out, fmt.Errorf("invalid http status. return code: %d", res.StatusCode) } defer func() { @@ -82,20 +85,41 @@ func (c *ThanosClientImpl) Get(ctx context.Context, query string) (out Metric, e } func (c *ThanosClientImpl) FetchRange(ctx context.Context, query string, start int, end int, step int) (out Metric, err error) { - rangeParam := fmt.Sprintf("&dedup=true&partial_response=false&start=%d&end=%d&step=%d&max_source_resolution=0s", start, end, step) - query = url.QueryEscape(query) + rangeParam - url := c.url + "/api/v1/query_range?query=" + query + body, err := c.fetchRange(ctx, query, start, end, step) + if err != nil { + return out, err + } + + /* + var a interface{} + err = json.Unmarshal(body, &a) + if err != nil { + return out, err + } + log.Info(helper.ModelToJson(a)) + */ + + err = json.Unmarshal(body, &out) + if err != nil { + return out, err + } + + return +} + +func (c *ThanosClientImpl) GetWorkload(ctx context.Context, query string) (out WorkloadMetric, err error) { + reqUrl := c.url + "/api/v1/query?query=" + url.QueryEscape(query) - log.Info(ctx, "url : ", url) - res, err := c.client.Get(url) + log.Info(ctx, "url : ", reqUrl) + res, err := c.client.Get(reqUrl) if err != nil { return out, err } if res == nil { - return out, fmt.Errorf("Failed to call thanos.") + return out, fmt.Errorf("failed to call thanos") } if res.StatusCode != 200 { - return out, fmt.Errorf("Invalid http status. return code: %d", res.StatusCode) + return out, fmt.Errorf("invalid http status. return code: %d", res.StatusCode) } defer func() { @@ -109,24 +133,58 @@ func (c *ThanosClientImpl) FetchRange(ctx context.Context, query string, start i return out, err } - /* - var a interface{} - err = json.Unmarshal(body, &a) - if err != nil { - return out, err - } - log.Info(helper.ModelToJson(a)) - */ - err = json.Unmarshal(body, &out) if err != nil { return out, err } + log.Info(ctx, helper.ModelToJson(out)) return } func (c *ThanosClientImpl) FetchPolicyRange(ctx context.Context, query string, start int, end int, step int) (pm *PolicyMetric, err error) { + body, err := c.fetchRange(ctx, query, start, end, step) + if err != nil { + return nil, err + } + + err = json.Unmarshal(body, &pm) + if err != nil { + return nil, err + } + + return pm, nil +} + +func (c *ThanosClientImpl) FetchPolicyTemplateRange(ctx context.Context, query string, start int, end int, step int) (ptm *PolicyTemplateMetric, err error) { + body, err := c.fetchRange(ctx, query, start, end, step) + if err != nil { + return nil, err + } + + err = json.Unmarshal(body, &ptm) + if err != nil { + return nil, err + } + + return ptm, nil +} + +func (c *ThanosClientImpl) FetchPolicyViolationCountRange(ctx context.Context, query string, start int, end int, step int) (pvcm *PolicyViolationCountMetric, err error) { + body, err := c.fetchRange(ctx, query, start, end, step) + if err != nil { + return nil, err + } + + err = json.Unmarshal(body, &pvcm) + if err != nil { + return nil, err + } + + return pvcm, nil +} + +func (c *ThanosClientImpl) fetchRange(ctx context.Context, query string, start int, end int, step int) ([]byte, error) { rangeParam := fmt.Sprintf("&dedup=true&partial_response=false&start=%d&end=%d&step=%d&max_source_resolution=0s", start, end, step) query = url.QueryEscape(query) + rangeParam requestUrl := c.url + "/api/v1/query_range?query=" + query @@ -153,10 +211,5 @@ func (c *ThanosClientImpl) FetchPolicyRange(ctx context.Context, query string, s return nil, err } - err = json.Unmarshal(body, &pm) - if err != nil { - return nil, err - } - - return pm, nil + return body, nil } diff --git a/pkg/thanos-client/types.go b/pkg/thanos-client/types.go index b01c14f3..cffb437a 100644 --- a/pkg/thanos-client/types.go +++ b/pkg/thanos-client/types.go @@ -42,3 +42,41 @@ type PolicyMetricDataResultMetric struct { Name string `json:"name"` Violation string `json:"violation_enforcement"` } + +type WorkloadMetric struct { + Status string `json:"status"` + Data struct { + ResultType string `json:"resultType"` + Result []struct { + Metric struct { + } `json:"metric"` + Value []interface{} `json:"value"` + } `json:"result"` + } `json:"data"` +} + +type PolicyTemplateMetric struct { + Status string `json:"status"` + Data struct { + ResultType string `json:"resultType"` + Result []struct { + Metric struct { + Kind string `json:"kind"` + } `json:"metric"` + Value []interface{} `json:"value"` + } `json:"result"` + } `json:"data"` +} + +type PolicyViolationCountMetric struct { + Status string `json:"status"` + Data struct { + ResultType string `json:"resultType"` + Result []struct { + Metric struct { + ViolationEnforcement string `json:"violation_enforcement,omitempty"` + } `json:"metric"` + Value []interface{} `json:"value"` + } `json:"result"` + } `json:"data"` +} From 88dac8b4d4d1be9e9adfd38693cc7d80df1f8cd3 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 19 Apr 2024 18:44:27 +0900 Subject: [PATCH 339/502] policy violation top5\n endpoint generation --- internal/delivery/api/generated_endpoints.go.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 8b457221..3fb31f0f 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -383,6 +383,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetWorkloadDashboard", Group: "Dashboard", }, + GetPolicyViolationTop5Dashboard: { + Name: "GetPolicyViolationTop5Dashboard", + Group: "Dashboard", + }, Admin_CreateSystemNotificationTemplate: { Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", @@ -1108,6 +1112,8 @@ func (e Endpoint) String() string { return "GetPolicyStatisticsDashboard" case GetWorkloadDashboard: return "GetWorkloadDashboard" + case GetPolicyViolationTop5Dashboard: + return "GetPolicyViolationTop5Dashboard" case Admin_CreateSystemNotificationTemplate: return "Admin_CreateSystemNotificationTemplate" case Admin_UpdateSystemNotificationTemplate: @@ -1570,6 +1576,8 @@ func GetEndpoint(name string) Endpoint { return GetPolicyStatisticsDashboard case "GetWorkloadDashboard": return GetWorkloadDashboard + case "GetPolicyViolationTop5Dashboard": + return GetPolicyViolationTop5Dashboard case "Admin_CreateSystemNotificationTemplate": return Admin_CreateSystemNotificationTemplate case "Admin_UpdateSystemNotificationTemplate": From 9d19fbc72a22263ae30bc873392009a2ce803f8d Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 19 Apr 2024 18:44:58 +0900 Subject: [PATCH 340/502] policy violation top5\n swagger generation --- api/swagger/docs.go | 80 ++++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.json | 80 ++++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 52 ++++++++++++++++++++++++++ 3 files changed, 212 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 5557423c..f16d23a9 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3582,6 +3582,57 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/dashboards/widgets/policy-violation-top5": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get policy violation top5", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get policy violation top5", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationTop5Response" + } + } + } + } + }, "/organizations/{organizationId}/dashboards/widgets/resources": { "get": { "security": [ @@ -12653,6 +12704,35 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationTop5Response": { + "type": "object", + "properties": { + "chartData": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData" + }, + "chartType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "string" + }, + "interval": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 807132e8..b35d6ae3 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3576,6 +3576,57 @@ } } }, + "/organizations/{organizationId}/dashboards/widgets/policy-violation-top5": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get policy violation top5", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Dashboard Widgets" + ], + "summary": "Get policy violation top5", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "duration", + "name": "duration", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "interval", + "name": "interval", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationTop5Response" + } + } + } + } + }, "/organizations/{organizationId}/dashboards/widgets/resources": { "get": { "security": [ @@ -12647,6 +12698,35 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationTop5Response": { + "type": "object", + "properties": { + "chartData": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData" + }, + "chartType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "string" + }, + "interval": { + "type": "string" + }, + "name": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index fb81bda2..e5f6fa25 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1748,6 +1748,25 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationTop5Response: + properties: + chartData: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.BarChartData' + chartType: + type: string + description: + type: string + duration: + type: string + interval: + type: string + name: + type: string + organizationId: + type: string + updatedAt: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardResourcesResponse: properties: resources: @@ -6595,6 +6614,39 @@ paths: summary: Get policy violation log tags: - Dashboard Widgets + /organizations/{organizationId}/dashboards/widgets/policy-violation-top5: + get: + consumes: + - application/json + description: Get policy violation top5 + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: duration + in: query + name: duration + required: true + type: string + - description: interval + in: query + name: interval + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationTop5Response' + security: + - JWT: [] + summary: Get policy violation top5 + tags: + - Dashboard Widgets /organizations/{organizationId}/dashboards/widgets/resources: get: consumes: From 4468e9cba4e77160952f97110431fa18b0352a69 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sun, 21 Apr 2024 13:16:01 +0900 Subject: [PATCH 341/502] =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../policy-template/policy-template-rego.go | 123 +++++++++++++++++- 1 file changed, 116 insertions(+), 7 deletions(-) diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index e5f83937..8a9e3731 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/open-policy-agent/opa/ast" + "github.com/open-policy-agent/opa/types" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/pkg/domain" "golang.org/x/exp/maps" @@ -16,16 +17,85 @@ const ( input_param_prefix = "input.parameters" input_extract_pattern = `input(\.parameters|\[\"parameters\"\])((\[\"[\w\-]+\"\])|(\[_\])|(\.\w+))*` //(\.\w+)*` // (\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))*` // input_extract_pattern = `input\.parameters((\[\".+\"\])?(\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))+` - obj_get_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+)\, \"*([^,\"]+)\"*, [^\)]+\)` - package_name_regex = `package ([\w\.]+)[\n\r]+` - import_regex = `import ([\w\.]+)[\n\r]+` + obj_get_list_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+), \"([^\"]+)\", \[\]\)` + obj_get_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+), \"([^\"]+)\", [^\)]+\)` + package_name_regex = `package ([\w\.]+)[\n\r]+` + import_regex = `import ([\w\.]+)[\n\r]+` ) var ( input_extract_regex = regexp.MustCompile(input_extract_pattern) + obj_get_list_regex = regexp.MustCompile(obj_get_list_pattern) obj_get_regex = regexp.MustCompile(obj_get_pattern) + array_param_map = buildArrayParameterMap() ) +// OPA 내장 함수 중 array 인자를 가진 함수와 array 인자의 위치를 담은 자료구조를 생성한다. +// // OPA 내장 함수 목록은 정책에 상관없으므로 처음 로딩될 때 한 번만 호출해 변수에 담아두고 사용하면 된다. +// OPA 엔진 버전에 따라 달라진다. 0.62 버전 기준으로 이 함수의 결과 값은 다음과 같다. +// map[all:[true] any:[true] array.concat:[true true] array.reverse:[true] array.slice:[true false false] concat:[false true] count:[true] glob.match:[false true false] graph.reachable:[false true] graph.reachable_paths:[false true] internal.print:[true] json.filter:[false true] json.patch:[false true] json.remove:[false true] max:[true] min:[true] net.cidr_contains_matches:[true true] net.cidr_merge:[true] object.filter:[false true] object.remove:[false true] object.subset:[true true] object.union_n:[true] product:[true] sort:[true] sprintf:[false true] strings.any_prefix_match:[true true] strings.any_suffix_match:[true true] sum:[true] time.clock:[true] time.date:[true] time.diff:[true true] time.format:[true] time.weekday:[true]] +func buildArrayParameterMap() map[string][]bool { + compiler := ast.NewCompiler() + + // 아주 단순한 rego 코드를 컴파일해도 컴파일러의 모든 Built-In 함수 정보를 컴파일 할 수 있음 + mod, err := ast.ParseModuleWithOpts("hello", "package hello\n hello {input.message = \"world\"}", ast.ParserOptions{}) + if err != nil { + return nil + } + + // 컴파일을 수행해야 Built-in 함수 정보 로딩할 수 있음 + modules := map[string]*ast.Module{} + modules["hello"] = mod + compiler.Compile(modules) + + return getArrayParameterMap(compiler) +} + +func getArrayParameterMap(compiler *ast.Compiler) map[string][]bool { + capabilities := compiler.Capabilities() + + var result = map[string][]bool{} + + if capabilities != nil { + for _, builtin := range capabilities.Builtins { + args := builtin.Decl.FuncArgs().Args + isArrayParam := make([]bool, len(args)) + + arrayCount := 0 + for i, typeVal := range args { + isArrayParam[i] = IsArray(typeVal) + + if isArrayParam[i] { + arrayCount += 1 + } + } + + if arrayCount > 0 { + result[builtin.Name] = isArrayParam + } + } + } + + return result +} + +func IsArray(t types.Type) bool { + switch specific_type := t.(type) { + case *types.Array: + return true + case types.Any: + { + for _, anyType := range specific_type { + if IsArray(anyType) { + return true + } + } + } + } + + return false +} + func extractInputExprFromModule(module *ast.Module) []string { rules := module.Rules @@ -69,6 +139,9 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str exprs := rule.Body localAssignMap := map[string]string{} + // if strings.Contains(rule.String(), "statefulset_vct_noname_msg") { + // fmt.Printf("1111111 %+ v%+v\n", rule.Head.Name, rule.Head.Key.String()) + // } for i, param := range passedParams { if isSubstitutionRequired(param) { argName := rule.Head.Args[i].String() @@ -95,7 +168,7 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str if expr.IsCall() { call, _ := expr.Terms.([]*ast.Term) - if len(call) > 2 { + if len(call) > 1 { ruleName := call[0].String() args := call[1:] @@ -103,6 +176,18 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str inputPassed, passingParams := processingInputArgs(args, localAssignMap) if inputPassed { + if is_arrays, ok := array_param_map[ruleName]; ok { + for i, passingParam := range passingParams { + is_array := is_arrays[i] + + if is_array && strings.HasPrefix(passingParam, "input.parameters.") && + !strings.HasSuffix(passingParam, "[_]") { + + paramRefs[passingParam+"[_]"] = "1" + } + } + } + for _, nvrule := range nonViolatonRule { if ruleName == nvrule.Head.Name.String() { @@ -163,6 +248,17 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str return false }) } + + headKey := rule.Head.Key + + if headKey != nil { + for _, nvrule := range nonViolatonRule { + ruleName := nvrule.Head.Name.String() + if strings.Contains(headKey.String(), ruleName) { + processRule(nvrule, paramRefs, []string{}, nonViolatonRule) + } + } + } } // object.get(object.get(input, "parameters", {}), "exemptImages", [])) -> input.parameters.exemptImages와 같은 패턴 변환 @@ -171,8 +267,10 @@ func replaceAllObjectGet(expr string) string { return expr } - result := obj_get_regex.ReplaceAllString(expr, "$1.$2") + result := obj_get_list_regex.ReplaceAllString(expr, "$1.$2"+`[_]`) + result = obj_get_regex.ReplaceAllString(result, "$1.$2") + // 정규식의 영향 없음 그냥 리턴 if result == expr { return expr } @@ -194,8 +292,9 @@ func processingInputArgs(args []*ast.Term, localAssignMap map[string]string) (bo if isSubstitutionRequired(arg) { passingParams = append(passingParams, arg) inputPassed = true + } else { + passingParams = append(passingParams, "") } - passingParams = append(passingParams, "") } } return inputPassed, passingParams @@ -333,6 +432,16 @@ func findKey(defs []*domain.ParameterDef, key string) *domain.ParameterDef { return nil } +func cutTrailingArrayNote(val string) string { + cut, found := strings.CutSuffix(val, "[_]") + + if found { + return cutTrailingArrayNote(cut) + } + + return val +} + func createKey(key string, isLast bool) *domain.ParameterDef { var finalType string @@ -340,7 +449,7 @@ func createKey(key string, isLast bool) *domain.ParameterDef { isArray := false if strings.HasSuffix(pKey, "[_]") { - pKey, _ = strings.CutSuffix(pKey, "[_]") + pKey = cutTrailingArrayNote(pKey) isArray = true } From b49ac01f5c6c9d30458ba7e6b3d46233d0857176 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 22 Apr 2024 14:41:17 +0900 Subject: [PATCH 342/502] Fix a bug where only the existing leader of a project was deleted if the user did not exist when changing the project leader. --- internal/usecase/project.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index a5f3bf0a..8bb2eaa5 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -183,25 +183,38 @@ func (u *ProjectUsecase) UpdateProject(ctx context.Context, p *model.Project, ne p.ProjectNamespaces = nil p.ProjectMembers = nil + // only project table update if err := u.projectRepo.UpdateProject(ctx, p); err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to update project.") } if newLeaderId != "" && currentLeaderId != newLeaderId { - if err := u.RemoveProjectMember(ctx, p.OrganizationId, currentMemberId); err != nil { - log.Error(ctx, err) - return errors.Wrap(err, "Failed to remove project member.") - } - pu, err := u.GetProjectUser(ctx, newLeaderId) if err != nil { return err } if pu == nil { - return errors.Wrap(err, "No userid") + return errors.Wrap(err, "The user doesn't exist.") + } + + // If project leader exists, remove leader + if currentMemberId != "" { + if err := u.RemoveProjectMember(ctx, p.OrganizationId, currentMemberId); err != nil { + log.Error(ctx, err) + return errors.Wrap(err, "Failed to remove project member.") + } + } + + if projectRoleId == "" { + pr, err := u.projectRepo.GetProjectRoleByName(ctx, "project-leader") + if err != nil { + return err + } + projectRoleId = pr.ID } + // If the Member does not exist in the Project, insert it, but if it does, update it. pm, err := u.projectRepo.GetProjectMemberByUserId(ctx, p.ID, newLeaderId) if err != nil { return err From a6b84a45e7bb70de56b0c2e3cd40c6a86ee77260 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 22 Apr 2024 15:04:56 +0900 Subject: [PATCH 343/502] =?UTF-8?q?Template=20CR=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=20=ED=8F=AC=EB=A7=B7=ED=8C=85=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../policy-template/policy-template-rego.go | 30 +++++++++++++++++++ internal/policy-template/tkspolicytemplate.go | 4 +-- internal/usecase/policy-template.go | 6 ++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index 8a9e3731..ab2665fa 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/open-policy-agent/opa/ast" + "github.com/open-policy-agent/opa/format" "github.com/open-policy-agent/opa/types" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/pkg/domain" @@ -558,3 +559,32 @@ func GetPackageFromRegoCode(regoCode string) string { return "" } + +func FormatRegoCode(rego string) string { + packageName := GetPackageFromRegoCode(rego) + + // 패키지 명을 파싱할 수 없으면 포맷팅할 수 있는 코드가 아닐 것이므로 그냥 리턴 + if packageName == "" { + return rego + } + + bytes, err := format.Source("rego", []byte(rego)) + + if err != nil { + return rego + } + + return strings.Replace(string(bytes), "\t", " ", -1) +} + +func FormatLibCode(libs []string) []string { + processedLibs := processLibs(libs) + + result := make([]string, len(processedLibs)) + + for i, lib := range processedLibs { + result[i] = FormatRegoCode(lib) + } + + return result +} diff --git a/internal/policy-template/tkspolicytemplate.go b/internal/policy-template/tkspolicytemplate.go index 45c2f2a3..9cb8e27f 100644 --- a/internal/policy-template/tkspolicytemplate.go +++ b/internal/policy-template/tkspolicytemplate.go @@ -47,8 +47,8 @@ type Validation struct { type Target struct { Target string `json:"target,omitempty"` - Rego string `json:"rego,omitempty" yaml:"rego,omitempty,flow"` - Libs []string `json:"libs,omitempty" yaml:"libs,omitempty,flow"` + Rego string `json:"rego,omitempty" yaml:"rego,omitempty"` + Libs []string `json:"libs,omitempty" yaml:"libs,omitempty"` Code []Code `json:"code,omitempty"` } diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index b235e781..3d60b872 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -117,6 +117,9 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp userId := user.GetUserId() dto.CreatorId = &userId + dto.Rego = policytemplate.FormatRegoCode(dto.Rego) + dto.Libs = policytemplate.FormatLibCode(dto.Libs) + id, err := u.repo.Create(ctx, dto) if err != nil { @@ -478,6 +481,9 @@ func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, return "", httpErrors.NewBadRequestError(err, "PT_INVALID_PARAMETER_SCHEMA", "") } + rego = policytemplate.FormatRegoCode(rego) + libs = policytemplate.FormatLibCode(libs) + return u.repo.CreatePolicyTemplateVersion(ctx, policyTemplateId, newVersion, schema, rego, libs) } From 922ce3ec6852d1bf43f1b6f0e04579fad05c9d55 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 22 Apr 2024 15:31:08 +0900 Subject: [PATCH 344/502] bugfix. fix update-my-profile --- internal/delivery/http/user.go | 14 +++++++------- internal/repository/user.go | 3 ++- pkg/domain/user.go | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index 4a572974..d886c251 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -507,7 +507,7 @@ func (u UserHandler) GetMyProfile(w http.ResponseWriter, r *http.Request) { // @Security JWT func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] + _, ok := vars["organizationId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("organizationId not found in path"), "C_INVALID_ORGANIZATION_ID", "")) return @@ -535,16 +535,16 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - var user model.User - if err = serializer.Map(r.Context(), input, &user); err != nil { - log.Error(r.Context(), err) + user, err := u.usecase.Get(r.Context(), requestUserInfo.GetUserId()) + if err != nil { ErrorJSON(w, r, err) return } + user.Name = input.Name + user.Email = input.Email + user.Department = input.Department - user.ID = requestUserInfo.GetUserId() - user.OrganizationId = organizationId - resUser, err := u.usecase.Update(ctx, &user) + resUser, err := u.usecase.Update(ctx, user) if err != nil { if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) diff --git a/internal/repository/user.go b/internal/repository/user.go index 72a129df..0d8f200a 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -191,7 +191,8 @@ func (r *UserRepository) ListUsersByRole(ctx context.Context, organizationId str } func (r *UserRepository) Update(ctx context.Context, user *model.User) (*model.User, error) { - res := r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", user.ID).Updates(model.User{ + res := r.db.WithContext(ctx).Model(&model.User{}).Where("id = ?", user.ID). + Select("Name", "Email", "Department", "Description").Updates(model.User{ Name: user.Name, Email: user.Email, Department: user.Department, diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 1258f1f4..030c64fd 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -154,7 +154,7 @@ type UpdateMyProfileRequest struct { Password string `json:"password" validate:"required"` Name string `json:"name" validate:"required,min=1,max=30"` Email string `json:"email" validate:"required,email"` - Department string `json:"department" validate:"required,min=0,max=50"` + Department string `json:"department" validate:"min=0,max=50"` } type UpdateMyProfileResponse struct { From dcb7b33a9ce19e0dd72e06c510c954b49f4bfaea Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 22 Apr 2024 15:34:33 +0900 Subject: [PATCH 345/502] change workload dashboard return type --- internal/usecase/dashboard.go | 77 ++++------------------------------- pkg/domain/dashboard.go | 31 +++++++++----- 2 files changed, 29 insertions(+), 79 deletions(-) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index def36d71..f97a0f48 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -870,11 +870,11 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin return nil, err } - dwr := &domain.GetDashboardWorkloadResponse{} + dwr := &domain.GetDashboardWorkloadResponse{Title: "자원별 Pod 배포 현황"} - // Deployment count - var count int - query := fmt.Sprintf("count (kube_deployment_status_replicas_available{taco_cluster=~'%s'} != 0)", clusterIdStr) + // Deployment pod count + count := 0 + query := fmt.Sprintf("sum (kube_deployment_status_replicas_available{taco_cluster=~'%s'} )", clusterIdStr) wm, err := thanosClient.GetWorkload(ctx, query) if err != nil { return nil, err @@ -882,31 +882,8 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } - dwr.DeploymentCount = count - // Deployment pod count - count = 0 - query = fmt.Sprintf("sum (kube_deployment_status_replicas_available{taco_cluster=~'%s'} )", clusterIdStr) - wm, err = thanosClient.GetWorkload(ctx, query) - if err != nil { - return nil, err - } - if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { - count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - } - dwr.DeploymentPodCount = count - - // StatefulSet count - count = 0 - query = fmt.Sprintf("count (kube_statefulset_status_replicas_available{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err = thanosClient.GetWorkload(ctx, query) - if err != nil { - return nil, err - } - if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { - count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - } - dwr.StatefulSetCount = count + dwr.Data = append(dwr.Data, domain.WorkloadData{Name: "Deployments", Value: count}) // StatefulSet pod count count = 0 @@ -918,19 +895,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } - dwr.StatefulSetPodCount = count - - // DaemonSet count - count = 0 - query = fmt.Sprintf("count (kube_daemonset_status_number_available{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err = thanosClient.GetWorkload(ctx, query) - if err != nil { - return nil, err - } - if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { - count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - } - dwr.DaemonSetCount = count + dwr.Data = append(dwr.Data, domain.WorkloadData{Name: "StatefulSets", Value: count}) // DaemonSet pod count count = 0 @@ -942,19 +907,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } - dwr.DaemonSetPodCount = count - - // CronJob count - count = 0 - query = fmt.Sprintf("count (kube_cronjob_status_active{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err = thanosClient.GetWorkload(ctx, query) - if err != nil { - return nil, err - } - if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { - count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - } - dwr.CronJobCount = count + dwr.Data = append(dwr.Data, domain.WorkloadData{Name: "DaemonSets", Value: count}) // CronJob pod count count = 0 @@ -966,19 +919,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } - dwr.CronJobPodCount = count - - // Job count - count = 0 - query = fmt.Sprintf("count (kube_job_status_active{taco_cluster=~'%s'} != 0)", clusterIdStr) - wm, err = thanosClient.GetWorkload(ctx, query) - if err != nil { - return nil, err - } - if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { - count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) - } - dwr.JobCount = count + dwr.Data = append(dwr.Data, domain.WorkloadData{Name: "CronJobs", Value: count}) // Job pod count count = 0 @@ -990,7 +931,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin if len(wm.Data.Result) > 0 && len(wm.Data.Result[0].Value) > 1 { count, _ = strconv.Atoi(wm.Data.Result[0].Value[1].(string)) } - dwr.JobPodCount = count + dwr.Data = append(dwr.Data, domain.WorkloadData{Name: "Jobs", Value: count}) return dwr, nil } diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 0f1c9a37..8aa6bb45 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -223,18 +223,27 @@ type GetDashboardPolicyStatisticsResponse struct { PolicyStatisticsResponse } -type GetDashboardWorkloadResponse struct { - DeploymentCount int `json:"deploymentCount"` - DeploymentPodCount int `json:"deploymentPodCount"` - StatefulSetCount int `json:"statefulSetCount"` - StatefulSetPodCount int `json:"statefulSetPodCount"` - DaemonSetCount int `json:"daemonSetCount"` - DaemonSetPodCount int `json:"daemonSetPodCount"` - CronJobCount int `json:"cronJobCount"` - CronJobPodCount int `json:"cronJobPodCount"` - JobCount int `json:"jobCount"` - JobPodCount int `json:"jobPodCount"` +type WorkloadData struct { + Name string `json:"name"` + Value int `json:"value"` } +type GetDashboardWorkloadResponse struct { + Title string `json:"title"` + Data []WorkloadData `json:"data"` +} + +//type GetDashboardWorkloadResponse struct { +// DeploymentCount int `json:"deploymentCount"` +// DeploymentPodCount int `json:"deploymentPodCount"` +// StatefulSetCount int `json:"statefulSetCount"` +// StatefulSetPodCount int `json:"statefulSetPodCount"` +// DaemonSetCount int `json:"daemonSetCount"` +// DaemonSetPodCount int `json:"daemonSetPodCount"` +// CronJobCount int `json:"cronJobCount"` +// CronJobPodCount int `json:"cronJobPodCount"` +// JobCount int `json:"jobCount"` +// JobPodCount int `json:"jobPodCount"` +//} type GetDashboardPolicyViolationTop5Response struct { GetDashboardPolicyViolationResponse From c5b63a1353661891e215b6f6863eaf4748100fca Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 22 Apr 2024 15:35:37 +0900 Subject: [PATCH 346/502] change workload dashboard return type\n swagger generate --- api/swagger/docs.go | 46 ++++++++++++++++------------------------ api/swagger/swagger.json | 46 ++++++++++++++++------------------------ api/swagger/swagger.yaml | 33 ++++++++++++---------------- pkg/domain/dashboard.go | 13 ------------ 4 files changed, 49 insertions(+), 89 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index f16d23a9..6558515d 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -12775,35 +12775,14 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse": { "type": "object", "properties": { - "cronJobCount": { - "type": "integer" - }, - "cronJobPodCount": { - "type": "integer" - }, - "daemonSetCount": { - "type": "integer" - }, - "daemonSetPodCount": { - "type": "integer" - }, - "deploymentCount": { - "type": "integer" - }, - "deploymentPodCount": { - "type": "integer" - }, - "jobCount": { - "type": "integer" - }, - "jobPodCount": { - "type": "integer" - }, - "statefulSetCount": { - "type": "integer" + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WorkloadData" + } }, - "statefulSetPodCount": { - "type": "integer" + "title": { + "type": "string" } } }, @@ -16121,6 +16100,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.WorkloadData": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index b35d6ae3..4cc6f13d 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -12769,35 +12769,14 @@ "github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse": { "type": "object", "properties": { - "cronJobCount": { - "type": "integer" - }, - "cronJobPodCount": { - "type": "integer" - }, - "daemonSetCount": { - "type": "integer" - }, - "daemonSetPodCount": { - "type": "integer" - }, - "deploymentCount": { - "type": "integer" - }, - "deploymentPodCount": { - "type": "integer" - }, - "jobCount": { - "type": "integer" - }, - "jobPodCount": { - "type": "integer" - }, - "statefulSetCount": { - "type": "integer" + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.WorkloadData" + } }, - "statefulSetPodCount": { - "type": "integer" + "title": { + "type": "string" } } }, @@ -16115,6 +16094,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.WorkloadData": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "integer" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index e5f6fa25..5c42d056 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1794,26 +1794,12 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardWorkloadResponse: properties: - cronJobCount: - type: integer - cronJobPodCount: - type: integer - daemonSetCount: - type: integer - daemonSetPodCount: - type: integer - deploymentCount: - type: integer - deploymentPodCount: - type: integer - jobCount: - type: integer - jobPodCount: - type: integer - statefulSetCount: - type: integer - statefulSetPodCount: - type: integer + data: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.WorkloadData' + type: array + title: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.GetMandatoryPoliciesResponse: properties: @@ -4021,6 +4007,13 @@ definitions: widgetKey: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.WorkloadData: + properties: + name: + type: string + value: + type: integer + type: object github_com_openinfradev_tks-api_pkg_domain_admin.AddPermittedPolicyTemplatesForOrganizationRequest: properties: policyTemplateIds: diff --git a/pkg/domain/dashboard.go b/pkg/domain/dashboard.go index 8aa6bb45..e6cf09c9 100644 --- a/pkg/domain/dashboard.go +++ b/pkg/domain/dashboard.go @@ -232,19 +232,6 @@ type GetDashboardWorkloadResponse struct { Data []WorkloadData `json:"data"` } -//type GetDashboardWorkloadResponse struct { -// DeploymentCount int `json:"deploymentCount"` -// DeploymentPodCount int `json:"deploymentPodCount"` -// StatefulSetCount int `json:"statefulSetCount"` -// StatefulSetPodCount int `json:"statefulSetPodCount"` -// DaemonSetCount int `json:"daemonSetCount"` -// DaemonSetPodCount int `json:"daemonSetPodCount"` -// CronJobCount int `json:"cronJobCount"` -// CronJobPodCount int `json:"cronJobPodCount"` -// JobCount int `json:"jobCount"` -// JobPodCount int `json:"jobPodCount"` -//} - type GetDashboardPolicyViolationTop5Response struct { GetDashboardPolicyViolationResponse } From 4f12238930e019f44e5e5068490a7da774255546 Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 22 Apr 2024 17:04:41 +0900 Subject: [PATCH 347/502] bugfix. fix delete tks role API --- internal/usecase/role.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/usecase/role.go b/internal/usecase/role.go index a07f0e92..58344f2a 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -57,7 +57,11 @@ func (r RoleUsecase) GetTksRole(ctx context.Context, organizationId string, id s } func (r RoleUsecase) DeleteTksRole(ctx context.Context, organizationId string, id string) error { - err := r.kc.DeleteGroup(ctx, organizationId, id) + role, err := r.repo.GetTksRole(ctx, organizationId, id) + if err != nil { + return err + } + err = r.kc.DeleteGroup(ctx, organizationId, role.Name+"@"+organizationId) if err != nil { return err } From e6694883e0e6b9ca60fed753a764123110dfa26d Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 22 Apr 2024 17:08:02 +0900 Subject: [PATCH 348/502] Add a search by project name --- internal/delivery/http/project.go | 8 ++++++-- internal/repository/project.go | 22 ++++++++++++++-------- internal/usecase/project.go | 10 +++++----- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 91d389b0..8bc55f74 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -166,6 +166,7 @@ func (p ProjectHandler) CreateProject(w http.ResponseWriter, r *http.Request) { // @Produce json // @Param organizationId path string true "Organization ID" // @Param query query string false "(all | only)" +// @Param projectName query string false "Project Name" // @Success 200 {object} domain.GetProjectsResponse // @Router /organizations/{organizationId}/projects [get] // @Security JWT @@ -184,6 +185,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { if queryName == "only" { onlyMyProject = true } + projectName := urlParams.Get("projectName") pg := pagination.NewPagination(&urlParams) @@ -194,7 +196,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, fmt.Errorf("failed to retrieve user info from request")) } myUserId := requestUserInfo.GetUserId().String() - pr, err := p.usecase.GetProjects(r.Context(), organizationId, myUserId, onlyMyProject, pg) + pr, err := p.usecase.GetProjects(r.Context(), organizationId, myUserId, onlyMyProject, projectName, pg) if err != nil { log.Error(r.Context(), "Failed to retrieve projects ", err) ErrorJSON(w, r, err) @@ -222,6 +224,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param organizationId path string true "Organization ID" +// @Param projectName query string false "Project Name" // @Success 200 {object} domain.GetProjectsResponse // @Router /admin/organizations/{organizationId}/projects [get] // @Security JWT @@ -235,8 +238,9 @@ func (p ProjectHandler) Admin_GetProjects(w http.ResponseWriter, r *http.Request } urlParams := r.URL.Query() + projectName := urlParams.Get("projectName") pg := pagination.NewPagination(&urlParams) - pr, err := p.usecase.GetProjects(r.Context(), organizationId, "", false, pg) + pr, err := p.usecase.GetProjects(r.Context(), organizationId, "", false, projectName, pg) if err != nil { log.Error(r.Context(), "Failed to retrieve projects ", err) ErrorJSON(w, r, err) diff --git a/internal/repository/project.go b/internal/repository/project.go index 48a3091b..96f8ee56 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -16,9 +16,9 @@ import ( type IProjectRepository interface { CreateProject(ctx context.Context, p *model.Project) (string, error) - GetProjects(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) - GetProjectsByUserId(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) ([]domain.ProjectResponse, error) - GetAllProjects(ctx context.Context, organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) + GetProjects(ctx context.Context, organizationId string, userId uuid.UUID, projectName string, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProjectsByUserId(ctx context.Context, organizationId string, userId uuid.UUID, projectName string, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetAllProjects(ctx context.Context, organizationId string, projectName string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) GetProjectById(ctx context.Context, organizationId string, projectId string) (*model.Project, error) GetProjectByIdAndLeader(ctx context.Context, organizationId string, projectId string) (*model.Project, error) GetProjectByName(ctx context.Context, organizationId string, projectName string) (*model.Project, error) @@ -64,7 +64,7 @@ func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) return p.ID, nil } -func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId string, userId uuid.UUID, projectName string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ @@ -100,6 +100,7 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ " and p.organization_id = @organizationId "+ + " and p.name like '%"+projectName+"%' "+ "union "+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " false as is_my_project, '' as project_role_id, '' as project_role_name, "+ @@ -135,6 +136,7 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " group by p.id) as pm_count on p.id = pm_count.project_id"+ " where p.id = pm.project_id "+ " and p.organization_id = @organizationId "+ + " and p.name like '%"+projectName+"%' "+ " and p.id not in (select projects.id "+ " from projects "+ " left join project_members on project_members.project_id = projects.id "+ @@ -149,7 +151,7 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri return pr, nil } -func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizationId string, userId uuid.UUID, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizationId string, userId uuid.UUID, projectName string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ @@ -184,7 +186,9 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio " where p.organization_id = @organizationId "+ " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ - " and p.organization_id = @organizationId", sql.Named("organizationId", organizationId), sql.Named("userId", userId)). + " and p.organization_id = @organizationId "+ + " and p.name like '%"+projectName+"%' ", + sql.Named("organizationId", organizationId), sql.Named("userId", userId)). Scan(&pr) if res.Error != nil { @@ -200,7 +204,7 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio return pr, nil } -func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId string, projectName string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " false as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ @@ -234,7 +238,9 @@ func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId s " where p.organization_id = @organizationId "+ " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ - " and p.organization_id = @organizationId", sql.Named("organizationId", organizationId)). + " and p.organization_id = @organizationId "+ + " and p.name like '%"+projectName+"%' ", + sql.Named("organizationId", organizationId)). Scan(&pr) if res.Error != nil { diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 8bb2eaa5..4b6635aa 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -30,7 +30,7 @@ const ( type IProjectUsecase interface { CreateProject(ctx context.Context, p *model.Project) (string, error) - GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) ([]domain.ProjectResponse, error) + GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, projectName string, pg *pagination.Pagination) ([]domain.ProjectResponse, error) GetProject(ctx context.Context, organizationId string, projectId string) (*model.Project, error) GetProjectWithLeader(ctx context.Context, organizationId string, projectId string) (*model.Project, error) IsProjectNameExist(ctx context.Context, organizationId string, projectName string) (bool, error) @@ -113,9 +113,9 @@ func (u *ProjectUsecase) CreateProject(ctx context.Context, p *model.Project) (s return projectId, nil } -func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { +func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, userId string, onlyMyProject bool, projectName string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { if userId == "" { - if pr, err = u.projectRepo.GetAllProjects(ctx, organizationId, pg); err != nil { + if pr, err = u.projectRepo.GetAllProjects(ctx, organizationId, projectName, pg); err != nil { log.Error(ctx, err) return nil, errors.Wrap(err, "Failed to get projects.") } @@ -126,9 +126,9 @@ func (u *ProjectUsecase) GetProjects(ctx context.Context, organizationId string, return nil, errors.Wrap(err, "Failed to parse uuid to string") } if !onlyMyProject { - pr, err = u.projectRepo.GetProjects(ctx, organizationId, userUuid, pg) + pr, err = u.projectRepo.GetProjects(ctx, organizationId, userUuid, projectName, pg) } else { - pr, err = u.projectRepo.GetProjectsByUserId(ctx, organizationId, userUuid, pg) + pr, err = u.projectRepo.GetProjectsByUserId(ctx, organizationId, userUuid, projectName, pg) } if err != nil { log.Error(ctx, err) From 7b00359267402bfd796a96f0790fe08408922207 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Mon, 22 Apr 2024 17:08:42 +0900 Subject: [PATCH 349/502] Add a search by project name\n swagger generate --- api/swagger/docs.go | 13 ++++++++++++- api/swagger/swagger.json | 13 ++++++++++++- api/swagger/swagger.yaml | 9 ++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 6558515d..17836561 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -350,6 +350,12 @@ const docTemplate = `{ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "Project Name", + "name": "projectName", + "in": "query" } ], "responses": { @@ -5281,6 +5287,12 @@ const docTemplate = `{ "description": "(all | only)", "name": "query", "in": "query" + }, + { + "type": "string", + "description": "Project Name", + "name": "projectName", + "in": "query" } ], "responses": { @@ -15371,7 +15383,6 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest": { "type": "object", "required": [ - "department", "email", "name", "password" diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 4cc6f13d..78268f7b 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -344,6 +344,12 @@ "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "Project Name", + "name": "projectName", + "in": "query" } ], "responses": { @@ -5275,6 +5281,12 @@ "description": "(all | only)", "name": "query", "in": "query" + }, + { + "type": "string", + "description": "Project Name", + "name": "projectName", + "in": "query" } ], "responses": { @@ -15365,7 +15377,6 @@ "github_com_openinfradev_tks-api_pkg_domain.UpdateMyProfileRequest": { "type": "object", "required": [ - "department", "email", "name", "password" diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 5c42d056..49f7ed45 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -3525,7 +3525,6 @@ definitions: password: type: string required: - - department - email - name - password @@ -4515,6 +4514,10 @@ paths: name: organizationId required: true type: string + - description: Project Name + in: query + name: projectName + type: string produces: - application/json responses: @@ -7630,6 +7633,10 @@ paths: in: query name: query type: string + - description: Project Name + in: query + name: projectName + type: string produces: - application/json responses: From 08f45fad2da3644bedabeb4d0eed3d463e579b7e Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 22 Apr 2024 23:42:54 +0900 Subject: [PATCH 350/502] feature. add policy notification hadlers --- api/swagger/docs.go | 187 ++++++++++++++++++ api/swagger/swagger.json | 187 ++++++++++++++++++ api/swagger/swagger.yaml | 121 ++++++++++++ internal/delivery/api/endpoint.go | 3 + .../delivery/api/generated_endpoints.go.go | 8 + internal/delivery/http/cloud-account.go | 10 + internal/delivery/http/policy-notification.go | 123 ++++++++++++ .../delivery/http/system-notification-rule.go | 10 + internal/delivery/http/system-notification.go | 16 +- internal/model/system-notification.go | 2 + internal/pagination/pagination.go | 9 + internal/repository/system-notification.go | 81 +++++++- internal/route/route.go | 21 +- internal/usecase/system-notification.go | 60 +++++- pkg/domain/policy-notification.go | 31 +++ pkg/domain/stack.go | 2 +- pkg/domain/system-notification.go | 1 + 17 files changed, 839 insertions(+), 33 deletions(-) create mode 100644 internal/delivery/http/policy-notification.go create mode 100644 pkg/domain/policy-notification.go diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 17836561..428b2ba2 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -4502,6 +4502,121 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/policy-notifications": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get PolicyNotifications", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyNotifications" + ], + "summary": "Get PolicyNotifications", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/policy-notifications/{policyNotificationId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get PolicyNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyNotifications" + ], + "summary": "Get PolicyNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "policyNotificationId", + "name": "policyNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationResponse" + } + } + } + } + }, "/organizations/{organizationId}/policy-statistics": { "get": { "security": [ @@ -12875,6 +12990,28 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationResponse": { + "type": "object", + "properties": { + "policyNotification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "policyNotifications": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse": { "type": "object", "properties": { @@ -13842,6 +13979,53 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse": { + "type": "object", + "properties": { + "cluster": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" + }, + "createdAt": { + "type": "string" + }, + "grafanaUrl": { + "type": "string" + }, + "id": { + "type": "string" + }, + "messageActionProposal": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, + "notificationType": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "rawData": { + "type": "string" + }, + "read": { + "type": "boolean" + }, + "severity": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyParameter": { "type": "object", "properties": { @@ -15080,6 +15264,9 @@ const docTemplate = `{ "rawData": { "type": "string" }, + "read": { + "type": "boolean" + }, "severity": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 78268f7b..379290e4 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -4496,6 +4496,121 @@ } } }, + "/organizations/{organizationId}/policy-notifications": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get PolicyNotifications", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyNotifications" + ], + "summary": "Get PolicyNotifications", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse" + } + } + } + } + }, + "/organizations/{organizationId}/policy-notifications/{policyNotificationId}": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get PolicyNotification", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "PolicyNotifications" + ], + "summary": "Get PolicyNotification", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "policyNotificationId", + "name": "policyNotificationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationResponse" + } + } + } + } + }, "/organizations/{organizationId}/policy-statistics": { "get": { "security": [ @@ -12869,6 +12984,28 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationResponse": { + "type": "object", + "properties": { + "policyNotification": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse" + }, + "policyNotifications": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse": { "type": "object", "properties": { @@ -13836,6 +13973,53 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse": { + "type": "object", + "properties": { + "cluster": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse" + }, + "createdAt": { + "type": "string" + }, + "grafanaUrl": { + "type": "string" + }, + "id": { + "type": "string" + }, + "messageActionProposal": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, + "notificationType": { + "type": "string" + }, + "organizationId": { + "type": "string" + }, + "rawData": { + "type": "string" + }, + "read": { + "type": "boolean" + }, + "severity": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.PolicyParameter": { "type": "object", "properties": { @@ -15074,6 +15258,9 @@ "rawData": { "type": "string" }, + "read": { + "type": "boolean" + }, "severity": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 49f7ed45..947fbb88 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1851,6 +1851,20 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PermissionResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationResponse: + properties: + policyNotification: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse' + type: object + github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse: + properties: + pagination: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' + policyNotifications: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse' + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetPolicyResponse: properties: policy: @@ -2482,6 +2496,37 @@ definitions: warn: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyNotificationResponse: + properties: + cluster: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleClusterResponse' + createdAt: + type: string + grafanaUrl: + type: string + id: + type: string + messageActionProposal: + type: string + messageContent: + type: string + messageTitle: + type: string + notificationType: + type: string + organizationId: + type: string + rawData: + type: string + read: + type: boolean + severity: + type: string + status: + type: string + updatedAt: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.PolicyParameter: properties: name: @@ -3313,6 +3358,8 @@ definitions: type: integer rawData: type: string + read: + type: boolean severity: type: string status: @@ -7134,6 +7181,80 @@ paths: summary: '[ExistsPolicyName] 정책 아름 존재 여부 확인' tags: - Policy + /organizations/{organizationId}/policy-notifications: + get: + consumes: + - application/json + description: Get PolicyNotifications + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: pageSize + in: query + name: pageSize + type: string + - description: pageNumber + in: query + name: pageNumber + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse' + security: + - JWT: [] + summary: Get PolicyNotifications + tags: + - PolicyNotifications + /organizations/{organizationId}/policy-notifications/{policyNotificationId}: + get: + consumes: + - application/json + description: Get PolicyNotification + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: policyNotificationId + in: path + name: policyNotificationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationResponse' + security: + - JWT: [] + summary: Get PolicyNotification + tags: + - PolicyNotifications /organizations/{organizationId}/policy-statistics: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 3d21b9ec..7ca962bf 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -155,6 +155,9 @@ const ( UpdateSystemNotification CreateSystemNotificationAction + // PolicyNotification + GetPolicyNotifications + // Stack GetStacks // 스택관리/조회 CreateStack // 스택관리/생성 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 3fb31f0f..3aa787fb 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -479,6 +479,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CreateSystemNotificationAction", Group: "SystemNotification", }, + GetPolicyNotifications: { + Name: "GetPolicyNotifications", + Group: "PolicyNotification", + }, GetStacks: { Name: "GetStacks", Group: "Stack", @@ -1160,6 +1164,8 @@ func (e Endpoint) String() string { return "UpdateSystemNotification" case CreateSystemNotificationAction: return "CreateSystemNotificationAction" + case GetPolicyNotifications: + return "GetPolicyNotifications" case GetStacks: return "GetStacks" case CreateStack: @@ -1624,6 +1630,8 @@ func GetEndpoint(name string) Endpoint { return UpdateSystemNotification case "CreateSystemNotificationAction": return CreateSystemNotificationAction + case "GetPolicyNotifications": + return GetPolicyNotifications case "GetStacks": return GetStacks case "CreateStack": diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 25e144c3..7aa18a57 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -3,6 +3,7 @@ package http import ( "fmt" "net/http" + "strconv" "github.com/google/uuid" "github.com/gorilla/mux" @@ -98,6 +99,15 @@ func (h *CloudAccountHandler) GetCloudAccounts(w http.ResponseWriter, r *http.Re urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) + for i, filter := range pg.GetFilters() { + if filter.Column == "status" { + for j, value := range filter.Values { + var s domain.CloudAccountStatus + pg.GetFilters()[i].Values[j] = strconv.Itoa(int(s.FromString(value))) + } + } + } + cloudAccounts, err := h.usecase.Fetch(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/delivery/http/policy-notification.go b/internal/delivery/http/policy-notification.go new file mode 100644 index 00000000..40122206 --- /dev/null +++ b/internal/delivery/http/policy-notification.go @@ -0,0 +1,123 @@ +package http + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/serializer" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "github.com/pkg/errors" +) + +type PolicyNotificationHandler struct { + usecase usecase.ISystemNotificationUsecase +} + +func NewPolicyNotificationHandler(h usecase.Usecase) *PolicyNotificationHandler { + return &PolicyNotificationHandler{ + usecase: h.SystemNotification, + } +} + +// GetPolicyNotification godoc +// +// @Tags PolicyNotifications +// @Summary Get PolicyNotifications +// @Description Get PolicyNotifications +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetPolicyNotificationsResponse +// @Router /organizations/{organizationId}/policy-notifications [get] +// @Security JWT +func (h *PolicyNotificationHandler) GetPolicyNotifications(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "", "")) + return + } + + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + for i, filter := range pg.GetFilters() { + if filter.Column == "status" { + for j, value := range filter.Values { + var s domain.SystemNotificationRuleStatus + pg.GetFilters()[i].Values[j] = strconv.Itoa(int(s.FromString(value))) + } + } + } + + policyNotifications, err := h.usecase.FetchPolicyNotifications(r.Context(), organizationId, pg) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetPolicyNotificationsResponse + out.PolicyNotifications = make([]domain.PolicyNotificationResponse, len(policyNotifications)) + for i, policyNotification := range policyNotifications { + if err := serializer.Map(r.Context(), policyNotification, &out.PolicyNotifications[i]); err != nil { + log.Info(r.Context(), err) + } + } + + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +// GetPolicyNotification godoc +// +// @Tags PolicyNotifications +// @Summary Get PolicyNotification +// @Description Get PolicyNotification +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param policyNotificationId path string true "policyNotificationId" +// @Success 200 {object} domain.GetPolicyNotificationResponse +// @Router /organizations/{organizationId}/policy-notifications/{policyNotificationId} [get] +// @Security JWT +func (h *PolicyNotificationHandler) GetPolicyNotification(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + strId, ok := vars["policyNotificationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid policyNotificationId"), "", "")) + return + } + + policyNotificationId, err := uuid.Parse(strId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "", "")) + return + } + + policyNotification, err := h.usecase.Get(r.Context(), policyNotificationId) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.GetPolicyNotificationResponse + if err := serializer.Map(r.Context(), policyNotification, &out.PolicyNotification); err != nil { + log.Info(r.Context(), err) + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 0f97dabe..a4f4cfa0 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "strconv" "github.com/google/uuid" "github.com/gorilla/mux" @@ -98,6 +99,15 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.Respon urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) + for i, filter := range pg.GetFilters() { + if filter.Column == "status" { + for j, value := range filter.Values { + var s domain.SystemNotificationRuleStatus + pg.GetFilters()[i].Values[j] = strconv.Itoa(int(s.FromString(value))) + } + } + } + systemNotificationRules, err := h.usecase.Fetch(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/delivery/http/system-notification.go b/internal/delivery/http/system-notification.go index 48deeea8..1df9eea4 100644 --- a/internal/delivery/http/system-notification.go +++ b/internal/delivery/http/system-notification.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "net/http" + "strconv" "github.com/google/uuid" "github.com/gorilla/mux" @@ -99,25 +100,16 @@ func (h *SystemNotificationHandler) GetSystemNotifications(w http.ResponseWriter urlParams := r.URL.Query() pg := pagination.NewPagination(&urlParams) - // convert status for i, filter := range pg.GetFilters() { if filter.Column == "status" { for j, value := range filter.Values { - switch value { - case "CREATED": - pg.GetFilters()[i].Values[j] = "0" - case "INPROGRESS": - pg.GetFilters()[i].Values[j] = "1" - case "CLOSED": - pg.GetFilters()[i].Values[j] = "2" - case "ERROR": - pg.GetFilters()[i].Values[j] = "3" - } + var s domain.SystemNotificationActionStatus + pg.GetFilters()[i].Values[j] = strconv.Itoa(int(s.FromString(value))) } } } - systemNotifications, err := h.usecase.Fetch(r.Context(), organizationId, pg) + systemNotifications, err := h.usecase.FetchSystemNotifications(r.Context(), organizationId, pg) if err != nil { ErrorJSON(w, r, err) return diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go index ca707c70..c33fadf5 100644 --- a/internal/model/system-notification.go +++ b/internal/model/system-notification.go @@ -36,6 +36,8 @@ type SystemNotification struct { Summary string RawData datatypes.JSON Status domain.SystemNotificationActionStatus `gorm:"index"` + Read bool `gorm:"-:all"` + Readers []User `gorm:"many2many:system_notification_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` } type SystemNotificationAction struct { diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go index 43feb12f..4b82ed84 100644 --- a/internal/pagination/pagination.go +++ b/internal/pagination/pagination.go @@ -87,6 +87,15 @@ func (p *Pagination) GetFilters() []Filter { return p.Filters } +func (p *Pagination) GetFilter(key string) *Filter { + for _, filter := range p.Filters { + if filter.Column == key { + return &filter + } + } + return nil +} + func (p *Pagination) AddFilter(f Filter) { p.Filters = append(p.Filters, f) } diff --git a/internal/repository/system-notification.go b/internal/repository/system-notification.go index 2a810edd..7d69a831 100644 --- a/internal/repository/system-notification.go +++ b/internal/repository/system-notification.go @@ -2,28 +2,32 @@ package repository import ( "context" + "fmt" "time" "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/clause" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/httpErrors" ) // Interfaces type ISystemNotificationRepository interface { Get(ctx context.Context, systemNotificationId uuid.UUID) (model.SystemNotification, error) GetByName(ctx context.Context, organizationId string, name string) (model.SystemNotification, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotification, error) + FetchSystemNotifications(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotification, error) + FetchPolicyNotifications(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotification, error) FetchPodRestart(ctx context.Context, organizationId string, start time.Time, end time.Time) ([]model.SystemNotification, error) Create(ctx context.Context, dto model.SystemNotification) (systemNotificationId uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotification) (err error) Delete(ctx context.Context, dto model.SystemNotification) (err error) - CreateSystemNotificationAction(ctx context.Context, dto model.SystemNotificationAction) (systemNotificationActionId uuid.UUID, err error) + UpdateRead(ctx context.Context, systemNotificationId uuid.UUID, user model.User) (err error) } type SystemNotificationRepository struct { @@ -42,6 +46,7 @@ func (r *SystemNotificationRepository) Get(ctx context.Context, systemNotificati if res.Error != nil { return model.SystemNotification{}, res.Error } + return } @@ -53,19 +58,70 @@ func (r *SystemNotificationRepository) GetByName(ctx context.Context, organizati return } -func (r *SystemNotificationRepository) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotification, err error) { +func (r *SystemNotificationRepository) FetchSystemNotifications(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotification, err error) { + userInfo, ok := request.UserFrom(ctx) + if !ok { + return out, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + if pg == nil { pg = pagination.NewPagination(nil) } - _, res := pg.Fetch(r.db.WithContext(ctx).Model(&model.SystemNotification{}). + db := r.db.WithContext(ctx).Model(&model.SystemNotification{}). Preload("SystemNotificationActions", func(db *gorm.DB) *gorm.DB { return db.Order("created_at ASC") }).Preload("SystemNotificationActions.Taker"). Preload("Cluster", "status = 2"). Preload("Organization"). Joins("join clusters on clusters.id = system_notifications.cluster_id AND clusters.status = 2"). - Where("system_notifications.organization_id = ?", organizationId), &out) + Where("system_notifications.organization_id = ? AND system_notifications.notification_type = 'SYSTEM_NOTIFICATION'", organizationId) + + readFilter := pg.GetFilter("read") + if readFilter != nil { + if readFilter.Values[0] == "true" { + db.Joins("join system_notification_users on system_notification_users.system_notification_id = system_notifications.id AND system_notification_users.user_id = ?", userInfo.GetUserId()) + } else { + db.Joins("left outer join system_notification_users on system_notification_users.system_notification_id = system_notifications.id AND system_notification_users.user_id = ?", userInfo.GetUserId()). + Where("system_notification_users.user_id is null") + } + } + + _, res := pg.Fetch(db, &out) + + if res.Error != nil { + return nil, res.Error + } + return +} + +func (r *SystemNotificationRepository) FetchPolicyNotifications(ctx context.Context, organizationId string, pg *pagination.Pagination) (out []model.SystemNotification, err error) { + userInfo, ok := request.UserFrom(ctx) + if !ok { + return out, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + + if pg == nil { + pg = pagination.NewPagination(nil) + } + + db := r.db.WithContext(ctx).Model(&model.SystemNotification{}). + Preload("Cluster", "status = 2"). + Preload("Organization"). + Joins("join clusters on clusters.id = system_notifications.cluster_id AND clusters.status = 2"). + Where("system_notifications.organization_id = ? AND system_notifications.notification_type = 'POLICY_NOTIFICATION'", organizationId) + + readFilter := pg.GetFilter("read") + if readFilter != nil { + if readFilter.Values[0] == "true" { + db.Joins("join system_notification_users on system_notification_users.system_notification_id = system_notifications.id AND system_notification_users.user_id = ?", userInfo.GetUserId()) + } else { + db.Joins("left outer join system_notification_users on system_notification_users.system_notification_id = system_notifications.id AND system_notification_users.user_id = ?", userInfo.GetUserId()). + Where("system_notification_users.user_id is null") + } + } + + _, res := pg.Fetch(db, &out) if res.Error != nil { return nil, res.Error @@ -147,3 +203,18 @@ func (r *SystemNotificationRepository) CreateSystemNotificationAction(ctx contex return systemNotification.ID, nil } + +func (r *SystemNotificationRepository) UpdateRead(ctx context.Context, systemNotificationId uuid.UUID, user model.User) (err error) { + var systemNotification = model.SystemNotification{} + res := r.db.WithContext(ctx).First(&systemNotification, "id = ?", systemNotificationId) + if res.Error != nil { + return res.Error + } + + users := []model.User{user} + err = r.db.WithContext(ctx).Model(&systemNotification).Association("Readers").Append(users) + if err != nil { + return err + } + return nil +} diff --git a/internal/route/route.go b/internal/route/route.go index 63aab31f..cc71e4da 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -217,15 +217,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/{dashboardKey}", customMiddleware.Handle(internalApi.GetDashboard, http.HandlerFunc(dashboardHandler.GetDashboard))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/dashboards/{dashboardKey}", customMiddleware.Handle(internalApi.UpdateDashboard, http.HandlerFunc(dashboardHandler.UpdateDashboard))).Methods(http.MethodPut) - systemNotificationHandler := delivery.NewSystemNotificationHandler(usecaseFactory) - r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/system-notifications", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications", customMiddleware.Handle(internalApi.GetSystemNotifications, http.HandlerFunc(systemNotificationHandler.GetSystemNotifications))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.GetSystemNotification, http.HandlerFunc(systemNotificationHandler.GetSystemNotification))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.DeleteSystemNotification, http.HandlerFunc(systemNotificationHandler.DeleteSystemNotification))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.UpdateSystemNotification, http.HandlerFunc(systemNotificationHandler.UpdateSystemNotification))).Methods(http.MethodPut) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions", customMiddleware.Handle(internalApi.CreateSystemNotificationAction, http.HandlerFunc(systemNotificationHandler.CreateSystemNotificationAction))).Methods(http.MethodPost) - r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) - systemNotificationTemplateHandler := delivery.NewSystemNotificationTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates", customMiddleware.Handle(internalApi.Admin_CreateSystemNotificationTemplate, http.HandlerFunc(systemNotificationTemplateHandler.CreateSystemNotificationTemplate))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/system-notification-templates", customMiddleware.Handle(internalApi.Admin_GetSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.GetSystemNotificationTemplates))).Methods(http.MethodGet) @@ -247,6 +238,18 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.DeleteSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.DeleteSystemNotificationRule))).Methods(http.MethodDelete) + systemNotificationHandler := delivery.NewSystemNotificationHandler(usecaseFactory) + r.HandleFunc(SYSTEM_API_PREFIX+SYSTEM_API_VERSION+"/system-notifications", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications", customMiddleware.Handle(internalApi.GetSystemNotifications, http.HandlerFunc(systemNotificationHandler.GetSystemNotifications))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.GetSystemNotification, http.HandlerFunc(systemNotificationHandler.GetSystemNotification))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.DeleteSystemNotification, http.HandlerFunc(systemNotificationHandler.DeleteSystemNotification))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}", customMiddleware.Handle(internalApi.UpdateSystemNotification, http.HandlerFunc(systemNotificationHandler.UpdateSystemNotification))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notifications/{systemNotificationId}/actions", customMiddleware.Handle(internalApi.CreateSystemNotificationAction, http.HandlerFunc(systemNotificationHandler.CreateSystemNotificationAction))).Methods(http.MethodPost) + r.HandleFunc(API_PREFIX+API_VERSION+"/alerttest", systemNotificationHandler.CreateSystemNotification).Methods(http.MethodPost) + + policyNotificationHandler := delivery.NewPolicyNotificationHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-notifications", customMiddleware.Handle(internalApi.GetSystemNotifications, http.HandlerFunc(policyNotificationHandler.GetPolicyNotifications))).Methods(http.MethodGet) + stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.CreateStack, http.HandlerFunc(stackHandler.CreateStack))).Methods(http.MethodPost) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 0d3f984e..30b389be 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -23,7 +23,8 @@ import ( type ISystemNotificationUsecase interface { Get(ctx context.Context, systemNotificationId uuid.UUID) (model.SystemNotification, error) GetByName(ctx context.Context, organizationId string, name string) (model.SystemNotification, error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotification, error) + FetchSystemNotifications(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotification, error) + FetchPolicyNotifications(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotification, error) Create(ctx context.Context, dto domain.CreateSystemNotificationRequest) (err error) Update(ctx context.Context, dto model.SystemNotification) error Delete(ctx context.Context, dto model.SystemNotification) error @@ -37,6 +38,7 @@ type SystemNotificationUsecase struct { organizationRepo repository.IOrganizationRepository appGroupRepo repository.IAppGroupRepository systemNotificationRuleRepo repository.ISystemNotificationRuleRepository + userRepo repository.IUserRepository } func NewSystemNotificationUsecase(r repository.Repository) ISystemNotificationUsecase { @@ -46,6 +48,7 @@ func NewSystemNotificationUsecase(r repository.Repository) ISystemNotificationUs appGroupRepo: r.AppGroup, organizationRepo: r.Organization, systemNotificationRuleRepo: r.SystemNotificationRule, + userRepo: r.User, } } @@ -165,11 +168,24 @@ func (u *SystemNotificationUsecase) Update(ctx context.Context, dto model.System } func (u *SystemNotificationUsecase) Get(ctx context.Context, systemNotificationId uuid.UUID) (systemNotification model.SystemNotification, err error) { + userInfo, ok := request.UserFrom(ctx) + if !ok { + return systemNotification, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + systemNotification, err = u.repo.Get(ctx, systemNotificationId) if err != nil { return systemNotification, err } - u.makeAdditionalInfo(&systemNotification) + u.makeAdditionalInfo(&systemNotification, userInfo.GetUserId()) + + user, err := u.userRepo.GetByUuid(ctx, userInfo.GetUserId()) + if err == nil { + err = u.repo.UpdateRead(ctx, systemNotificationId, user) + if err != nil { + return systemNotification, err + } + } return } @@ -185,14 +201,37 @@ func (u *SystemNotificationUsecase) GetByName(ctx context.Context, organizationI return } -func (u *SystemNotificationUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (systemNotifications []model.SystemNotification, err error) { - systemNotifications, err = u.repo.Fetch(ctx, organizationId, pg) +func (u *SystemNotificationUsecase) FetchSystemNotifications(ctx context.Context, organizationId string, pg *pagination.Pagination) (systemNotifications []model.SystemNotification, err error) { + userInfo, ok := request.UserFrom(ctx) + if !ok { + return systemNotifications, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + + systemNotifications, err = u.repo.FetchSystemNotifications(ctx, organizationId, pg) + if err != nil { + return nil, err + } + + for i := range systemNotifications { + u.makeAdditionalInfo(&systemNotifications[i], userInfo.GetUserId()) + } + + return systemNotifications, nil +} + +func (u *SystemNotificationUsecase) FetchPolicyNotifications(ctx context.Context, organizationId string, pg *pagination.Pagination) (systemNotifications []model.SystemNotification, err error) { + userInfo, ok := request.UserFrom(ctx) + if !ok { + return systemNotifications, httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + + systemNotifications, err = u.repo.FetchPolicyNotifications(ctx, organizationId, pg) if err != nil { return nil, err } for i := range systemNotifications { - u.makeAdditionalInfo(&systemNotifications[i]) + u.makeAdditionalInfo(&systemNotifications[i], userInfo.GetUserId()) } return systemNotifications, nil @@ -256,7 +295,8 @@ func (u *SystemNotificationUsecase) getOrganizationFromCluster(clusters *[]model return "", fmt.Errorf("No martched organization %s", strId) } -func (u *SystemNotificationUsecase) makeAdditionalInfo(systemNotification *model.SystemNotification) { +func (u *SystemNotificationUsecase) makeAdditionalInfo(systemNotification *model.SystemNotification, userId uuid.UUID) { + systemNotification.FiredAt = &systemNotification.CreatedAt //systemNotification.Status = model.SystemNotificationActionStatus_CREATED @@ -273,6 +313,14 @@ func (u *SystemNotificationUsecase) makeAdditionalInfo(systemNotification *model systemNotification.TakedSec = int((systemNotification.SystemNotificationActions[0].CreatedAt).Sub(systemNotification.CreatedAt).Seconds()) //systemNotification.Status = systemNotification.SystemNotificationActions[len(systemNotification.SystemNotificationActions)-1].Status } + + systemNotification.Read = false + for _, v := range systemNotification.Readers { + if v.ID == userId { + systemNotification.Read = true + break + } + } } func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, systemNotification domain.SystemNotificationRequest, clusterId domain.ClusterId) (url string) { diff --git a/pkg/domain/policy-notification.go b/pkg/domain/policy-notification.go new file mode 100644 index 00000000..50467266 --- /dev/null +++ b/pkg/domain/policy-notification.go @@ -0,0 +1,31 @@ +package domain + +import ( + "time" +) + +type PolicyNotificationResponse struct { + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Severity string `json:"severity"` + MessageTitle string `json:"messageTitle"` + MessageContent string `json:"messageContent"` + MessageActionProposal string `json:"messageActionProposal"` + Cluster SimpleClusterResponse `json:"cluster"` + GrafanaUrl string `json:"grafanaUrl"` + Status string `json:"status"` + RawData string `json:"rawData"` + NotificationType string `json:"notificationType"` + Read bool `json:"read"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type GetPolicyNotificationsResponse struct { + PolicyNotifications []PolicyNotificationResponse `json:"policyNotifications"` + Pagination PaginationResponse `json:"pagination"` +} + +type GetPolicyNotificationResponse struct { + PolicyNotification PolicyNotificationResponse `json:"policyNotification"` +} diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 37f9de81..8e4c8c79 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -66,7 +66,7 @@ func (m StackStatus) FromString(s string) StackStatus { } const MAX_STEP_CLUSTER_CREATE = 26 -const MAX_STEP_CLUSTER_REMOVE = 14 +const MAX_STEP_CLUSTER_REMOVE = 16 const MAX_STEP_LMA_CREATE_PRIMARY = 39 const MAX_STEP_LMA_CREATE_MEMBER = 29 const MAX_STEP_LMA_REMOVE = 12 diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index f95868ef..8c2f63f1 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -98,6 +98,7 @@ type SystemNotificationResponse struct { LastTaker SimpleUserResponse `json:"lastTaker"` RawData string `json:"rawData"` NotificationType string `json:"notificationType"` + Read bool `json:"read"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } From 91c73f6f1f4cc3b41fbd212268873c51500a2212 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 23 Apr 2024 09:56:24 +0900 Subject: [PATCH 351/502] trivial. add route policyNotification --- internal/delivery/api/endpoint.go | 1 + internal/route/route.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 7ca962bf..6deb8330 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -157,6 +157,7 @@ const ( // PolicyNotification GetPolicyNotifications + GetPolicyNotification // Stack GetStacks // 스택관리/조회 diff --git a/internal/route/route.go b/internal/route/route.go index cc71e4da..876fe9ed 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -249,6 +249,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa policyNotificationHandler := delivery.NewPolicyNotificationHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-notifications", customMiddleware.Handle(internalApi.GetSystemNotifications, http.HandlerFunc(policyNotificationHandler.GetPolicyNotifications))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-notification", customMiddleware.Handle(internalApi.GetSystemNotification, http.HandlerFunc(policyNotificationHandler.GetPolicyNotification))).Methods(http.MethodGet) stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) From c6c2c5d1b11d743a9fbc909859a789de3d5262da Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 23 Apr 2024 10:22:07 +0900 Subject: [PATCH 352/502] =?UTF-8?q?Gatekeeper=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=20=EC=8A=A4=ED=82=A4=EB=A7=88=EC=97=90=20addtionalPro?= =?UTF-8?q?perties=EA=B0=80=20=EC=B6=94=EA=B0=80=EB=90=98=EC=96=B4=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/paramdef-util.go | 19 ++++++++++++------- internal/policy-template/policy-operator.go | 2 +- internal/policy-template/validation.go | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/internal/policy-template/paramdef-util.go b/internal/policy-template/paramdef-util.go index e87ffbb2..a0e4c64d 100644 --- a/internal/policy-template/paramdef-util.go +++ b/internal/policy-template/paramdef-util.go @@ -141,21 +141,26 @@ func CompareParamDefAndExtractedParamDef(paramdef *domain.ParameterDef, extracte return true } -func ParamDefsToJSONSchemaProeprties(paramdefs []*domain.ParameterDef) *apiextensionsv1.JSONSchemaProps { +func ParamDefsToJSONSchemaProeprties(paramdefs []*domain.ParameterDef, forValidation bool) *apiextensionsv1.JSONSchemaProps { if len(paramdefs) == 0 { return nil } result := apiextensionsv1.JSONSchemaProps{ - Type: "object", - Properties: convert(paramdefs), - AdditionalProperties: &apiextensionsv1.JSONSchemaPropsOrBool{Allows: false}, + Type: "object", + Properties: convert(paramdefs, forValidation), + } + + // 파라미터 validation인 경우에는 AddtionalProperties로 스키마에 없는 필드가 처리되지 않아야 함 + // Operator에 보낼때는 해당 속성이 없어야 함 + if forValidation { + result.AdditionalProperties = &apiextensionsv1.JSONSchemaPropsOrBool{Allows: false} } return &result } -func convert(paramdefs []*domain.ParameterDef) map[string]apiextensionsv1.JSONSchemaProps { +func convert(paramdefs []*domain.ParameterDef, forValidation bool) map[string]apiextensionsv1.JSONSchemaProps { result := map[string]apiextensionsv1.JSONSchemaProps{} for _, paramdef := range paramdefs { @@ -167,7 +172,7 @@ func convert(paramdefs []*domain.ParameterDef) map[string]apiextensionsv1.JSONSc result[paramdef.Key] = apiextensionsv1.JSONSchemaProps{ Type: "array", Items: &apiextensionsv1.JSONSchemaPropsOrArray{ - Schema: ParamDefsToJSONSchemaProeprties(paramdef.Children), + Schema: ParamDefsToJSONSchemaProeprties(paramdef.Children, forValidation), }, } case isArary: @@ -178,7 +183,7 @@ func convert(paramdefs []*domain.ParameterDef) map[string]apiextensionsv1.JSONSc }, } case isObject: - props := ParamDefsToJSONSchemaProeprties(paramdef.Children) + props := ParamDefsToJSONSchemaProeprties(paramdef.Children, forValidation) if props != nil { result[paramdef.Key] = *props diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index ad192c00..1d1fd9a6 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -104,7 +104,7 @@ func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) * Kind: policyTemplate.Kind, }, Validation: &Validation{ - OpenAPIV3Schema: ParamDefsToJSONSchemaProeprties(policyTemplate.ParametersSchema), + OpenAPIV3Schema: ParamDefsToJSONSchemaProeprties(policyTemplate.ParametersSchema, false), }, }, }, diff --git a/internal/policy-template/validation.go b/internal/policy-template/validation.go index 5cb01946..ccb83b00 100644 --- a/internal/policy-template/validation.go +++ b/internal/policy-template/validation.go @@ -47,7 +47,7 @@ func ValidateParamDefs(paramdefs []*domain.ParameterDef) error { } func ValidateJSONusingParamdefs(paramdefs []*domain.ParameterDef, jsonStr string) error { - jsonSchema := ParamDefsToJSONSchemaProeprties(paramdefs) + jsonSchema := ParamDefsToJSONSchemaProeprties(paramdefs, true) if jsonSchema == nil { // 파라미터가 없는데 "{}" 이나 ""이면 에러가 아님 From 26b7a8c3c0b2f0a716a4bb82f31da23db920ef0e Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 23 Apr 2024 11:03:10 +0900 Subject: [PATCH 353/502] =?UTF-8?q?tkspolicy=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20params->parameters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/policy-operator.go | 2 +- internal/policy-template/tkspolicy.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 1d1fd9a6..0f5b12a9 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -72,7 +72,7 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { Clusters: targetClusterIds, Template: policy.PolicyTemplate.Kind, Match: policy.Match, - Params: params, + Parameters: params, }, } } diff --git a/internal/policy-template/tkspolicy.go b/internal/policy-template/tkspolicy.go index 106f6ac4..e5be875b 100644 --- a/internal/policy-template/tkspolicy.go +++ b/internal/policy-template/tkspolicy.go @@ -28,7 +28,7 @@ type TKSPolicySpec struct { Clusters []string `json:"clusters"` Template string `json:"template" validate:"required"` - Params *apiextensionsv1.JSON `json:"params,omitempty"` + Parameters *apiextensionsv1.JSON `json:"parameters,omitempty"` Match *domain.Match `json:"match,omitempty"` EnforcementAction string `json:"enforcementAction,omitempty"` } From 68840303c88a4db1c5e93fc3909cdcea93854b9a Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 23 Apr 2024 15:32:33 +0900 Subject: [PATCH 354/502] feature. fix filter bugs --- api/swagger/docs.go | 3 +++ api/swagger/swagger.json | 3 +++ api/swagger/swagger.yaml | 2 ++ internal/filter/operator.go | 8 ++++---- pkg/domain/system-notification.go | 1 + 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 428b2ba2..38e47a3d 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -15249,6 +15249,9 @@ const docTemplate = `{ "messageTitle": { "type": "string" }, + "name": { + "type": "string" + }, "node": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 379290e4..483d81ab 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -15243,6 +15243,9 @@ "messageTitle": { "type": "string" }, + "name": { + "type": "string" + }, "node": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 947fbb88..c407380e 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -3348,6 +3348,8 @@ definitions: type: string messageTitle: type: string + name: + type: string node: type: string notificationType: diff --git a/internal/filter/operator.go b/internal/filter/operator.go index de992369..4dcd01b5 100644 --- a/internal/filter/operator.go +++ b/internal/filter/operator.go @@ -35,7 +35,7 @@ var ( if dataType != DataTypeText && dataType != DataTypeEnum { return filter.Where(tx, "FALSE") } - query := castEnumAsText(column, dataType) + " LIKE ?" + query := castEnumAsText(column, dataType) + " ILIKE ?" value := sqlutil.EscapeLike(filter.Args[0]) + "%" return filter.Where(tx, query, value) }, @@ -46,7 +46,7 @@ var ( if dataType != DataTypeText && dataType != DataTypeEnum { return filter.Where(tx, "FALSE") } - query := castEnumAsText(column, dataType) + " LIKE ?" + query := castEnumAsText(column, dataType) + " ILIKE ?" value := "%" + sqlutil.EscapeLike(filter.Args[0]) return filter.Where(tx, query, value) }, @@ -57,7 +57,7 @@ var ( if dataType != DataTypeText && dataType != DataTypeEnum { return filter.Where(tx, "FALSE") } - query := castEnumAsText(column, dataType) + " LIKE ?" + query := castEnumAsText(column, dataType) + " ILIKE ?" value := "%" + sqlutil.EscapeLike(filter.Args[0]) + "%" return filter.Where(tx, query, value) }, @@ -68,7 +68,7 @@ var ( if dataType != DataTypeText && dataType != DataTypeEnum { return filter.Where(tx, "FALSE") } - query := castEnumAsText(column, dataType) + " NOT LIKE ?" + query := castEnumAsText(column, dataType) + " NOT ILIKE ?" value := "%" + sqlutil.EscapeLike(filter.Args[0]) + "%" return filter.Where(tx, query, value) }, diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 8c2f63f1..27d9dc5b 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -80,6 +80,7 @@ type CreateSystemNotificationRequest struct { type SystemNotificationResponse struct { ID string `json:"id"` + Name string `json:"name"` OrganizationId string `json:"organizationId"` Severity string `json:"severity"` MessageTitle string `json:"messageTitle"` From 68b3272a77a0106fa034dc70380b3be42e5b628d Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 23 Apr 2024 22:43:46 +0900 Subject: [PATCH 355/502] =?UTF-8?q?OPA=20Gatekeeper=20=EC=A0=84=EC=9A=A9?= =?UTF-8?q?=ED=95=A8=EC=88=98=20external=5Fdata=EB=A5=BC=20=EB=AC=B8?= =?UTF-8?q?=EB=B2=95=20=EC=B2=B4=ED=81=AC=20=EC=8B=9C=20=EC=A0=95=ED=99=95?= =?UTF-8?q?=ED=9E=88=20=EC=9D=B8=EC=8B=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../policy-template/policy-template-rego.go | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index ab2665fa..0279cf7f 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -25,23 +25,23 @@ const ( ) var ( - input_extract_regex = regexp.MustCompile(input_extract_pattern) - obj_get_list_regex = regexp.MustCompile(obj_get_list_pattern) - obj_get_regex = regexp.MustCompile(obj_get_pattern) - array_param_map = buildArrayParameterMap() + input_extract_regex = regexp.MustCompile(input_extract_pattern) + obj_get_list_regex = regexp.MustCompile(obj_get_list_pattern) + obj_get_regex = regexp.MustCompile(obj_get_pattern) + array_param_map, capabilities = buildArrayParameterMap() ) // OPA 내장 함수 중 array 인자를 가진 함수와 array 인자의 위치를 담은 자료구조를 생성한다. // // OPA 내장 함수 목록은 정책에 상관없으므로 처음 로딩될 때 한 번만 호출해 변수에 담아두고 사용하면 된다. // OPA 엔진 버전에 따라 달라진다. 0.62 버전 기준으로 이 함수의 결과 값은 다음과 같다. // map[all:[true] any:[true] array.concat:[true true] array.reverse:[true] array.slice:[true false false] concat:[false true] count:[true] glob.match:[false true false] graph.reachable:[false true] graph.reachable_paths:[false true] internal.print:[true] json.filter:[false true] json.patch:[false true] json.remove:[false true] max:[true] min:[true] net.cidr_contains_matches:[true true] net.cidr_merge:[true] object.filter:[false true] object.remove:[false true] object.subset:[true true] object.union_n:[true] product:[true] sort:[true] sprintf:[false true] strings.any_prefix_match:[true true] strings.any_suffix_match:[true true] sum:[true] time.clock:[true] time.date:[true] time.diff:[true true] time.format:[true] time.weekday:[true]] -func buildArrayParameterMap() map[string][]bool { +func buildArrayParameterMap() (map[string][]bool, *ast.Capabilities) { compiler := ast.NewCompiler() // 아주 단순한 rego 코드를 컴파일해도 컴파일러의 모든 Built-In 함수 정보를 컴파일 할 수 있음 mod, err := ast.ParseModuleWithOpts("hello", "package hello\n hello {input.message = \"world\"}", ast.ParserOptions{}) if err != nil { - return nil + return nil, nil } // 컴파일을 수행해야 Built-in 함수 정보 로딩할 수 있음 @@ -49,7 +49,26 @@ func buildArrayParameterMap() map[string][]bool { modules["hello"] = mod compiler.Compile(modules) - return getArrayParameterMap(compiler) + var external_data = &ast.Builtin{ + Name: "external_data", + Decl: types.NewFunction( + types.Args( + types.Named("a", types.NewObject( + []*types.StaticProperty{ + types.NewStaticProperty("provider", types.S), + types.NewStaticProperty("keys", types.NewArray([]types.Type{types.S}, types.A)), + }, + nil, + )), + ), + types.Named("output", types.A), + ), // TODO(sr): types.A? ^^^^^^^ (also below) + } + + capabilities := compiler.Capabilities() + capabilities.Builtins = append(capabilities.Builtins, external_data) + + return getArrayParameterMap(compiler), capabilities } func getArrayParameterMap(compiler *ast.Compiler) map[string][]bool { @@ -140,9 +159,6 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str exprs := rule.Body localAssignMap := map[string]string{} - // if strings.Contains(rule.String(), "statefulset_vct_noname_msg") { - // fmt.Printf("1111111 %+ v%+v\n", rule.Head.Name, rule.Head.Key.String()) - // } for i, param := range passedParams { if isSubstitutionRequired(param) { argName := rule.Head.Args[i].String() @@ -493,7 +509,7 @@ func CompileRegoWithLibs(rego string, libs []string) (compiler *ast.Compiler, er regoPackage := GetPackageFromRegoCode(rego) - regoModule, err := ast.ParseModuleWithOpts(regoPackage, rego, ast.ParserOptions{}) + regoModule, err := ast.ParseModuleWithOpts(regoPackage, rego, ast.ParserOptions{Capabilities: capabilities}) if err != nil { return nil, err } @@ -514,7 +530,7 @@ func CompileRegoWithLibs(rego string, libs []string) (compiler *ast.Compiler, er return nil, fmt.Errorf("lib[%d] is not valid, empty package name", i) } - libModule, err := ast.ParseModuleWithOpts(libPackage, lib, ast.ParserOptions{}) + libModule, err := ast.ParseModuleWithOpts(libPackage, lib, ast.ParserOptions{Capabilities: capabilities}) if err != nil { return nil, err } @@ -522,7 +538,8 @@ func CompileRegoWithLibs(rego string, libs []string) (compiler *ast.Compiler, er modules[libPackage] = libModule } - compiler = ast.NewCompiler() + compiler = ast.NewCompiler().WithCapabilities(capabilities) + compiler.Compile(modules) return compiler, nil @@ -535,14 +552,15 @@ func MergeAndCompileRegoWithLibs(rego string, libs []string) (modules map[string merged := MergeRegoAndLibs(rego, libs) - module, err := ast.ParseModuleWithOpts(regoPackage, merged, ast.ParserOptions{}) + module, err := ast.ParseModuleWithOpts(regoPackage, merged, ast.ParserOptions{Capabilities: capabilities}) if err != nil { return modules, err } modules[regoPackage] = module - compiler := ast.NewCompiler() + compiler := ast.NewCompiler().WithCapabilities(capabilities) + compiler.Compile(modules) return modules, nil From 8af79192574ea85c1fcf8e0640ae579bbee49b78 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 24 Apr 2024 10:56:35 +0900 Subject: [PATCH 356/502] feature. add policy notification to default gernetation --- internal/delivery/http/organization.go | 18 +++--- internal/usecase/system-notification-rule.go | 58 +++++++++++++++++--- pkg/domain/system-notification-template.go | 1 + scripts/init_postgres.sql | 18 +++++- 4 files changed, 74 insertions(+), 21 deletions(-) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 99bb32cc..524e78ae 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -148,17 +148,13 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r } organization.AdminId = &admin.ID - /* - 0415 팀미팅의 결과, 기본 시스템 알림은 decapod 시스템을 사용한다. - - // Default systemNotificationRules 생성 - err = h.systemNotificationRuleUsecase.MakeDefaultSystemNotificationRules(r.Context(), organizationId, &organization) - if err != nil { - log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) - ErrorJSON(w, r, err) - return - } - */ + // Default systemNotificationRules 생성 + err = h.systemNotificationRuleUsecase.MakeDefaultSystemNotificationRules(r.Context(), organizationId, &organization) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } var out domain.CreateOrganizationResponse if err = serializer.Map(r.Context(), organization, &out); err != nil { diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 5f5cdaf6..59073c78 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -184,7 +184,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c ruleId := uuid.New() rules = append(rules, model.SystemNotificationRule{ ID: ruleId, - Name: domain.SN_TYPE_NODE_CPU_HIGH_LOAD + "-critical", + Name: domain.SN_TYPE_NODE_CPU_HIGH_LOAD + "-warning", Description: "", OrganizationId: organizationId, NotificationType: template.NotificationType, @@ -192,7 +192,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c SystemNotificationTemplateId: template.ID, SystemNotificationCondition: model.SystemNotificationCondition{ SystemNotificationRuleId: ruleId, - Severity: "critical", + Severity: "warning", Duration: "3m", Parameter: []byte("[{\"order\": 0, \"value\": \"10\", \"operator\": \"<\"}]"), EnableEmail: true, @@ -245,7 +245,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c SystemNotificationCondition: model.SystemNotificationCondition{ SystemNotificationRuleId: ruleId, Severity: "critical", - Duration: "3m", + Duration: "30m", Parameter: []byte("[{\"order\": 0, \"value\": \"0\", \"operator\": \"<\"}]"), EnableEmail: true, EnablePortal: true, @@ -271,7 +271,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c SystemNotificationCondition: model.SystemNotificationCondition{ SystemNotificationRuleId: ruleId, Severity: "critical", - Duration: "3m", + Duration: "30m", Parameter: []byte("[{\"order\": 0, \"value\": \"0\", \"operator\": \"<\"}]"), EnableEmail: true, EnablePortal: true, @@ -297,7 +297,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c SystemNotificationCondition: model.SystemNotificationCondition{ SystemNotificationRuleId: ruleId, Severity: "critical", - Duration: "3m", + Duration: "30m", Parameter: []byte("[{\"order\": 0, \"value\": \"2\", \"operator\": \">\"}]"), EnableEmail: true, EnablePortal: true, @@ -323,22 +323,62 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c SystemNotificationCondition: model.SystemNotificationCondition{ SystemNotificationRuleId: ruleId, Severity: "critical", - Duration: "3m", - Parameter: []byte("[{\"order\": 0, \"value\": \"2\", \"operator\": \">\"}]"), + Duration: "1m", + Parameter: []byte("[{\"order\": 0, \"value\": \"1\", \"operator\": \"==\"}]"), EnableEmail: true, EnablePortal: true, }, TargetUsers: []model.User{organizationAdmin}, - MessageTitle: "<> / <>", - MessageContent: "클러스터(<>)의 자원(<> - <> / <>)에서 정책(<> / <>)위반이 발생했습니다. 메시지: <>", + MessageTitle: "정책 위반(<> / <>)", + MessageContent: "스택 (<>)의 자원(<> - <> / <>)에서 정책(<> / <>)위반이 발생했습니다. 메시지 - <>", MessageActionProposal: "정책위반이 발생하였습니다.(<> / <>)", Status: domain.SystemNotificationRuleStatus_PENDING, CreatorId: organization.AdminId, UpdatorId: organization.AdminId, }) + } else if template.Name == domain.SN_TYPE_POLICY_BLOCKED { + ruleId := uuid.New() + rules = append(rules, model.SystemNotificationRule{ + ID: ruleId, + Name: domain.SN_TYPE_POLICY_BLOCKED + "-critical", + Description: "", + OrganizationId: organizationId, + NotificationType: template.NotificationType, + IsSystem: true, + SystemNotificationTemplateId: template.ID, + SystemNotificationCondition: model.SystemNotificationCondition{ + SystemNotificationRuleId: ruleId, + Severity: "critical", + Duration: "1m", + Parameter: []byte("[{\"order\": 0, \"value\": \"1\", \"operator\": \"==\"}]"), + EnableEmail: true, + EnablePortal: true, + }, + TargetUsers: []model.User{organizationAdmin}, + MessageTitle: "정책 위반(<> / <>) 시도", + MessageContent: "스택 (<>)의 자원(<> - <> / <>)에서 정책(<> / <>)위반 시도가 발생했습니다. 메시지 - <>", + MessageActionProposal: "정책위반이 시도가 발생하였습니다.(<> / <>)", + Status: domain.SystemNotificationRuleStatus_PENDING, + CreatorId: organization.AdminId, + UpdatorId: organization.AdminId, + }) } } + /* + - alert: policy-blocked + annotations: + Checkpoint: "정책위반이 시도가 발생하였습니다.({{ $labels.kind }} / {{ $labels.name }})" + description: "클러스터 ( {{ $labels.taco_cluster }})의 자원({{ $labels.violating_kind }} - {{ $labels.violating_namespace }} / {{ $labels.violating_nam }})에서 정책({{ $labels.kind }} / {{ $labels.name }})위반 시도가 발생했습니다. 메시지 - {{ $labels.violation_msg }}" + discriminative: $labels.kind,$labels.name,$labels.taco_cluster,$labels.violating_kind,$labels.violating_name,$labels.violating_namespace,$labels.violation_msg + message: 정책 위반({{ $labels.kind }} / {{ $labels.name }}) 시도 + expr: opa_scorecard_constraint_violations{namespace!='kube-system|taco-system|gatekeeper-system',violation_enforcement=''} == 1 + for: 1m + labels: + severity: critical + + */ + err = u.repo.Creates(ctx, rules) if err != nil { return err diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index d8a87797..d2e54fa0 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -10,6 +10,7 @@ const SN_TYPE_NODE_DISK_FULL = "node-disk-full" const SN_TYPE_PVC_FULL = "pvc-full" const SN_TYPE_POD_RESTART_FREQUENTLY = "pod-restart-frequently" const SN_TYPE_POLICY_AUDITED = "policy-audited" +const SN_TYPE_POLICY_BLOCKED = "policy-blocked" const ( NT_SYSTEM_NOTIFICATION = "SYSTEM_NOTIFICATION" diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index 6f2ba46d..c04c371f 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -67,7 +67,9 @@ values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'S insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', 'pod-restart-frequently', true, 'SYSTEM_NOTIFICATION','increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:])', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('7355d0f9-7c14-4f70-92ea-a9868624ff82', 'policy-audited', 'policy-audited', true, 'POLICY', 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system"}', null, null, now(), now() ); +values ('7355d0f9-7c14-4f70-92ea-a9868624ff82', 'policy-audited', 'policy-audited', true, 'POLICY_NOTIFICATION', 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system", violation_enforcement="warn"}', null, null, now(), now() ); +insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) +values ('792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'policy-blocked', 'policy-blocked', true, 'POLICY_NOTIFICATION', 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system",violation_enforcement=""}', null, null, now(), now() ); ## SystemNotificationTemplates -> SystemNotificationMetricParameters insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) @@ -105,3 +107,17 @@ insert into system_notification_metric_parameters ( "order", system_notification values ( 5, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'VIOLATING_NAME', '$labels.violating_name', now(), now() ); insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) values ( 6, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'VIOLATION_MSG', '$labels.violation_msg', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 0, '792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'STACK', '$labels.taco_cluster', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 1, '792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'NAME', '$labels.name', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 2, '792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'KIND', '$labels.kind', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 3, '792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'VIOLATING_KIND', '$labels.violating_kind', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 4, '792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'VIOLATING_NAMESPACE', '$labels.violating_namespace', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 5, '792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'VIOLATING_NAME', '$labels.violating_name', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) +values ( 6, '792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'VIOLATION_MSG', '$labels.violation_msg', now(), now() ); From a36c2481d8ff66f67e707a151deb8dea10db41c2 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Wed, 24 Apr 2024 14:34:26 +0900 Subject: [PATCH 357/502] =?UTF-8?q?ListPolicy=EC=97=90=20filledParameter?= =?UTF-8?q?=20=EC=98=B5=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy.go | 28 +++++++++++++++++++++++++++- internal/usecase/policy.go | 24 +++++++++++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 9a45cd31..a06144a9 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -3,6 +3,7 @@ package http import ( "fmt" "net/http" + "strconv" "github.com/google/uuid" "github.com/gorilla/mux" @@ -352,6 +353,7 @@ func (h *PolicyHandler) GetPolicy(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param filledParameter query string false "filledParameter" // @Param pageSize query string false "pageSize" // @Param pageNumber query string false "pageNumber" // @Param sortColumn query string false "sortColumn" @@ -373,7 +375,19 @@ func (h *PolicyHandler) ListPolicy(w http.ResponseWriter, r *http.Request) { pg := pagination.NewPagination(&urlParams) - policies, err := h.usecase.Fetch(r.Context(), organizationId, pg) + filledParameter := false + + parse := urlParams.Get("filledParameter") + if len(parse) > 0 { + parsedBool, err := strconv.ParseBool(parse) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid fillParameter: '%s'", parse), "PT_INVALID_FILLPARAMETER", "")) + return + } + filledParameter = parsedBool + } + + policies, err := h.usecase.Fetch(r.Context(), organizationId, pg, filledParameter) if err != nil { ErrorJSON(w, r, err) return @@ -394,6 +408,18 @@ func (h *PolicyHandler) ListPolicy(w http.ResponseWriter, r *http.Request) { log.Error(r.Context(), err) } } + + if filledParameter { + parameterSchema := policy.PolicyTemplate.ParametersSchema + parameters := policy.Parameters + + err = policytemplate.FillParamDefFromJsonStr(parameterSchema, parameters) + if err != nil { + log.Error(r.Context(), err) + } else { + out.Policies[i].FilledParameters = parameterSchema + } + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 5f28f28e..0ebbc371 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -29,7 +29,7 @@ type IPolicyUsecase interface { Delete(ctx context.Context, organizationId string, policyId uuid.UUID) (err error) Get(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) GetForEdit(ctx context.Context, organizationId string, policyId uuid.UUID) (policy *model.Policy, err error) - Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.Policy, error) + Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination, filledParameter bool) (*[]model.Policy, error) IsPolicyIdExist(ctx context.Context, organizationId string, policyId uuid.UUID) (exists bool, err error) IsPolicyNameExist(ctx context.Context, organizationId string, policyName string) (exists bool, err error) UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusterIds []string) (err error) @@ -412,8 +412,26 @@ func (u *PolicyUsecase) GetForEdit(ctx context.Context, organizationId string, p return policy, err } -func (u *PolicyUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) (*[]model.Policy, error) { - return u.repo.Fetch(ctx, organizationId, pg) +func (u *PolicyUsecase) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination, filledParameter bool) (*[]model.Policy, error) { + policies, err := u.repo.Fetch(ctx, organizationId, pg) + + if err != nil { + return nil, err + } + + // 단순 Fetch인 경우에는 Policy에 해당하는 Template만 Join해 줌 + // PolicyTemplate의 최신 버전을 조회해서 파라미터 스키마 등을 조회해서 넣어줘야 함 + if filledParameter { + for i, policy := range *policies { + policyTemplate, err := u.templateRepo.GetByID(ctx, policy.TemplateId) + + if err == nil && policyTemplate != nil { + (*policies)[i].PolicyTemplate = *policyTemplate + } + } + } + + return policies, err } func (u *PolicyUsecase) IsPolicyNameExist(ctx context.Context, organizationId string, policyName string) (exists bool, err error) { From 68913cf0bdad0ce2e3b2c002a65410618573ebde Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Apr 2024 14:39:21 +0900 Subject: [PATCH 358/502] minor fix. change user deletion from hard to soft --- internal/model/user.go | 2 ++ internal/repository/user.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/model/user.go b/internal/model/user.go index d03052ab..a6b34a82 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -8,6 +8,8 @@ import ( ) type User struct { + gorm.Model + ID uuid.UUID `gorm:"primarykey;type:uuid" json:"id"` AccountId string `json:"accountId"` Password string `gorm:"-:all" json:"password"` diff --git a/internal/repository/user.go b/internal/repository/user.go index 0d8f200a..2e3c3340 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -246,7 +246,7 @@ func (r *UserRepository) DeleteWithUuid(ctx context.Context, uuid uuid.UUID) err return err } - res := r.db.WithContext(ctx).Unscoped().Delete(&user) + res := r.db.WithContext(ctx).Delete(&user) if res.Error != nil { log.Errorf(ctx, "error is :%s(%T)", res.Error.Error(), res.Error) return res.Error From 9abca250a6c232f7c0f29517bb9aaf3d6edb5a0a Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Apr 2024 15:32:25 +0900 Subject: [PATCH 359/502] bugfix. fix update role name error --- internal/keycloak/keycloak.go | 20 ++++++++++++++++++++ internal/usecase/role.go | 12 ++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 7f99c050..22abce52 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -36,6 +36,7 @@ type IKeycloak interface { LeaveGroup(ctx context.Context, organizationId string, userId string, groupName string) error CreateGroup(ctx context.Context, organizationId string, groupName string) (string, error) DeleteGroup(ctx context.Context, organizationId string, groupName string) error + UpdateGroup(ctx context.Context, organizationId string, oldGroupName string, newGroupName string) error EnsureClientRoleWithClientName(ctx context.Context, organizationId string, clientName string, roleName string) error DeleteClientRoleWithClientName(ctx context.Context, organizationId string, clientName string, roleName string) error @@ -85,6 +86,25 @@ func (k *Keycloak) DeleteGroup(ctx context.Context, organizationId string, group return nil } +func (k *Keycloak) UpdateGroup(ctx context.Context, organizationId string, oldGroupName string, newGroupName string) error { + token := k.adminCliToken + groups, err := k.client.GetGroups(context.Background(), token.AccessToken, organizationId, gocloak.GetGroupsParams{ + Search: &oldGroupName, + }) + if err != nil { + log.Error(ctx, err) + return httpErrors.NewInternalServerError(err, "", "") + } + if len(groups) == 0 { + return httpErrors.NewNotFoundError(fmt.Errorf("group not found"), "", "") + } + err = k.client.UpdateGroup(context.Background(), token.AccessToken, organizationId, gocloak.Group{ + ID: groups[0].ID, + Name: gocloak.StringP(newGroupName + "@" + organizationId), + }) + return nil +} + func (k *Keycloak) LoginAdmin(ctx context.Context, accountId string, password string) (*model.User, error) { JWTToken, err := k.client.LoginAdmin(context.Background(), accountId, password, DefaultMasterRealm) if err != nil { diff --git a/internal/usecase/role.go b/internal/usecase/role.go index 58344f2a..7b181c93 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -68,8 +68,16 @@ func (r RoleUsecase) DeleteTksRole(ctx context.Context, organizationId string, i return r.repo.Delete(ctx, id) } -func (r RoleUsecase) UpdateTksRole(ctx context.Context, role *model.Role) error { - err := r.repo.Update(ctx, role) +func (r RoleUsecase) UpdateTksRole(ctx context.Context, newRole *model.Role) error { + role, err := r.repo.GetTksRole(ctx, newRole.OrganizationID, newRole.ID) + if err != nil { + return err + } + err = r.kc.UpdateGroup(ctx, role.OrganizationID, role.Name, newRole.Name) + if err != nil { + return err + } + err = r.repo.Update(ctx, newRole) if err != nil { return err } From 30b9e84547ed2cdbf5143e0f14b7d4ae264c4e5c Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Apr 2024 15:37:48 +0900 Subject: [PATCH 360/502] fix lint error --- internal/keycloak/keycloak.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 22abce52..46cd34bd 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -102,6 +102,10 @@ func (k *Keycloak) UpdateGroup(ctx context.Context, organizationId string, oldGr ID: groups[0].ID, Name: gocloak.StringP(newGroupName + "@" + organizationId), }) + if err != nil { + log.Error(ctx, err) + return httpErrors.NewInternalServerError(err, "", "") + } return nil } From a3e7fa62b2a7f2bfd5c6caa333472e2177fc1ea3 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 24 Apr 2024 16:26:14 +0900 Subject: [PATCH 361/502] trivial. update status when snr deleting --- internal/usecase/system-notification-rule.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 59073c78..841e4446 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -158,6 +158,12 @@ func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, systemNotifi if err != nil { return err } + + // update status for appling kubernetes + if err = u.repo.UpdateStatus(ctx, systemNotificationRuleId, domain.SystemNotificationRuleStatus_PENDING); err != nil { + return err + } + return } From 6a2e4c2804e35823344c0bd6c7c916caced392a2 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Apr 2024 15:51:24 +0900 Subject: [PATCH 362/502] temporary logic for master realm to bypass get permissions --- internal/delivery/http/project.go | 1 + internal/delivery/http/user.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 8bc55f74..e376cba6 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -205,6 +205,7 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { var out domain.GetProjectsResponse out.Projects = pr + log.Debugf(r.Context(), "Pagination: %+v", pg) if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index d886c251..b32e5c86 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -781,6 +781,12 @@ func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Re organizationId = v } + // ToDo: admin portal에 대해서는 현재 permission 관련 로직을 적용하지 않아 임시로 빈 값을 리턴하도록 함 + if organizationId == "master" { + ResponseJSON(w, r, http.StatusOK, domain.GetUsersPermissionsResponse{}) + return + } + user, err := u.usecase.GetByAccountId(r.Context(), accountId, organizationId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) From 9f3065055a7f827146384a77d659e23f8bda86b2 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Apr 2024 17:25:11 +0900 Subject: [PATCH 363/502] bugfix. fix update my-profile API --- internal/delivery/http/user.go | 1 + internal/usecase/user.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index b32e5c86..c1572286 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -540,6 +540,7 @@ func (u UserHandler) UpdateMyProfile(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } + user.ID = requestUserInfo.GetUserId() user.Name = input.Name user.Email = input.Email user.Department = input.Department diff --git a/internal/usecase/user.go b/internal/usecase/user.go index c67fd1de..35be8fb9 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -364,6 +364,7 @@ func (u *UserUsecase) UpdateByAccountId(ctx context.Context, user *model.User) ( if ((*users)[0].Email != user.Email) || ((*users)[0].Name != user.Name) { err = u.kc.UpdateUser(ctx, user.Organization.ID, &gocloak.User{ + ID: gocloak.StringP(user.ID.String()), Email: gocloak.StringP(user.Email), FirstName: gocloak.StringP(user.Name), }) From ab33142103e04a9cd5a91e617bc5e65ef2843c97 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Apr 2024 17:46:32 +0900 Subject: [PATCH 364/502] minor fix. Ordering Permissions in the order of Read Create Update Delete --- internal/delivery/http/user.go | 30 ++++++++++++++++++++++++++++++ internal/repository/permission.go | 3 ++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index c1572286..fe1cfa76 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "sort" "strings" "github.com/gorilla/mux" @@ -826,11 +827,40 @@ func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Re func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { var permissionResponse domain.MergePermissionResponse + var sortOrder = map[string]int{ + "READ": 0, + "CREATE": 1, + "UPDATE": 2, + "DELETE": 3, + } + permissionResponse.Key = permission.Key if permission.IsAllowed != nil { permissionResponse.IsAllowed = permission.IsAllowed } + if len(permission.Children) > 0 { + if permission.Children[0].IsAllowed != nil { + sort.Slice(permission.Children, func(i, j int) bool { + key1 := permission.Children[i].Key + key2 := permission.Children[j].Key + + order1, exists1 := sortOrder[key1] + order2, exists2 := sortOrder[key2] + + if exists1 && exists2 { + return order1 < order2 + } else if exists1 { + return true + } else if exists2 { + return false + } + + return key1 < key2 + }) + } + } + for _, child := range permission.Children { permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child)) } diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 144d0a68..22a7d6bb 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -55,7 +55,8 @@ func (r PermissionRepository) Create(ctx context.Context, p *model.Permission) e func (r PermissionRepository) List(ctx context.Context, roleId string) ([]*model.Permission, error) { var permissions []*model.Permission - err := r.db.WithContext(ctx).Preload("Children.Children.Children.Children").Where("parent_id IS NULL AND role_id = ?", roleId).Find(&permissions).Error + err := r.db.WithContext(ctx).Preload("Children.Children.Children.Children"). + Where("parent_id IS NULL AND role_id = ?", roleId).Find(&permissions).Error if err != nil { return nil, err } From e0ed7cba5f7d09ab5eaa8a3e6a674e62dd55a858 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Apr 2024 17:48:25 +0900 Subject: [PATCH 365/502] remove unnecessary log --- internal/delivery/http/project.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index e376cba6..8bc55f74 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -205,7 +205,6 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { var out domain.GetProjectsResponse out.Projects = pr - log.Debugf(r.Context(), "Pagination: %+v", pg) if out.Pagination, err = pg.Response(r.Context()); err != nil { log.Info(r.Context(), err) } From 74ea85c2ff2dc4af4aeebfadcd13a710de8df9b8 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 24 Apr 2024 19:52:06 +0900 Subject: [PATCH 366/502] bugfix. Fix merged permission error --- internal/delivery/http/user.go | 7 +------ internal/model/permission.go | 2 +- internal/usecase/permission.go | 14 +++++++------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index fe1cfa76..c1ce69cc 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -795,13 +795,8 @@ func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Re return } - var roles []*model.Role - for _, role := range user.Roles { - roles = append(roles, &role) - } - var permissionSets []*model.PermissionSet - for _, role := range roles { + for _, role := range user.Roles { permissionSet, err := u.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) diff --git a/internal/model/permission.go b/internal/model/permission.go index 595596d3..8cdb4e16 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -104,7 +104,7 @@ func NewAdminPermissionSet() *PermissionSet { } func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { - if root.Children == nil { + if root.Children == nil || len(root.Children) == 0 { return append(edgePermissions, root) } diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index 7db6be5d..f05e81d0 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -125,18 +125,18 @@ func (p PermissionUsecase) MergePermissionWithOrOperator(ctx context.Context, pe continue } - out.Dashboard = p.mergePermission(out.Dashboard, ps.Dashboard) - out.Stack = p.mergePermission(out.Stack, ps.Stack) - out.Policy = p.mergePermission(out.Policy, ps.Policy) - out.ProjectManagement = p.mergePermission(out.ProjectManagement, ps.ProjectManagement) - out.Notification = p.mergePermission(out.Notification, ps.Notification) - out.Configuration = p.mergePermission(out.Configuration, ps.Configuration) + out.Dashboard = p.mergePermission(ctx, out.Dashboard, ps.Dashboard) + out.Stack = p.mergePermission(ctx, out.Stack, ps.Stack) + out.Policy = p.mergePermission(ctx, out.Policy, ps.Policy) + out.ProjectManagement = p.mergePermission(ctx, out.ProjectManagement, ps.ProjectManagement) + out.Notification = p.mergePermission(ctx, out.Notification, ps.Notification) + out.Configuration = p.mergePermission(ctx, out.Configuration, ps.Configuration) } return out } -func (p PermissionUsecase) mergePermission(mergedPermission, permission *model.Permission) *model.Permission { +func (p PermissionUsecase) mergePermission(ctx context.Context, mergedPermission, permission *model.Permission) *model.Permission { var mergedEdgePermissions []*model.Permission mergedEdgePermissions = model.GetEdgePermission(mergedPermission, mergedEdgePermissions, nil) From 6eb54866b3004af59db1e3428aa7a98bb09539a8 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 25 Apr 2024 01:03:19 +0900 Subject: [PATCH 367/502] =?UTF-8?q?tks=20=EC=9A=94=EC=B2=AD=EC=9D=B4=20?= =?UTF-8?q?=EC=A0=95=EC=B1=85=EC=97=90=20=EC=B0=A8=EB=8B=A8=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EA=B0=80=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/policy-operator.go | 2 +- internal/policy-template/tksguard-rego.go | 42 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 internal/policy-template/tksguard-rego.go diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 0f5b12a9..0626ea11 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -110,7 +110,7 @@ func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) * }, Targets: []Target{{ Target: "admission.k8s.gatekeeper.sh", - Rego: stripCarriageReturn(policyTemplate.Rego), + Rego: stripCarriageReturn(AddTksGuardToRego(policyTemplate.Rego)), Libs: stripCarriageReturns(policyTemplate.Libs), }}, Version: policyTemplate.Version, diff --git a/internal/policy-template/tksguard-rego.go b/internal/policy-template/tksguard-rego.go new file mode 100644 index 00000000..e19a94bc --- /dev/null +++ b/internal/policy-template/tksguard-rego.go @@ -0,0 +1,42 @@ +package policytemplate + +import "regexp" + +// (?m)은 멀티라인 모드로 각 라인의 시작이 ^레 매칭되도록 처리 +// general_violation 등 violation을 포함하지만 violation이 아닌 정책을 매칭하지 않기 위해 멀티라인 모드 필요함 +// OPA 포맷팅하면 violation rule은 공백없이 violation[ 으로 시작하므로 개행 문자 전까지 매칭 +const violation_regex_pattern = `(?m)^violation\[[^\n\r]+[\n\r]+` + +var violation_regex = regexp.MustCompile(violation_regex_pattern) + +// violation 정책 헤드 매칭 후 다음에 삽입할 주석 및 가드 정책 +const tks_guard_rego_rulename = ` # Do not delete following line, added by TKS + ___not_tks_triggered_request___ + +` + +// 가드 정책의 내용 +// 해당 정책이 undefined로 빠지면 violation의 뒷 부분이 평가되지 않음 +// 처음 블럭은 userInfo가 설정되지 않은 audit 모드에서 정책 평가가 스킵되는 것을 방지하기 위한처리 +// 그 다음 블럭은 username이 tks_users 목록에 없고, tks_groups와 groups의 교집합 크기가 0인 경우에 true이며 그 외는 undefined +// 죽 username 및 groups가 정의된 리스트와 매칭되는 것이 하나라도 있으면 정책이 undefined가 됨 +const tks_guard_rego_rulelogic = ` +# Do not delete or edit following rule, managed by TKS +___not_tks_triggered_request___ { + not input.review.userInfo +} { + tks_users := {"kubernetes-admin","system:serviceaccount:kube-system:argocd-manager"} + tks_groups := {"system:masters"} + + not tks_users[input.review.userInfo.username] + + count({g |g := input.review.userInfo.groups[_]; tks_groups[g]}) == 0 +} +# Do not delete or edit end` + +// violation 정책에 가드 정책 추가 +func AddTksGuardToRego(rego string) string { + // 매칭되는 violation 정책의 바디 첫부분에 가드 정책 체크를 추가하고 rego 코드 맨 끝에 실제 코드 내용 추가함 + return violation_regex.ReplaceAllString(rego, `${0}`+tks_guard_rego_rulename) + + tks_guard_rego_rulelogic +} From 5b77b05bc8786964671afe9d17b628f4059cfd4c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Apr 2024 11:27:55 +0900 Subject: [PATCH 368/502] feature. add api to audit --- api/swagger/docs.go | 38 ++++++++- api/swagger/swagger.json | 38 ++++++++- api/swagger/swagger.yaml | 22 ++++++ internal/delivery/http/cloud-account.go | 14 +++- .../delivery/http/system-notification-rule.go | 12 ++- internal/delivery/http/user.go | 7 +- internal/middleware/audit/audit-map.go | 79 ++++++++++++++----- internal/middleware/audit/audit.go | 2 +- internal/model/system-notification-rule.go | 4 +- internal/repository/audit.go | 3 +- internal/repository/organization.go | 2 +- .../repository/system-notification-rule.go | 8 +- internal/usecase/cloud-account.go | 30 +++---- internal/usecase/system-notification-rule.go | 28 ++----- pkg/domain/cloud-account.go | 3 +- pkg/domain/stack.go | 1 + pkg/domain/system-notification-rule.go | 5 ++ pkg/domain/user.go | 4 + 18 files changed, 223 insertions(+), 77 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 38e47a3d..95641852 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -4144,6 +4144,12 @@ const docTemplate = `{ "in": "path", "required": true }, + { + "type": "string", + "description": "filledParameter", + "name": "filledParameter", + "in": "query" + }, { "type": "string", "description": "pageSize", @@ -9256,7 +9262,10 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteSystemNotificationRuleResponse" + } } } } @@ -10060,7 +10069,10 @@ const docTemplate = `{ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteUserResponse" + } } } } @@ -12416,6 +12428,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeleteSystemNotificationRuleResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest": { "type": "object", "properties": { @@ -12424,6 +12447,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeleteUserResponse": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { @@ -14950,6 +14981,9 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.StackResponse": { "type": "object", "properties": { + "appServeAppCnt": { + "type": "integer" + }, "cloudAccount": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 483d81ab..77d95ec3 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -4138,6 +4138,12 @@ "in": "path", "required": true }, + { + "type": "string", + "description": "filledParameter", + "name": "filledParameter", + "in": "query" + }, { "type": "string", "description": "pageSize", @@ -9250,7 +9256,10 @@ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteSystemNotificationRuleResponse" + } } } } @@ -10054,7 +10063,10 @@ ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteUserResponse" + } } } } @@ -12410,6 +12422,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeleteSystemNotificationRuleResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest": { "type": "object", "properties": { @@ -12418,6 +12441,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.DeleteUserResponse": { + "type": "object", + "properties": { + "accountId": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.EndpointResponse": { "type": "object", "properties": { @@ -14944,6 +14975,9 @@ "github_com_openinfradev_tks-api_pkg_domain.StackResponse": { "type": "object", "properties": { + "appServeAppCnt": { + "type": "integer" + }, "cloudAccount": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index c407380e..37c5bb82 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1479,11 +1479,23 @@ definitions: type: string type: array type: object + github_com_openinfradev_tks-api_pkg_domain.DeleteSystemNotificationRuleResponse: + properties: + id: + type: string + name: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.DeleteUserRequest: properties: adminPassword: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.DeleteUserResponse: + properties: + accountId: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.EndpointResponse: properties: group: @@ -3151,6 +3163,8 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.StackResponse: properties: + appServeAppCnt: + type: integer cloudAccount: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleCloudAccountResponse' conf: @@ -6946,6 +6960,10 @@ paths: name: organizationId required: true type: string + - description: filledParameter + in: query + name: filledParameter + type: string - description: pageSize in: query name: pageSize @@ -10139,6 +10157,8 @@ paths: responses: "200": description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteSystemNotificationRuleResponse' security: - JWT: [] summary: Delete SystemNotificationRule @@ -10648,6 +10668,8 @@ paths: responses: "200": description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DeleteUserResponse' security: - JWT: [] summary: Delete user diff --git a/internal/delivery/http/cloud-account.go b/internal/delivery/http/cloud-account.go index 7aa18a57..2a01b9a7 100644 --- a/internal/delivery/http/cloud-account.go +++ b/internal/delivery/http/cloud-account.go @@ -265,13 +265,18 @@ func (h *CloudAccountHandler) DeleteCloudAccount(w http.ResponseWriter, r *http. } dto.ID = parsedId - err = h.usecase.Delete(r.Context(), dto) + cloudAccount, err := h.usecase.Delete(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) return } - ResponseJSON(w, r, http.StatusOK, nil) + out := domain.DeleteCloudAccountResponse{ + ID: cloudAccount.ID.String(), + Name: cloudAccount.Name, + } + + ResponseJSON(w, r, http.StatusOK, out) } // DeleteForceCloudAccount godoc @@ -300,14 +305,15 @@ func (h *CloudAccountHandler) DeleteForceCloudAccount(w http.ResponseWriter, r * return } - err = h.usecase.DeleteForce(r.Context(), parsedId) + cloudAccount, err := h.usecase.DeleteForce(r.Context(), parsedId) if err != nil { ErrorJSON(w, r, err) return } out := domain.DeleteCloudAccountResponse{ - ID: cloudAccountId, + ID: cloudAccount.ID.String(), + Name: cloudAccount.Name, } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index a4f4cfa0..3d900a35 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -256,7 +256,7 @@ func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.Resp // @Produce json // @Param organizationId path string true "organizationId" // @Param systemNotificationRuleId path string true "systemNotificationRuleId" -// @Success 200 {object} nil +// @Success 200 {object} domain.DeleteSystemNotificationRuleResponse // @Router /organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId} [delete] // @Security JWT func (h *SystemNotificationRuleHandler) DeleteSystemNotificationRule(w http.ResponseWriter, r *http.Request) { @@ -272,12 +272,18 @@ func (h *SystemNotificationRuleHandler) DeleteSystemNotificationRule(w http.Resp return } - err = h.usecase.Delete(r.Context(), systemNotificationRuleId) + systemNotificationRule, err := h.usecase.Delete(r.Context(), systemNotificationRuleId) if err != nil { ErrorJSON(w, r, err) return } - ResponseJSON(w, r, http.StatusOK, nil) + + out := domain.DeleteSystemNotificationRuleResponse{ + ID: strId, + Name: systemNotificationRule.Name, + } + + ResponseJSON(w, r, http.StatusOK, out) } // CheckSystemNotificationRuleName godoc diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index d886c251..129570aa 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -249,7 +249,7 @@ func (u UserHandler) convertUserRolesToSimpleRoleResponse(roles []model.Role) [] // @Produce json // @Param organizationId path string true "organizationId" // @Param accountId path string true "accountId" -// @Success 200 {object} nil +// @Success 200 {object} domain.DeleteUserResponse // @Router /organizations/{organizationId}/users/{accountId} [delete] // @Security JWT func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { @@ -277,7 +277,10 @@ func (u UserHandler) Delete(w http.ResponseWriter, r *http.Request) { return } - ResponseJSON(w, r, http.StatusOK, nil) + out := domain.DeleteUserResponse{ + AccountId: userId, + } + ResponseJSON(w, r, http.StatusOK, out) } // Update godoc diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index 9029b11b..eb6babba 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -12,10 +12,10 @@ import ( "github.com/openinfradev/tks-api/pkg/log" ) -type fnAudit = func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) +type fnAudit = func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) var auditMap = map[internalApi.Endpoint]fnAudit{ - internalApi.CreateStack: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + internalApi.CreateStack: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreateStackRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -25,7 +25,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("스택 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreateProject: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateProject: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreateProjectRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -35,7 +35,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("프로젝트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreateCloudAccount: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateCloudAccount: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreateCloudAccountRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -45,17 +45,27 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("클라우드 어카운트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.DeleteCloudAccount: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.DeleteCloudAccount: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { if isSuccess(statusCode) { output := domain.DeleteCloudAccountResponse{} - if err := json.Unmarshal(in, &output); err != nil { + if err := json.Unmarshal(out, &output); err != nil { log.Error(ctx, err) } - return fmt.Sprintf("클라우드어카운트 [ID:%s]를 삭제하였습니다.", output.ID), "" + return fmt.Sprintf("클라우드어카운트 [%s]를 삭제하였습니다.", output.Name), "" } else { - return "클라우드어카운트 [%s]를 삭제하는데 실패하였습니다. ", errorText(ctx, out) + return "클라우드어카운트를 삭제하는데 실패하였습니다. ", errorText(ctx, out) } - }, internalApi.CreateUser: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.DeleteForceCloudAccount: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { + if isSuccess(statusCode) { + output := domain.DeleteCloudAccountResponse{} + if err := json.Unmarshal(out, &output); err != nil { + log.Error(ctx, err) + } + return fmt.Sprintf("클라우드어카운트 [%s]를 강제 삭제하였습니다.", output.Name), "" + } else { + return "클라우드어카운트를 강제 삭제하는데 실패하였습니다. ", errorText(ctx, out) + } + }, internalApi.CreateUser: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreateUserRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -65,7 +75,17 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("사용자 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateOrganization: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.DeleteUser: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { + if isSuccess(statusCode) { + output := domain.DeleteUserResponse{} + if err := json.Unmarshal(out, &output); err != nil { + log.Error(ctx, err) + } + return fmt.Sprintf("사용자 [%s]를 삭제하였습니다.", output.AccountId), "" + } else { + return "사용자를 삭제하는데 실패하였습니다. ", errorText(ctx, out) + } + }, internalApi.Admin_CreateOrganization: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreateOrganizationRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -75,17 +95,17 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("조직 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_DeleteOrganization: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_DeleteOrganization: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { if isSuccess(statusCode) { output := domain.DeleteOrganizationResponse{} - if err := json.Unmarshal(in, &output); err != nil { + if err := json.Unmarshal(out, &output); err != nil { log.Error(ctx, err) } return fmt.Sprintf("조직 [ID:%s]를 삭제하였습니다.", output.ID), "" } else { - return "조직 [%s]를 삭제하는데 실패하였습니다. ", errorText(ctx, out) + return "조직을 삭제하는데 실패하였습니다. ", errorText(ctx, out) } - }, internalApi.CreateAppServeApp: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateAppServeApp: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreateAppServeAppRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -95,18 +115,17 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("앱서빙 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateStackTemplate: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateStackTemplate: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreateStackTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) } - log.Info(ctx, input) if isSuccess(statusCode) { return fmt.Sprintf("스택 템플릿 [%s]를 생성하였습니다.", input.Name), "" } else { return fmt.Sprintf("스택 템플릿 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateUser: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateUser: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreateUserRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -116,7 +135,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreatePolicyTemplate: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreatePolicyTemplate: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { input := domain.CreatePolicyTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -126,12 +145,32 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("폴리시템플릿 [%s]을 생성하는데 실패하였습니다.", input.TemplateName), errorText(ctx, out) } + }, internalApi.CreateSystemNotificationRule: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { + input := domain.CreateSystemNotificationRuleRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(ctx, err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("시스템알림설정 [%s]를 생성하였습니다.", input.Name), "" + } else { + return fmt.Sprintf("시스템알림설정 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) + } + }, internalApi.DeleteSystemNotificationRule: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { + if isSuccess(statusCode) { + output := domain.DeleteSystemNotificationRuleResponse{} + if err := json.Unmarshal(out, &output); err != nil { + log.Error(ctx, err) + } + return fmt.Sprintf("시스템알림설정 [%s]를 삭제하였습니다.", output.Name), "" + } else { + return "시스템알림설정을 삭제하는데 실패하였습니다. ", errorText(ctx, out) + } }, } -func errorText(ctx context.Context, out *bytes.Buffer) string { +func errorText(ctx context.Context, out []byte) string { var e httpErrors.RestError - if err := json.NewDecoder(out).Decode(&e); err != nil { + if err := json.NewDecoder(bytes.NewBuffer(out)).Decode(&e); err != nil { log.Error(ctx, err) return "" } diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 93af1e14..c8e30c7f 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -56,7 +56,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han if err != nil { log.Error(r.Context(), err) } - message, description = fn(r.Context(), lrw.GetBody(), body, statusCode) + message, description = fn(r.Context(), lrw.GetBody().Bytes(), body, statusCode) r.Body = io.NopCloser(bytes.NewBuffer(body)) dto := model.Audit{ diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index de12cfaf..f2a890fd 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -15,8 +15,8 @@ type SystemNotificationCondition struct { Duration string Parameter datatypes.JSON Parameters []domain.SystemNotificationParameter `gorm:"-:all"` - EnableEmail bool `gorm:"default:false"` - EnablePortal bool `gorm:"default:true"` + EnableEmail bool + EnablePortal bool } type SystemNotificationRule struct { diff --git a/internal/repository/audit.go b/internal/repository/audit.go index 094a2424..b62cda44 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -44,7 +44,8 @@ func (r *AuditRepository) Fetch(ctx context.Context, pg *pagination.Pagination) pg = pagination.NewPagination(nil) } - db := r.db.WithContext(ctx).Model(&model.Audit{}).Preload(clause.Associations).Preload("User.Roles") + db := r.db.WithContext(ctx).Model(&model.Audit{}).Preload(clause.Associations). + Preload("User.Roles") _, res := pg.Fetch(db, &out) if res.Error != nil { diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 146227fd..f91e720b 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -91,7 +91,7 @@ func (r *OrganizationRepository) Fetch(ctx context.Context, pg *pagination.Pagin for _, filter := range pg.Filters { if filter.Relation == "Admin" { db = db.Joins("left outer join users on users.id::text = organizations.admin_id::text"). - Where("users.name like ?", "%"+filter.Values[0]+"%") + Where("users.name ilike ?", "%"+filter.Values[0]+"%") break } } diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 209c29d9..7edb3a8e 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -10,6 +10,7 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" + "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces @@ -77,7 +78,7 @@ func (r *SystemNotificationRuleRepository) FetchWithOrganization(ctx context.Con if filter.Relation == "TargetUsers" { db = db.Joins("left outer join system_notification_rule_users on system_notification_rules.id = system_notification_rule_users.system_notification_rule_id"). Joins("left outer join users on system_notification_rule_users.user_id = users.id"). - Where("users.name like ?", "%"+filter.Values[0]+"%") + Where("users.name ilike ?", "%"+filter.Values[0]+"%") break } } @@ -124,7 +125,10 @@ func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model m.MessageActionProposal = dto.MessageActionProposal m.UpdatorId = dto.UpdatorId - res = r.db.WithContext(ctx).Session(&gorm.Session{FullSaveAssociations: true}).Updates(&m) + log.Info(ctx, "KTKFREE1 ", m.SystemNotificationCondition.EnableEmail) + log.Info(ctx, "KTKFREE2 ", m.SystemNotificationCondition.EnablePortal) + + res = r.db.WithContext(ctx).Session(&gorm.Session{FullSaveAssociations: true}).Save(&m) if res.Error != nil { return res.Error } diff --git a/internal/usecase/cloud-account.go b/internal/usecase/cloud-account.go index 9cf649f4..45853c1b 100644 --- a/internal/usecase/cloud-account.go +++ b/internal/usecase/cloud-account.go @@ -39,8 +39,8 @@ type ICloudAccountUsecase interface { Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.CloudAccount, error) Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) Update(ctx context.Context, dto model.CloudAccount) error - Delete(ctx context.Context, dto model.CloudAccount) error - DeleteForce(ctx context.Context, cloudAccountId uuid.UUID) error + Delete(ctx context.Context, dto model.CloudAccount) (model.CloudAccount, error) + DeleteForce(ctx context.Context, cloudAccountId uuid.UUID) (model.CloudAccount, error) } type CloudAccountUsecase struct { @@ -179,21 +179,21 @@ func (u *CloudAccountUsecase) Fetch(ctx context.Context, organizationId string, return } -func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount) (err error) { +func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount) (out model.CloudAccount, err error) { user, ok := request.UserFrom(ctx) if !ok { - return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + return out, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } userId := user.GetUserId() cloudAccount, err := u.Get(ctx, dto.ID) if err != nil { - return httpErrors.NewNotFoundError(err, "", "") + return cloudAccount, httpErrors.NewNotFoundError(err, "", "") } dto.UpdatorId = &userId if u.getClusterCnt(ctx, dto.ID) > 0 { - return fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") + return cloudAccount, fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") } workflowId, err := u.argo.SumbitWorkflowFromWftpl( @@ -211,38 +211,38 @@ func (u *CloudAccountUsecase) Delete(ctx context.Context, dto model.CloudAccount }) if err != nil { log.Error(ctx, "failed to submit argo workflow template. err : ", err) - return fmt.Errorf("Failed to call argo workflow : %s", err) + return cloudAccount, fmt.Errorf("Failed to call argo workflow : %s", err) } log.Info(ctx, "submited workflow :", workflowId) if err := u.repo.InitWorkflow(ctx, dto.ID, workflowId, domain.CloudAccountStatus_DELETING); err != nil { - return errors.Wrap(err, "Failed to initialize status") + return cloudAccount, errors.Wrap(err, "Failed to initialize status") } - return nil + return cloudAccount, nil } -func (u *CloudAccountUsecase) DeleteForce(ctx context.Context, cloudAccountId uuid.UUID) (err error) { +func (u *CloudAccountUsecase) DeleteForce(ctx context.Context, cloudAccountId uuid.UUID) (out model.CloudAccount, err error) { cloudAccount, err := u.repo.Get(ctx, cloudAccountId) if err != nil { - return err + return cloudAccount, err } if !strings.Contains(cloudAccount.Name, domain.CLOUD_ACCOUNT_INCLUSTER) && cloudAccount.Status != domain.CloudAccountStatus_CREATE_ERROR { - return fmt.Errorf("The status is not CREATE_ERROR. %s", cloudAccount.Status) + return cloudAccount, fmt.Errorf("The status is not CREATE_ERROR. %s", cloudAccount.Status) } if u.getClusterCnt(ctx, cloudAccountId) > 0 { - return fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") + return cloudAccount, fmt.Errorf("사용 중인 클러스터가 있어 삭제할 수 없습니다.") } err = u.repo.Delete(ctx, cloudAccountId) if err != nil { - return err + return cloudAccount, err } - return nil + return cloudAccount, nil } func (u *CloudAccountUsecase) GetResourceQuota(ctx context.Context, cloudAccountId uuid.UUID) (available bool, out domain.ResourceQuota, err error) { diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 841e4446..01ef4c36 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -21,7 +21,7 @@ type ISystemNotificationRuleUsecase interface { Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.SystemNotificationRule, error) Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRule uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationRule) error - Delete(ctx context.Context, systemNotificationRuleId uuid.UUID) error + Delete(ctx context.Context, systemNotificationRuleId uuid.UUID) (model.SystemNotificationRule, error) GetByName(ctx context.Context, name string) (model.SystemNotificationRule, error) MakeDefaultSystemNotificationRules(ctx context.Context, organizationId string, dto *model.Organization) error } @@ -141,30 +141,30 @@ func (u *SystemNotificationRuleUsecase) Fetch(ctx context.Context, organizationI return res, nil } -func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, systemNotificationRuleId uuid.UUID) (err error) { +func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, systemNotificationRuleId uuid.UUID) (out model.SystemNotificationRule, err error) { systemNotificationRule, err := u.repo.Get(ctx, systemNotificationRuleId) if err != nil { - return err + return out, err } user, ok := request.UserFrom(ctx) if !ok { - return httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") + return out, httpErrors.NewBadRequestError(fmt.Errorf("Invalid token"), "", "") } userId := user.GetUserId() systemNotificationRule.UpdatorId = &userId err = u.repo.Delete(ctx, systemNotificationRule) if err != nil { - return err + return out, err } // update status for appling kubernetes if err = u.repo.UpdateStatus(ctx, systemNotificationRuleId, domain.SystemNotificationRuleStatus_PENDING); err != nil { - return err + return out, err } - return + return systemNotificationRule, nil } func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx context.Context, organizationId string, dto *model.Organization) error { @@ -371,20 +371,6 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c } } - /* - - alert: policy-blocked - annotations: - Checkpoint: "정책위반이 시도가 발생하였습니다.({{ $labels.kind }} / {{ $labels.name }})" - description: "클러스터 ( {{ $labels.taco_cluster }})의 자원({{ $labels.violating_kind }} - {{ $labels.violating_namespace }} / {{ $labels.violating_nam }})에서 정책({{ $labels.kind }} / {{ $labels.name }})위반 시도가 발생했습니다. 메시지 - {{ $labels.violation_msg }}" - discriminative: $labels.kind,$labels.name,$labels.taco_cluster,$labels.violating_kind,$labels.violating_name,$labels.violating_namespace,$labels.violation_msg - message: 정책 위반({{ $labels.kind }} / {{ $labels.name }}) 시도 - expr: opa_scorecard_constraint_violations{namespace!='kube-system|taco-system|gatekeeper-system',violation_enforcement=''} == 1 - for: 1m - labels: - severity: critical - - */ - err = u.repo.Creates(ctx, rules) if err != nil { return err diff --git a/pkg/domain/cloud-account.go b/pkg/domain/cloud-account.go index 591356ac..dfac5409 100644 --- a/pkg/domain/cloud-account.go +++ b/pkg/domain/cloud-account.go @@ -133,5 +133,6 @@ type GetCloudAccountResourceQuotaResponse struct { } type DeleteCloudAccountResponse struct { - ID string `json:"id"` + ID string `json:"id"` + Name string `json:"name"` } diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 8e4c8c79..90f4f96b 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -133,6 +133,7 @@ type StackResponse struct { Favorited bool `json:"favorited"` ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` Resource DashboardStackResponse `json:"resource,omitempty"` + AppServeAppCnt int `json:"appServeAppCnt"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index c8026d38..c7d1853c 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -121,3 +121,8 @@ type UpdateSystemNotificationRuleRequest struct { type CheckSystemNotificationRuleNameResponse struct { Existed bool `json:"existed"` } + +type DeleteSystemNotificationRuleResponse struct { + ID string `json:"id"` + Name string `json:"name"` +} diff --git a/pkg/domain/user.go b/pkg/domain/user.go index 030c64fd..e602d74d 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -219,3 +219,7 @@ type Admin_UpdateUserResponse struct { type DeleteUserRequest struct { AdminPassword string `json:"adminPassword"` } + +type DeleteUserResponse struct { + AccountId string `json:"accountId"` +} From fac8202190e715887c199139eff5720b55d09ae1 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 25 Apr 2024 11:58:10 +0900 Subject: [PATCH 369/502] bugfix. fix permission ordering error --- internal/delivery/http/role.go | 3 +-- internal/delivery/http/user.go | 30 ---------------------- internal/model/permission.go | 8 ++++++ internal/usecase/permission.go | 47 ++++++++++++++++++++++++++++++++-- 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 978f2275..1ff872be 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -2,8 +2,6 @@ package http import ( "context" - "net/http" - "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -12,6 +10,7 @@ import ( "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" + "net/http" ) type IRoleHandler interface { diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index c1ce69cc..8af0f65b 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "net/http" - "sort" "strings" "github.com/gorilla/mux" @@ -822,40 +821,11 @@ func (u UserHandler) GetPermissionsByAccountId(w http.ResponseWriter, r *http.Re func convertModelToMergedPermissionSetResponse(ctx context.Context, permission *model.Permission) *domain.MergePermissionResponse { var permissionResponse domain.MergePermissionResponse - var sortOrder = map[string]int{ - "READ": 0, - "CREATE": 1, - "UPDATE": 2, - "DELETE": 3, - } - permissionResponse.Key = permission.Key if permission.IsAllowed != nil { permissionResponse.IsAllowed = permission.IsAllowed } - if len(permission.Children) > 0 { - if permission.Children[0].IsAllowed != nil { - sort.Slice(permission.Children, func(i, j int) bool { - key1 := permission.Children[i].Key - key2 := permission.Children[j].Key - - order1, exists1 := sortOrder[key1] - order2, exists2 := sortOrder[key2] - - if exists1 && exists2 { - return order1 < order2 - } else if exists1 { - return true - } else if exists2 { - return false - } - - return key1 < key2 - }) - } - } - for _, child := range permission.Children { permissionResponse.Children = append(permissionResponse.Children, convertModelToMergedPermissionSetResponse(ctx, child)) } diff --git a/internal/model/permission.go b/internal/model/permission.go index 8cdb4e16..4c395c85 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -9,6 +9,14 @@ import ( type PermissionKind string +var SortOrder = map[string]int{ + OperationRead: 0, + OperationCreate: 1, + OperationUpdate: 2, + OperationDelete: 3, + OperationDownload: 4, +} + const ( DashBoardPermission PermissionKind = "대시보드" StackPermission PermissionKind = "스택" diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index f05e81d0..532e723c 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -5,6 +5,7 @@ import ( "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" + "sort" ) type IPermissionUsecase interface { @@ -80,17 +81,32 @@ func (p PermissionUsecase) GetPermissionSetByRoleId(ctx context.Context, roleId case string(model.ConfigurationPermission): permissionSet.Configuration = permission } + + p.sortPermissionRecursive(permission) } return permissionSet, nil } func (p PermissionUsecase) ListPermissions(ctx context.Context, roleId string) ([]*model.Permission, error) { - return p.repo.List(ctx, roleId) + permissions, err := p.repo.List(ctx, roleId) + if err != nil { + return nil, err + } + for _, permission := range permissions { + p.sortPermissionRecursive(permission) + } + + return permissions, nil } func (p PermissionUsecase) GetPermission(ctx context.Context, id uuid.UUID) (*model.Permission, error) { - return p.repo.Get(ctx, id) + permission, err := p.repo.Get(ctx, id) + if err != nil { + return nil, err + } + p.sortPermissionRecursive(permission) + return permission, nil } func (p PermissionUsecase) DeletePermission(ctx context.Context, id uuid.UUID) error { @@ -149,3 +165,30 @@ func (p PermissionUsecase) mergePermission(ctx context.Context, mergedPermission return mergedPermission } + +func (p PermissionUsecase) sortPermissionRecursive(permission *model.Permission) { + if len(permission.Children) > 0 { + if permission.Children[0].IsAllowed != nil { + sort.Slice(permission.Children, func(i, j int) bool { + key1 := permission.Children[i].Key + key2 := permission.Children[j].Key + + order1, exists1 := model.SortOrder[key1] + order2, exists2 := model.SortOrder[key2] + + if exists1 && exists2 { + return order1 < order2 + } else if exists1 { + return true + } else if exists2 { + return false + } + + return key1 < key2 + }) + } + for _, child := range permission.Children { + p.sortPermissionRecursive(child) + } + } +} From 92bc8bdbcfb0e9727a0341ab6b7b1195f6e2ca7d Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Apr 2024 13:49:18 +0900 Subject: [PATCH 370/502] feature. change audit scheme and remove database constraint --- api/swagger/docs.go | 42 +++++-------------- api/swagger/swagger.json | 42 +++++-------------- api/swagger/swagger.yaml | 29 ++++--------- internal/delivery/http/audit.go | 6 --- internal/middleware/audit/audit.go | 25 +++++++++-- internal/model/audit.go | 6 ++- internal/model/user.go | 3 +- internal/repository/audit.go | 12 +++--- .../repository/system-notification-rule.go | 4 -- internal/usecase/audit.go | 31 +++++++++++--- pkg/domain/audit.go | 22 +++++----- 11 files changed, 102 insertions(+), 120 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 95641852..a785a78d 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -10974,17 +10974,23 @@ const docTemplate = `{ "message": { "type": "string" }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" - }, "organizationId": { "type": "string" }, "updatedAt": { "type": "string" }, - "user": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles" + "userAccountId": { + "type": "string" + }, + "userId": { + "type": "string" + }, + "userName": { + "type": "string" + }, + "userRoles": { + "type": "string" } } }, @@ -14849,32 +14855,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.StackConfResponse": { "type": "object", "required": [ diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 77d95ec3..8e3be501 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -10968,17 +10968,23 @@ "message": { "type": "string" }, - "organization": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse" - }, "organizationId": { "type": "string" }, "updatedAt": { "type": "string" }, - "user": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles" + "userAccountId": { + "type": "string" + }, + "userId": { + "type": "string" + }, + "userName": { + "type": "string" + }, + "userRoles": { + "type": "string" } } }, @@ -14843,32 +14849,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles": { - "type": "object", - "properties": { - "accountId": { - "type": "string" - }, - "department": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.StackConfResponse": { "type": "object", "required": [ diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 37c5bb82..94b618be 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -500,14 +500,18 @@ definitions: type: string message: type: string - organization: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleOrganizationResponse' organizationId: type: string updatedAt: type: string - user: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles' + userAccountId: + type: string + userId: + type: string + userName: + type: string + userRoles: + type: string type: object github_com_openinfradev_tks-api_pkg_domain.Axis: properties: @@ -3072,23 +3076,6 @@ definitions: name: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponseWithRoles: - properties: - accountId: - type: string - department: - type: string - email: - type: string - id: - type: string - name: - type: string - roles: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleRoleResponse' - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.StackConfResponse: properties: tksCpNode: diff --git a/internal/delivery/http/audit.go b/internal/delivery/http/audit.go index 58fda3fb..520521c1 100644 --- a/internal/delivery/http/audit.go +++ b/internal/delivery/http/audit.go @@ -71,12 +71,6 @@ func (h *AuditHandler) GetAudits(w http.ResponseWriter, r *http.Request) { if err := serializer.Map(r.Context(), audit, &out.Audits[i]); err != nil { log.Info(r.Context(), err) } - out.Audits[i].User.Roles = make([]domain.SimpleRoleResponse, len(audit.User.Roles)) - for j, role := range audit.User.Roles { - if err := serializer.Map(r.Context(), role, &out.Audits[i].User.Roles[j]); err != nil { - log.Info(r.Context(), err) - } - } } if out.Pagination, err = pg.Response(r.Context()); err != nil { diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index c8e30c7f..f3d81d7e 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -20,12 +20,14 @@ type Interface interface { } type defaultAudit struct { - repo repository.IAuditRepository + repo repository.IAuditRepository + userRepo repository.IUserRepository } func NewDefaultAudit(repo repository.Repository) *defaultAudit { return &defaultAudit{ - repo: repo.Audit, + repo: repo.Audit, + userRepo: repo.User, } } @@ -59,13 +61,30 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han message, description = fn(r.Context(), lrw.GetBody().Bytes(), body, statusCode) r.Body = io.NopCloser(bytes.NewBuffer(body)) + u, err := a.userRepo.GetByUuid(r.Context(), userId) + if err != nil { + log.Error(r.Context(), err) + return + } + + userRoles := "" + for i, role := range u.Roles { + if i > 0 { + userRoles = userRoles + "," + } + userRoles = userRoles + role.Name + } + dto := model.Audit{ OrganizationId: organizationId, Group: internalApi.ApiMap[endpoint].Group, Message: message, Description: description, ClientIP: GetClientIpAddress(w, r), - UserId: &userId, + UserId: &u.ID, + UserAccountId: u.AccountId, + UserName: u.Name, + UserRoles: userRoles, } if _, err := a.repo.Create(r.Context(), dto); err != nil { log.Error(r.Context(), err) diff --git a/internal/model/audit.go b/internal/model/audit.go index 1f39c252..0059d02c 100644 --- a/internal/model/audit.go +++ b/internal/model/audit.go @@ -11,11 +11,13 @@ type Audit struct { ID uuid.UUID `gorm:"primarykey"` OrganizationId string - Organization Organization `gorm:"foreignKey:OrganizationId"` + Organization Organization Group string Message string Description string ClientIP string UserId *uuid.UUID `gorm:"type:uuid"` - User User `gorm:"foreignKey:UserId"` + UserAccountId string + UserName string + UserRoles string } diff --git a/internal/model/user.go b/internal/model/user.go index a6b34a82..dfaa0db7 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -1,9 +1,10 @@ package model import ( - "gorm.io/gorm" "time" + "gorm.io/gorm" + "github.com/google/uuid" ) diff --git a/internal/repository/audit.go b/internal/repository/audit.go index b62cda44..7988e396 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -6,7 +6,6 @@ import ( "github.com/google/uuid" "gorm.io/gorm" - "gorm.io/gorm/clause" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -32,7 +31,7 @@ func NewAuditRepository(db *gorm.DB) IAuditRepository { // Logics func (r *AuditRepository) Get(ctx context.Context, auditId uuid.UUID) (out model.Audit, err error) { - res := r.db.WithContext(ctx).Preload(clause.Associations).Preload("User.Roles").First(&out, "id = ?", auditId) + res := r.db.WithContext(ctx).First(&out, "id = ?", auditId) if res.Error != nil { return } @@ -44,8 +43,7 @@ func (r *AuditRepository) Fetch(ctx context.Context, pg *pagination.Pagination) pg = pagination.NewPagination(nil) } - db := r.db.WithContext(ctx).Model(&model.Audit{}).Preload(clause.Associations). - Preload("User.Roles") + db := r.db.WithContext(ctx).Model(&model.Audit{}) _, res := pg.Fetch(db, &out) if res.Error != nil { @@ -62,7 +60,11 @@ func (r *AuditRepository) Create(ctx context.Context, dto model.Audit) (auditId Message: dto.Message, Description: dto.Description, ClientIP: dto.ClientIP, - UserId: dto.UserId} + UserId: &dto.ID, + UserAccountId: dto.UserAccountId, + UserName: dto.UserName, + UserRoles: dto.UserRoles, + } res := r.db.WithContext(ctx).Create(&audit) if res.Error != nil { return uuid.Nil, res.Error diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 7edb3a8e..21ccbf99 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -10,7 +10,6 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/openinfradev/tks-api/pkg/log" ) // Interfaces @@ -125,9 +124,6 @@ func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model m.MessageActionProposal = dto.MessageActionProposal m.UpdatorId = dto.UpdatorId - log.Info(ctx, "KTKFREE1 ", m.SystemNotificationCondition.EnableEmail) - log.Info(ctx, "KTKFREE2 ", m.SystemNotificationCondition.EnablePortal) - res = r.db.WithContext(ctx).Session(&gorm.Session{FullSaveAssociations: true}).Save(&m) if res.Error != nil { return res.Error diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index 9a0f06cc..09b09ee0 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -19,23 +19,42 @@ type IAuditUsecase interface { } type AuditUsecase struct { - repo repository.IAuditRepository + repo repository.IAuditRepository + userRepo repository.IUserRepository } func NewAuditUsecase(r repository.Repository) IAuditUsecase { return &AuditUsecase{ - repo: r.Audit, + repo: r.Audit, + userRepo: r.User, } } func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { - if dto.UserId == nil { - user, ok := request.UserFrom(ctx) + if dto.UserId == nil || *dto.UserId == uuid.Nil { + userInfo, ok := request.UserFrom(ctx) if ok { - userId := user.GetUserId() - dto.UserId = &userId + id := userInfo.GetUserId() + dto.UserId = &id } } + + user, err := u.userRepo.GetByUuid(ctx, *dto.UserId) + if err != nil { + return auditId, err + } + + userRoles := "" + for i, role := range user.Roles { + if i > 0 { + userRoles = userRoles + "," + } + userRoles = userRoles + role.Name + } + dto.UserAccountId = user.AccountId + dto.UserName = user.Name + dto.UserRoles = userRoles + auditId, err = u.repo.Create(ctx, dto) if err != nil { return uuid.Nil, httpErrors.NewInternalServerError(err, "", "") diff --git a/pkg/domain/audit.go b/pkg/domain/audit.go index 2353b2bb..feca68e7 100644 --- a/pkg/domain/audit.go +++ b/pkg/domain/audit.go @@ -5,16 +5,18 @@ import ( ) type AuditResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Organization SimpleOrganizationResponse `json:"organization"` - Description string `json:"description"` - Group string `json:"group"` - Message string `json:"message"` - ClientIP string `json:"clientIP"` - User SimpleUserResponseWithRoles `json:"user"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Description string `json:"description"` + Group string `json:"group"` + Message string `json:"message"` + ClientIP string `json:"clientIP"` + UserId string `json:"userId"` + UserAccountId string `json:"userAccountId"` + UserName string `json:"userName"` + UserRoles string `json:"userRoles"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type CreateAuditRequest struct { From 0dc9934a9d9b5274ae5709cc7cb8210537ad32de Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Apr 2024 13:59:42 +0900 Subject: [PATCH 371/502] trivial. fix typo --- internal/repository/audit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/repository/audit.go b/internal/repository/audit.go index 7988e396..30b8c44f 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -60,7 +60,7 @@ func (r *AuditRepository) Create(ctx context.Context, dto model.Audit) (auditId Message: dto.Message, Description: dto.Description, ClientIP: dto.ClientIP, - UserId: &dto.ID, + UserId: dto.UserId, UserAccountId: dto.UserAccountId, UserName: dto.UserName, UserRoles: dto.UserRoles, From e4b0bdb98a9a81cacb75627b1516c3e4e20df241 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Apr 2024 15:02:04 +0900 Subject: [PATCH 372/502] trivial. add organization name to audits --- api/swagger/docs.go | 3 +++ api/swagger/swagger.json | 3 +++ api/swagger/swagger.yaml | 2 ++ internal/middleware/audit/audit.go | 19 ++++++++++--------- internal/model/audit.go | 22 +++++++++++----------- internal/repository/audit.go | 17 +++-------------- internal/usecase/audit.go | 2 ++ pkg/domain/audit.go | 25 +++++++++++++------------ 8 files changed, 47 insertions(+), 46 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index a785a78d..55dabf07 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -10977,6 +10977,9 @@ const docTemplate = `{ "organizationId": { "type": "string" }, + "organizationName": { + "type": "string" + }, "updatedAt": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 8e3be501..14eb42e7 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -10971,6 +10971,9 @@ "organizationId": { "type": "string" }, + "organizationName": { + "type": "string" + }, "updatedAt": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 94b618be..a88ae611 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -502,6 +502,8 @@ definitions: type: string organizationId: type: string + organizationName: + type: string updatedAt: type: string userAccountId: diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index f3d81d7e..189232ec 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -76,15 +76,16 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han } dto := model.Audit{ - OrganizationId: organizationId, - Group: internalApi.ApiMap[endpoint].Group, - Message: message, - Description: description, - ClientIP: GetClientIpAddress(w, r), - UserId: &u.ID, - UserAccountId: u.AccountId, - UserName: u.Name, - UserRoles: userRoles, + OrganizationId: organizationId, + OrganizationName: u.Organization.Name, + Group: internalApi.ApiMap[endpoint].Group, + Message: message, + Description: description, + ClientIP: GetClientIpAddress(w, r), + UserId: &u.ID, + UserAccountId: u.AccountId, + UserName: u.Name, + UserRoles: userRoles, } if _, err := a.repo.Create(r.Context(), dto); err != nil { log.Error(r.Context(), err) diff --git a/internal/model/audit.go b/internal/model/audit.go index 0059d02c..c8e8a5ed 100644 --- a/internal/model/audit.go +++ b/internal/model/audit.go @@ -9,15 +9,15 @@ import ( type Audit struct { gorm.Model - ID uuid.UUID `gorm:"primarykey"` - OrganizationId string - Organization Organization - Group string - Message string - Description string - ClientIP string - UserId *uuid.UUID `gorm:"type:uuid"` - UserAccountId string - UserName string - UserRoles string + ID uuid.UUID `gorm:"primarykey"` + OrganizationId string + OrganizationName string + Group string + Message string + Description string + ClientIP string + UserId *uuid.UUID `gorm:"type:uuid"` + UserAccountId string + UserName string + UserRoles string } diff --git a/internal/repository/audit.go b/internal/repository/audit.go index 30b8c44f..f33f4835 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -53,23 +53,12 @@ func (r *AuditRepository) Fetch(ctx context.Context, pg *pagination.Pagination) } func (r *AuditRepository) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { - audit := model.Audit{ - ID: uuid.New(), - OrganizationId: dto.OrganizationId, - Group: dto.Group, - Message: dto.Message, - Description: dto.Description, - ClientIP: dto.ClientIP, - UserId: dto.UserId, - UserAccountId: dto.UserAccountId, - UserName: dto.UserName, - UserRoles: dto.UserRoles, - } - res := r.db.WithContext(ctx).Create(&audit) + dto.ID = uuid.New() + res := r.db.WithContext(ctx).Create(&dto) if res.Error != nil { return uuid.Nil, res.Error } - return audit.ID, nil + return dto.ID, nil } func (r *AuditRepository) Delete(ctx context.Context, auditId uuid.UUID) (err error) { diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index 09b09ee0..92c7c97c 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -51,6 +51,8 @@ func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uui } userRoles = userRoles + role.Name } + dto.OrganizationId = user.Organization.ID + dto.OrganizationName = user.Organization.Name dto.UserAccountId = user.AccountId dto.UserName = user.Name dto.UserRoles = userRoles diff --git a/pkg/domain/audit.go b/pkg/domain/audit.go index feca68e7..12b3b7ba 100644 --- a/pkg/domain/audit.go +++ b/pkg/domain/audit.go @@ -5,18 +5,19 @@ import ( ) type AuditResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Description string `json:"description"` - Group string `json:"group"` - Message string `json:"message"` - ClientIP string `json:"clientIP"` - UserId string `json:"userId"` - UserAccountId string `json:"userAccountId"` - UserName string `json:"userName"` - UserRoles string `json:"userRoles"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + OrganizationName string `json:"organizationName"` + Description string `json:"description"` + Group string `json:"group"` + Message string `json:"message"` + ClientIP string `json:"clientIP"` + UserId string `json:"userId"` + UserAccountId string `json:"userAccountId"` + UserName string `json:"userName"` + UserRoles string `json:"userRoles"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } type CreateAuditRequest struct { From 655df01a51bac110c179040aed7f4332898d5a91 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Apr 2024 15:18:00 +0900 Subject: [PATCH 373/502] trivial. add favorite field to stack response --- internal/delivery/http/stack.go | 2 +- internal/usecase/stack.go | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 1692669f..726c3253 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -93,7 +93,7 @@ func (h *StackHandler) InstallStack(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, nil) } -// GetStack godoc +// GetStacks godoc // // @Tags Stacks // @Summary Get Stacks diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 13bb6635..faabfd33 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -350,6 +350,12 @@ func (u *StackUsecase) Fetch(ctx context.Context, organizationId string, pg *pag } } + if cluster.Favorites != nil && len(*cluster.Favorites) > 0 { + outStack.Favorited = true + } else { + outStack.Favorited = false + } + out = append(out, outStack) } From 0152704d4957ee61cedc4f9ead0e4ec177d56ebf Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 25 Apr 2024 15:30:10 +0900 Subject: [PATCH 374/502] trivial. add appserveapps count to stack response --- internal/model/stack.go | 1 + internal/usecase/stack.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/internal/model/stack.go b/internal/model/stack.go index 2f7b518b..4d837019 100644 --- a/internal/model/stack.go +++ b/internal/model/stack.go @@ -32,6 +32,7 @@ type Stack = struct { Resource domain.DashboardStack PolicyIds []string Conf StackConf + AppServeAppCnt int } type StackConf struct { diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index faabfd33..f3c8621c 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -254,6 +254,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod out.PrimaryCluster = true } + // Resources stackResources, _ := u.dashbordUsecase.GetStacks(ctx, cluster.OrganizationId) for _, resource := range stackResources { if resource.ID == domain.StackId(cluster.ID) { @@ -268,6 +269,7 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod return out, err } + // Grafana URL for _, appGroup := range appGroupsInPrimaryCluster { if appGroup.AppGroupType == domain.AppGroupType_LMA { applications, err := u.appGroupRepo.GetApplications(ctx, appGroup.ID, domain.ApplicationType_GRAFANA) @@ -280,6 +282,20 @@ func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out mod } } + // Favorited + if cluster.Favorites != nil && len(*cluster.Favorites) > 0 { + out.Favorited = true + } else { + out.Favorited = false + } + + // AppServeApps + appServeAppCnt, err := u.appServeAppRepo.GetNumOfAppsOnStack(ctx, cluster.OrganizationId, cluster.ID.String()) + if err != nil { + log.Error(ctx, err) + } + out.AppServeAppCnt = int(appServeAppCnt) + return } From 318f93d3fdc498f9e34dd206833dc80673e3cd36 Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 25 Apr 2024 16:45:52 +0900 Subject: [PATCH 375/502] Add more info when retrieve projects --- internal/delivery/http/project.go | 56 ++++++++++++++++++++----------- internal/repository/project.go | 43 +++++++++++++++++++++--- internal/usecase/project.go | 11 ++++++ pkg/domain/project.go | 26 +++++++------- 4 files changed, 99 insertions(+), 37 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 8bc55f74..88d238b9 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -210,10 +210,9 @@ func (p ProjectHandler) GetProjects(w http.ResponseWriter, r *http.Request) { } if pr == nil { - ResponseJSON(w, r, http.StatusNotFound, domain.GetProjectsResponse{}) - } else { - ResponseJSON(w, r, http.StatusOK, out) + out.Projects = make([]domain.ProjectResponse, 0) } + ResponseJSON(w, r, http.StatusOK, out) } // Admin_GetProjects godoc @@ -293,25 +292,47 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } + if project == nil { + project, err := p.usecase.GetProject(r.Context(), organizationId, projectId) + if err != nil { + log.Error(r.Context(), "Failed to retrieve project", err) + ErrorJSON(w, r, err) + return + } + if project == nil { + ResponseJSON(w, r, http.StatusOK, domain.GetProjectResponse{}) + } + } - var projectRoleId, projectRoleName string requestUserInfo, ok := request.UserFrom(r.Context()) if !ok { ErrorJSON(w, r, fmt.Errorf("failed to retrieve user info from request")) } - userProjectRole := requestUserInfo.GetRoleProjectMapping() - if userProjectRole != nil { - projectRoleName = userProjectRole[project.ID] - } - projectRoles, err := p.usecase.GetProjectRoles(r.Context(), usecase.ProjectAll) + myUserId := requestUserInfo.GetUserId().String() + + var projectRoleId, projectRoleName string + //userProjectRole := requestUserInfo.GetRoleProjectMapping() + //if userProjectRole != nil { + // projectRoleName = userProjectRole[project.ID] + //} + //projectRoles, err := p.usecase.GetProjectRoles(r.Context(), usecase.ProjectAll) + //if err != nil { + // ErrorJSON(w, r, fmt.Errorf("failed to retrieve project role")) + //} + //for _, projectRole := range projectRoles { + // if projectRoleName == projectRole.Name { + // projectRoleId = projectRole.ID + // break + // } + //} + + pm, err := p.usecase.GetProjectMemberByUserId(r.Context(), project.ID, myUserId) if err != nil { - ErrorJSON(w, r, fmt.Errorf("failed to retrieve project role")) + log.Warnf(r.Context(), "failed to retrieve project member %+v", err) } - for _, projectRole := range projectRoles { - if projectRoleName == projectRole.Name { - projectRoleId = projectRole.ID - break - } + if pm != nil { + projectRoleId = pm.ProjectRole.ID + projectRoleName = pm.ProjectRole.Name } //appCount, err := p.usecase.GetAppCount(organizationId, projectId) @@ -322,11 +343,6 @@ func (p ProjectHandler) GetProject(w http.ResponseWriter, r *http.Request) { //} var out domain.GetProjectResponse - if project == nil { - ResponseJSON(w, r, http.StatusNotFound, out) - return - } - var projectLeaderId, projectLeaderName, projectLeaderAccountId, projectLeaderDepartment string for _, pu := range project.ProjectMembers { projectLeaderId = pu.ProjectUser.ID.String() diff --git a/internal/repository/project.go b/internal/repository/project.go index 96f8ee56..6ffc35c0 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -66,9 +66,13 @@ func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId string, userId uuid.UUID, projectName string, pg *pagination.Pagination) (pr []domain.ProjectResponse, err error) { res := r.db.WithContext(ctx).Raw(""+ + "select id, organization_id, name, description, created_at, is_my_project, project_role_id, project_role_name, namespace_count, app_count, member_count, "+ + " project_leader_id, project_leader_name"+ + " from ( "+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ - " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ + " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count, "+ + " pm_leader.project_leader_id as project_leader_id, pm_leader.project_leader_name as project_leader_name "+ " from projects as p "+ " left join "+ " (select pm.project_id as project_id, pm.project_user_id as project_user_id, pm.project_role_id as project_role_id, "+ @@ -79,6 +83,11 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " left join users on users.id = pm.project_user_id "+ " where pm.project_user_id = @userId) as pm on p.id = pm.project_id "+ " left join "+ + " (select pm.project_id as project_id, pm.project_user_id as project_leader_id, users.name as project_leader_name "+ + " from project_members as pm "+ + " left join users on users.id = pm.project_user_id "+ + " where pm.is_project_leader = true) as pm_leader on p.id = pm_leader.project_id "+ + " left join "+ " (select p.id as project_id, count(pn.stack_id || pn.project_id) as count "+ " from project_namespaces as pn "+ " left join projects as p on pn.project_id = p.id "+ @@ -99,12 +108,14 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " where p.organization_id = @organizationId "+ " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ + " and p.id = pm_leader.project_id "+ " and p.organization_id = @organizationId "+ " and p.name like '%"+projectName+"%' "+ "union "+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " false as is_my_project, '' as project_role_id, '' as project_role_name, "+ - " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ + " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count, "+ + " pm_leader.project_leader_id as project_leader_id, pm_leader.project_leader_name as project_leader_name "+ " from projects as p "+ " left join "+ " (select pm.project_id as project_id, pm.project_user_id as project_user_id, pm.project_role_id as project_role_id, "+ @@ -115,6 +126,11 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " left join users on users.id = pm.project_user_id "+ " where pm.project_user_id <> @userId) as pm on p.id = pm.project_id "+ " left join "+ + " (select pm.project_id as project_id, pm.project_user_id as project_leader_id, users.name as project_leader_name "+ + " from project_members as pm "+ + " left join users on users.id = pm.project_user_id "+ + " where pm.is_project_leader = true) as pm_leader on p.id = pm_leader.project_id "+ + " left join "+ " (select p.id as project_id, count(pn.stack_id || pn.project_id) as count "+ " from project_namespaces as pn "+ " left join projects as p on pn.project_id = p.id "+ @@ -135,12 +151,15 @@ func (r *ProjectRepository) GetProjects(ctx context.Context, organizationId stri " where p.organization_id = @organizationId "+ " group by p.id) as pm_count on p.id = pm_count.project_id"+ " where p.id = pm.project_id "+ + " and p.id = pm_leader.project_id "+ " and p.organization_id = @organizationId "+ " and p.name like '%"+projectName+"%' "+ " and p.id not in (select projects.id "+ " from projects "+ " left join project_members on project_members.project_id = projects.id "+ - " where project_members.project_user_id = @userId) ", + " where project_members.project_user_id = @userId) "+ + ") as union_project "+ + "order by is_my_project desc ", sql.Named("organizationId", organizationId), sql.Named("userId", userId)). Scan(&pr) if res.Error != nil { @@ -155,7 +174,8 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " true as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ - " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ + " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count, "+ + " pm_leader.project_leader_id as project_leader_id, pm_leader.project_leader_name as project_leader_name "+ " from projects as p "+ " left join "+ " (select pm.project_id as project_id, pm.project_user_id as project_user_id, pm.project_role_id as project_role_id, "+ @@ -166,6 +186,11 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio " left join users on users.id = pm.project_user_id "+ " where pm.project_user_id = @userId) as pm on p.id = pm.project_id "+ " left join "+ + " (select pm.project_id as project_id, pm.project_user_id as project_leader_id, users.name as project_leader_name "+ + " from project_members as pm "+ + " left join users on users.id = pm.project_user_id "+ + " where pm.is_project_leader = true) as pm_leader on p.id = pm_leader.project_id "+ + " left join "+ " (select p.id as project_id, count(pn.stack_id || pn.project_id) as count "+ " from project_namespaces as pn "+ " left join projects as p on pn.project_id = p.id "+ @@ -186,6 +211,7 @@ func (r *ProjectRepository) GetProjectsByUserId(ctx context.Context, organizatio " where p.organization_id = @organizationId "+ " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ + " and p.id = pm_leader.project_id "+ " and p.organization_id = @organizationId "+ " and p.name like '%"+projectName+"%' ", sql.Named("organizationId", organizationId), sql.Named("userId", userId)). @@ -208,7 +234,8 @@ func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId s res := r.db.WithContext(ctx).Raw(""+ "select distinct p.id as id, p.organization_id as organization_id, p.name as name, p.description as description, p.created_at as created_at, "+ " false as is_my_project, pm.project_role_id as project_role_id, pm.pr_name as project_role_name, "+ - " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count "+ + " pn.count as namespace_count, asa.count as app_count, pm_count.count as member_count, "+ + " pm_leader.project_leader_id as project_leader_id, pm_leader.project_leader_name as project_leader_name "+ " from projects as p "+ " left join "+ " (select distinct pm.project_id as project_id, '' as project_user_id, '' as project_role_id, "+ @@ -218,6 +245,11 @@ func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId s " left join project_roles as pr on pr.id = pm.project_role_id "+ " left join users on users.id = pm.project_user_id) as pm on p.id = pm.project_id "+ " left join "+ + " (select pm.project_id as project_id, pm.project_user_id as project_leader_id, users.name as project_leader_name "+ + " from project_members as pm "+ + " left join users on users.id = pm.project_user_id "+ + " where pm.is_project_leader = true) as pm_leader on p.id = pm_leader.project_id "+ + " left join "+ " (select p.id as project_id, count(pn.stack_id || pn.project_id) as count "+ " from project_namespaces as pn "+ " left join projects as p on pn.project_id = p.id "+ @@ -238,6 +270,7 @@ func (r *ProjectRepository) GetAllProjects(ctx context.Context, organizationId s " where p.organization_id = @organizationId "+ " group by p.id) as pm_count on p.id = pm_count.project_id "+ " where p.id = pm.project_id "+ + " and p.id = pm_leader.project_id "+ " and p.organization_id = @organizationId "+ " and p.name like '%"+projectName+"%' ", sql.Named("organizationId", organizationId)). diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 4b6635aa..093a748c 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -40,6 +40,7 @@ type IProjectUsecase interface { AddProjectMember(ctx context.Context, organizationId string, pm *model.ProjectMember) (string, error) GetProjectUser(ctx context.Context, projectUserId string) (*model.ProjectUser, error) GetProjectMember(ctx context.Context, projectMemberId string) (*model.ProjectMember, error) + GetProjectMemberByUserId(ctx context.Context, projectId string, userId string) (*model.ProjectMember, error) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) ([]model.ProjectMember, error) GetProjectMemberCount(ctx context.Context, projectMemberId string) (*domain.GetProjectMemberCountResponse, error) RemoveProjectMember(ctx context.Context, organizationId string, projectMemberId string) error @@ -326,6 +327,16 @@ func (u *ProjectUsecase) GetProjectMember(ctx context.Context, projectMemberId s return pm, nil } +func (u *ProjectUsecase) GetProjectMemberByUserId(ctx context.Context, projectId string, userId string) (pm *model.ProjectMember, err error) { + pm, err = u.projectRepo.GetProjectMemberByUserId(ctx, projectId, userId) + if err != nil { + log.Error(ctx, err) + return pm, errors.Wrap(err, "Failed to get project member.") + } + + return pm, nil +} + func (u *ProjectUsecase) GetProjectMembers(ctx context.Context, projectId string, query int, pg *pagination.Pagination) (pms []model.ProjectMember, err error) { if query == ProjectLeader { pms, err = u.projectRepo.GetProjectMembersByProjectIdAndRoleName(ctx, projectId, "project-leader", pg) diff --git a/pkg/domain/project.go b/pkg/domain/project.go index e5f45890..dca4cc91 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -3,18 +3,20 @@ package domain import "time" type ProjectResponse struct { - ID string `json:"id"` - OrganizationId string `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - IsMyProject string `json:"isMyProject"` - ProjectRoleId string `json:"projectRoleId"` - ProjectRoleName string `json:"projectRoleName"` - NamespaceCount int `json:"namespaceCount"` - AppCount int `json:"appCount"` - MemberCount int `json:"memberCount"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt *time.Time `json:"updatedAt"` + ID string `json:"id"` + OrganizationId string `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + IsMyProject string `json:"isMyProject"` + ProjectRoleId string `json:"projectRoleId"` + ProjectRoleName string `json:"projectRoleName"` + ProjectLeaderId string `json:"projectLeaderId"` + ProjectLeaderName string `json:"projectLeaderName"` + NamespaceCount int `json:"namespaceCount"` + AppCount int `json:"appCount"` + MemberCount int `json:"memberCount"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt *time.Time `json:"updatedAt"` } type GetProjectsResponse struct { From 5b08f0128b5746f972c6e9e9ae453861dcd4a28c Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Thu, 25 Apr 2024 16:46:32 +0900 Subject: [PATCH 376/502] Add more info when retrieve projects\n swagger generatte --- api/swagger/docs.go | 6 ++++++ api/swagger/swagger.json | 6 ++++++ api/swagger/swagger.yaml | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 95641852..64a254b4 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -14476,6 +14476,12 @@ const docTemplate = `{ "organizationId": { "type": "string" }, + "projectLeaderId": { + "type": "string" + }, + "projectLeaderName": { + "type": "string" + }, "projectRoleId": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 77d95ec3..2cf1c745 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -14470,6 +14470,12 @@ "organizationId": { "type": "string" }, + "projectLeaderId": { + "type": "string" + }, + "projectLeaderName": { + "type": "string" + }, "projectRoleId": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 37c5bb82..57b4ca36 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2827,6 +2827,10 @@ definitions: type: integer organizationId: type: string + projectLeaderId: + type: string + projectLeaderName: + type: string projectRoleId: type: string projectRoleName: From b0234d06d63ed8551a313cdb42b497d618f520ab Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Thu, 25 Apr 2024 18:26:26 +0900 Subject: [PATCH 377/502] app-serving: make GetLatestTask API work --- internal/delivery/http/app-serve-app.go | 28 +++++++++++++++++++++--- internal/model/app-serve-app.go | 4 ++-- internal/repository/app-serve-app.go | 29 +++++++++++++++++++------ internal/usecase/app-serve-app.go | 10 ++++----- 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index e667e4e6..46440ebc 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -394,27 +394,49 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * return } + projectId, ok := vars["projectId"] + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid projectId: [%s]", projectId), "C_INVALID_PROJECT_ID", "")) + return + } + appId, ok := vars["appId"] fmt.Printf("appId = [%s]\n", appId) if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid appId"), "", "")) return } - task, err := h.usecase.GetAppServeAppLatestTask(r.Context(), appId) + + // Check if projectId exists + prj, err := h.prjUsecase.GetProject(r.Context(), organizationId, projectId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("Error while checking project record: %s", err), "", "")) + return + } else if prj == nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found: %s", projectId), "C_INVALID_PROJECT_ID", "")) + } + + task, app, err := h.usecase.GetAppServeAppLatestTask(r.Context(), appId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } if task == nil { - ErrorJSON(w, r, httpErrors.NewNoContentError(fmt.Errorf("no task exists"), "", "")) + ErrorJSON(w, r, httpErrors.NewNoContentError(fmt.Errorf("No task exists"), "", "")) return } var out domain.GetAppServeAppTaskResponse - if err := serializer.Map(r.Context(), task, &out.AppServeAppTask); err != nil { + if err := serializer.Map(r.Context(), *app, &out.AppServeApp); err != nil { + log.Info(r.Context(), err) + } + if err := serializer.Map(r.Context(), *task, &out.AppServeAppTask); err != nil { log.Info(r.Context(), err) } + out.Stages = makeStages(r.Context(), task, app) + ResponseJSON(w, r, http.StatusOK, out) } diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go index 5291cd7c..d19e647f 100644 --- a/internal/model/app-serve-app.go +++ b/internal/model/app-serve-app.go @@ -1,9 +1,9 @@ package model import ( + "github.com/google/uuid" + "gorm.io/gorm" "time" - "github.com/google/uuid" - "gorm.io/gorm" ) type AppServeApp struct { diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 090df5f6..9d8a32d8 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -20,8 +20,8 @@ type IAppServeAppRepository interface { GetAppServeAppTasksByAppId(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) + GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, *model.AppServeApp, error) - GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) IsAppServeAppExist(ctx context.Context, appId string) (int64, error) @@ -182,20 +182,35 @@ func (r *AppServeAppRepository) GetAppServeAppTaskById(ctx context.Context, task return &task, &app, nil } -func (r *AppServeAppRepository) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) { +func (r *AppServeAppRepository) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, *model.AppServeApp, error) { var task model.AppServeAppTask + var app model.AppServeApp + var cluster model.Cluster - // TODO: Does this work?? where's app ID here? - res := r.db.WithContext(ctx).Order("created_at desc").First(&task) + res := r.db.WithContext(ctx).Order("created_at desc").Where("app_serve_app_id = ?", appId).First(&task) if res.Error != nil { log.Debug(ctx, res.Error) - return nil, res.Error + return nil, nil, res.Error } if res.RowsAffected == 0 { - return nil, nil + return nil, nil, fmt.Errorf("No task with App ID %s", appId) } - return &task, nil + // Retrieve app info + res = r.db.WithContext(ctx).Where("id = ?", appId).First(&app) + if res.Error != nil { + log.Debug(ctx, res.Error) + return nil, nil, res.Error + } + if res.RowsAffected == 0 { + return nil, nil, fmt.Errorf("Couldn't find app with ID %s", appId) + } + + // Add cluster name to app object + r.db.WithContext(ctx).Select("name").Where("id = ?", app.TargetClusterId).First(&cluster) + app.TargetClusterName = cluster.Name + + return &task, &app, nil } func (r *AppServeAppRepository) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) { diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index fa6efe24..e712f08d 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -29,7 +29,7 @@ type IAppServeAppUsecase interface { GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) - GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) + GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, *model.AppServeApp, error) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) IsAppServeAppExist(ctx context.Context, appId string) (bool, error) IsAppServeAppNameExist(ctx context.Context, orgId string, appName string) (bool, error) @@ -242,13 +242,13 @@ func (u *AppServeAppUsecase) GetAppServeAppTaskById(ctx context.Context, taskId return task, app, nil } -func (u *AppServeAppUsecase) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) { - task, err := u.repo.GetAppServeAppLatestTask(ctx, appId) +func (u *AppServeAppUsecase) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, *model.AppServeApp, error) { + task, app, err := u.repo.GetAppServeAppLatestTask(ctx, appId) if err != nil { - return nil, err + return nil, nil, err } - return task, nil + return task, app, nil } func (u *AppServeAppUsecase) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) { From c9d17c8a9d0d0d3ab28d558a38d938a893c1deaa Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Thu, 25 Apr 2024 19:03:29 +0900 Subject: [PATCH 378/502] bugfix: pass value to serializer --- internal/delivery/http/app-serve-app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 46440ebc..fbf81a7f 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -361,7 +361,7 @@ func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Reque app.AppServeAppTasks = newTasks var out domain.GetAppServeAppResponse - if err := serializer.Map(r.Context(), app, &out.AppServeApp); err != nil { + if err := serializer.Map(r.Context(), *app, &out.AppServeApp); err != nil { log.Info(r.Context(), err) } @@ -846,6 +846,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re return } + // TODO: use new API instead of the legacy app, err := h.usecase.GetAppServeAppById(r.Context(), appId) if err != nil { ErrorJSON(w, r, err) From ca51a4583d8b0f847bfe33fde1cdf5ced71eaa90 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 26 Apr 2024 10:18:35 +0900 Subject: [PATCH 379/502] =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20=EA=B0=9C=EC=84=A0,=20=EA=B8=80=EB=A1=9C?= =?UTF-8?q?=EB=B2=8C=20=EB=B3=80=EC=88=98=20=ED=95=A0=EB=8B=B9=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../policy-template/policy-template-rego.go | 156 +++++++++++++----- 1 file changed, 118 insertions(+), 38 deletions(-) diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index 0279cf7f..1817b47e 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -120,6 +120,7 @@ func extractInputExprFromModule(module *ast.Module) []string { rules := module.Rules passedInputMap := []string{} + globalAssignMap := map[string]string{} violationRule := []*ast.Rule{} nonViolatonRule := []*ast.Rule{} @@ -129,13 +130,19 @@ func extractInputExprFromModule(module *ast.Module) []string { violationRule = append(violationRule, rule) } else { nonViolatonRule = append(nonViolatonRule, rule) + + if rule.Head.Assign && rule.Head.Value != nil { + if _, ok := rule.Head.Value.Value.(ast.Call); !ok { + globalAssignMap[string(rule.Head.Name)] = rule.Head.Value.String() + } + } } } paramRefs := map[string]string{} for _, rule := range violationRule { - processRule(rule, paramRefs, passedInputMap, nonViolatonRule) + processRule(rule, globalAssignMap, paramRefs, passedInputMap, nonViolatonRule) } // 중복제거를 위해 사용한 맵을 소팅하기 위해 키 리스트로 변환 @@ -155,10 +162,46 @@ func extractInputExprFromModule(module *ast.Module) []string { return paramRefsList } -func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []string, nonViolatonRule []*ast.Rule) { - exprs := rule.Body +func processRule(rule *ast.Rule, globalAssignMap map[string]string, paramRefs map[string]string, passedParams []string, nonViolatonRule []*ast.Rule) map[string]string { localAssignMap := map[string]string{} + // 규칙이 단순 assign이면 value의 정책 호출을 따라가 봐야 함 + if rule.Head.Assign { + if call, ok := rule.Head.Value.Value.(ast.Call); ok { + ruleName := call[0].String() + + args := call[1:] + + argStrs := make([]string, len(args)) + + for i, arg := range args { + argStrs[i] = arg.String() + } + + for _, nvrule := range nonViolatonRule { + if ruleName == nvrule.Head.Name.String() { + return processRule(nvrule, globalAssignMap, paramRefs, argStrs, nonViolatonRule) + } + } + } else { + value := rule.Head.Value.String() + + if isSubstitutionRequired(value) { + paramRefs[value] = "1" + + localAssignMap[string(rule.Head.Name)] = value + + // fmt.Println("1818181818", rule.Head.Value) + return localAssignMap + } + } + + // 더 처리할 건 없음 + return nil + } + + exprs := rule.Body + for i, param := range passedParams { if isSubstitutionRequired(param) { argName := rule.Head.Args[i].String() @@ -169,9 +212,17 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str for _, expr := range exprs { exprString := expr.String() - exprString = substituteWithLocalAssignMap(localAssignMap, exprString) - exprString = replaceAllObjectGet(exprString) - exprString = substituteWithLocalAssignMap(localAssignMap, exprString) + if len(localAssignMap) > 0 { + exprString = substituteWithAssignMap(localAssignMap, exprString) + exprString = replaceAllObjectGet(exprString) + exprString = substituteWithAssignMap(localAssignMap, exprString) + } + + if len(globalAssignMap) > 0 { + exprString = substituteWithAssignMap(globalAssignMap, exprString) + exprString = replaceAllObjectGet(exprString) + exprString = substituteWithAssignMap(globalAssignMap, exprString) + } matches := input_extract_regex.FindAllString(exprString, -1) @@ -187,7 +238,6 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str call, _ := expr.Terms.([]*ast.Term) if len(call) > 1 { ruleName := call[0].String() - args := call[1:] inputPassed, passingParams := processingInputArgs(args, localAssignMap) @@ -207,8 +257,12 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str for _, nvrule := range nonViolatonRule { if ruleName == nvrule.Head.Name.String() { - - processRule(nvrule, paramRefs, passingParams, nonViolatonRule) + updateLocals := processRule(nvrule, globalAssignMap, paramRefs, passingParams, nonViolatonRule) + for k, v := range updateLocals { + if _, ok := localAssignMap[k]; !ok { + localAssignMap[k] = v + } + } } } } @@ -224,7 +278,13 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str for _, nvrule := range nonViolatonRule { if ruleName == nvrule.Head.Name.String() { - processRule(nvrule, paramRefs, []string{}, nonViolatonRule) + updateLocals := processRule(nvrule, globalAssignMap, paramRefs, []string{}, nonViolatonRule) + + for k, v := range updateLocals { + if _, ok := localAssignMap[k]; !ok { + localAssignMap[k] = v + } + } } } } @@ -245,7 +305,13 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str if inputPassed { for _, nvrule := range nonViolatonRule { if ruleName == nvrule.Head.Name.String() { - processRule(nvrule, paramRefs, passingParams, nonViolatonRule) + updateLocals := processRule(nvrule, globalAssignMap, paramRefs, passingParams, nonViolatonRule) + + for k, v := range updateLocals { + if _, ok := localAssignMap[k]; !ok { + localAssignMap[k] = v + } + } } } } @@ -255,7 +321,13 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str for _, nvrule := range nonViolatonRule { ruleName := nvrule.Head.Name.String() if t.Value.String() == ruleName { - processRule(nvrule, paramRefs, []string{}, nonViolatonRule) + updateLocals := processRule(nvrule, globalAssignMap, paramRefs, []string{}, nonViolatonRule) + + for k, v := range updateLocals { + if _, ok := localAssignMap[k]; !ok { + localAssignMap[k] = v + } + } } } @@ -272,10 +344,18 @@ func processRule(rule *ast.Rule, paramRefs map[string]string, passedParams []str for _, nvrule := range nonViolatonRule { ruleName := nvrule.Head.Name.String() if strings.Contains(headKey.String(), ruleName) { - processRule(nvrule, paramRefs, []string{}, nonViolatonRule) + updateLocals := processRule(nvrule, globalAssignMap, paramRefs, []string{}, nonViolatonRule) + + for k, v := range updateLocals { + if _, ok := localAssignMap[k]; !ok { + localAssignMap[k] = v + } + } } } } + + return nil } // object.get(object.get(input, "parameters", {}), "exemptImages", [])) -> input.parameters.exemptImages와 같은 패턴 변환 @@ -302,9 +382,12 @@ func processingInputArgs(args []*ast.Term, localAssignMap map[string]string) (bo for i := 0; i < len(args); i++ { if args[i] != nil { arg := args[i].String() - arg = substituteWithLocalAssignMap(localAssignMap, arg) - arg = replaceAllObjectGet(arg) - arg = substituteWithLocalAssignMap(localAssignMap, arg) + + if len(localAssignMap) > 0 { + arg = substituteWithAssignMap(localAssignMap, arg) + arg = replaceAllObjectGet(arg) + arg = substituteWithAssignMap(localAssignMap, arg) + } if isSubstitutionRequired(arg) { passingParams = append(passingParams, arg) @@ -328,11 +411,8 @@ func updateLocalAssignMap(expr *ast.Expr, localAssignMap map[string]string) { } } -func substituteWithLocalAssignMap(localAssignMap map[string]string, exprString string) string { - for k, v := range localAssignMap { - //pattern := `([^\w\"])` + "parameters" + `([^\w\"])` - // pattern := `([ \[\]\(\)])` + k + `([ \[\]\(\)\.])` - +func substituteWithAssignMap(assignMap map[string]string, exprString string) string { + for k, v := range assignMap { if strings.Contains(exprString, v) { continue } else if exprString == k { @@ -388,23 +468,6 @@ func ExtractParameter(modules map[string]*ast.Module) []*domain.ParameterDef { return defStore.store } -func MergeRegoAndLibs(rego string, libs []string) string { - if len(libs) == 0 { - return rego - } - - var re = regexp.MustCompile(import_regex) - var re2 = regexp.MustCompile(package_name_regex) - - result := re.ReplaceAllString(rego, "") - - for _, lib := range processLibs(libs) { - result += re2.ReplaceAllString(lib, "") - } - - return result -} - type ParamDefStore struct { store []*domain.ParameterDef } @@ -545,6 +608,23 @@ func CompileRegoWithLibs(rego string, libs []string) (compiler *ast.Compiler, er return compiler, nil } +func MergeRegoAndLibs(rego string, libs []string) string { + if len(libs) == 0 { + return rego + } + + var re = regexp.MustCompile(import_regex) + var re2 = regexp.MustCompile(package_name_regex) + + result := re.ReplaceAllString(rego, "") + + for _, lib := range processLibs(libs) { + result += re2.ReplaceAllString(lib, "") + } + + return result +} + func MergeAndCompileRegoWithLibs(rego string, libs []string) (modules map[string]*ast.Module, err error) { modules = map[string]*ast.Module{} From e4b33a83983a942eaed27276be0b1bef7670c19b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 26 Apr 2024 15:26:19 +0900 Subject: [PATCH 380/502] feature. personalization systemNotifications --- .../delivery/http/system-notification-rule.go | 9 +++++ internal/model/system-notification.go | 1 + internal/repository/organization.go | 2 +- .../repository/system-notification-rule.go | 4 +- internal/repository/system-notification.go | 25 ++++-------- internal/repository/user.go | 4 +- internal/usecase/system-notification-rule.go | 29 +++++++++----- .../usecase/system-notification-template.go | 4 ++ internal/usecase/system-notification.go | 40 ++++++++++--------- pkg/httpErrors/errorCode.go | 13 +++--- scripts/init_postgres.sql | 2 + 11 files changed, 78 insertions(+), 55 deletions(-) diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 3d900a35..8c815cec 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -61,6 +61,11 @@ func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.Resp } dto.OrganizationId = organizationId + if !dto.SystemNotificationCondition.EnablePortal { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid EnablePortal"), "SNR_INVALID_ENABLE_PORTAL", "")) + return + } + id, err := h.usecase.Create(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) @@ -239,6 +244,10 @@ func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(w http.Resp dto.OrganizationId = organizationId dto.ID = systemNotificationRuleId + if !dto.SystemNotificationCondition.EnablePortal { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid EnablePortal"), "SNR_INVALID_ENABLE_PORTAL", "")) + return + } err = h.usecase.Update(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go index c33fadf5..26906afe 100644 --- a/internal/model/system-notification.go +++ b/internal/model/system-notification.go @@ -38,6 +38,7 @@ type SystemNotification struct { Status domain.SystemNotificationActionStatus `gorm:"index"` Read bool `gorm:"-:all"` Readers []User `gorm:"many2many:system_notification_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` + SystemNotificationRuleId *uuid.UUID } type SystemNotificationAction struct { diff --git a/internal/repository/organization.go b/internal/repository/organization.go index f91e720b..0b53d9bf 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -90,7 +90,7 @@ func (r *OrganizationRepository) Fetch(ctx context.Context, pg *pagination.Pagin // [TODO] more pretty! for _, filter := range pg.Filters { if filter.Relation == "Admin" { - db = db.Joins("left outer join users on users.id::text = organizations.admin_id::text"). + db = db.Joins("join users on users.id::text = organizations.admin_id::text"). Where("users.name ilike ?", "%"+filter.Values[0]+"%") break } diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 21ccbf99..b298fc30 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -75,8 +75,8 @@ func (r *SystemNotificationRuleRepository) FetchWithOrganization(ctx context.Con // [TODO] more pretty! for _, filter := range pg.Filters { if filter.Relation == "TargetUsers" { - db = db.Joins("left outer join system_notification_rule_users on system_notification_rules.id = system_notification_rule_users.system_notification_rule_id"). - Joins("left outer join users on system_notification_rule_users.user_id = users.id"). + db = db.Joins("join system_notification_rule_users on system_notification_rules.id = system_notification_rule_users.system_notification_rule_id"). + Joins("join users on system_notification_rule_users.user_id = users.id"). Where("users.name ilike ?", "%"+filter.Values[0]+"%") break } diff --git a/internal/repository/system-notification.go b/internal/repository/system-notification.go index 7d69a831..1f43a560 100644 --- a/internal/repository/system-notification.go +++ b/internal/repository/system-notification.go @@ -75,6 +75,9 @@ func (r *SystemNotificationRepository) FetchSystemNotifications(ctx context.Cont Preload("Cluster", "status = 2"). Preload("Organization"). Joins("join clusters on clusters.id = system_notifications.cluster_id AND clusters.status = 2"). + Joins("left outer join system_notification_rules ON system_notification_rules.id = system_notifications.system_notification_rule_id"). + Joins("left outer join system_notification_rule_users ON system_notification_rule_users.system_notification_rule_id = system_notifications.system_notification_rule_id"). + Where("system_notification_rule_users.user_id is null OR system_notification_rule_users.user_id = ?", userInfo.GetUserId()). Where("system_notifications.organization_id = ? AND system_notifications.notification_type = 'SYSTEM_NOTIFICATION'", organizationId) readFilter := pg.GetFilter("read") @@ -140,26 +143,14 @@ func (r *SystemNotificationRepository) FetchPodRestart(ctx context.Context, orga } func (r *SystemNotificationRepository) Create(ctx context.Context, dto model.SystemNotification) (systemNotificationId uuid.UUID, err error) { - systemNotification := model.SystemNotification{ - ID: uuid.New(), - OrganizationId: dto.OrganizationId, - Name: dto.Name, - Severity: dto.Severity, - MessageTitle: dto.MessageTitle, - MessageContent: dto.MessageContent, - MessageActionProposal: dto.MessageActionProposal, - ClusterId: dto.ClusterId, - Node: dto.Node, - GrafanaUrl: dto.GrafanaUrl, - Summary: dto.Summary, - RawData: dto.RawData, - Status: domain.SystemNotificationActionStatus_CREATED, - } - res := r.db.WithContext(ctx).Create(&systemNotification) + + dto.ID = uuid.New() + dto.Status = domain.SystemNotificationActionStatus_CREATED + res := r.db.WithContext(ctx).Create(&dto) if res.Error != nil { return uuid.Nil, res.Error } - return systemNotification.ID, nil + return dto.ID, nil } func (r *SystemNotificationRepository) Update(ctx context.Context, dto model.SystemNotification) (err error) { diff --git a/internal/repository/user.go b/internal/repository/user.go index 2e3c3340..08d66169 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -127,7 +127,9 @@ func (r *UserRepository) ListWithPagination(ctx context.Context, pg *pagination. // [TODO] more pretty! for _, filter := range pg.Filters { if filter.Relation == "Roles" { - db = db.Where("id IN (SELECT user_id FROM user_roles WHERE name IN ?)", filter.Values) + db = db.Joins("join user_roles on user_roles.user_id = users.id"). + Joins("join roles on roles.id = user_roles.role_id"). + Where("roles.name ilike ?", "%"+filter.Values[0]+"%") break } } diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 01ef4c36..d777e432 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -154,6 +154,10 @@ func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, systemNotifi userId := user.GetUserId() systemNotificationRule.UpdatorId = &userId + if systemNotificationRule.IsSystem { + return out, httpErrors.NewBadRequestError(fmt.Errorf("cannot delete system rules"), "SNR_CANNOT_DELETE_SYSTEM_RULE", "") + } + err = u.repo.Delete(ctx, systemNotificationRule) if err != nil { return out, err @@ -173,10 +177,13 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c return err } - organizationAdmin, err := u.userRepo.GetByUuid(ctx, *organization.AdminId) - if err != nil { - return err - } + /* + // 240426 : 기본 알림 설정은 "전체" 를 대상자로 한다. + organizationAdmin, err := u.userRepo.GetByUuid(ctx, *organization.AdminId) + if err != nil { + return err + } + */ pg := pagination.NewPaginationWithFilter("is_system", "", "$eq", []string{"1"}) templates, err := u.systemNotificationTemplateRepo.Fetch(ctx, pg) @@ -204,7 +211,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnableEmail: true, EnablePortal: true, }, - TargetUsers: []model.User{organizationAdmin}, + TargetUsers: []model.User{}, MessageTitle: "CPU 사용량이 높습니다", MessageContent: "스택 (<>)의 노드(<>)의 idle process의 cpu 점유율이 3분 동안 0% 입니다. (현재 사용률 {{$value}}). 워커 노드 CPU가 과부하 상태입니다. 일시적인 서비스 Traffic 증가, Workload의 SW 오류, Server HW Fan Fail등 다양한 원인으로 인해 발생할 수 있습니다.", MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행 되는 pod중 CPU 자원을 많이 점유하는 pod의 설정을 점검해 보시길 제안드립니다. 예를 들어 pod spec의 limit 설정으로 과도한 CPU자원 점유을 막을 수 있습니다.", @@ -230,7 +237,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnableEmail: true, EnablePortal: true, }, - TargetUsers: []model.User{organizationAdmin}, + TargetUsers: []model.User{}, MessageTitle: "메모리 사용량이 높습니다", MessageContent: "스택 (<>)의 노드(<>)의 Memory 사용량이 3분동안 80% 를 넘어서고 있습니다. (현재 사용률 {{$value}}). 워커 노드의 Memory 사용량이 80%를 넘었습니다. 일시적인 서비스 증가 및 SW 오류등 다양한 원인으로 발생할 수 있습니다.", MessageActionProposal: "일시적인 Service Traffic의 증가가 관측되지 않았다면, Alert발생 노드에서 실행되는 pod중 Memory 사용량이 높은 pod들에 대한 점검을 제안드립니다.", @@ -256,7 +263,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnableEmail: true, EnablePortal: true, }, - TargetUsers: []model.User{organizationAdmin}, + TargetUsers: []model.User{}, MessageTitle: "노드 디스크 사용량이 높습니다.", MessageContent: "지난 6시간동안의 추세로 봤을 때, 스택 (<>)의 노드(<>)의 root 볼륨은 24시간 안에 Disk full이 예상됨. 현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰 것으로 예상됩니다.", MessageActionProposal: "Disk 용량 최적화(삭제 및 Backup)을 수행하시길 권고합니다. 삭제할 내역이 없으면 증설 계획을 수립해 주십시요.", @@ -282,7 +289,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnableEmail: true, EnablePortal: true, }, - TargetUsers: []model.User{organizationAdmin}, + TargetUsers: []model.User{}, MessageTitle: "PVC 사용량이 높습니다.", MessageContent: "지난 6시간동안의 추세로 봤을 때, 스택 (<>)의 파드(<>)가 24시간 안에 Disk full이 예상됨. 현재 Disk 사용 추세기준 24시간 내에 Disk 용량이 꽉 찰것으로 예상됩니다. (<> 스택, <> PVC)", MessageActionProposal: "Disk 용량 최적화(삭제 및 Backup)을 수행하시길 권고합니다. 삭제할 내역이 없으면 증설 계획을 수립해 주십시요.", @@ -308,7 +315,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnableEmail: true, EnablePortal: true, }, - TargetUsers: []model.User{organizationAdmin}, + TargetUsers: []model.User{}, MessageTitle: "스택의 Pod가 재기동되고 있습니다.", MessageContent: "스택 (<>)의 파드(<>)가 30분 동안 5회 이상 재기동 ({{$value}} 회). 특정 Pod가 빈번하게 재기동 되고 있습니다. 점검이 필요합니다. (<> 스택, <> 파드)", MessageActionProposal: "pod spec. 에 대한 점검이 필요합니다. pod의 log 및 status를 확인해 주세요.", @@ -334,7 +341,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnableEmail: true, EnablePortal: true, }, - TargetUsers: []model.User{organizationAdmin}, + TargetUsers: []model.User{}, MessageTitle: "정책 위반(<> / <>)", MessageContent: "스택 (<>)의 자원(<> - <> / <>)에서 정책(<> / <>)위반이 발생했습니다. 메시지 - <>", MessageActionProposal: "정책위반이 발생하였습니다.(<> / <>)", @@ -360,7 +367,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c EnableEmail: true, EnablePortal: true, }, - TargetUsers: []model.User{organizationAdmin}, + TargetUsers: []model.User{}, MessageTitle: "정책 위반(<> / <>) 시도", MessageContent: "스택 (<>)의 자원(<> - <> / <>)에서 정책(<> / <>)위반 시도가 발생했습니다. 메시지 - <>", MessageActionProposal: "정책위반이 시도가 발생하였습니다.(<> / <>)", diff --git a/internal/usecase/system-notification-template.go b/internal/usecase/system-notification-template.go index ebfd6cd7..f0c7743f 100644 --- a/internal/usecase/system-notification-template.go +++ b/internal/usecase/system-notification-template.go @@ -140,6 +140,10 @@ func (u *SystemNotificationTemplateUsecase) Delete(ctx context.Context, systemNo userId := user.GetUserId() systemNotificationTemplate.UpdatorId = &userId + if systemNotificationTemplate.IsSystem { + return httpErrors.NewBadRequestError(fmt.Errorf("cannot delete systemNotificationTemplate"), "SNT_CANNOT_DELETE_SYSTEM_TEMPLATE", "") + } + // check if used // system_notification_rules pg := pagination.NewPaginationWithFilter("system_notification_template_id", "", "$eq", []string{systemNotificationTemplateId.String()}) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 30b389be..3027ff4d 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -107,18 +107,27 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre node = systemNotification.Labels.Instance } + var systemNotificationRuleId *uuid.UUID + if systemNotification.Annotations.SystemNotificationRuleId != "" { + id, err := uuid.Parse(systemNotification.Annotations.SystemNotificationRuleId) + if err == nil { + systemNotificationRuleId = &id + } + } + dto := model.SystemNotification{ - OrganizationId: organizationId, - Name: systemNotification.Labels.AlertName, - Severity: systemNotification.Labels.Severity, - Node: node, - MessageTitle: systemNotification.Annotations.Message, - MessageContent: systemNotification.Annotations.Description, - MessageActionProposal: systemNotification.Annotations.Checkpoint, - Summary: systemNotification.Annotations.Summary, - ClusterId: domain.ClusterId(clusterId), - GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, systemNotification, domain.ClusterId(clusterId)), - RawData: rawData, + OrganizationId: organizationId, + Name: systemNotification.Labels.AlertName, + Severity: systemNotification.Labels.Severity, + Node: node, + MessageTitle: systemNotification.Annotations.Message, + MessageContent: systemNotification.Annotations.Description, + MessageActionProposal: systemNotification.Annotations.Checkpoint, + Summary: systemNotification.Annotations.Summary, + ClusterId: domain.ClusterId(clusterId), + GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, systemNotification, domain.ClusterId(clusterId)), + RawData: rawData, + SystemNotificationRuleId: systemNotificationRuleId, } _, err = u.repo.Create(ctx, dto) @@ -128,13 +137,8 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre } // 사용자가 생성한 알림 - if systemNotification.Annotations.SystemNotificationRuleId != "" { - systemNotificationRuleId, err := uuid.Parse(systemNotification.Annotations.SystemNotificationRuleId) - if err != nil { - log.Error(ctx, "Failed to parse uuid ", err) - continue - } - rule, err := u.systemNotificationRuleRepo.Get(ctx, systemNotificationRuleId) + if systemNotificationRuleId != nil { + rule, err := u.systemNotificationRuleRepo.Get(ctx, *systemNotificationRuleId) if err != nil { log.Error(ctx, "Failed to get systemNotificationRule ", err) continue diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index ff17fbef..b51c2b9a 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -85,17 +85,20 @@ var errorMap = map[ErrorCode]string{ "AL_NOT_FOUND_ALERT": "지정한 앨럿이 존재하지 않습니다.", // SystemNotificationTemplate - "SNT_CREATE_ALREADY_EXISTED_NAME": "알림템플릿에 이미 존재하는 이름입니다.", - "SNT_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿을 가져오는데 실패했습니다.", - "SNT_FAILED_UPDATE_ORGANIZATION": "알림템플릿에 조직을 설정하는데 실패했습니다.", - "SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.", - "SNT_FAILED_DELETE_EXIST_RULES": "알림템플릿을 사용하고 있는 알림 설정이 있습니다. 알림 설정을 삭제하세요.", + "SNT_CREATE_ALREADY_EXISTED_NAME": "알림템플릿에 이미 존재하는 이름입니다.", + "SNT_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿을 가져오는데 실패했습니다.", + "SNT_FAILED_UPDATE_ORGANIZATION": "알림템플릿에 조직을 설정하는데 실패했습니다.", + "SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.", + "SNT_FAILED_DELETE_EXIST_RULES": "알림템플릿을 사용하고 있는 알림 설정이 있습니다. 알림 설정을 삭제하세요.", + "SNT_CANNOT_DELETE_SYSTEM_TEMPLATE": "시스템 알림템플릿은 삭제 할 수 없습니다.", // SystemNotificationRule "SNR_CREATE_ALREADY_EXISTED_NAME": "알림 설정에 이미 존재하는 이름입니다.", "SNR_FAILED_FETCH_SYSTEM_NOTIFICATION_RULE": "알림 설정을 가져오는데 실패했습니다.", "SNR_FAILED_UPDATE_ORGANIZATION": "알림 설정에 조직을 설정하는데 실패했습니다.", "SNR_NOT_EXISTED_SYSTEM_NOTIFICATION_RULE": "업데이트할 알림 설정이 존재하지 않습니다.", + "SNR_INVALID_ENABLE_PORTAL": "알림 방법의 포탈은 설정을 변경할 수 없습니다.", + "SNR_CANNOT_DELETE_SYSTEM_RULE": "시스템 알림 설정은 삭제 할 수 없습니다.", // AppGroup "AG_NOT_FOUND_CLUSTER": "지장한 클러스터가 존재하지 않습니다.", diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index c04c371f..ef542216 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -1,3 +1,5 @@ +ALTER DATABASE tks SET timezone = 'Asia/Seoul'; + ## Roles insert into roles ( id, name, description, created_at, updated_at ) values ( '2ea4415c-9748-493f-91ba-4a64506b7be8', 'tks-admin', 'tks-admin', now(), now() ); insert into roles ( id, name, description, created_at, updated_at ) values ( 'b2b689f0-ceeb-46c2-b280-0bc06896acd1', 'admin', 'admin', now(), now() ); From 3ebeed27987e9ccca1f151081b9e19fb699e87d0 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 26 Apr 2024 17:53:41 +0900 Subject: [PATCH 381/502] feature. change email html --- internal/mail/content.go | 8 +- internal/mail/contents/authcode.html | 228 ++++++----- .../mail/contents/organization_creation.html | 387 ++++++++++++------ .../mail/contents/system_notification.html | 260 +++++++----- .../mail/contents/temporary_password.html | 192 +++++---- internal/usecase/system-notification.go | 2 +- 6 files changed, 661 insertions(+), 416 deletions(-) diff --git a/internal/mail/content.go b/internal/mail/content.go index 417d00cf..06787c9b 100644 --- a/internal/mail/content.go +++ b/internal/mail/content.go @@ -98,9 +98,7 @@ func MakeGeneratingOrganizationMessage( return m, nil } -func MakeSystemNotificationMessage(ctx context.Context, organizationId string, title string, to []string) (*MessageInfo, error) { - subject := "[TKS] 시스템 알림이 발생하였습니다." - +func MakeSystemNotificationMessage(ctx context.Context, organizationId string, title string, content string, to []string) (*MessageInfo, error) { tmpl, err := template.ParseFS(templateFS, "contents/system_notification.html") if err != nil { log.Errorf(ctx, "failed to parse template, %v", err) @@ -109,6 +107,8 @@ func MakeSystemNotificationMessage(ctx context.Context, organizationId string, t data := map[string]string{ "OrganizationId": organizationId, + "Title": title, + "Content": content, } var tpl bytes.Buffer @@ -120,7 +120,7 @@ func MakeSystemNotificationMessage(ctx context.Context, organizationId string, t m := &MessageInfo{ From: from, To: to, - Subject: subject, + Subject: title, Body: tpl.String(), } diff --git a/internal/mail/contents/authcode.html b/internal/mail/contents/authcode.html index 09f79474..ab429c31 100644 --- a/internal/mail/contents/authcode.html +++ b/internal/mail/contents/authcode.html @@ -2,106 +2,136 @@ - 이메일인증 안내 - - - -
+ 이메일 인증 안내 + +
- - - - - - - - -
SKT Enterprise
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + +
- 이메일 인증 안내 -
안녕하세요.
항상 저희 TKS Cloud Service를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
- 고객님께서 입력하신 이메일 주소 인증을 위해 아래 6자리 인증번호를 -
화면에 입력해 주세요.
이메일 인증코드
{{.AuthCode}}
더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
감사합니다.
SKT Enterprise
+ + + + + + + + + + + + + + + + + + + + + + - - - - + + +
+ 이메일 인증 안내 +
+ 안녕하세요.
+ 항상 저희 SKT Enterprise를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
+ 고객님께서 입력하신 이메일 주소 인증을 위해 아래 6자리 인증번호를 화면에 입력해 주세요. +
+ 이메일 인증 코드 + +
+ + + + + + +
{{.AuthCode}}
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + + + +
본 메일은 발신 전용 메일로, 회신 되지 않습니다.
우편번호: 04539 서울특별시중구을지로65 (을지로2가) SK T-타워 SK텔레콤㈜ 대표이사 : 유영상
COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED.
+ 더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
+ 감사합니다. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 본 메일은 발신 전용 메일로, 회신 되지 않습니다. +
+ 우편번호: 04539 서울특별시 중구 을지로 65 (을지로 2가) SK T-타워 SK텔레콤(주) 대표이사 : 유영상
+ COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED. +
-
+
- - - - + + + + \ No newline at end of file diff --git a/internal/mail/contents/organization_creation.html b/internal/mail/contents/organization_creation.html index 988411d7..de0ad1f8 100644 --- a/internal/mail/contents/organization_creation.html +++ b/internal/mail/contents/organization_creation.html @@ -1,129 +1,260 @@ - - - - - 조직 생성 - - - -
- - - - - - - - - - - - - - - -
SKT Enterprise
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ​ - - - - - - - - - - - - -
- 조직 생성 안내 -
안녕하세요.
항상 저희 TKS Cloud Service를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
- 조직이 생성되었습니다. -
아래의 정보를 이용하여 로그인 해주시기 바랍니다.
로그인 정보
- • 조직코드: {{.OrganizationId}} -
• 아이디: {{.Id}} -
• 비밀번호: {{.Password}} -
조직 정보
- • 조직이름: {{.OrganizationName}} -
• 관리자 이름: {{.AdminName}} -
더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
감사합니다.
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
본 메일은 발신 전용 메일로, 회신 되지 않습니다.
우편번호: 04539 서울특별시중구을지로65 (을지로2가) SK T-타워 SK텔레콤㈜ 대표이사 : 유영상
COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED.
-
-
- - + + + + + + + 조직 생성 + + + +
+ + + + + + + + + + + + + + + + + + + + +
SKT Enterprise
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 조직 생성 안내 +
+ 안녕하세요.
+ 항상 저희 SKT Enterprise를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
+ 조직이 생성되었습니다.
+ 아래의 정보를 이용하여 로그인 해주시기 바랍니다. +
+ 로그인 정보 +
+ + + + + + + + + + + + + + + + + + + +
+ 조직코드 + + {{.OrganizationId}} +
+ 아이디 + + {{.Id}} +
+ 비밀번호 + + {{.Password}} +
+
+ 조직 정보 +
+ + + + + + + + + + + + +
+ 조직 이름 + + {{.OrganizationName}} +
+ 관리자 이름 + + {{.AdminName}} +
+
+ 더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
+ 감사합니다. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 본 메일은 발신 전용 메일로, 회신 되지 않습니다. +
+ 우편번호: 04539 서울특별시 중구 을지로 65 (을지로 2가) SK T-타워 SK텔레콤(주) 대표이사 : 유영상
+ COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED. +
+
+
+
+ + diff --git a/internal/mail/contents/system_notification.html b/internal/mail/contents/system_notification.html index 105d3ef4..1e222cba 100644 --- a/internal/mail/contents/system_notification.html +++ b/internal/mail/contents/system_notification.html @@ -1,105 +1,161 @@ - - - - + + + + + + 시스템 알림 - - -
- - - - - - - - - - - - - - - -
SKT Enterprise
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 조직 생성 안내 -
안녕하세요.
항상 저희 TKS Cloud Service를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
- 시스템 알림 -
테스트
로그인 정보
더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
감사합니다.
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
본 메일은 발신 전용 메일로, 회신 되지 않습니다.
우편번호: 04539 서울특별시중구을지로65 (을지로2가) SK T-타워 SK텔레콤㈜ 대표이사 : 유영상
COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED.
-
-
- + + +
+ + + + + + + + + + + + + + + + + + + + +
+ SKT Enterprise +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + {{.Title}} + +
+ 안녕하세요.
+ 항상 저희 SKT Enterprise를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
+ 아래 내용으로 시스템 알림이 발생 되었습니다.
+ 내용 확인 후 조치 해주시기 바랍니다. +
+ 내용 +
+ + + + +
+ {{.Content}} +
+
+ 더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
+ 감사합니다. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 본 메일은 발신 전용 메일로, 회신 되지 않습니다. +
+ 우편번호: 04539 서울특별시 중구 을지로 65 (을지로 2가) SK T-타워 SK텔레콤(주) 대표이사 : 유영상
+ COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED. +
+
+
+
+ - - \ No newline at end of file + diff --git a/internal/mail/contents/temporary_password.html b/internal/mail/contents/temporary_password.html index 654ee0d0..dd3cd495 100644 --- a/internal/mail/contents/temporary_password.html +++ b/internal/mail/contents/temporary_password.html @@ -2,112 +2,140 @@ - 임시 비밀번호 발급 + 임시 비밀번호 발급 안내 - - -
+
+ + + - + + + + + + - - - - + + - - - - +
SKT EnterpriseSKT Enterprise
- +
+ - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 임시 비밀번호 발급 안내 + + + 임시 비밀번호 발급 안내 +
안녕하세요.
항상 저희 TKS Cloud Service를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
- 임시 비밀번호가 발급되었습니다. -
로그인 후 비밀번호를 변경하여 사용해 주시기 바랍니다.
조직 코드: {{.OrganizationId}}
아이디: {{.AccountId}}
임시 비밀번호
{{.TemporaryPassword}}
더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
감사합니다.
-
- - - - - + - - - - + + - - - + + + + - + + + + - - - + - - - - + + + + + +
+ 안녕하세요.
+ 항상 저희 SKT Enterprise를 사랑해 주시고 성원해 주시는 고객님께 감사드립니다.
+ 로그인 후 비밀번호를 변경하여 사용해 주시기 바랍니다. +
본 메일은 발신 전용 메일로, 회신 되지 않습니다.
+ 임시 비밀번호 +
+ + + + + + + +
+ {{.TemporaryPassword}} +
+ +
우편번호: 04539 서울특별시중구을지로65 (을지로2가) SK T-타워 SK텔레콤㈜ 대표이사 : 유영상
COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED.
+ 더욱 편리한 서비스를 제공하기 위해 항상 최선을 다하겠습니다.
+ 감사합니다. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 본 메일은 발신 전용 메일로, 회신 되지 않습니다. +
+ 우편번호: 04539 서울특별시 중구 을지로 65 (을지로 2가) SK T-타워 SK텔레콤(주) 대표이사 : 유영상
+ COPYRIGHT SK TELECOM CO., LTD. ALL RIGHTS RESERVED. +
+
- + \ No newline at end of file diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 3027ff4d..6add4b68 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -149,7 +149,7 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre for _, user := range rule.TargetUsers { to = append(to, user.Email) } - message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, to) + message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, systemNotification.Annotations.Description, to) if err != nil { log.Error(ctx, fmt.Sprintf("Failed to make email content. err : %s", err.Error())) continue From 0b70cd8eaabb643c311616e541f301d11145e6ce Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Fri, 26 Apr 2024 11:45:25 +0900 Subject: [PATCH 382/502] refactor app-serving APIs including deprecation of legacy one --- internal/delivery/http/app-serve-app.go | 154 +++++++---------------- internal/repository/app-serve-app.go | 70 +++-------- internal/route/route.go | 1 - internal/usecase/app-serve-app.go | 160 +++++++++++++++--------- 4 files changed, 161 insertions(+), 224 deletions(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index fbf81a7f..aa29a745 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -158,8 +158,6 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re task.Output = "" task.CreatedAt = now - app.AppServeAppTasks = append(app.AppServeAppTasks, task) - // Validate name param re, _ := regexp.Compile("^[a-z][a-z0-9-]*$") if !(re.MatchString(app.Name)) { @@ -216,7 +214,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re return } - _, _, err = h.usecase.CreateAppServeApp(r.Context(), &app) + _, _, err = h.usecase.CreateAppServeApp(r.Context(), &app, &task) if err != nil { ErrorJSON(w, r, err) return @@ -304,73 +302,6 @@ func (h *AppServeAppHandler) GetAppServeApps(w http.ResponseWriter, r *http.Requ ResponseJSON(w, r, http.StatusOK, out) } -// GetAppServeApp godoc -// -// @Tags AppServeApps -// @Summary Get appServeApp -// @Description Get appServeApp by giving params -// @Accept json -// @Produce json -// @Param organizationId path string true "Organization ID" -// @Param projectId path string true "Project ID" -// @Param appId path string true "App ID" -// @Success 200 {object} domain.GetAppServeAppResponse -// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId} [get] -// @Security JWT -func (h *AppServeAppHandler) GetAppServeApp(w http.ResponseWriter, r *http.Request) { - ////////////////////////////////////////////////////////////////////////////////////////// - // TODO: this API will'be deprecated soon once the new task-related API's are verified. - // Until then, this is available (except for stage info) just for backward compatibility. - ////////////////////////////////////////////////////////////////////////////////////////// - - vars := mux.Vars(r) - - organizationId, ok := vars["organizationId"] - fmt.Printf("organizationId = [%v]\n", organizationId) - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) - return - } - - appId, ok := vars["appId"] - fmt.Printf("appId = [%s]\n", appId) - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid appId"), "C_INVALID_ASA_ID", "")) - return - } - app, err := h.usecase.GetAppServeAppById(r.Context(), appId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - if app == nil { - ErrorJSON(w, r, httpErrors.NewNoContentError(fmt.Errorf("no appId"), "D_NO_ASA", "")) - return - } - - newTasks := make([]model.AppServeAppTask, 0) - - for idx, t := range app.AppServeAppTasks { - // Rollbacking to latest task should be blocked. - if idx > 0 && strings.Contains(t.Status, "SUCCESS") && t.Status != "ABORT_SUCCESS" && - t.Status != "ROLLBACK_SUCCESS" { - t.AvailableRollback = true - } - newTasks = append(newTasks, t) - } - app.AppServeAppTasks = newTasks - - var out domain.GetAppServeAppResponse - if err := serializer.Map(r.Context(), *app, &out.AppServeApp); err != nil { - log.Info(r.Context(), err) - } - - // NOTE: makeStages function's been changed to use task instead of app - //out.Stages = makeStages(app) - - ResponseJSON(w, r, http.StatusOK, out) -} - // GetAppServeAppLatestTask godoc // // @Tags AppServeApps @@ -417,7 +348,7 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found: %s", projectId), "C_INVALID_PROJECT_ID", "")) } - task, app, err := h.usecase.GetAppServeAppLatestTask(r.Context(), appId) + task, err := h.usecase.GetAppServeAppLatestTask(r.Context(), appId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -426,6 +357,18 @@ func (h *AppServeAppHandler) GetAppServeAppLatestTask(w http.ResponseWriter, r * ErrorJSON(w, r, httpErrors.NewNoContentError(fmt.Errorf("No task exists"), "", "")) return } + // Rollbacking to latest task should be blocked. + task.AvailableRollback = false + + app, err := h.usecase.GetAppServeAppById(r.Context(), appId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if app == nil { + ErrorJSON(w, r, httpErrors.NewNoContentError(fmt.Errorf("No app exists"), "D_NO_ASA", "")) + return + } var out domain.GetAppServeAppTaskResponse if err := serializer.Map(r.Context(), *app, &out.AppServeApp); err != nil { @@ -605,7 +548,7 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found: %s", projectId), "C_INVALID_PROJECT_ID", "")) } - task, app, err := h.usecase.GetAppServeAppTaskById(r.Context(), taskId) + task, err := h.usecase.GetAppServeAppTaskById(r.Context(), taskId) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return @@ -615,6 +558,17 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * return } + app, err := h.usecase.GetAppServeAppById(r.Context(), appId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if app == nil { + ErrorJSON(w, r, httpErrors.NewNoContentError(fmt.Errorf("No app exists"), "D_NO_ASA", "")) + return + } + + // TODO: this should be false for latest task if strings.Contains(task.Status, "SUCCESS") && task.Status != "ABORT_SUCCESS" && task.Status != "ROLLBACK_SUCCESS" { task.AvailableRollback = true @@ -703,8 +657,6 @@ func makeStage(ctx context.Context, task *model.AppServeAppTask, app *model.AppS } actions = append(actions, action) } - } else { - log.Error(ctx, "Not supported strategy!") } } else if stage.Status == "PROMOTE_WAIT" && strategy == "blue-green" { @@ -846,14 +798,15 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re return } - // TODO: use new API instead of the legacy - app, err := h.usecase.GetAppServeAppById(r.Context(), appId) + // Get latest task + latestTask, err := h.usecase.GetAppServeAppLatestTask(r.Context(), appId) if err != nil { - ErrorJSON(w, r, err) + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } - if len(app.AppServeAppTasks) < 1 { - ErrorJSON(w, r, err) + if latestTask == nil { + ErrorJSON(w, r, httpErrors.NewNoContentError(fmt.Errorf("No task exists"), "", "")) + return } // unmarshal request that only contains task-specific params @@ -864,28 +817,8 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re return } - // Instead of setting default value, some fields should be retrieved - // from existing app config. - //appReq.SetDefaultValue() - var task model.AppServeAppTask - //tasks := app.AppServeAppTasks - //sort.Slice(tasks, func(i, j int) bool { - // return tasks[i].CreatedAt.String() > tasks[j].CreatedAt.String() - //}) - //for _, t := range tasks { - // if t.Status == "DEPLOY_SUCCESS" { - // latestTask = t - // break - // } - //} - //if err = serializer.Map(r.Context(), latestTask, &task); err != nil { - // ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) - // return - //} - - var latestTask = app.AppServeAppTasks[0] - if err = serializer.Map(r.Context(), latestTask, &task); err != nil { + if err = serializer.Map(r.Context(), *latestTask, &task); err != nil { //ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "", "")) return } @@ -895,12 +828,15 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re return } - //updateVersion, err := strconv.Atoi(latestTask.Version) - //if err != nil { - // ErrorJSON(w, r, httpErrors.NewInternalServerError(err,"")) - //} - //task.Version = strconv.Itoa(updateVersion + 1) - task.Version = strconv.Itoa(len(app.AppServeAppTasks) + 1) + // Set new version + verInt, err := strconv.Atoi(latestTask.Version) + if err != nil { + ErrorJSON(w, r, err) + return + } + newVerStr := strconv.Itoa(verInt + 1) + + task.Version = newVerStr //task.AppServeAppId = app.ID task.Status = "PREPARING" task.RollbackVersion = "" @@ -908,9 +844,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re task.CreatedAt = time.Now() task.UpdatedAt = nil - fmt.Println("===========================") - fmt.Printf("%v\n", task) - fmt.Println("===========================") + log.Debugf(r.Context(), "New task in update request: %v\n", task) var res string if appReq.Promote { @@ -918,7 +852,7 @@ func (h *AppServeAppHandler) UpdateAppServeApp(w http.ResponseWriter, r *http.Re } else if appReq.Abort { res, err = h.usecase.AbortAppServeApp(r.Context(), appId) } else { - res, err = h.usecase.UpdateAppServeApp(r.Context(), app, &task) + res, err = h.usecase.UpdateAppServeApp(r.Context(), appId, &task) } if err != nil { diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 9d8a32d8..7126e957 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -14,13 +14,13 @@ import ( ) type IAppServeAppRepository interface { - CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) + CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, err error) GetAppServeApps(ctx context.Context, organizationId string, projectId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) GetAppServeAppTasksByAppId(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) - GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) - GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, *model.AppServeApp, error) + GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, error) + GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) @@ -42,14 +42,14 @@ func NewAppServeAppRepository(db *gorm.DB) IAppServeAppRepository { } } -func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) { +func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, err error) { app.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&app) if res.Error != nil { - return "", "", res.Error + return "", res.Error } - return app.ID, app.AppServeAppTasks[0].ID, nil + return app.ID, nil } // Update creates new appServeApp task for existing appServeApp. @@ -100,10 +100,6 @@ func (r *AppServeAppRepository) GetAppServeApps(ctx context.Context, organizatio return } -// //////////////////////////////////////////////////////////////////////////////////////// -// TODO: this API will'be deprecated soon once the new task-related API's are verified. -// Until then, this is available (except for stage info) just for backward compatibility. -// //////////////////////////////////////////////////////////////////////////////////////// func (r *AppServeAppRepository) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) { var app model.AppServeApp var cluster model.Cluster @@ -117,12 +113,6 @@ func (r *AppServeAppRepository) GetAppServeAppById(ctx context.Context, appId st return nil, fmt.Errorf("No app with ID %s", appId) } - // Populate tasks into app object - if err := r.db.WithContext(ctx).Model(&app).Order("created_at desc").Association("AppServeAppTasks").Find(&app.AppServeAppTasks); err != nil { - log.Debug(ctx, err) - return nil, err - } - // Add cluster name to app object r.db.WithContext(ctx).Select("name").Where("id = ?", app.TargetClusterId).First(&cluster) app.TargetClusterName = cluster.Name @@ -150,67 +140,35 @@ func (r *AppServeAppRepository) GetAppServeAppTasksByAppId(ctx context.Context, } // Return single task info along with its parent app info -func (r *AppServeAppRepository) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { +func (r *AppServeAppRepository) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, error) { var task model.AppServeAppTask - var app model.AppServeApp - var cluster model.Cluster // Retrieve task info res := r.db.WithContext(ctx).Where("id = ?", taskId).First(&task) if res.Error != nil { log.Debug(ctx, res.Error) - return nil, nil, res.Error - } - if res.RowsAffected == 0 { - return nil, nil, fmt.Errorf("No task with ID %s", taskId) - } - - // Retrieve app info - res = r.db.WithContext(ctx).Where("id = ?", task.AppServeAppId).First(&app) - if res.Error != nil { - log.Debug(ctx, res.Error) - return nil, nil, res.Error + return nil, res.Error } if res.RowsAffected == 0 { - return nil, nil, fmt.Errorf("Couldn't find app with ID %s associated with task %s", app.ID, taskId) + return nil, fmt.Errorf("No task with ID %s", taskId) } - // Add cluster name to app object - r.db.WithContext(ctx).Select("name").Where("id = ?", app.TargetClusterId).First(&cluster) - app.TargetClusterName = cluster.Name - - return &task, &app, nil + return &task, nil } -func (r *AppServeAppRepository) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, *model.AppServeApp, error) { +func (r *AppServeAppRepository) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) { var task model.AppServeAppTask - var app model.AppServeApp - var cluster model.Cluster res := r.db.WithContext(ctx).Order("created_at desc").Where("app_serve_app_id = ?", appId).First(&task) if res.Error != nil { log.Debug(ctx, res.Error) - return nil, nil, res.Error - } - if res.RowsAffected == 0 { - return nil, nil, fmt.Errorf("No task with App ID %s", appId) - } - - // Retrieve app info - res = r.db.WithContext(ctx).Where("id = ?", appId).First(&app) - if res.Error != nil { - log.Debug(ctx, res.Error) - return nil, nil, res.Error + return nil, res.Error } if res.RowsAffected == 0 { - return nil, nil, fmt.Errorf("Couldn't find app with ID %s", appId) + return nil, fmt.Errorf("No task with App ID %s", appId) } - // Add cluster name to app object - r.db.WithContext(ctx).Select("name").Where("id = ?", app.TargetClusterId).First(&cluster) - app.TargetClusterName = cluster.Name - - return &task, &app, nil + return &task, nil } func (r *AppServeAppRepository) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) { diff --git a/internal/route/route.go b/internal/route/route.go index 876fe9ed..a3dd917f 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -163,7 +163,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps", customMiddleware.Handle(internalApi.CreateAppServeApp, http.HandlerFunc(appServeAppHandler.CreateAppServeApp))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps", customMiddleware.Handle(internalApi.GetAppServeApps, http.HandlerFunc(appServeAppHandler.GetAppServeApps))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/count", customMiddleware.Handle(internalApi.GetNumOfAppsOnStack, http.HandlerFunc(appServeAppHandler.GetNumOfAppsOnStack))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.GetAppServeApp, http.HandlerFunc(appServeAppHandler.GetAppServeApp))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks", customMiddleware.Handle(internalApi.GetAppServeAppTasksByAppId, http.HandlerFunc(appServeAppHandler.GetAppServeAppTasksByAppId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}", customMiddleware.Handle(internalApi.GetAppServeAppTaskDetail, http.HandlerFunc(appServeAppHandler.GetAppServeAppTaskDetail))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task", customMiddleware.Handle(internalApi.GetAppServeAppLatestTask, http.HandlerFunc(appServeAppHandler.GetAppServeAppLatestTask))).Methods(http.MethodGet) diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index e712f08d..5aac397d 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -24,19 +24,19 @@ import ( ) type IAppServeAppUsecase interface { - CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) + CreateAppServeApp(ctx context.Context, app *model.AppServeApp, task *model.AppServeAppTask) (appId string, taskId string, err error) GetAppServeApps(ctx context.Context, organizationId string, projectId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) - GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) - GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, *model.AppServeApp, error) + GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, error) + GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) IsAppServeAppExist(ctx context.Context, appId string) (bool, error) IsAppServeAppNameExist(ctx context.Context, orgId string, appName string) (bool, error) IsAppServeAppNamespaceExist(ctx context.Context, clusterId string, namespace string) (bool, error) UpdateAppServeAppStatus(ctx context.Context, appId string, taskId string, status string, output string) (ret string, err error) DeleteAppServeApp(ctx context.Context, appId string) (res string, err error) - UpdateAppServeApp(ctx context.Context, app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) + UpdateAppServeApp(ctx context.Context, appId string, appTask *model.AppServeAppTask) (ret string, err error) UpdateAppServeAppEndpoint(ctx context.Context, appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) (string, error) PromoteAppServeApp(ctx context.Context, appId string) (ret string, err error) AbortAppServeApp(ctx context.Context, appId string) (ret string, err error) @@ -59,7 +59,7 @@ func NewAppServeAppUsecase(r repository.Repository, argoClient argowf.ArgoClient } } -func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (string, string, error) { +func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.AppServeApp, task *model.AppServeAppTask) (string, string, error) { if app == nil { return "", "", fmt.Errorf("invalid app obj") } @@ -69,29 +69,29 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A // (Refer to 'tks-appserve-template') if app.Type != "deploy" { // Validate param - if app.AppServeAppTasks[0].ArtifactUrl == "" { + if task.ArtifactUrl == "" { return "", "", fmt.Errorf("error: For 'build'/'all' type task, 'artifact_url' is mandatory param") } // Construct imageUrl - imageUrl := viper.GetString("image-registry-url") + "/" + app.Name + "-" + app.TargetClusterId + ":" + app.AppServeAppTasks[0].Version - app.AppServeAppTasks[0].ImageUrl = imageUrl + imageUrl := viper.GetString("image-registry-url") + "/" + app.Name + "-" + app.TargetClusterId + ":" + task.Version + task.ImageUrl = imageUrl if app.AppType == "springboot" { // Construct executable_path - artiUrl := app.AppServeAppTasks[0].ArtifactUrl + artiUrl := task.ArtifactUrl tempArr := strings.Split(artiUrl, "/") exeFilename := tempArr[len(tempArr)-1] executablePath := "/usr/src/myapp/" + exeFilename - app.AppServeAppTasks[0].ExecutablePath = executablePath + task.ExecutablePath = executablePath } } else { // Validate param for 'deploy' type. // TODO: check params for legacy spring app case if app.AppType == "springboot" { - if app.AppServeAppTasks[0].ImageUrl == "" || app.AppServeAppTasks[0].ExecutablePath == "" || - app.AppServeAppTasks[0].Profile == "" || app.AppServeAppTasks[0].ResourceSpec == "" { + if task.ImageUrl == "" || task.ExecutablePath == "" || + task.Profile == "" || task.ResourceSpec == "" { return "", "", fmt.Errorf("Error: For 'deploy' type task, the following params must be provided." + @@ -100,7 +100,7 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A } } - extEnv := app.AppServeAppTasks[0].ExtraEnv + extEnv := task.ExtraEnv if extEnv != "" { /* Preprocess extraEnv param */ log.Debug(ctx, "extraEnv received: ", extEnv) @@ -125,12 +125,18 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A log.Debug(ctx, "After transform, extraEnv: ", extEnv) } - appId, taskId, err := u.repo.CreateAppServeApp(ctx, app) + appId, err := u.repo.CreateAppServeApp(ctx, app) if err != nil { log.Error(ctx, err) return "", "", errors.Wrap(err, "Failed to create app.") } + taskId, err := u.repo.CreateTask(ctx, task) + if err != nil { + log.Error(ctx, err) + return "", "", errors.Wrap(err, "Failed to create task.") + } + fmt.Printf("appId = %s, taskId = %s", appId, taskId) // TODO: Validate PV params @@ -141,7 +147,7 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A opts := argowf.SubmitOptions{} opts.Parameters = []string{ "type=" + app.Type, - "strategy=" + app.AppServeAppTasks[0].Strategy, + "strategy=" + task.Strategy, "app_type=" + app.AppType, "organization_id=" + app.OrganizationId, "project_id=" + app.ProjectId, @@ -150,22 +156,22 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A "namespace=" + app.Namespace, "asa_id=" + appId, "asa_task_id=" + taskId, - "artifact_url=" + app.AppServeAppTasks[0].ArtifactUrl, - "image_url=" + app.AppServeAppTasks[0].ImageUrl, - "port=" + app.AppServeAppTasks[0].Port, - "profile=" + app.AppServeAppTasks[0].Profile, + "artifact_url=" + task.ArtifactUrl, + "image_url=" + task.ImageUrl, + "port=" + task.Port, + "profile=" + task.Profile, "extra_env=" + extEnv, - "app_config=" + app.AppServeAppTasks[0].AppConfig, - "app_secret=" + app.AppServeAppTasks[0].AppSecret, - "resource_spec=" + app.AppServeAppTasks[0].ResourceSpec, - "executable_path=" + app.AppServeAppTasks[0].ExecutablePath, + "app_config=" + task.AppConfig, + "app_secret=" + task.AppSecret, + "resource_spec=" + task.ResourceSpec, + "executable_path=" + task.ExecutablePath, "git_repo_url=" + viper.GetString("git-repository-url"), "harbor_pw_secret=" + viper.GetString("harbor-pw-secret"), - "pv_enabled=" + strconv.FormatBool(app.AppServeAppTasks[0].PvEnabled), - "pv_storage_class=" + app.AppServeAppTasks[0].PvStorageClass, - "pv_access_mode=" + app.AppServeAppTasks[0].PvAccessMode, - "pv_size=" + app.AppServeAppTasks[0].PvSize, - "pv_mount_path=" + app.AppServeAppTasks[0].PvMountPath, + "pv_enabled=" + strconv.FormatBool(task.PvEnabled), + "pv_storage_class=" + task.PvStorageClass, + "pv_access_mode=" + task.PvAccessMode, + "pv_size=" + task.PvSize, + "pv_mount_path=" + task.PvMountPath, "tks_api_url=" + viper.GetString("external-address"), } @@ -204,6 +210,7 @@ func (u *AppServeAppUsecase) GetAppServeAppById(ctx context.Context, appId strin return asa, httpErrors.NewInternalServerError(errors.Wrap(err, fmt.Sprintf("Failed to get organization for app %s", asa.Name)), "S_FAILED_FETCH_ORGANIZATION", "") } + // Get app groups in primary clustser appGroupsInPrimaryCluster, err := u.appGroupRepo.Fetch(ctx, domain.ClusterId(organization.PrimaryClusterId), nil) if err != nil { return asa, err @@ -217,6 +224,7 @@ func (u *AppServeAppUsecase) GetAppServeAppById(ctx context.Context, appId strin } if len(applications) > 0 { asa.GrafanaUrl = applications[0].Endpoint + "/d/tks_appserving_dashboard/tks-appserving-dashboard?refresh=30s&var-cluster=" + asa.TargetClusterId + "&var-kubernetes_namespace_name=" + asa.Namespace + "&var-kubernetes_pod_name=All&var-kubernetes_container_name=main&var-TopK=10" + log.Debugf(ctx, "Found grafanaURL: %s", asa.GrafanaUrl) } } } @@ -227,28 +235,29 @@ func (u *AppServeAppUsecase) GetAppServeAppById(ctx context.Context, appId strin func (u *AppServeAppUsecase) GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) { tasks, err := u.repo.GetAppServeAppTasksByAppId(ctx, appId, pg) if err != nil { - log.Debugf(ctx, "Tasks: %v", tasks) + log.Debugf(ctx, "Error while getting task list. Tasks: %v", tasks) + return nil, err } return tasks, nil } -func (u *AppServeAppUsecase) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, *model.AppServeApp, error) { - task, app, err := u.repo.GetAppServeAppTaskById(ctx, taskId) +func (u *AppServeAppUsecase) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, error) { + task, err := u.repo.GetAppServeAppTaskById(ctx, taskId) if err != nil { - return nil, nil, err + return nil, err } - return task, app, nil + return task, nil } -func (u *AppServeAppUsecase) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, *model.AppServeApp, error) { - task, app, err := u.repo.GetAppServeAppLatestTask(ctx, appId) +func (u *AppServeAppUsecase) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) { + task, err := u.repo.GetAppServeAppLatestTask(ctx, appId) if err != nil { - return nil, nil, err + return nil, err } - return task, app, nil + return task, nil } func (u *AppServeAppUsecase) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) { @@ -360,14 +369,28 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(ctx context.Context, appId string /******************** * Start delete task * ********************/ + latestTask, err := u.repo.GetAppServeAppLatestTask(ctx, appId) + if err != nil { + return "", err + } + + verInt, err := strconv.Atoi(latestTask.Version) + if err != nil { + return "", errors.Wrap(err, "Failed to convert version to integer.") + } + newVerStr := strconv.Itoa(verInt + 1) + + // Temp Debug + log.Debugf(ctx, "Old version: %s", latestTask.Version) + log.Debugf(ctx, "New version: %s", newVerStr) appTask := &model.AppServeAppTask{ AppServeAppId: app.ID, - Version: strconv.Itoa(len(app.AppServeAppTasks) + 1), + Version: newVerStr, ArtifactUrl: "", - ImageUrl: app.AppServeAppTasks[0].ImageUrl, + ImageUrl: latestTask.ImageUrl, Status: "DELETING", - Profile: app.AppServeAppTasks[0].Profile, + Profile: "", Output: "", CreatedAt: time.Now(), } @@ -413,18 +436,18 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(ctx context.Context, appId string "Confirm result by checking the app status after a while.", app.Name), nil } -func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, app *model.AppServeApp, appTask *model.AppServeAppTask) (ret string, err error) { +func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, appId string, appTask *model.AppServeAppTask) (ret string, err error) { if appTask == nil { return "", errors.New("invalid parameters. appTask is nil") } - app_, err := u.repo.GetAppServeAppById(ctx, app.ID) + app, err := u.repo.GetAppServeAppById(ctx, appId) if err != nil { return "", fmt.Errorf("error while getting ASA Info from DB. Err: %s", err) } // Block update if the app's current status is one of those. - if app_.Status == "PROMOTE_WAIT" || app_.Status == "PROMOTING" || app_.Status == "ABORTING" { + if app.Status == "PROMOTE_WAIT" || app.Status == "PROMOTING" || app.Status == "ABORTING" { return "승인대기 또는 프로모트 작업 중에는 업그레이드를 수행할 수 없습니다", fmt.Errorf("Update not possible. The app is waiting for promote or in the middle of promote process.") } @@ -559,10 +582,15 @@ func (u *AppServeAppUsecase) PromoteAppServeApp(ctx context.Context, appId strin } // Get the latest task ID so that the task status can be modified inside workflow once the promotion is done. - latestTaskId := app.AppServeAppTasks[0].ID - strategy := app.AppServeAppTasks[0].Strategy - log.Info(ctx, "latestTaskId = ", latestTaskId) - log.Info(ctx, "strategy = ", strategy) + latestTask, err := u.repo.GetAppServeAppLatestTask(ctx, appId) + if err != nil { + return "", err + } + + latestTaskId := latestTask.ID + strategy := latestTask.Strategy + log.Debug(ctx, "latestTaskId = ", latestTaskId) + log.Debug(ctx, "strategy = ", strategy) log.Info(ctx, "Updating app status to 'PROMOTING'..") @@ -612,8 +640,13 @@ func (u *AppServeAppUsecase) AbortAppServeApp(ctx context.Context, appId string) } // Get the latest task ID so that the task status can be modified inside workflow once the abort process is done. - latestTaskId := app.AppServeAppTasks[0].ID - log.Info(ctx, "latestTaskId = ", latestTaskId) + latestTask, err := u.repo.GetAppServeAppLatestTask(ctx, appId) + if err != nil { + return "", err + } + + latestTaskId := latestTask.ID + log.Debug(ctx, "latestTaskId = ", latestTaskId) log.Info(ctx, "Updating app status to 'ABORTING'..") err = u.repo.UpdateStatus(ctx, appId, latestTaskId, "ABORTING", "") @@ -659,30 +692,43 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(ctx context.Context, appId stri } // Find target(dest) task - var task model.AppServeAppTask - for _, t := range app.AppServeAppTasks { - if t.ID == taskId { - task = t - break - } + task, err := u.repo.GetAppServeAppTaskById(ctx, taskId) + if err != nil { + return "", err + } + + if task.AppServeAppId != appId { + return "", fmt.Errorf("Rollback target task doesn't belong to current app. It belongs to: %s", task.AppServeAppId) + } + + // Find latest task for version info + latestTask, err := u.repo.GetAppServeAppLatestTask(ctx, appId) + if err != nil { + return "", err } // Save target version targetVer := task.Version targetRev := task.HelmRevision + verInt, err := strconv.Atoi(latestTask.Version) + if err != nil { + return "", errors.Wrap(err, "Failed to convert version to integer.") + } + newVerStr := strconv.Itoa(verInt + 1) + // Insert new values to the target task object task.ID = "" task.Output = "" task.Status = "ROLLBACKING" - task.Version = strconv.Itoa(len(app.AppServeAppTasks) + 1) + task.Version = newVerStr task.CreatedAt = time.Now() task.UpdatedAt = nil task.HelmRevision = 0 task.RollbackVersion = targetVer // Creates new task record from the target task - newTaskId, err := u.repo.CreateTask(ctx, &task) + newTaskId, err := u.repo.CreateTask(ctx, task) if err != nil { log.Info(ctx, "taskId = ", newTaskId) return "", fmt.Errorf("failed to rollback app-serve application. Err: %s", err) From 27fca661a8f7b5acfa50e95b40a294cb18f883fc Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Fri, 26 Apr 2024 17:56:21 +0900 Subject: [PATCH 383/502] trivial: adjust indent with gofmt --- internal/model/app-serve-app.go | 33 ++++++++++++++-------------- pkg/domain/app-serve-app.go | 39 ++++++++++++++------------------- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go index d19e647f..b8f2a655 100644 --- a/internal/model/app-serve-app.go +++ b/internal/model/app-serve-app.go @@ -7,23 +7,22 @@ import ( ) type AppServeApp struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - Name string `gorm:"index" json:"name,omitempty"` // application name - Namespace string `json:"namespace,omitempty"` // application namespace - OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to - ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to - Type string `json:"type,omitempty"` // type (build/deploy/all) - AppType string `json:"appType,omitempty"` // appType (spring/springboot) - EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app - PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment - TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed - TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name - Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app - GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app - CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` - UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` - AppServeAppTasks []AppServeAppTask `gorm:"foreignKey:AppServeAppId" json:"appServeAppTasks"` + ID string `gorm:"primarykey" json:"id,omitempty"` + Name string `gorm:"index" json:"name,omitempty"` // application name + Namespace string `json:"namespace,omitempty"` // application namespace + OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to + Type string `json:"type,omitempty"` // type (build/deploy/all) + AppType string `json:"appType,omitempty"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed + TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name + Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` + UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` } type AppServeAppTask struct { diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index b1db60af..3c56f3c7 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -3,23 +3,22 @@ package domain import "time" type AppServeAppResponse struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` // application name - Namespace string `json:"namespace,omitempty"` // application namespace - OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to - ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to - Type string `json:"type,omitempty"` // type (build/deploy/all) - AppType string `json:"appType,omitempty"` // appType (spring/springboot) - EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app - PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment - TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed - TargetClusterName string `json:"targetClusterName,omitempty"` // target cluster name - Status string `json:"status,omitempty"` // status is status of deployed app - GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app - CreatedAt time.Time `json:"createdAt" ` - UpdatedAt *time.Time `json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt"` - AppServeAppTasks []AppServeAppTaskResponse `json:"appServeAppTasks"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` // application name + Namespace string `json:"namespace,omitempty"` // application namespace + OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to + Type string `json:"type,omitempty"` // type (build/deploy/all) + AppType string `json:"appType,omitempty"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed + TargetClusterName string `json:"targetClusterName,omitempty"` // target cluster name + Status string `json:"status,omitempty"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + CreatedAt time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt"` } type AppServeAppTaskResponse struct { @@ -147,12 +146,6 @@ type GetAppServeAppsResponse struct { Pagination PaginationResponse `json:"pagination"` } -// TODO: This will be deprecated later -type GetAppServeAppResponse struct { - AppServeApp AppServeAppResponse `json:"appServeApp"` - Stages []StageResponse `json:"stages"` -} - type GetAppServeAppTasksResponse struct { AppServeAppTasks []AppServeAppTaskResponse `json:"appServeAppTasks"` Pagination PaginationResponse `json:"pagination"` From 3258d32759ccd34a1e17217ed5abab91c5dddae2 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 26 Apr 2024 18:08:50 +0900 Subject: [PATCH 384/502] trivial. update html temporary_password --- .../mail/contents/temporary_password.html | 58 ++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/internal/mail/contents/temporary_password.html b/internal/mail/contents/temporary_password.html index dd3cd495..5f4ed8b3 100644 --- a/internal/mail/contents/temporary_password.html +++ b/internal/mail/contents/temporary_password.html @@ -54,17 +54,59 @@
- - - - - From 6b2e6eed9496e558d7267016e211d6d687ec1b07 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 26 Apr 2024 18:23:34 +0900 Subject: [PATCH 385/502] trivial. add default systemNotificationTemplate when organization created --- internal/usecase/system-notification-rule.go | 5 +++++ internal/usecase/system-notification-template.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index d777e432..ad04ee57 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -191,6 +191,11 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c return err } + err = u.organizationRepo.AddSystemNotificationTemplates(ctx, organizationId, templates) + if err != nil { + return httpErrors.NewBadRequestError(err, "ST_FAILED_ADD_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE", "") + } + rules := make([]model.SystemNotificationRule, 0) for _, template := range templates { if template.Name == domain.SN_TYPE_NODE_CPU_HIGH_LOAD { diff --git a/internal/usecase/system-notification-template.go b/internal/usecase/system-notification-template.go index f0c7743f..99240baf 100644 --- a/internal/usecase/system-notification-template.go +++ b/internal/usecase/system-notification-template.go @@ -188,7 +188,7 @@ func (u *SystemNotificationTemplateUsecase) UpdateOrganizations(ctx context.Cont func (u *SystemNotificationTemplateUsecase) AddOrganizationSystemNotificationTemplates(ctx context.Context, organizationId string, systemNotificationTemplateIds []string) error { _, err := u.organizationRepo.Get(ctx, organizationId) if err != nil { - return httpErrors.NewBadRequestError(err, "O_NOT_EXISTED_NAME", "") + return httpErrors.NewBadRequestError(err, "ST_NOT_EXISTED_NAME", "") } systemNotificationTemplates := make([]model.SystemNotificationTemplate, 0) From b0bb0848b9eac245b7cd5ff58d50a91667fe64e7 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Fri, 26 Apr 2024 18:52:55 +0900 Subject: [PATCH 386/502] add description column to appserving table --- internal/model/app-serve-app.go | 1 + pkg/domain/app-serve-app.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go index b8f2a655..0a5e9f77 100644 --- a/internal/model/app-serve-app.go +++ b/internal/model/app-serve-app.go @@ -20,6 +20,7 @@ type AppServeApp struct { TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + Description string `json:"description,omitempty"` // description for application CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index 3c56f3c7..b12c192b 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -16,6 +16,7 @@ type AppServeAppResponse struct { TargetClusterName string `json:"targetClusterName,omitempty"` // target cluster name Status string `json:"status,omitempty"` // status is status of deployed app GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app + Description string `json:"description,omitempty"` // description for application CreatedAt time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` From 1c2e27bc4c51007ed6bd55914073059298c28bf0 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Fri, 26 Apr 2024 22:33:24 +0900 Subject: [PATCH 387/502] update swagger docs --- api/swagger/docs.go | 183 ++------------------------------------- api/swagger/swagger.json | 183 ++------------------------------------- api/swagger/swagger.yaml | 127 ++------------------------- 3 files changed, 22 insertions(+), 471 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 55dabf07..e394f4af 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -5943,55 +5943,6 @@ const docTemplate = `{ } }, "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse" - } - } - } - }, "put": { "security": [ { @@ -10272,12 +10223,6 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_internal_model.AppServeApp": { "type": "object", "properties": { - "appServeAppTasks": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask" - } - }, "appType": { "description": "appType (spring/springboot)", "type": "string" @@ -10288,6 +10233,10 @@ const docTemplate = `{ "deletedAt": { "type": "string" }, + "description": { + "description": "description for application", + "type": "string" + }, "endpointUrl": { "description": "endpoint URL of deployed app", "type": "string" @@ -10340,106 +10289,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_internal_model.AppServeAppTask": { - "type": "object", - "properties": { - "appConfig": { - "description": "java app config", - "type": "string" - }, - "appSecret": { - "description": "java app secret", - "type": "string" - }, - "appServeAppId": { - "description": "ID for appServeApp that this task belongs to", - "type": "string" - }, - "artifactUrl": { - "description": "URL of java app artifact (Eg, Jar)", - "type": "string" - }, - "availableRollback": { - "type": "boolean" - }, - "createdAt": { - "description": "createdAt is a creation timestamp for the application", - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "executablePath": { - "description": "Executable path of app image", - "type": "string" - }, - "extraEnv": { - "description": "env variable list for java app", - "type": "string" - }, - "helmRevision": { - "description": "revision of deployed helm release", - "type": "integer" - }, - "id": { - "type": "string" - }, - "imageUrl": { - "description": "URL of built image for app", - "type": "string" - }, - "output": { - "description": "output for task result", - "type": "string" - }, - "port": { - "description": "java app port", - "type": "string" - }, - "profile": { - "description": "java app profile", - "type": "string" - }, - "pvAccessMode": { - "type": "string" - }, - "pvEnabled": { - "type": "boolean" - }, - "pvMountPath": { - "type": "string" - }, - "pvSize": { - "type": "string" - }, - "pvStorageClass": { - "type": "string" - }, - "resourceSpec": { - "description": "resource spec of app pod", - "type": "string" - }, - "rollbackVersion": { - "description": "rollback target version", - "type": "string" - }, - "status": { - "description": "status is app status", - "type": "string" - }, - "strategy": { - "description": "deployment strategy (eg, rolling-update)", - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "description": "application version", - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { @@ -10716,12 +10565,6 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse": { "type": "object", "properties": { - "appServeAppTasks": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" - } - }, "appType": { "description": "appType (spring/springboot)", "type": "string" @@ -10732,6 +10575,10 @@ const docTemplate = `{ "deletedAt": { "type": "string" }, + "description": { + "description": "description for application", + "type": "string" + }, "endpointUrl": { "description": "endpoint URL of deployed app", "type": "string" @@ -12626,20 +12473,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse": { - "type": "object", - "properties": { - "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" - }, - "stages": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 14eb42e7..9c99f48b 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -5937,55 +5937,6 @@ } }, "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}": { - "get": { - "security": [ - { - "JWT": [] - } - ], - "description": "Get appServeApp by giving params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "AppServeApps" - ], - "summary": "Get appServeApp", - "parameters": [ - { - "type": "string", - "description": "Organization ID", - "name": "organizationId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Project ID", - "name": "projectId", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "App ID", - "name": "appId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse" - } - } - } - }, "put": { "security": [ { @@ -10266,12 +10217,6 @@ "github_com_openinfradev_tks-api_internal_model.AppServeApp": { "type": "object", "properties": { - "appServeAppTasks": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask" - } - }, "appType": { "description": "appType (spring/springboot)", "type": "string" @@ -10282,6 +10227,10 @@ "deletedAt": { "type": "string" }, + "description": { + "description": "description for application", + "type": "string" + }, "endpointUrl": { "description": "endpoint URL of deployed app", "type": "string" @@ -10334,106 +10283,6 @@ } } }, - "github_com_openinfradev_tks-api_internal_model.AppServeAppTask": { - "type": "object", - "properties": { - "appConfig": { - "description": "java app config", - "type": "string" - }, - "appSecret": { - "description": "java app secret", - "type": "string" - }, - "appServeAppId": { - "description": "ID for appServeApp that this task belongs to", - "type": "string" - }, - "artifactUrl": { - "description": "URL of java app artifact (Eg, Jar)", - "type": "string" - }, - "availableRollback": { - "type": "boolean" - }, - "createdAt": { - "description": "createdAt is a creation timestamp for the application", - "type": "string" - }, - "deletedAt": { - "type": "string" - }, - "executablePath": { - "description": "Executable path of app image", - "type": "string" - }, - "extraEnv": { - "description": "env variable list for java app", - "type": "string" - }, - "helmRevision": { - "description": "revision of deployed helm release", - "type": "integer" - }, - "id": { - "type": "string" - }, - "imageUrl": { - "description": "URL of built image for app", - "type": "string" - }, - "output": { - "description": "output for task result", - "type": "string" - }, - "port": { - "description": "java app port", - "type": "string" - }, - "profile": { - "description": "java app profile", - "type": "string" - }, - "pvAccessMode": { - "type": "string" - }, - "pvEnabled": { - "type": "boolean" - }, - "pvMountPath": { - "type": "string" - }, - "pvSize": { - "type": "string" - }, - "pvStorageClass": { - "type": "string" - }, - "resourceSpec": { - "description": "resource spec of app pod", - "type": "string" - }, - "rollbackVersion": { - "description": "rollback target version", - "type": "string" - }, - "status": { - "description": "status is app status", - "type": "string" - }, - "strategy": { - "description": "deployment strategy (eg, rolling-update)", - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "version": { - "description": "application version", - "type": "string" - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ActionResponse": { "type": "object", "properties": { @@ -10710,12 +10559,6 @@ "github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse": { "type": "object", "properties": { - "appServeAppTasks": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse" - } - }, "appType": { "description": "appType (spring/springboot)", "type": "string" @@ -10726,6 +10569,10 @@ "deletedAt": { "type": "string" }, + "description": { + "description": "description for application", + "type": "string" + }, "endpointUrl": { "description": "endpoint URL of deployed app", "type": "string" @@ -12620,20 +12467,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse": { - "type": "object", - "properties": { - "appServeApp": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse" - }, - "stages": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index a88ae611..79aa6077 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2,10 +2,6 @@ basePath: /api/1.0/ definitions: github_com_openinfradev_tks-api_internal_model.AppServeApp: properties: - appServeAppTasks: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_internal_model.AppServeAppTask' - type: array appType: description: appType (spring/springboot) type: string @@ -13,6 +9,9 @@ definitions: type: string deletedAt: type: string + description: + description: description for application + type: string endpointUrl: description: endpoint URL of deployed app type: string @@ -51,78 +50,6 @@ definitions: updatedAt: type: string type: object - github_com_openinfradev_tks-api_internal_model.AppServeAppTask: - properties: - appConfig: - description: java app config - type: string - appSecret: - description: java app secret - type: string - appServeAppId: - description: ID for appServeApp that this task belongs to - type: string - artifactUrl: - description: URL of java app artifact (Eg, Jar) - type: string - availableRollback: - type: boolean - createdAt: - description: createdAt is a creation timestamp for the application - type: string - deletedAt: - type: string - executablePath: - description: Executable path of app image - type: string - extraEnv: - description: env variable list for java app - type: string - helmRevision: - description: revision of deployed helm release - type: integer - id: - type: string - imageUrl: - description: URL of built image for app - type: string - output: - description: output for task result - type: string - port: - description: java app port - type: string - profile: - description: java app profile - type: string - pvAccessMode: - type: string - pvEnabled: - type: boolean - pvMountPath: - type: string - pvSize: - type: string - pvStorageClass: - type: string - resourceSpec: - description: resource spec of app pod - type: string - rollbackVersion: - description: rollback target version - type: string - status: - description: status is app status - type: string - strategy: - description: deployment strategy (eg, rolling-update) - type: string - updatedAt: - type: string - version: - description: application version - type: string - type: object github_com_openinfradev_tks-api_pkg_domain.ActionResponse: properties: body: @@ -313,10 +240,6 @@ definitions: - AppGroupType_SERVICE_MESH github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse: properties: - appServeAppTasks: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppTaskResponse' - type: array appType: description: appType (spring/springboot) type: string @@ -324,6 +247,9 @@ definitions: type: string deletedAt: type: string + description: + description: description for application + type: string endpointUrl: description: endpoint URL of deployed app type: string @@ -1609,15 +1535,6 @@ definitions: pagination: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object - github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse: - properties: - appServeApp: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.AppServeAppResponse' - stages: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StageResponse' - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse: properties: appServeApp: @@ -7991,38 +7908,6 @@ paths: summary: Uninstall appServeApp tags: - AppServeApps - get: - consumes: - - application/json - description: Get appServeApp by giving params - parameters: - - description: Organization ID - in: path - name: organizationId - required: true - type: string - - description: Project ID - in: path - name: projectId - required: true - type: string - - description: App ID - in: path - name: appId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppResponse' - security: - - JWT: [] - summary: Get appServeApp - tags: - - AppServeApps put: consumes: - application/json From 42b43913ad02dce3fa8b0507d964f0895d4e7c2f Mon Sep 17 00:00:00 2001 From: donggyu Date: Mon, 29 Apr 2024 08:06:37 +0900 Subject: [PATCH 388/502] fix to update with empty value --- internal/repository/project.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/repository/project.go b/internal/repository/project.go index 6ffc35c0..d1649eb7 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -615,7 +615,7 @@ func (r *ProjectRepository) GetProjectNamespaceByPrimaryKey(ctx context.Context, } func (r *ProjectRepository) UpdateProjectNamespace(ctx context.Context, pn *model.ProjectNamespace) error { - res := r.db.WithContext(ctx).Model(&pn).Updates(model.ProjectNamespace{Description: pn.Description, UpdatedAt: pn.UpdatedAt}) + res := r.db.WithContext(ctx).Model(&pn).Select("Description").Updates(model.ProjectNamespace{Description: pn.Description, UpdatedAt: pn.UpdatedAt}) if res.Error != nil { return res.Error } From edebf72830ac61c8460c332a1d62924d52200893 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Mon, 29 Apr 2024 15:01:17 +0900 Subject: [PATCH 389/502] bugfix: relate task with parent app on create job --- internal/repository/app-serve-app.go | 7 +++++-- internal/usecase/app-serve-app.go | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 7126e957..2267fd94 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -26,7 +26,7 @@ type IAppServeAppRepository interface { IsAppServeAppExist(ctx context.Context, appId string) (int64, error) IsAppServeAppNameExist(ctx context.Context, orgId string, appName string) (int64, error) - CreateTask(ctx context.Context, task *model.AppServeAppTask) (taskId string, err error) + CreateTask(ctx context.Context, task *model.AppServeAppTask, appId string) (taskId string, err error) UpdateStatus(ctx context.Context, appId string, taskId string, status string, output string) error UpdateEndpoint(ctx context.Context, appId string, taskId string, endpoint string, previewEndpoint string, helmRevision int32) error GetTaskCountById(ctx context.Context, appId string) (int64, error) @@ -53,8 +53,11 @@ func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *mode } // Update creates new appServeApp task for existing appServeApp. -func (r *AppServeAppRepository) CreateTask(ctx context.Context, task *model.AppServeAppTask) (string, error) { +func (r *AppServeAppRepository) CreateTask(ctx context.Context, task *model.AppServeAppTask, appId string) (string, error) { task.ID = uuid.New().String() + if len(appId) > 0 { + task.AppServeAppId = appId + } res := r.db.WithContext(ctx).Create(task) if res.Error != nil { return "", res.Error diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 5aac397d..017d606e 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -131,7 +131,7 @@ func (u *AppServeAppUsecase) CreateAppServeApp(ctx context.Context, app *model.A return "", "", errors.Wrap(err, "Failed to create app.") } - taskId, err := u.repo.CreateTask(ctx, task) + taskId, err := u.repo.CreateTask(ctx, task, appId) if err != nil { log.Error(ctx, err) return "", "", errors.Wrap(err, "Failed to create task.") @@ -395,7 +395,7 @@ func (u *AppServeAppUsecase) DeleteAppServeApp(ctx context.Context, appId string CreatedAt: time.Now(), } - taskId, err := u.repo.CreateTask(ctx, appTask) + taskId, err := u.repo.CreateTask(ctx, appTask, "") if err != nil { log.Error(ctx, "taskId = ", taskId) log.Error(ctx, "Failed to create delete task. Err:", err) @@ -503,7 +503,8 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, appId string log.Debug(ctx, "After transform, extraEnv: ", extEnv) } - taskId, err := u.repo.CreateTask(ctx, appTask) + // TODO: Check if appId is necessary here. + taskId, err := u.repo.CreateTask(ctx, appTask, appId) if err != nil { log.Info(ctx, "taskId = ", taskId) return "", fmt.Errorf("failed to update app-serve application. Err: %s", err) @@ -728,7 +729,7 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(ctx context.Context, appId stri task.RollbackVersion = targetVer // Creates new task record from the target task - newTaskId, err := u.repo.CreateTask(ctx, task) + newTaskId, err := u.repo.CreateTask(ctx, task, "") if err != nil { log.Info(ctx, "taskId = ", newTaskId) return "", fmt.Errorf("failed to rollback app-serve application. Err: %s", err) From adfaa0fa3547cc6d760127daf69133b89d21324b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 29 Apr 2024 15:52:05 +0900 Subject: [PATCH 390/502] feature. add api stack-templates/template-ids --- api/swagger/docs.go | 39 ++++++++++++++ api/swagger/swagger.json | 39 ++++++++++++++ api/swagger/swagger.yaml | 24 +++++++++ go.mod | 2 + go.sum | 27 ++++++++++ internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 16 ++++++ internal/delivery/http/stack-template.go | 23 +++++++++ internal/route/route.go | 1 + internal/usecase/stack-template.go | 51 +++++++++++++++++++ pkg/domain/stack-template.go | 4 ++ pkg/httpErrors/errorCode.go | 1 + 12 files changed, 228 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 2371d775..8b636d98 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -1332,6 +1332,34 @@ const docTemplate = `{ } } }, + "/admin/stack-templates/template-ids": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get GetStackTemplateTemplateIds", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get GetStackTemplateTemplateIds", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateTemplateIdsResponse" + } + } + } + } + }, "/admin/stack-templates/{stackTemplateId}": { "get": { "security": [ @@ -13144,6 +13172,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateTemplateIdsResponse": { + "type": "object", + "properties": { + "templateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 3334db04..c2ab38c6 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -1326,6 +1326,34 @@ } } }, + "/admin/stack-templates/template-ids": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get GetStackTemplateTemplateIds", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get GetStackTemplateTemplateIds", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateTemplateIdsResponse" + } + } + } + } + }, "/admin/stack-templates/{stackTemplateId}": { "get": { "security": [ @@ -13138,6 +13166,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateTemplateIdsResponse": { + "type": "object", + "properties": { + "templateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index e4cc9a2a..43b89c95 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1967,6 +1967,13 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateTemplateIdsResponse: + properties: + templateIds: + items: + type: string + type: array + type: object github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse: properties: pagination: @@ -5198,6 +5205,23 @@ paths: summary: Get GetStackTemplateServices tags: - StackTemplates + /admin/stack-templates/template-ids: + get: + consumes: + - application/json + description: Get GetStackTemplateTemplateIds + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplateTemplateIdsResponse' + security: + - JWT: [] + summary: Get GetStackTemplateTemplateIds + tags: + - StackTemplates /admin/system-notification-templates: get: consumes: diff --git a/go.mod b/go.mod index 1b0c3724..14113d1d 100644 --- a/go.mod +++ b/go.mod @@ -59,6 +59,8 @@ require ( github.com/Code-Hex/uniseg v0.2.0 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect + github.com/PuerkitoBio/goquery v1.9.1 // indirect + github.com/andybalholm/cascadia v1.3.2 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 // indirect diff --git a/go.sum b/go.sum index ba79e3e7..ef39f393 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,10 @@ github.com/Nerzal/gocloak/v13 v13.9.0/go.mod h1:YYuDcXZ7K2zKECyVP7pPqjKxx2AzYSpK github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI= +github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= +github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= +github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aws/aws-sdk-go-v2 v1.25.0 h1:sv7+1JVJxOu/dD/sz/csHX7jFqmP001TIY7aytBWDSQ= github.com/aws/aws-sdk-go-v2 v1.25.0/go.mod h1:G104G1Aho5WqF+SR3mDIobTABQzpYV0WxMsKxlMggOA= @@ -330,6 +334,7 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -342,6 +347,7 @@ go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -353,6 +359,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -366,9 +374,13 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -382,6 +394,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -391,10 +405,18 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -402,6 +424,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -415,6 +440,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 6deb8330..c3cb77cf 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -99,6 +99,7 @@ const ( Admin_GetStackTemplates Admin_GetStackTemplate Admin_GetStackTemplateServices + Admin_GetStackTemplateTemplateIds Admin_CreateStackTemplate Admin_UpdateStackTemplate Admin_DeleteStackTemplate diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 3aa787fb..498d16ff 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -291,6 +291,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "Admin_GetStackTemplateServices", Group: "StackTemplate", }, + Admin_GetStackTemplateTemplateIds: { + Name: "Admin_GetStackTemplateTemplateIds", + Group: "StackTemplate", + }, Admin_CreateStackTemplate: { Name: "Admin_CreateStackTemplate", Group: "StackTemplate", @@ -483,6 +487,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyNotifications", Group: "PolicyNotification", }, + GetPolicyNotification: { + Name: "GetPolicyNotification", + Group: "PolicyNotification", + }, GetStacks: { Name: "GetStacks", Group: "Stack", @@ -1070,6 +1078,8 @@ func (e Endpoint) String() string { return "Admin_GetStackTemplate" case Admin_GetStackTemplateServices: return "Admin_GetStackTemplateServices" + case Admin_GetStackTemplateTemplateIds: + return "Admin_GetStackTemplateTemplateIds" case Admin_CreateStackTemplate: return "Admin_CreateStackTemplate" case Admin_UpdateStackTemplate: @@ -1166,6 +1176,8 @@ func (e Endpoint) String() string { return "CreateSystemNotificationAction" case GetPolicyNotifications: return "GetPolicyNotifications" + case GetPolicyNotification: + return "GetPolicyNotification" case GetStacks: return "GetStacks" case CreateStack: @@ -1536,6 +1548,8 @@ func GetEndpoint(name string) Endpoint { return Admin_GetStackTemplate case "Admin_GetStackTemplateServices": return Admin_GetStackTemplateServices + case "Admin_GetStackTemplateTemplateIds": + return Admin_GetStackTemplateTemplateIds case "Admin_CreateStackTemplate": return Admin_CreateStackTemplate case "Admin_UpdateStackTemplate": @@ -1632,6 +1646,8 @@ func GetEndpoint(name string) Endpoint { return CreateSystemNotificationAction case "GetPolicyNotifications": return GetPolicyNotifications + case "GetPolicyNotification": + return GetPolicyNotification case "GetStacks": return GetStacks case "CreateStack": diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 708c769f..78faf378 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -274,6 +274,29 @@ func (h *StackTemplateHandler) GetStackTemplateServices(w http.ResponseWriter, r ResponseJSON(w, r, http.StatusOK, out) } +// GetStackTemplateTemplateIds godoc +// +// @Tags StackTemplates +// @Summary Get GetStackTemplateTemplateIds +// @Description Get GetStackTemplateTemplateIds +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetStackTemplateTemplateIdsResponse +// @Router /admin/stack-templates/template-ids [get] +// @Security JWT +func (h *StackTemplateHandler) GetStackTemplateTemplateIds(w http.ResponseWriter, r *http.Request) { + + var out domain.GetStackTemplateTemplateIdsResponse + templateIds, err := h.usecase.GetTemplateIds(r.Context()) + if err != nil { + templateIds = []string{"aws-reference", "aws-msa-reference", "eks-reference", "eks-msa-reference", "byoh-reference"} + } + + out.TemplateIds = templateIds + + ResponseJSON(w, r, http.StatusOK, out) +} + // UpdateStackTemplateOrganizations godoc // // @Tags StackTemplates diff --git a/internal/route/route.go b/internal/route/route.go index a3dd917f..09e8b1eb 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -188,6 +188,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa stackTemplateHandler := delivery.NewStackTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplates))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/services", customMiddleware.Handle(internalApi.Admin_GetStackTemplateServices, http.HandlerFunc(stackTemplateHandler.GetStackTemplateServices))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/template-ids", customMiddleware.Handle(internalApi.Admin_GetStackTemplateTemplateIds, http.HandlerFunc(stackTemplateHandler.GetStackTemplateTemplateIds))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/name/{name}/existence", customMiddleware.Handle(internalApi.Admin_CheckStackTemplateName, http.HandlerFunc(stackTemplateHandler.CheckStackTemplateName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_GetStackTemplates, http.HandlerFunc(stackTemplateHandler.GetStackTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates", customMiddleware.Handle(internalApi.Admin_CreateStackTemplate, http.HandlerFunc(stackTemplateHandler.CreateStackTemplate))).Methods(http.MethodPost) diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 403372c3..41c95a46 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -3,7 +3,10 @@ package usecase import ( "context" "fmt" + "net/http" + "strings" + "github.com/PuerkitoBio/goquery" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal" "github.com/openinfradev/tks-api/internal/middleware/auth/request" @@ -11,9 +14,11 @@ import ( "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/kubernetes" "github.com/openinfradev/tks-api/pkg/log" "github.com/pkg/errors" "gorm.io/gorm" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type IStackTemplateUsecase interface { @@ -27,6 +32,7 @@ type IStackTemplateUsecase interface { GetByName(ctx context.Context, name string) (model.StackTemplate, error) AddOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error RemoveOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error + GetTemplateIds(ctx context.Context) ([]string, error) } type StackTemplateUsecase struct { @@ -227,6 +233,51 @@ func (u *StackTemplateUsecase) RemoveOrganizationStackTemplates(ctx context.Cont return nil } +func (u *StackTemplateUsecase) GetTemplateIds(ctx context.Context) (out []string, err error) { + clientset_admin, err := kubernetes.GetClientAdminCluster(ctx) + if err != nil { + return out, errors.Wrap(err, "Failed to get client set for admin cluster") + } + + secrets, err := clientset_admin.CoreV1().Secrets("argo").Get(context.TODO(), "git-svc-token", metav1.GetOptions{}) + if err != nil { + log.Error(ctx, "cannot found git-svc-token. so use default hard-corded values") + return out, err + } + + gitSvcUrl := string(secrets.Data["GIT_SVC_URL"]) + username := string(secrets.Data["USERNAME"]) + branch := string(secrets.Data["GIT_BASE_BRANCH"]) + url := fmt.Sprintf("%s/%s/decapod-site/src/branch/%s", gitSvcUrl, username, branch) + log.Info(ctx, "git url : ", url) + + rsp, err := http.Get(url) + if err != nil { + return out, err + } + defer rsp.Body.Close() + + html, err := goquery.NewDocumentFromReader(rsp.Body) + if err != nil { + return out, err + } + + wrapper := html.Find("#repo-files-table > tbody") + items := wrapper.Find("a.muted") + items.Each(func(idx int, sel *goquery.Selection) { + href, _ := sel.Attr("href") + if strings.Contains(href, "reference") { + arr := strings.Split(href, "/") + log.Info(ctx, arr[len(arr)-1]) + + out = append(out, arr[len(arr)-1]) + } + + }) + + return +} + func servicesFromIds(serviceIds []string) []byte { services := "[" for i, serviceId := range serviceIds { diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index ae1cb4da..0416b4c0 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -111,3 +111,7 @@ type AddOrganizationStackTemplatesRequest struct { type RemoveOrganizationStackTemplatesRequest struct { StackTemplateIds []string `json:"stackTemplateIds" validate:"required"` } + +type GetStackTemplateTemplateIdsResponse struct { + TemplateIds []string `json:"templateIds"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index b51c2b9a..99e8a908 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -117,6 +117,7 @@ var errorMap = map[ErrorCode]string{ "ST_FAILED_ADD_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE": "조직에 시스템알람템플릿을 추가하는데 실패하였습니다.", "ST_FAILED_REMOVE_ORGANIZATION_SYSTEM_NOTIFICATION_TEMPLATE": "조직에서 시스템알람템플릿을 삭제하는데 실패하였습니다.", "ST_FAILED_DELETE_EXIST_CLUSTERS": "스택템플릿을 사용하고 있는 스택이 있습니다. 스택을 삭제하세요.", + "C_INVALID_STACK_TEMPLATE_TEMPLATE_IDS": "템플릿아이디를 조회하는데 실패하였습니다.", // PolicyTemplate "PT_CREATE_ALREADY_EXISTED_NAME": "정첵 템플릿에 이미 존재하는 이름입니다.", From 3d36c94c3751556a0504fc49d567125473d5d00c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 29 Apr 2024 20:01:24 +0900 Subject: [PATCH 391/502] feature. policy notifiation --- internal/delivery/http/project.go | 21 ++++++++++++++------ internal/usecase/dashboard.go | 1 + internal/usecase/project.go | 14 +++++++++++-- internal/usecase/system-notification-rule.go | 14 ++++++------- internal/usecase/system-notification.go | 1 + 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 88d238b9..0239e86c 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -2,11 +2,12 @@ package http import ( "fmt" - "github.com/openinfradev/tks-api/internal/keycloak" "net/http" "strings" "time" + "github.com/openinfradev/tks-api/internal/keycloak" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/pagination" @@ -59,14 +60,16 @@ type IProjectHandler interface { } type ProjectHandler struct { - usecase usecase.IProjectUsecase - authUsecase usecase.IAuthUsecase + usecase usecase.IProjectUsecase + authUsecase usecase.IAuthUsecase + dashboardUsecase usecase.IDashboardUsecase } func NewProjectHandler(u usecase.Usecase) IProjectHandler { return &ProjectHandler{ - usecase: u.Project, - authUsecase: u.Auth, + usecase: u.Project, + authUsecase: u.Auth, + dashboardUsecase: u.Dashboard, } } @@ -1829,7 +1832,13 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, return } - resourcesUsage, err := p.usecase.GetResourcesUsage(r.Context(), organizationId, projectId, projectNamespace, domain.StackId(stackId)) + thanosClient, err := p.dashboardUsecase.GetThanosClient(r.Context(), organizationId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Failed to get thanos client"), "", "")) + return + } + + resourcesUsage, err := p.usecase.GetResourcesUsage(r.Context(), thanosClient, organizationId, projectId, projectNamespace, domain.StackId(stackId)) if err != nil { log.Error(r.Context(), "Failed to get project resources.", err) ErrorJSON(w, r, err) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index f97a0f48..c1bd54d5 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -41,6 +41,7 @@ type IDashboardUsecase interface { GetPolicyViolationLog(ctx context.Context, organizationId string) (*domain.GetDashboardPolicyViolationLogResponse, error) GetWorkload(ctx context.Context, organizationId string) (*domain.GetDashboardWorkloadResponse, error) GetPolicyViolationTop5(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) + GetThanosClient(ctx context.Context, organizationId string) (thanos.ThanosClient, error) } type DashboardUsecase struct { diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 093a748c..80775111 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -16,6 +16,7 @@ import ( "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/kubernetes" "github.com/openinfradev/tks-api/pkg/log" + thanos "github.com/openinfradev/tks-api/pkg/thanos-client" "github.com/pkg/errors" "gopkg.in/yaml.v3" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -60,7 +61,7 @@ type IProjectUsecase interface { GetProjectNamespaceKubeconfig(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (string, error) GetProjectKubeconfig(ctx context.Context, organizationId string, projectId string) (string, error) GetK8sResources(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceK8sResources, err error) - GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) + GetResourcesUsage(ctx context.Context, thanosClient thanos.ThanosClient, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) AssignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error UnassignKeycloakClientRoleToMember(ctx context.Context, organizationId string, projectId string, clientId string, projectMemberId string) error } @@ -905,11 +906,20 @@ func (u *ProjectUsecase) GetK8sResources(ctx context.Context, organizationId str return } -func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) { +func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, thanosClient thanos.ThanosClient, organizationId string, projectId string, namespace string, stackId domain.StackId) (out domain.ProjectNamespaceResourcesUsage, err error) { _, err = u.clusterRepository.Get(ctx, domain.ClusterId(stackId)) if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } + /* + query := "sum(rate(container_cpu_usage_seconds_total{image!=\"\"}[10m]) ) by (taco_cluster, namespace)" + result, err := thanosClient.Get(ctx, query) + if err != nil { + return out, err + } + log.Info(ctx, helper.ModelToJson(result)) + + */ out.Cpu = "1.0 %" out.Memory = "2.0 %" diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index ad04ee57..22afda6b 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -203,7 +203,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c rules = append(rules, model.SystemNotificationRule{ ID: ruleId, Name: domain.SN_TYPE_NODE_CPU_HIGH_LOAD + "-warning", - Description: "", + Description: "기본 시스템 알림 - CPU 사용량", OrganizationId: organizationId, NotificationType: template.NotificationType, IsSystem: true, @@ -229,7 +229,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c rules = append(rules, model.SystemNotificationRule{ ID: ruleId, Name: domain.SN_TYPE_NODE_MEMORY_HIGH_UTILIZATION + "-warning", - Description: "", + Description: "기본 시스템 알림 - 메모리 사용량", OrganizationId: organizationId, NotificationType: template.NotificationType, IsSystem: true, @@ -255,7 +255,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c rules = append(rules, model.SystemNotificationRule{ ID: ruleId, Name: domain.SN_TYPE_NODE_DISK_FULL + "-critical", - Description: "", + Description: "기본 시스템 알림 - 노드 디스크 사용량", OrganizationId: organizationId, NotificationType: template.NotificationType, IsSystem: true, @@ -281,7 +281,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c rules = append(rules, model.SystemNotificationRule{ ID: ruleId, Name: domain.SN_TYPE_PVC_FULL + "-critical", - Description: "", + Description: "기본 시스템 알림 - PVC 사용량", OrganizationId: organizationId, NotificationType: template.NotificationType, IsSystem: true, @@ -307,7 +307,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c rules = append(rules, model.SystemNotificationRule{ ID: ruleId, Name: domain.SN_TYPE_POD_RESTART_FREQUENTLY + "-critical", - Description: "", + Description: "기본 시스템 알림 - Pod 재기동", OrganizationId: organizationId, NotificationType: template.NotificationType, IsSystem: true, @@ -333,7 +333,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c rules = append(rules, model.SystemNotificationRule{ ID: ruleId, Name: domain.SN_TYPE_POLICY_AUDITED + "-critical", - Description: "", + Description: "기본 시스템 알림 - 정책 위반", OrganizationId: organizationId, NotificationType: template.NotificationType, IsSystem: true, @@ -359,7 +359,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c rules = append(rules, model.SystemNotificationRule{ ID: ruleId, Name: domain.SN_TYPE_POLICY_BLOCKED + "-critical", - Description: "", + Description: "기본 시스템 알림 - 정책 위반 시도", OrganizationId: organizationId, NotificationType: template.NotificationType, IsSystem: true, diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 6add4b68..4a2a8db2 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -128,6 +128,7 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre GrafanaUrl: u.makeGrafanaUrl(ctx, primaryCluster, systemNotification, domain.ClusterId(clusterId)), RawData: rawData, SystemNotificationRuleId: systemNotificationRuleId, + NotificationType: systemNotification.Annotations.AlertType, } _, err = u.repo.Create(ctx, dto) From b0d49bfbd39a6d73f527710b8ca0889286daf66c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 29 Apr 2024 20:04:14 +0900 Subject: [PATCH 392/502] trivial. enable log for policyNotification --- internal/usecase/system-notification.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 4a2a8db2..2ee8b34f 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -8,6 +8,7 @@ import ( "time" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/mail" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" @@ -57,6 +58,8 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre return fmt.Errorf("No data found") } + log.Info(ctx, helper.ModelToJson(input)) + allClusters, err := u.clusterRepo.Fetch(ctx, nil) if err != nil { return fmt.Errorf("No clusters") From a92839af45626f0ace55e99dc7ced53633d3b9f9 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 29 Apr 2024 17:19:52 +0900 Subject: [PATCH 393/502] =?UTF-8?q?kind=20=ED=99=94=EC=9D=B4=ED=8A=B8?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20?= =?UTF-8?q?apigroup=20autofill?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy.go | 17 +++++ internal/policy-template/kind-util.go | 94 +++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 internal/policy-template/kind-util.go diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index a06144a9..ab42458c 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -99,6 +99,15 @@ func (h *PolicyHandler) CreatePolicy(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } + } else { + normaized, err := policytemplate.CheckAndNormalizeKinds(input.Match.Kinds) + + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match error: %s", err), "P_INVALID_MATCH", "")) + return + } + + input.Match.Kinds = normaized } if len(input.PolicyResourceName) > 0 { @@ -191,6 +200,14 @@ func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } + } else { + normaized, err := policytemplate.CheckAndNormalizeKinds(input.Match.Kinds) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match error: %s", err), "P_INVALID_MATCH", "")) + return + } + + input.Match.Kinds = normaized } var templateId *uuid.UUID = nil diff --git a/internal/policy-template/kind-util.go b/internal/policy-template/kind-util.go new file mode 100644 index 00000000..b19a766b --- /dev/null +++ b/internal/policy-template/kind-util.go @@ -0,0 +1,94 @@ +package policytemplate + +import ( + "fmt" + "slices" + + "github.com/openinfradev/tks-api/pkg/domain" +) + +var KindToApiGroup = map[string]string{ + "Pod": "", + "Node": "", + "Namespace": "", + "Service": "", + "Secret": "", + "ConfigMap": "", + "PersistentVolume": "", + "PersistentVolumeClaim": "", + "ReplicationController": "", //deprecated + "ServiceAccount": "", + "LimitRange": "", + "ResourceQuota": "", + "Deployment": "apps", + "ReplicaSet": "apps", + "StatefulSet": "apps", + "DaemonSet": "apps", + "HorizontalPodAutoscaler": "autoscaling", + "VerticalPodAutoscaler": "autoscaling", // 확인 안됨 + "Job": "batch", + "CronJob": "batch", + "Ingress": "networking.k8s.io", + "NetworkPolicy": "networking.k8s.io", + "StorageClass": "storage.k8s.io", + "VolumeAttachment": "storage.k8s.io", + "Role": "rbac.authorization.k8s.io", + "RoleBinding": "rbac.authorization.k8s.io", + "ClusterRole": "rbac.authorization.k8s.io", + "ClusterRoleBinding": "rbac.authorization.k8s.io", + "ValidatingWebhookConfiguration": "admissionregistration.k8s.io", + "MutatingWebhookConfiguration": "admissionregistration.k8s.io", + "CustomResourceDefinition": "apiextensions.k8s.io", + "Certificate": "cert-manager.io", + "Issuer": "cert-manager.io", + "Lease": "coordination.k8s.io", + "Lock": "coordination.k8s.io", // 안 나옴 + "EndpointSlice": "discovery.k8s.io", + "Event": "events.k8s.io", + "FlowSchema": "flowcontrol.apiserver.k8s.io", + "PriorityLevelConfiguration": "flowcontrol.apiserver.k8s.io", + "ManagedNamespacedResource": "meta.k8s.io", + "PriorityClass": "scheduling.k8s.io", + "PodSecurityPolicy": "policy", + "PodDisruptionBudget": "policy", +} + +func CheckAndNormalizeKinds(kinds []domain.Kinds) ([]domain.Kinds, error) { + if kinds == nil { + return nil, nil + } + + var result = []domain.Kinds{} + var invalidKinds = []string{} + var normalizedMap = map[string]domain.Kinds{} + + for _, kind := range kinds { + for _, kinditem := range kind.Kinds { + if apiGroup, ok := KindToApiGroup[kinditem]; ok { + if ai, ok := normalizedMap[apiGroup]; ok { + if !slices.Contains(ai.Kinds, kinditem) { + ai.Kinds = append(ai.Kinds, kinditem) + normalizedMap[apiGroup] = ai + } + } else { + normalizedMap[apiGroup] = domain.Kinds{ + APIGroups: []string{apiGroup}, + Kinds: []string{kinditem}, + } + } + } else { + invalidKinds = append(invalidKinds, kinditem) + } + } + } + + if len(invalidKinds) > 0 { + return nil, fmt.Errorf("invalid kinds: %v", invalidKinds) + } + + for _, nornormalized := range normalizedMap { + result = append(result, nornormalized) + } + + return result, nil +} From 1d226cef851b6dc96c5b78865f209ed999de79b4 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 30 Apr 2024 00:25:18 +0900 Subject: [PATCH 394/502] =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=8B=9C=20=EB=8F=99=EC=9D=BC?= =?UTF-8?q?=ED=95=9C=20=EB=84=A4=EC=9E=84=20=EC=A4=91=EB=B3=B5=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95=20=EB=93=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/usecase/policy-template.go | 3 ++- pkg/domain/admin/policy-template.go | 2 +- pkg/domain/policy-template.go | 2 +- pkg/domain/policy.go | 8 ++++---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 3d60b872..8611035f 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -277,7 +277,8 @@ func (u *PolicyTemplateUsecase) Update(ctx context.Context, organizationId *stri updateMap := make(map[string]interface{}) - if templateName != nil { + // 기존 이름과 같은 경우면 체크 필요없으므로 다른 경우에만 처리하도록 추가 + if templateName != nil && *templateName != policyTemplate.TemplateName { if policyTemplate.IsTksTemplate() { exists, err := u.repo.ExistByName(ctx, *templateName) if err == nil && exists { diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index 413609a3..1e0867ef 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -67,7 +67,7 @@ type CreateOrganizationPolicyTemplateReponse struct { type UpdatePolicyTemplateRequest struct { TemplateName *string `json:"templateName,omitempty" validate:"required,name" example:"필수 Label 검사"` Description *string `json:"description,omitempty"` - Severity *string `json:"severity,omitempty" validate:"oneof=low medium high" enums:"low,medium,high" example:"medium"` + Severity *string `json:"severity,omitempty" validate:"omitempty,oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated *bool `json:"deprecated,omitempty" example:"false"` PermittedOrganizationIds *[]string `json:"permittedOrganizationIds,omitempty"` } diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 59311718..3d41e3b8 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -53,7 +53,7 @@ type CreatePolicyTemplateReponse struct { type UpdatePolicyTemplateRequest struct { TemplateName *string `json:"templateName,omitempty" validate:"required,name" example:"필수 Label 검사"` Description *string `json:"description,omitempty"` - Severity *string `json:"severity,omitempty" validate:"oneof=low medium high" enums:"low,medium,high" example:"medium"` + Severity *string `json:"severity,omitempty" validate:"omitempty,oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated *bool `json:"deprecated,omitempty" example:"false"` PermittedOrganizationIds *[]string `json:"permittedOrganizationIds,omitempty"` } diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index 411da352..6550f948 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -73,11 +73,11 @@ type UpdatePolicyRequest struct { TargetClusterIds *[]string `json:"targetClusterIds,omitempty" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` Mandatory *bool `json:"mandatory,omitempty"` - PolicyName *string `json:"policyName,omitempty" validate:"required,name" example:"label 정책"` - Description *string `json:"description"` + PolicyName *string `json:"policyName,omitempty" validate:"name" example:"label 정책"` + Description *string `json:"description,omitempty"` TemplateId *string `json:"templateId,omitempty" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` - EnforcementAction *string `json:"enforcementAction" validate:"required,oneof=deny dryrun warn" enum:"warn,deny,dryrun" example:"deny"` - Parameters *string `json:"parameters" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` + EnforcementAction *string `json:"enforcementAction" validate:"omitempty,oneof=deny dryrun warn" enum:"warn,deny,dryrun" example:"deny"` + Parameters *string `json:"parameters,omitempty" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` Match *Match `json:"match,omitempty"` MatchYaml *string `json:"matchYaml,omitempty"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` From f419aeb74210584fa1196a582153d31630b99587 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 30 Apr 2024 09:59:00 +0900 Subject: [PATCH 395/502] trivial. add debug log for policyNotification --- internal/delivery/http/system-notification.go | 20 +++++++++---------- pkg/domain/system-notification.go | 2 ++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/internal/delivery/http/system-notification.go b/internal/delivery/http/system-notification.go index 1df9eea4..150af690 100644 --- a/internal/delivery/http/system-notification.go +++ b/internal/delivery/http/system-notification.go @@ -1,6 +1,7 @@ package http import ( + "bytes" "fmt" "io" "net/http" @@ -47,19 +48,18 @@ func (h *SystemNotificationHandler) CreateSystemNotification(w http.ResponseWrit INFO[2023-04-26 18:14:11] {"receiver":"webhook-systemNotification","status":"firing","systemNotifications":[{"status":"firing","labels":{"systemNotificationname":"TestSystemNotification1"},"annotations":{},"startsAt":"2023-04-26T09:14:01.489894015Z","endsAt":"0001-01-01T00:00:00Z","generatorURL":"","fingerprint":"0dafe30dffce9487"}],"groupLabels":{"systemNotificationname":"TestSystemNotification1"},"commonLabels":{"systemNotificationname":"TestSystemNotification1"},"commonAnnotations":{},"externalURL":"http://lma-systemNotificationmanager.lma:9093","version":"4","groupKey":"{}:{systemNotificationname=\"TestSystemNotification1\"}","truncatedSystemNotifications":0} */ - /* - // webhook 으로 부터 받은 body parse - bodyBytes, err := io.ReadAll(r.Body) - if err != nil { - log.Error(r.Context(),err) - } - bodyString := string(bodyBytes) - log.Info(r.Context(),bodyString) - */ + // webhook 으로 부터 받은 body parse + bodyBytes, err := io.ReadAll(r.Body) + if err != nil { + log.Error(r.Context(), err) + } + r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + bodyString := string(bodyBytes) + log.Info(r.Context(), bodyString) // 외부로부터(systemNotification manager) 오는 데이터이므로, dto 변환없이 by-pass 처리한다. input := domain.CreateSystemNotificationRequest{} - err := UnmarshalRequestInput(r, &input) + err = UnmarshalRequestInput(r, &input) if err != nil { ErrorJSON(w, r, err) return diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 27d9dc5b..8ba0f1e8 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -60,6 +60,8 @@ type SystemNotificationRequest struct { Discriminative string `json:"discriminative"` AlertType string `json:"alertType"` SystemNotificationRuleId string `json:"systemNotificationRuleId"` + PolicyName string `json:"policyName"` + PolicyTemplate string `json:"policyTemplate"` } `json:"annotations"` } From 8303c1e16ab4bf6f6a56784d26f1966f690a8044 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 30 Apr 2024 10:46:26 +0900 Subject: [PATCH 396/502] =?UTF-8?q?Policy=20Get=EC=97=90=EC=84=9C=20NotFou?= =?UTF-8?q?nd=20=EC=97=90=EB=9F=AC=EB=A5=BC=20=EB=B3=84=EB=8F=84=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/repository/policy.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 75dc7a90..63be3517 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -184,13 +184,8 @@ func (r *PolicyRepository) GetBy(ctx context.Context, organizationId string, key res := r.db.WithContext(ctx).Preload(clause.Associations). Where(query, organizationId, value).First(&policy) if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - log.Infof(ctx, "Not found policy %s='%v'", key, value) - return nil, nil - } else { - log.Error(ctx, res.Error) - return nil, res.Error - } + log.Error(ctx, res.Error) + return nil, res.Error } return &policy, nil From eec78c6ed994a923791f5c8bbe0ff563c4f5ce7f Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 30 Apr 2024 11:15:01 +0900 Subject: [PATCH 397/502] bugfix: pass project_id on rollbacking app --- internal/usecase/app-serve-app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 017d606e..f64506a2 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -503,7 +503,7 @@ func (u *AppServeAppUsecase) UpdateAppServeApp(ctx context.Context, appId string log.Debug(ctx, "After transform, extraEnv: ", extEnv) } - // TODO: Check if appId is necessary here. + // TODO: Check if appId is necessary here. taskId, err := u.repo.CreateTask(ctx, appTask, appId) if err != nil { log.Info(ctx, "taskId = ", taskId) @@ -752,6 +752,7 @@ func (u *AppServeAppUsecase) RollbackAppServeApp(ctx context.Context, appId stri workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ "organization_id=" + app.OrganizationId, + "project_id=" + app.ProjectId, "target_cluster_id=" + app.TargetClusterId, "app_name=" + app.Name, "namespace=" + app.Namespace, From 292c485a1efaf6a091e2d3224382558bc6f52095 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 30 Apr 2024 11:17:37 +0900 Subject: [PATCH 398/502] =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C(=EC=A1=B0=EC=A7=81)=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=98=84=EC=9E=AC=20=EB=B2=84=EC=A0=84=EA=B3=BC=20?= =?UTF-8?q?=EC=B5=9C=EC=8B=A0=20=EB=B2=84=EC=A0=84=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy-template.go | 2 +- internal/model/policy-template.go | 2 ++ internal/usecase/policy-template.go | 33 +++++++++++++++++++++++ pkg/domain/policy-template.go | 24 +++++++++++++++-- 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index caf54f5c..b43bbc42 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -1247,7 +1247,7 @@ func (h *PolicyTemplateHandler) ListPolicyTemplate(w http.ResponseWriter, r *htt } var out domain.ListPolicyTemplateResponse - out.PolicyTemplates = make([]domain.PolicyTemplateResponse, len(policyTemplates)) + out.PolicyTemplates = make([]domain.PolicyTemplateTwoVersionResponse, len(policyTemplates)) for i, policyTemplate := range policyTemplates { if err := serializer.Map(r.Context(), policyTemplate, &out.PolicyTemplates[i]); err != nil { log.Info(r.Context(), err) diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index 1864a214..ca2c28ff 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -32,6 +32,8 @@ type PolicyTemplate struct { TemplateName string Type string // Org or Tks Version string `gorm:"-:all"` // 삭제 예정 + CurrentVersion string `gorm:"-:all"` + LatestVersion string `gorm:"-:all"` SupportedVersions []PolicyTemplateSupportedVersion `gorm:"foreignKey:PolicyTemplateId"` OrganizationId *string // Org 인 경우에만 설정 Organization Organization `gorm:"foreignKey:OrganizationId"` diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 8611035f..f54a4f96 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/openinfradev/tks-api/pkg/log" + "k8s.io/apimachinery/pkg/api/errors" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" @@ -146,6 +147,18 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, organizationId *strin log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) } + var primaryClusterId string + + if organizationId != nil { + org, err := u.organizationRepo.Get(ctx, *organizationId) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } else { + primaryClusterId = org.PrimaryClusterId + } + } + for i := range policyTemplates { // 단순히 참조하면 업데이트가 안되므로 pointer derefrencing policyTemplate := &policyTemplates[i] @@ -154,6 +167,26 @@ func (u *PolicyTemplateUsecase) Fetch(ctx context.Context, organizationId *strin (*policyTemplate).PermittedOrganizations = *organizations } } + + if organizationId != nil { + (*policyTemplate).LatestVersion = policyTemplate.Version + + // 에러 없이 primaryClusterId를 가져왔을 때만 처리 + if len(primaryClusterId) > 0 { + + templateCR, err := policytemplate.GetTksPolicyTemplateCR(ctx, primaryClusterId, policyTemplate.ResoureName()) + + if err == nil && templateCR != nil { + (*policyTemplate).CurrentVersion = templateCR.Spec.Version + } else if errors.IsNotFound(err) || templateCR == nil { + // 템플릿이 존재하지 않으면 최신 버전으로 배포되므로 + (*policyTemplate).CurrentVersion = policyTemplate.LatestVersion + } else { + // 통신 실패 등 기타 에러, 버전을 세팅하지 않아 에러임을 알수 있도록 로그를 남김 + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } + } + } } return policyTemplates, err diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 3d41e3b8..5927282d 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -23,6 +23,26 @@ type PolicyTemplateResponse struct { Libs []string `json:"libs" example:"rego 코드"` } +type PolicyTemplateTwoVersionResponse struct { + ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` + Type string `json:"type" enums:"tks,organization" example:"tks"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + + TemplateName string `json:"templateName" example:"필수 Label 검사"` + Kind string `json:"kind" example:"K8sRequiredLabels"` + Severity string `json:"severity" enums:"low,medium,high" example:"medium"` + Deprecated bool `json:"deprecated" example:"false"` + CurrentVersion string `json:"currentVersion,omitempty" example:"v1.0.1"` + LatestVersion string `json:"latestVersion,omitempty" example:"v1.0.1"` + Description string `json:"description,omitempty" example:"이 정책은 ..."` + ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` + Rego string `json:"rego" example:"rego 코드"` + Libs []string `json:"libs" example:"rego 코드"` +} + type SimplePolicyTemplateResponse struct { ID string `json:"id" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` Type string `json:"type" enums:"tks,organization" example:"tks"` @@ -91,8 +111,8 @@ type GetPolicyTemplateResponse struct { } type ListPolicyTemplateResponse struct { - PolicyTemplates []PolicyTemplateResponse `json:"policyTemplates"` - Pagination PaginationResponse `json:"pagination"` + PolicyTemplates []PolicyTemplateTwoVersionResponse `json:"policyTemplates"` + Pagination PaginationResponse `json:"pagination"` } type PolicyTemplateStatistics struct { From 996e02f67c272c3b4787abead097aa91efba5366 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 30 Apr 2024 13:31:29 +0900 Subject: [PATCH 399/502] feature. implemtation policy-violation-log --- internal/delivery/http/dashboard.go | 49 +++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/internal/delivery/http/dashboard.go b/internal/delivery/http/dashboard.go index f978f281..99e3f04b 100644 --- a/internal/delivery/http/dashboard.go +++ b/internal/delivery/http/dashboard.go @@ -2,18 +2,20 @@ package http import ( "fmt" + "net/http" + "strings" + "time" + "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" policytemplate "github.com/openinfradev/tks-api/internal/policy-template" "github.com/openinfradev/tks-api/internal/serializer" "github.com/openinfradev/tks-api/internal/usecase" "github.com/openinfradev/tks-api/pkg/domain" "github.com/openinfradev/tks-api/pkg/httpErrors" "github.com/openinfradev/tks-api/pkg/log" - "net/http" - "strings" - "time" ) type IDashboardHandler interface { @@ -35,16 +37,18 @@ type IDashboardHandler interface { } type DashboardHandler struct { - usecase usecase.IDashboardUsecase - organizationUsecase usecase.IOrganizationUsecase - policyUsecase usecase.IPolicyUsecase + usecase usecase.IDashboardUsecase + organizationUsecase usecase.IOrganizationUsecase + policyUsecase usecase.IPolicyUsecase + systemNotificationUsecase usecase.ISystemNotificationUsecase } func NewDashboardHandler(h usecase.Usecase) IDashboardHandler { return &DashboardHandler{ - usecase: h.Dashboard, - organizationUsecase: h.Organization, - policyUsecase: h.Policy, + usecase: h.Dashboard, + organizationUsecase: h.Organization, + policyUsecase: h.Policy, + systemNotificationUsecase: h.SystemNotification, } } @@ -650,8 +654,13 @@ func (h *DashboardHandler) GetPolicyViolation(w http.ResponseWriter, r *http.Req // @Description Get policy violation log // @Accept json // @Produce json -// @Param organizationId path string true "Organization ID" -// @Success 200 {object} domain.GetDashboardPolicyViolationLogResponse +// @Param organizationId path string true "organizationId" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetPolicyNotificationsResponse // @Router /organizations/{organizationId}/dashboards/widgets/policy-violation-log [get] // @Security JWT func (h *DashboardHandler) GetPolicyViolationLog(w http.ResponseWriter, r *http.Request) { @@ -663,13 +672,27 @@ func (h *DashboardHandler) GetPolicyViolationLog(w http.ResponseWriter, r *http. return } - out, err := h.usecase.GetPolicyViolationLog(r.Context(), organizationId) + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + + policyNotifications, err := h.systemNotificationUsecase.FetchPolicyNotifications(r.Context(), organizationId, pg) if err != nil { - log.Error(r.Context(), "Failed to make policy violation log", err) ErrorJSON(w, r, err) return } + var out domain.GetPolicyNotificationsResponse + out.PolicyNotifications = make([]domain.PolicyNotificationResponse, len(policyNotifications)) + for i, policyNotification := range policyNotifications { + if err := serializer.Map(r.Context(), policyNotification, &out.PolicyNotifications[i]); err != nil { + log.Info(r.Context(), err) + } + } + + if out.Pagination, err = pg.Response(r.Context()); err != nil { + log.Info(r.Context(), err) + } + ResponseJSON(w, r, http.StatusOK, out) } From 4321b06a0de76bbc9d961610e5b37e4d9c2bb976 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 30 Apr 2024 13:45:57 +0900 Subject: [PATCH 400/502] =?UTF-8?q?currentVersion,=20latestVersion=20omite?= =?UTF-8?q?mpty=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/domain/policy-template.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 5927282d..a5200616 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -35,8 +35,8 @@ type PolicyTemplateTwoVersionResponse struct { Kind string `json:"kind" example:"K8sRequiredLabels"` Severity string `json:"severity" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` - CurrentVersion string `json:"currentVersion,omitempty" example:"v1.0.1"` - LatestVersion string `json:"latestVersion,omitempty" example:"v1.0.1"` + CurrentVersion string `json:"currentVersion" example:"v1.0.1"` + LatestVersion string `json:"latestVersion" example:"v1.0.1"` Description string `json:"description,omitempty" example:"이 정책은 ..."` ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` Rego string `json:"rego" example:"rego 코드"` From 3b4a17fc2c7ed80aec634bc86dd7c10ddc9c2cbc Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 30 Apr 2024 13:49:10 +0900 Subject: [PATCH 401/502] trivial. resize tks-api logs --- internal/middleware/logging/logging.go | 5 ++++- internal/serializer/serializer.go | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/middleware/logging/logging.go b/internal/middleware/logging/logging.go index feee3af4..c4da756c 100644 --- a/internal/middleware/logging/logging.go +++ b/internal/middleware/logging/logging.go @@ -12,6 +12,8 @@ import ( "github.com/openinfradev/tks-api/pkg/log" ) +const MAX_LOG_LEN = 1000 + func LoggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -29,7 +31,8 @@ func LoggingMiddleware(next http.Handler) http.Handler { next.ServeHTTP(lrw, r) statusCode := lrw.GetStatusCode() - log.Infof(r.Context(), "[API_RESPONSE] [%d][%s][%s]", statusCode, http.StatusText(statusCode), lrw.GetBody().String()) + + log.Infof(r.Context(), "[API_RESPONSE] [%d][%s][%s]", statusCode, http.StatusText(statusCode), lrw.GetBody().String()[:MAX_LOG_LEN-1]) log.Infof(r.Context(), "***** END [%s %s] *****", r.Method, r.RequestURI) }) } diff --git a/internal/serializer/serializer.go b/internal/serializer/serializer.go index ddb434a7..6003de3b 100644 --- a/internal/serializer/serializer.go +++ b/internal/serializer/serializer.go @@ -81,7 +81,7 @@ func recursiveMap(ctx context.Context, src interface{}, dst interface{}, convert dstField.Set(reflect.ValueOf(converted)) } } else { - log.Debugf(ctx, "no converter found for %s -> %s", srcField.Type(), dstField.Type()) + //log.Debugf(ctx, "no converter found for %s -> %s", srcField.Type(), dstField.Type()) continue } } From 03fc9c5f7f5233110e0d1efb2f158d39e482b5a1 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 30 Apr 2024 13:56:28 +0900 Subject: [PATCH 402/502] trivial. bug fix --- internal/middleware/logging/logging.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/middleware/logging/logging.go b/internal/middleware/logging/logging.go index c4da756c..31e2c456 100644 --- a/internal/middleware/logging/logging.go +++ b/internal/middleware/logging/logging.go @@ -32,7 +32,11 @@ func LoggingMiddleware(next http.Handler) http.Handler { statusCode := lrw.GetStatusCode() - log.Infof(r.Context(), "[API_RESPONSE] [%d][%s][%s]", statusCode, http.StatusText(statusCode), lrw.GetBody().String()[:MAX_LOG_LEN-1]) + if len(lrw.GetBody().String()) > MAX_LOG_LEN { + log.Infof(r.Context(), "[API_RESPONSE] [%d][%s][%s]", statusCode, http.StatusText(statusCode), lrw.GetBody().String()[:MAX_LOG_LEN-1]) + } else { + log.Infof(r.Context(), "[API_RESPONSE] [%d][%s][%s]", statusCode, http.StatusText(statusCode), lrw.GetBody().String()) + } log.Infof(r.Context(), "***** END [%s %s] *****", r.Method, r.RequestURI) }) } From fc89d2b5482a89d34f37d0702ccaef2a87f50639 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 30 Apr 2024 14:01:08 +0900 Subject: [PATCH 403/502] tirivial. add policyName to policyNotification --- api/swagger/docs.go | 44 +++++++++++++++++++++++++++---- api/swagger/swagger.json | 44 +++++++++++++++++++++++++++---- api/swagger/swagger.yaml | 31 +++++++++++++++++++--- pkg/domain/policy-notification.go | 1 + 4 files changed, 106 insertions(+), 14 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 8b636d98..0f7b8583 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -3600,17 +3600,51 @@ const docTemplate = `{ "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse" } } } @@ -12700,9 +12734,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse": { - "type": "object" - }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse": { "type": "object", "properties": { @@ -13921,6 +13952,9 @@ const docTemplate = `{ "organizationId": { "type": "string" }, + "policyName": { + "type": "string" + }, "rawData": { "type": "string" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index c2ab38c6..a11a64b7 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -3594,17 +3594,51 @@ "parameters": [ { "type": "string", - "description": "Organization ID", + "description": "organizationId", "name": "organizationId", "in": "path", "required": true + }, + { + "type": "string", + "description": "pageSize", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "description": "pageNumber", + "name": "pageNumber", + "in": "query" + }, + { + "type": "string", + "description": "sortColumn", + "name": "soertColumn", + "in": "query" + }, + { + "type": "string", + "description": "sortOrder", + "name": "sortOrder", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "filters", + "name": "filters", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse" } } } @@ -12694,9 +12728,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse": { - "type": "object" - }, "github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse": { "type": "object", "properties": { @@ -13915,6 +13946,9 @@ "organizationId": { "type": "string" }, + "policyName": { + "type": "string" + }, "rawData": { "type": "string" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 43b89c95..707c8d93 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1662,8 +1662,6 @@ definitions: updatedResources: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.DashboardPolicyUpdate' type: object - github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse: - type: object github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationResponse: properties: chartData: @@ -2458,6 +2456,8 @@ definitions: type: string organizationId: type: string + policyName: + type: string rawData: type: string read: @@ -6590,18 +6590,41 @@ paths: - application/json description: Get policy violation log parameters: - - description: Organization ID + - description: organizationId in: path name: organizationId required: true type: string + - description: pageSize + in: query + name: pageSize + type: string + - description: pageNumber + in: query + name: pageNumber + type: string + - description: sortColumn + in: query + name: soertColumn + type: string + - description: sortOrder + in: query + name: sortOrder + type: string + - collectionFormat: csv + description: filters + in: query + items: + type: string + name: filters + type: array produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetDashboardPolicyViolationLogResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetPolicyNotificationsResponse' security: - JWT: [] summary: Get policy violation log diff --git a/pkg/domain/policy-notification.go b/pkg/domain/policy-notification.go index 50467266..f57b8de7 100644 --- a/pkg/domain/policy-notification.go +++ b/pkg/domain/policy-notification.go @@ -6,6 +6,7 @@ import ( type PolicyNotificationResponse struct { ID string `json:"id"` + PolicyName string `json:"policyName"` OrganizationId string `json:"organizationId"` Severity string `json:"severity"` MessageTitle string `json:"messageTitle"` From 0b1fb06d0c0ec2bdda7ef95852620e68c9cfc18c Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 30 Apr 2024 14:27:44 +0900 Subject: [PATCH 404/502] policy match kind: nil derefence error fix --- internal/delivery/http/policy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index ab42458c..6f982bdd 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -99,7 +99,7 @@ func (h *PolicyHandler) CreatePolicy(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } - } else { + } else if input.Match != nil { normaized, err := policytemplate.CheckAndNormalizeKinds(input.Match.Kinds) if err != nil { @@ -200,7 +200,7 @@ func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } - } else { + } else if input.Match != nil { normaized, err := policytemplate.CheckAndNormalizeKinds(input.Match.Kinds) if err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match error: %s", err), "P_INVALID_MATCH", "")) From ed18996cfcc7df97b348c16e1b5b3166b5686125 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 30 Apr 2024 15:39:47 +0900 Subject: [PATCH 405/502] =?UTF-8?q?policy=20resource=20name=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=B2=B4=ED=81=AC=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 ++++ internal/delivery/http/policy.go | 45 ++++++++++++++++++- internal/route/route.go | 1 + internal/usecase/policy.go | 7 ++- pkg/httpErrors/errorCode.go | 22 ++++----- 6 files changed, 70 insertions(+), 14 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index c3cb77cf..c847c189 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -268,6 +268,7 @@ const ( UpdatePolicy UpdatePolicyTargetClusters ExistsPolicyName + ExistsPolicyResourceName GetPolicyEdit AddPoliciesForStack DeletePoliciesForStack diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 498d16ff..937cb4d0 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -839,6 +839,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "ExistsPolicyName", Group: "Policy", }, + ExistsPolicyResourceName: { + Name: "ExistsPolicyResourceName", + Group: "Policy", + }, GetPolicyEdit: { Name: "GetPolicyEdit", Group: "Policy", @@ -1352,6 +1356,8 @@ func (e Endpoint) String() string { return "UpdatePolicyTargetClusters" case ExistsPolicyName: return "ExistsPolicyName" + case ExistsPolicyResourceName: + return "ExistsPolicyResourceName" case GetPolicyEdit: return "GetPolicyEdit" case AddPoliciesForStack: @@ -1822,6 +1828,8 @@ func GetEndpoint(name string) Endpoint { return UpdatePolicyTargetClusters case "ExistsPolicyName": return ExistsPolicyName + case "ExistsPolicyResourceName": + return ExistsPolicyResourceName case "GetPolicyEdit": return GetPolicyEdit case "AddPoliciesForStack": diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index ab42458c..905a6db6 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -33,6 +33,7 @@ type IPolicyHandler interface { GetMandatoryPolicies(w http.ResponseWriter, r *http.Request) SetMandatoryPolicies(w http.ResponseWriter, r *http.Request) ExistsPolicyName(w http.ResponseWriter, r *http.Request) + ExistsPolicyResourceName(w http.ResponseWriter, r *http.Request) ListStackPolicyStatus(w http.ResponseWriter, r *http.Request) GetStackPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) UpdateStackPolicyTemplateStatus(w http.ResponseWriter, r *http.Request) @@ -618,7 +619,7 @@ func (h *PolicyHandler) SetMandatoryPolicies(w http.ResponseWriter, r *http.Requ // ExistsPolicyName godoc // // @Tags Policy -// @Summary [ExistsPolicyName] 정책 아름 존재 여부 확인 +// @Summary [ExistsPolicyName] 정책 이름 존재 여부 확인 // @Description 해당 이름을 가진 정책이 이미 존재하는지 확인한다. // @Accept json // @Produce json @@ -638,7 +639,7 @@ func (h *PolicyHandler) ExistsPolicyName(w http.ResponseWriter, r *http.Request) policyName, ok := vars["policyName"] if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyTemplateName not found in path"), + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyName not found in path"), "P_INVALID_POLICY_NAME", "")) return } @@ -655,6 +656,46 @@ func (h *PolicyHandler) ExistsPolicyName(w http.ResponseWriter, r *http.Request) ResponseJSON(w, r, http.StatusOK, out) } +// ExistsPolicyResourceName godoc +// +// @Tags Policy +// @Summary [ExistsPolicyResourceName] 정책 자원 이름 존재 여부 확인 +// @Description 해당 자원 이름을 가진 정책이 이미 존재하는지 확인한다. +// @Accept json +// @Produce json +// @Param organizationId path string true "조직 식별자(o로 시작)" +// @Param policyResourceName path string true "정책 자원 이름(쿠버네티스 배포 시 자원 이름)" +// @Success 200 {object} domain.CheckExistedResponse +// @Router /organizations/{organizationId}/policies/resource-name/{policyResourceName}/existence [get] +// @Security JWT +func (h *PolicyHandler) ExistsPolicyResourceName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), + "C_INVALID_ORGANIZATION_ID", "")) + return + } + + policyResourceName, ok := vars["policyResourceName"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("policyResourceName not found in path"), + "P_INVALID_POLICY_RESOURCE_NAME", "")) + return + } + + exist, err := h.usecase.IsPolicyResourceNameExist(r.Context(), organizationId, policyResourceName) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.CheckExistedResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} + // ListStackPolicyStatus godoc // // @Tags StackPolicyStatus diff --git a/internal/route/route.go b/internal/route/route.go index 09e8b1eb..56e2500e 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -364,6 +364,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.DeletePolicy, http.HandlerFunc(policyHandler.DeletePolicy))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/{policyId}", customMiddleware.Handle(internalApi.UpdatePolicy, http.HandlerFunc(policyHandler.UpdatePolicy))).Methods(http.MethodPatch) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/name/{policyName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyName, http.HandlerFunc(policyHandler.ExistsPolicyName))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policies/resource-name/{policyResourceName}/existence", customMiddleware.Handle(internalApi.ExistsPolicyResourceName, http.HandlerFunc(policyHandler.ExistsPolicyResourceName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.AddPoliciesForStack, http.HandlerFunc(policyHandler.AddPoliciesForStack))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/policies", customMiddleware.Handle(internalApi.DeletePoliciesForStack, http.HandlerFunc(policyHandler.DeletePoliciesForStack))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/statistics", customMiddleware.Handle(internalApi.StackPolicyStatistics, http.HandlerFunc(policyHandler.StackPolicyStatistics))).Methods(http.MethodGet) diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 0ebbc371..73fafafd 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -32,6 +32,7 @@ type IPolicyUsecase interface { Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination, filledParameter bool) (*[]model.Policy, error) IsPolicyIdExist(ctx context.Context, organizationId string, policyId uuid.UUID) (exists bool, err error) IsPolicyNameExist(ctx context.Context, organizationId string, policyName string) (exists bool, err error) + IsPolicyResourceNameExist(ctx context.Context, organizationId string, policyResourceName string) (exists bool, err error) UpdatePolicyTargetClusters(ctx context.Context, organizationId string, policyId uuid.UUID, currentClusterIds []string, targetClusterIds []string) (err error) SetMandatoryPolicies(ctx context.Context, organizationId string, mandatoryPolicyIds []uuid.UUID, nonMandatoryPolicyIds []uuid.UUID) (err error) GetMandatoryPolicies(ctx context.Context, organizationId string) (response *domain.GetMandatoryPoliciesResponse, err error) @@ -105,7 +106,7 @@ func (u *PolicyUsecase) Create(ctx context.Context, organizationId string, dto m } if exists { - return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_CREATE_ALREADY_EXISTED_RESOURCE_NAME", "policy resource name already exists") + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_RESOURCE_NAME", "policy resource name already exists") } dto.TargetClusters = make([]model.Cluster, len(dto.TargetClusterIds)) @@ -438,6 +439,10 @@ func (u *PolicyUsecase) IsPolicyNameExist(ctx context.Context, organizationId st return u.repo.ExistByName(ctx, organizationId, policyName) } +func (u *PolicyUsecase) IsPolicyResourceNameExist(ctx context.Context, organizationId string, policyResoName string) (exists bool, err error) { + return u.repo.ExistByResourceName(ctx, organizationId, policyResoName) +} + func (u *PolicyUsecase) IsPolicyIdExist(ctx context.Context, organizationId string, policyId uuid.UUID) (exists bool, err error) { return u.repo.ExistByID(ctx, organizationId, policyId) } diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 99e8a908..21fb3510 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -135,17 +135,17 @@ var errorMap = map[ErrorCode]string{ "PT_INVALID_PARAMETER_SCHEMA": "파라미터 스키마에 잘못된 타입이 지정되었습니다.", // Policy - "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", - "P_NOT_FOUND_POLICY": "정책이 존재하지 않습니다.", - "P_INVALID_POLICY_NAME": "유효하지 않은 정책 이름입니다. 정책 이름을 확인하세요.", - "P_CREATE_ALREADY_EXISTED_RESOURCE_NAME": "유효하지 않은 정책 자원 이름(k8s 자원 이름)입니다. 정책 자원 이름을 확인하세요.", - "P_INVALID_MATCH": "유효하지 않은 match 설정입니다. match 설정을 확인하세요.", - "P_FAILED_FETCH_POLICY": "정책 ID에 해당하는 정책을 가져오는데 실패했습니다.", - "P_FAILED_FETCH_CLUSTER": "정책의 클러스터 정보를 가져오는데 실패했습니다.", - "P_FAILED_FETCH_TEMPLATE": "정책의 템플릿 정보를 가져오는데 실패했습니다.", - "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", - "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", - "P_INVALID_POLICY_PARAMETER": "정책 파라미터가 템플릿의 파라미터 스키마에 유효하지 않습니다. 파라미터를 확인하세요.", + "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", + "P_NOT_FOUND_POLICY": "정책이 존재하지 않습니다.", + "P_INVALID_POLICY_NAME": "유효하지 않은 정책 이름입니다. 정책 이름을 확인하세요.", + "P_INVALID_POLICY_RESOURCE_NAME": "유효하지 않은 정책 자원 이름(k8s 자원 이름)입니다. 정책 자원 이름을 확인하세요.", + "P_INVALID_MATCH": "유효하지 않은 match 설정입니다. match 설정을 확인하세요.", + "P_FAILED_FETCH_POLICY": "정책 ID에 해당하는 정책을 가져오는데 실패했습니다.", + "P_FAILED_FETCH_CLUSTER": "정책의 클러스터 정보를 가져오는데 실패했습니다.", + "P_FAILED_FETCH_TEMPLATE": "정책의 템플릿 정보를 가져오는데 실패했습니다.", + "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", + "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", + "P_INVALID_POLICY_PARAMETER": "정책 파라미터가 템플릿의 파라미터 스키마에 유효하지 않습니다. 파라미터를 확인하세요.", } func (m ErrorCode) GetText() string { From 7a1d19fd252b6603f1e16e35691a28490c4a7d1f Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 30 Apr 2024 17:26:30 +0900 Subject: [PATCH 406/502] add update stack-template name --- internal/repository/stack-template.go | 3 ++- pkg/domain/stack-template.go | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index e94b70fc..143b345e 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -99,7 +99,8 @@ func (r *StackTemplateRepository) Update(ctx context.Context, dto model.StackTem "KubeType": dto.KubeType, "Services": dto.Services, "Description": dto.Description, - "UpdatorId": dto.UpdatorId}) + "UpdatorId": dto.UpdatorId, + "Name": dto.Name}) if res.Error != nil { return res.Error } diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index 0416b4c0..a2cdaca4 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -90,6 +90,7 @@ type UpdateStackTemplateRequest struct { KubeType string `json:"kubeType" validate:"required"` OrganizationIds []string `json:"organizationIds" validate:"required"` ServiceIds []string `json:"serviceIds" validate:"required"` + Name string `json:"name" validate:"required,name"` } type GetStackTemplateServicesResponse struct { From aa8b7efddd80e46cb71ef1affe91d701857720b7 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 30 Apr 2024 17:29:14 +0900 Subject: [PATCH 407/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=EB=AA=85=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=B2=84=EA=B7=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/usecase/policy.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index 73fafafd..c5d6f6ba 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -245,21 +245,21 @@ func (u *PolicyUsecase) Update(ctx context.Context, organizationId string, polic updateMap["mandatory"] = mandatory } - if policyName != nil { - policy, err := u.repo.GetByName(ctx, organizationId, *policyName) - if err != nil { + // 정책명을 업데이트하기로 설정하였고 + if policyName != nil && policy.PolicyName != *policyName { + exists, err := u.repo.ExistByName(ctx, organizationId, *policyName) + + if err != nil && !errors.IsNotFound(err) { return err } // 이름이 같은 정책이 존재하지만 아이디가 서로 다른 경우, 즉 다른 정책이 해당 이름 사용 중임 - if policy != nil && policyId != policy.ID { + if exists { return httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "P_INVALID_POLICY_NAME", "policy name already exists") } // 해당 이름 사용중인 정책이 없으면 업데이트, 있으면 동일 정책이므로 업데이트 안 함 - if policy == nil { - updateMap["policy_name"] = policyName - } + updateMap["policy_name"] = policyName } if description != nil { From 8d77f7ecbeb166f408936f96c7ac8b4be32c3cb5 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 4 Apr 2024 17:39:49 +0900 Subject: [PATCH 408/502] refactoring: Move user filter logic to separate file for modularity --- internal/delivery/api/endpoint.go | 6 +- .../auth/authorizer/adminApiFilter.go | 36 +++++ .../middleware/auth/authorizer/authorizer.go | 1 + .../auth/authorizer/organizationFilter.go | 41 ++++++ internal/middleware/auth/authorizer/rbac.go | 130 +----------------- 5 files changed, 82 insertions(+), 132 deletions(-) create mode 100644 internal/middleware/auth/authorizer/adminApiFilter.go create mode 100644 internal/middleware/auth/authorizer/organizationFilter.go diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index c847c189..3ec1a0d3 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -161,14 +161,14 @@ const ( GetPolicyNotification // Stack - GetStacks // 스택관리/조회 CreateStack // 스택관리/생성 - CheckStackName // 스택관리/조회 + GetStacks // 스택관리/조회 GetStack // 스택관리/조회 UpdateStack // 스택관리/수정 DeleteStack // 스택관리/삭제 - GetStackKubeConfig // 스택관리/조회 + CheckStackName // 스택관리/조회 GetStackStatus // 스택관리/조회 + GetStackKubeConfig // 스택관리/조회 SetFavoriteStack // 스택관리/조회 DeleteFavoriteStack // 스택관리/조회 InstallStack // 스택관리 / 조회 diff --git a/internal/middleware/auth/authorizer/adminApiFilter.go b/internal/middleware/auth/authorizer/adminApiFilter.go new file mode 100644 index 00000000..e19fcf22 --- /dev/null +++ b/internal/middleware/auth/authorizer/adminApiFilter.go @@ -0,0 +1,36 @@ +package authorizer + +import ( + "fmt" + internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "net/http" + "strings" +) + +func AdminApiFilter(handler http.Handler, repo repository.Repository) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + return + } + + endpointInfo, ok := request.EndpointFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) + return + } + + if strings.HasPrefix(endpointInfo.String(), "Admin_") { + if requestUserInfo.GetOrganizationId() != "master" { + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return + } + } + + handler.ServeHTTP(w, r) + }) +} diff --git a/internal/middleware/auth/authorizer/authorizer.go b/internal/middleware/auth/authorizer/authorizer.go index 1ce71727..dc0b830d 100644 --- a/internal/middleware/auth/authorizer/authorizer.go +++ b/internal/middleware/auth/authorizer/authorizer.go @@ -22,6 +22,7 @@ func NewDefaultAuthorization(repo repository.Repository) *defaultAuthorization { //d.addFilters(RBACFilter) //d.addFilters(RBACFilterWithEndpoint) d.addFilters(AdminApiFilter) + d.addFilters(OrganizationFilter) return d } diff --git a/internal/middleware/auth/authorizer/organizationFilter.go b/internal/middleware/auth/authorizer/organizationFilter.go new file mode 100644 index 00000000..bcd9f925 --- /dev/null +++ b/internal/middleware/auth/authorizer/organizationFilter.go @@ -0,0 +1,41 @@ +package authorizer + +import ( + "fmt" + "github.com/gorilla/mux" + internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" + "net/http" +) + +func OrganizationFilter(handler http.Handler, repo repository.Repository) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + return + } + + if requestUserInfo.GetOrganizationId() != "" && requestUserInfo.GetOrganizationId() == "master" { + handler.ServeHTTP(w, r) + return + } + + vars := mux.Vars(r) + requestedOrganization, ok := vars["organizationId"] + if !ok { + log.Warn(r.Context(), "OrganizationFilter: organizationId not found. Passing through unsafely.") + handler.ServeHTTP(w, r) + } + + if requestedOrganization != requestUserInfo.GetOrganizationId() { + log.Debugf(r.Context(), "OrganizationFilter: requestedOrganization: %s, userOrganization: %s", requestedOrganization, requestUserInfo.GetOrganizationId()) + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + } + + handler.ServeHTTP(w, r) + }) +} diff --git a/internal/middleware/auth/authorizer/rbac.go b/internal/middleware/auth/authorizer/rbac.go index 9813558e..996379fc 100644 --- a/internal/middleware/auth/authorizer/rbac.go +++ b/internal/middleware/auth/authorizer/rbac.go @@ -1,62 +1,10 @@ package authorizer import ( - "fmt" - "net/http" - "strings" - - "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/internal" - internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" + "net/http" ) -func RBACFilter(handler http.Handler, repo repository.Repository) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) - return - } - organizationRole := requestUserInfo.GetRoleOrganizationMapping()[requestUserInfo.GetOrganizationId()] - - // TODO: 추후 tks-admin role 수정 필요 - if organizationRole == "tks-admin" { - handler.ServeHTTP(w, r) - return - } - - vars := mux.Vars(r) - // Organization Filter - if organizationRole == "admin" || organizationRole == "user" { - if orgId, ok := vars["organizationId"]; ok { - if orgId != requestUserInfo.GetOrganizationId() { - internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) - return - } - } else { - log.Warn(r.Context(), "RBACFilter: organizationId not found. Passing through unsafely.") - } - } - - // User Resource Filter - if strings.HasPrefix(r.URL.Path, internal.API_PREFIX+internal.API_VERSION+"/organizations/"+requestUserInfo.GetOrganizationId()+"/user") { - switch r.Method { - case http.MethodPost, http.MethodPut, http.MethodDelete: - if organizationRole != "admin" { - internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) - return - } - } - } - - handler.ServeHTTP(w, r) - }) -} - func RBACFilterWithEndpoint(handler http.Handler, repo repository.Repository) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { //requestEndpointInfo, ok := request.EndpointFrom(r.Context()) @@ -91,79 +39,3 @@ func RBACFilterWithEndpoint(handler http.Handler, repo repository.Repository) ht handler.ServeHTTP(w, r) }) } - -func AdminApiFilter(handler http.Handler, repo repository.Repository) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) - return - } - - endpointInfo, ok := request.EndpointFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) - return - } - - if strings.HasPrefix(endpointInfo.String(), "Admin") { - if requestUserInfo.GetOrganizationId() != "master" { - internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) - return - } - } - - handler.ServeHTTP(w, r) - }) -} - -func RequestOrganizationValidationFilter(handler http.Handler, repo repository.Repository) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) - return - } - - vars := mux.Vars(r) - organizationId, ok := vars["organizationId"] - if !ok { - //internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("organizationId not found"), "", "")) - //return - log.Warn(r.Context(), "RequestOrganizationValidationFilter: organizationId not found. Passing through unsafely.") - } - if organizationId != requestUserInfo.GetOrganizationId() { - internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) - return - } - - handler.ServeHTTP(w, r) - }) -} - -//type pair struct { -// regexp string -// method string -//} -// -//var LeaderPair = []pair{ -// {`/organizations/o[A-Za-z0-9]{8}/projects(?:\?.*)?$`, http.MethodPost}, -// {`/organizations/o[A-Za-z0-9]{8}/projects(?:\?.*)?$`, http.MethodGet}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodGet}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodPut}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodDelete}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members(?:\?.*)?$`, http.MethodPost}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members(?:\?.*)?$`, http.MethodGet}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(?:\?.*)?$`, http.MethodDelete}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/role(?:\?.*)?$`, http.MethodPut}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace(?:\?.*)?$`, http.MethodPost}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace(?:\?.*)?$`, http.MethodGet}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace/n[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodGet}, -// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace/n[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodDelete}, -//} -//var roleApiMapper = make(map[string][]pair) -// -//func projectFilter(url string, method string, userInfo user.Info) bool { -// -// return true -//} From 4febb732bebaffadbc482ed230cf68491488666c Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 4 Apr 2024 18:58:48 +0900 Subject: [PATCH 409/502] minor fix. lint fix --- internal/delivery/http/organization.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 524e78ae..6549554a 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -34,7 +34,7 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { } } -// CreateOrganization godoc +// Admin_CreateOrganization CreateOrganization godoc // // @Tags Organizations // @Summary Create organization in Admin portal From 4a510043dd78997df6398e10ded3a388dd9c5c00 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 5 Apr 2024 19:56:30 +0900 Subject: [PATCH 410/502] improvement: make more efficient auto-gen code using map rather than case-switch --- hack/endpoint-codegen.go | 104 +++++++++++++++++++++++------------ internal/model/permission.go | 42 +++++++------- 2 files changed, 87 insertions(+), 59 deletions(-) diff --git a/hack/endpoint-codegen.go b/hack/endpoint-codegen.go index 354082b3..fc48fee4 100644 --- a/hack/endpoint-codegen.go +++ b/hack/endpoint-codegen.go @@ -36,7 +36,7 @@ package api //) //` -const apiMapTemplateStr = `var ApiMap = map[Endpoint]EndpointInfo{ +const apiMapTemplateStr = `var MapWithEndpoint = map[Endpoint]EndpointInfo{ {{- range .}} {{.Name}}: { Name: "{{.Name}}", @@ -46,30 +46,51 @@ const apiMapTemplateStr = `var ApiMap = map[Endpoint]EndpointInfo{ } ` -const stringFunctionTemplateStr = `func (e Endpoint) String() string { - switch e { -{{- range .}} - case {{.Name}}: - return "{{.Name}}" -{{- end}} - default: - return "" +const restCodeTemplateStr = `var MapWithName = reverseApiMap() + +func reverseApiMap() map[string]Endpoint { + m := make(map[string]Endpoint) + for k, v := range MapWithEndpoint { + m[v.Name] = k } + return m } -` -const getEndpointFunctionTemplateStr = `func GetEndpoint(name string) Endpoint { - switch name { -{{- range .}} - case "{{.Name}}": - return {{.Name}} -{{- end}} - default: - return -1 - } +func (e Endpoint) String() string { + return MapWithEndpoint[e].Name +} + +func GetEndpoint(name string) Endpoint { + return MapWithName[name] } + ` +// +//const stringFunctionTemplateStr = `func (e Endpoint) String() string { +// switch e { +//{{- range .}} +// case {{.Name}}: +// return "{{.Name}}" +//{{- end}} +// default: +// return "" +// } +//} +//` +// +//const getEndpointFunctionTemplateStr = `func GetEndpoint(name string) Endpoint { +// switch name { +//{{- range .}} +// case "{{.Name}}": +// return {{.Name}} +//{{- end}} +// default: +// return -1 +// } +//} +//` + func main() { fset := token.NewFileSet() node, err := parser.ParseFile(fset, endpointFilePath, nil, parser.ParseComments) @@ -157,31 +178,42 @@ func main() { log.Fatalf("failed to execute template: %v", err) } - // contents for stringFunction - stringFunctionTemplate := template.New("stringFunction") - stringFunctionTemplate, err = stringFunctionTemplate.Parse(stringFunctionTemplateStr) + restCodeTemplate := template.New("restCode") + restCodeTemplate, err = restCodeTemplate.Parse(restCodeTemplateStr) if err != nil { log.Fatalf("failed to parse template: %v", err) } - var stringFunctionCode bytes.Buffer - if err := stringFunctionTemplate.Execute(&stringFunctionCode, endpoints); err != nil { - log.Fatalf("failed to execute template: %v", err) - } - - // contents for getEndpointFunction - getEndpointFunctionTemplate := template.New("getEndpointFunction") - getEndpointFunctionTemplate, err = getEndpointFunctionTemplate.Parse(getEndpointFunctionTemplateStr) - if err != nil { - log.Fatalf("failed to parse template: %v", err) - } - var getEndpointFunctionCode bytes.Buffer - if err := getEndpointFunctionTemplate.Execute(&getEndpointFunctionCode, endpoints); err != nil { + var restCode bytes.Buffer + if err := restCodeTemplate.Execute(&restCode, nil); err != nil { log.Fatalf("failed to execute template: %v", err) } + // + //// contents for stringFunction + //stringFunctionTemplate := template.New("stringFunction") + //stringFunctionTemplate, err = stringFunctionTemplate.Parse(stringFunctionTemplateStr) + //if err != nil { + // log.Fatalf("failed to parse template: %v", err) + //} + //var stringFunctionCode bytes.Buffer + //if err := stringFunctionTemplate.Execute(&stringFunctionCode, endpoints); err != nil { + // log.Fatalf("failed to execute template: %v", err) + //} + // + //// contents for getEndpointFunction + //getEndpointFunctionTemplate := template.New("getEndpointFunction") + //getEndpointFunctionTemplate, err = getEndpointFunctionTemplate.Parse(getEndpointFunctionTemplateStr) + //if err != nil { + // log.Fatalf("failed to parse template: %v", err) + //} + //var getEndpointFunctionCode bytes.Buffer + //if err := getEndpointFunctionTemplate.Execute(&getEndpointFunctionCode, endpoints); err != nil { + // log.Fatalf("failed to execute template: %v", err) + //} // replace original file(endpointFilePath) with new contents //contents := indexCode.String() + endpointCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() - contents := indexCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() + //contents := indexCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() + contents := indexCode.String() + apiMapCode.String() + restCode.String() newFilePath := strings.Replace(endpointFilePath, "endpoint", "generated_endpoints.go", 1) if err := ioutil.WriteFile(newFilePath, []byte(contents), 0644); err != nil { diff --git a/internal/model/permission.go b/internal/model/permission.go index 4c395c85..cc9f25e6 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -154,6 +154,7 @@ func newDashboard() *Permission { Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( + api.GetDashboard, api.GetChartsDashboard, api.GetChartDashboard, api.GetStacksDashboard, @@ -165,6 +166,10 @@ func newDashboard() *Permission { Name: "수정", Key: OperationUpdate, IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateDashboard, + api.UpdateDashboard, + ), }, }, }, @@ -191,12 +196,12 @@ func newStack() *Permission { Key: OperationRead, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( + // Stack api.GetStacks, api.GetStack, api.CheckStackName, api.GetStackStatus, api.GetStackKubeConfig, - api.SetFavoriteStack, api.DeleteFavoriteStack, @@ -219,19 +224,14 @@ func newStack() *Permission { Key: OperationCreate, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( + // Stack api.CreateStack, api.InstallStack, - api.CreateAppgroup, // Cluster - api.CreateCluster, - api.ImportCluster, - api.InstallCluster, api.CreateBootstrapKubeconfig, - - // AppGroup - api.CreateAppgroup, - api.CreateApplication, + api.GetBootstrapKubeconfig, + api.GetNodes, ), }, { @@ -249,6 +249,7 @@ func newStack() *Permission { Key: OperationDelete, IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( + // Stack api.DeleteStack, // Cluster @@ -802,6 +803,7 @@ func newConfiguration() *Permission { api.GetUser, api.CheckId, api.CheckEmail, + api.GetPermissionsByAccountId, ), }, { @@ -811,8 +813,6 @@ func newConfiguration() *Permission { IsAllowed: helper.BoolP(false), Endpoints: endpointObjects( api.CreateUser, - api.CheckId, - api.CheckEmail, ), }, { @@ -949,15 +949,9 @@ func newCommon() *Permission { api.VerifyIdentityForLostPassword, api.VerifyToken, - // Stack - api.SetFavoriteStack, - api.DeleteFavoriteStack, - - // Project - api.SetFavoriteProject, - api.SetFavoriteProjectNamespace, - api.UnSetFavoriteProject, - api.UnSetFavoriteProjectNamespace, + // User + api.GetUser, + api.GetPermissionsByAccountId, // MyProfile api.GetMyProfile, @@ -966,9 +960,11 @@ func newCommon() *Permission { api.RenewPasswordExpiredDate, api.DeleteMyProfile, - // StackTemplate - api.GetOrganizationStackTemplates, - api.GetOrganizationStackTemplate, + // Organization + api.GetOrganization, + + // Role + api.GetPermissionsByRoleId, // Utiliy api.CompileRego, From fd8c758ef37bce55a6295eadc578a3594ce39644 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 2 May 2024 14:30:36 +0900 Subject: [PATCH 411/502] change permission endpoint mapping --- internal/database/database.go | 3 +- internal/delivery/api/endpoint.go | 3 + .../delivery/api/endpoints_permission_test.go | 3 +- .../delivery/api/generated_endpoints.go.go | 976 +----------------- internal/delivery/http/endpoint.go | 59 ++ internal/delivery/http/permission.go | 4 +- internal/delivery/http/role.go | 4 - internal/middleware/audit/audit.go | 2 +- .../auth/authorizer/organizationFilter.go | 2 + internal/model/{end-point.go => endpoint.go} | 0 internal/model/permission-endpoint.go | 435 ++++++++ internal/model/permission.go | 522 +++------- internal/repository/permission.go | 5 + internal/route/route.go | 4 + internal/usecase/endpoint.go | 26 + internal/usecase/role.go | 198 +++- internal/usecase/usecase.go | 1 + pkg/domain/endpoint.go | 4 + pkg/domain/permission.go | 12 +- 19 files changed, 898 insertions(+), 1365 deletions(-) create mode 100644 internal/delivery/http/endpoint.go rename internal/model/{end-point.go => endpoint.go} (100%) create mode 100644 internal/model/permission-endpoint.go create mode 100644 internal/usecase/endpoint.go diff --git a/internal/database/database.go b/internal/database/database.go index 9fcb1a37..44f7f095 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -63,6 +63,7 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&model.CacheEmailCode{}, &model.ExpiredTokenTime{}, &model.Role{}, + &model.PermissionEndpoint{}, &model.CloudAccount{}, &model.StackTemplate{}, &model.Organization{}, @@ -131,7 +132,7 @@ func EnsureDefaultRows(db *gorm.DB) error { for _, ep := range eps { storedEps[ep.Name] = struct{}{} } - for _, ep := range api.ApiMap { + for _, ep := range api.MapWithEndpoint { if _, ok := storedEps[ep.Name]; !ok { if err := repoFactory.Endpoint.Create(ctx, &model.Endpoint{ Name: ep.Name, diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 3ec1a0d3..d632c86b 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -220,6 +220,9 @@ const ( // Permission GetPermissionTemplates + // Endpoint + GetEndpoints + // Admin_User Admin_CreateUser Admin_ListUser diff --git a/internal/delivery/api/endpoints_permission_test.go b/internal/delivery/api/endpoints_permission_test.go index b012f456..a4ba98bf 100644 --- a/internal/delivery/api/endpoints_permission_test.go +++ b/internal/delivery/api/endpoints_permission_test.go @@ -8,7 +8,7 @@ import ( func TestEndpointsUsage(t *testing.T) { var allEndpoints []string - for _, v := range api.ApiMap { + for _, v := range api.MapWithEndpoint { allEndpoints = append(allEndpoints, v.Name) } //allEndpoints := []Endpoint{ @@ -26,7 +26,6 @@ func TestEndpointsUsage(t *testing.T) { ps.Stack, ps.Policy, ps.Common, - ps.Admin, } leafPermissions := make([]*model.Permission, 0) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 937cb4d0..799fe4fd 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -2,7 +2,7 @@ package api -var ApiMap = map[Endpoint]EndpointInfo{ +var MapWithEndpoint = map[Endpoint]EndpointInfo{ Login: { Name: "Login", Group: "Auth", @@ -491,16 +491,12 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPolicyNotification", Group: "PolicyNotification", }, - GetStacks: { - Name: "GetStacks", - Group: "Stack", - }, CreateStack: { Name: "CreateStack", Group: "Stack", }, - CheckStackName: { - Name: "CheckStackName", + GetStacks: { + Name: "GetStacks", Group: "Stack", }, GetStack: { @@ -515,14 +511,18 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "DeleteStack", Group: "Stack", }, - GetStackKubeConfig: { - Name: "GetStackKubeConfig", + CheckStackName: { + Name: "CheckStackName", Group: "Stack", }, GetStackStatus: { Name: "GetStackStatus", Group: "Stack", }, + GetStackKubeConfig: { + Name: "GetStackKubeConfig", + Group: "Stack", + }, SetFavoriteStack: { Name: "SetFavoriteStack", Group: "Stack", @@ -691,6 +691,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetPermissionTemplates", Group: "Permission", }, + GetEndpoints: { + Name: "GetEndpoints", + Group: "Endpoint", + }, Admin_CreateUser: { Name: "Admin_CreateUser", Group: "Admin_User", @@ -936,947 +940,21 @@ var ApiMap = map[Endpoint]EndpointInfo{ Group: "Utility", }, } -func (e Endpoint) String() string { - switch e { - case Login: - return "Login" - case Logout: - return "Logout" - case RefreshToken: - return "RefreshToken" - case FindId: - return "FindId" - case FindPassword: - return "FindPassword" - case VerifyIdentityForLostId: - return "VerifyIdentityForLostId" - case VerifyIdentityForLostPassword: - return "VerifyIdentityForLostPassword" - case VerifyToken: - return "VerifyToken" - case CreateUser: - return "CreateUser" - case ListUser: - return "ListUser" - case GetUser: - return "GetUser" - case DeleteUser: - return "DeleteUser" - case UpdateUsers: - return "UpdateUsers" - case UpdateUser: - return "UpdateUser" - case ResetPassword: - return "ResetPassword" - case CheckId: - return "CheckId" - case CheckEmail: - return "CheckEmail" - case GetPermissionsByAccountId: - return "GetPermissionsByAccountId" - case GetMyProfile: - return "GetMyProfile" - case UpdateMyProfile: - return "UpdateMyProfile" - case UpdateMyPassword: - return "UpdateMyPassword" - case RenewPasswordExpiredDate: - return "RenewPasswordExpiredDate" - case DeleteMyProfile: - return "DeleteMyProfile" - case Admin_CreateOrganization: - return "Admin_CreateOrganization" - case Admin_DeleteOrganization: - return "Admin_DeleteOrganization" - case GetOrganizations: - return "GetOrganizations" - case GetOrganization: - return "GetOrganization" - case CheckOrganizationName: - return "CheckOrganizationName" - case UpdateOrganization: - return "UpdateOrganization" - case UpdatePrimaryCluster: - return "UpdatePrimaryCluster" - case CreateCluster: - return "CreateCluster" - case GetClusters: - return "GetClusters" - case ImportCluster: - return "ImportCluster" - case GetCluster: - return "GetCluster" - case DeleteCluster: - return "DeleteCluster" - case GetClusterSiteValues: - return "GetClusterSiteValues" - case InstallCluster: - return "InstallCluster" - case CreateBootstrapKubeconfig: - return "CreateBootstrapKubeconfig" - case GetBootstrapKubeconfig: - return "GetBootstrapKubeconfig" - case GetNodes: - return "GetNodes" - case CreateAppgroup: - return "CreateAppgroup" - case GetAppgroups: - return "GetAppgroups" - case GetAppgroup: - return "GetAppgroup" - case DeleteAppgroup: - return "DeleteAppgroup" - case GetApplications: - return "GetApplications" - case CreateApplication: - return "CreateApplication" - case GetAppServeAppTasksByAppId: - return "GetAppServeAppTasksByAppId" - case GetAppServeAppTaskDetail: - return "GetAppServeAppTaskDetail" - case CreateAppServeApp: - return "CreateAppServeApp" - case GetAppServeApps: - return "GetAppServeApps" - case GetNumOfAppsOnStack: - return "GetNumOfAppsOnStack" - case GetAppServeApp: - return "GetAppServeApp" - case GetAppServeAppLatestTask: - return "GetAppServeAppLatestTask" - case IsAppServeAppExist: - return "IsAppServeAppExist" - case IsAppServeAppNameExist: - return "IsAppServeAppNameExist" - case DeleteAppServeApp: - return "DeleteAppServeApp" - case UpdateAppServeApp: - return "UpdateAppServeApp" - case UpdateAppServeAppStatus: - return "UpdateAppServeAppStatus" - case UpdateAppServeAppEndpoint: - return "UpdateAppServeAppEndpoint" - case RollbackAppServeApp: - return "RollbackAppServeApp" - case GetCloudAccounts: - return "GetCloudAccounts" - case CreateCloudAccount: - return "CreateCloudAccount" - case CheckCloudAccountName: - return "CheckCloudAccountName" - case CheckAwsAccountId: - return "CheckAwsAccountId" - case GetCloudAccount: - return "GetCloudAccount" - case UpdateCloudAccount: - return "UpdateCloudAccount" - case DeleteCloudAccount: - return "DeleteCloudAccount" - case DeleteForceCloudAccount: - return "DeleteForceCloudAccount" - case GetResourceQuota: - return "GetResourceQuota" - case Admin_GetStackTemplates: - return "Admin_GetStackTemplates" - case Admin_GetStackTemplate: - return "Admin_GetStackTemplate" - case Admin_GetStackTemplateServices: - return "Admin_GetStackTemplateServices" - case Admin_GetStackTemplateTemplateIds: - return "Admin_GetStackTemplateTemplateIds" - case Admin_CreateStackTemplate: - return "Admin_CreateStackTemplate" - case Admin_UpdateStackTemplate: - return "Admin_UpdateStackTemplate" - case Admin_DeleteStackTemplate: - return "Admin_DeleteStackTemplate" - case Admin_UpdateStackTemplateOrganizations: - return "Admin_UpdateStackTemplateOrganizations" - case Admin_CheckStackTemplateName: - return "Admin_CheckStackTemplateName" - case GetOrganizationStackTemplates: - return "GetOrganizationStackTemplates" - case GetOrganizationStackTemplate: - return "GetOrganizationStackTemplate" - case AddOrganizationStackTemplates: - return "AddOrganizationStackTemplates" - case RemoveOrganizationStackTemplates: - return "RemoveOrganizationStackTemplates" - case CreateDashboard: - return "CreateDashboard" - case GetDashboard: - return "GetDashboard" - case UpdateDashboard: - return "UpdateDashboard" - case GetChartsDashboard: - return "GetChartsDashboard" - case GetChartDashboard: - return "GetChartDashboard" - case GetStacksDashboard: - return "GetStacksDashboard" - case GetResourcesDashboard: - return "GetResourcesDashboard" - case GetPolicyStatusDashboard: - return "GetPolicyStatusDashboard" - case GetPolicyUpdateDashboard: - return "GetPolicyUpdateDashboard" - case GetPolicyEnforcementDashboard: - return "GetPolicyEnforcementDashboard" - case GetPolicyViolationDashboard: - return "GetPolicyViolationDashboard" - case GetPolicyViolationLogDashboard: - return "GetPolicyViolationLogDashboard" - case GetPolicyStatisticsDashboard: - return "GetPolicyStatisticsDashboard" - case GetWorkloadDashboard: - return "GetWorkloadDashboard" - case GetPolicyViolationTop5Dashboard: - return "GetPolicyViolationTop5Dashboard" - case Admin_CreateSystemNotificationTemplate: - return "Admin_CreateSystemNotificationTemplate" - case Admin_UpdateSystemNotificationTemplate: - return "Admin_UpdateSystemNotificationTemplate" - case Admin_DeleteSystemNotificationTemplate: - return "Admin_DeleteSystemNotificationTemplate" - case Admin_GetSystemNotificationTemplates: - return "Admin_GetSystemNotificationTemplates" - case Admin_GetSystemNotificationTemplate: - return "Admin_GetSystemNotificationTemplate" - case Admin_CheckSystemNotificationTemplateName: - return "Admin_CheckSystemNotificationTemplateName" - case GetOrganizationSystemNotificationTemplates: - return "GetOrganizationSystemNotificationTemplates" - case GetOrganizationSystemNotificationTemplate: - return "GetOrganizationSystemNotificationTemplate" - case AddOrganizationSystemNotificationTemplates: - return "AddOrganizationSystemNotificationTemplates" - case RemoveOrganizationSystemNotificationTemplates: - return "RemoveOrganizationSystemNotificationTemplates" - case CreateSystemNotificationRule: - return "CreateSystemNotificationRule" - case GetSystemNotificationRules: - return "GetSystemNotificationRules" - case GetSystemNotificationRule: - return "GetSystemNotificationRule" - case CheckSystemNotificationRuleName: - return "CheckSystemNotificationRuleName" - case DeleteSystemNotificationRule: - return "DeleteSystemNotificationRule" - case UpdateSystemNotificationRule: - return "UpdateSystemNotificationRule" - case MakeDefaultSystemNotificationRules: - return "MakeDefaultSystemNotificationRules" - case CreateSystemNotification: - return "CreateSystemNotification" - case GetSystemNotifications: - return "GetSystemNotifications" - case GetSystemNotification: - return "GetSystemNotification" - case DeleteSystemNotification: - return "DeleteSystemNotification" - case UpdateSystemNotification: - return "UpdateSystemNotification" - case CreateSystemNotificationAction: - return "CreateSystemNotificationAction" - case GetPolicyNotifications: - return "GetPolicyNotifications" - case GetPolicyNotification: - return "GetPolicyNotification" - case GetStacks: - return "GetStacks" - case CreateStack: - return "CreateStack" - case CheckStackName: - return "CheckStackName" - case GetStack: - return "GetStack" - case UpdateStack: - return "UpdateStack" - case DeleteStack: - return "DeleteStack" - case GetStackKubeConfig: - return "GetStackKubeConfig" - case GetStackStatus: - return "GetStackStatus" - case SetFavoriteStack: - return "SetFavoriteStack" - case DeleteFavoriteStack: - return "DeleteFavoriteStack" - case InstallStack: - return "InstallStack" - case CreateProject: - return "CreateProject" - case GetProjectRoles: - return "GetProjectRoles" - case GetProjectRole: - return "GetProjectRole" - case GetProjects: - return "GetProjects" - case GetProject: - return "GetProject" - case UpdateProject: - return "UpdateProject" - case DeleteProject: - return "DeleteProject" - case AddProjectMember: - return "AddProjectMember" - case GetProjectMember: - return "GetProjectMember" - case GetProjectMembers: - return "GetProjectMembers" - case RemoveProjectMember: - return "RemoveProjectMember" - case UpdateProjectMemberRole: - return "UpdateProjectMemberRole" - case CreateProjectNamespace: - return "CreateProjectNamespace" - case GetProjectNamespaces: - return "GetProjectNamespaces" - case GetProjectNamespace: - return "GetProjectNamespace" - case UpdateProjectNamespace: - return "UpdateProjectNamespace" - case DeleteProjectNamespace: - return "DeleteProjectNamespace" - case SetFavoriteProject: - return "SetFavoriteProject" - case SetFavoriteProjectNamespace: - return "SetFavoriteProjectNamespace" - case UnSetFavoriteProject: - return "UnSetFavoriteProject" - case UnSetFavoriteProjectNamespace: - return "UnSetFavoriteProjectNamespace" - case GetProjectKubeconfig: - return "GetProjectKubeconfig" - case GetProjectNamespaceK8sResources: - return "GetProjectNamespaceK8sResources" - case GetProjectNamespaceKubeconfig: - return "GetProjectNamespaceKubeconfig" - case GetAudits: - return "GetAudits" - case GetAudit: - return "GetAudit" - case DeleteAudit: - return "DeleteAudit" - case CreateTksRole: - return "CreateTksRole" - case ListTksRoles: - return "ListTksRoles" - case GetTksRole: - return "GetTksRole" - case DeleteTksRole: - return "DeleteTksRole" - case UpdateTksRole: - return "UpdateTksRole" - case GetPermissionsByRoleId: - return "GetPermissionsByRoleId" - case UpdatePermissionsByRoleId: - return "UpdatePermissionsByRoleId" - case IsRoleNameExisted: - return "IsRoleNameExisted" - case AppendUsersToRole: - return "AppendUsersToRole" - case GetUsersInRoleId: - return "GetUsersInRoleId" - case RemoveUsersFromRole: - return "RemoveUsersFromRole" - case GetPermissionTemplates: - return "GetPermissionTemplates" - case Admin_CreateUser: - return "Admin_CreateUser" - case Admin_ListUser: - return "Admin_ListUser" - case Admin_GetUser: - return "Admin_GetUser" - case Admin_DeleteUser: - return "Admin_DeleteUser" - case Admin_UpdateUser: - return "Admin_UpdateUser" - case Admin_ListTksRoles: - return "Admin_ListTksRoles" - case Admin_GetTksRole: - return "Admin_GetTksRole" - case Admin_GetProjects: - return "Admin_GetProjects" - case Admin_ListPolicyTemplate: - return "Admin_ListPolicyTemplate" - case Admin_CreatePolicyTemplate: - return "Admin_CreatePolicyTemplate" - case Admin_DeletePolicyTemplate: - return "Admin_DeletePolicyTemplate" - case Admin_GetPolicyTemplate: - return "Admin_GetPolicyTemplate" - case Admin_UpdatePolicyTemplate: - return "Admin_UpdatePolicyTemplate" - case Admin_GetPolicyTemplateDeploy: - return "Admin_GetPolicyTemplateDeploy" - case Admin_ListPolicyTemplateStatistics: - return "Admin_ListPolicyTemplateStatistics" - case Admin_ListPolicyTemplateVersions: - return "Admin_ListPolicyTemplateVersions" - case Admin_CreatePolicyTemplateVersion: - return "Admin_CreatePolicyTemplateVersion" - case Admin_DeletePolicyTemplateVersion: - return "Admin_DeletePolicyTemplateVersion" - case Admin_GetPolicyTemplateVersion: - return "Admin_GetPolicyTemplateVersion" - case Admin_ExistsPolicyTemplateKind: - return "Admin_ExistsPolicyTemplateKind" - case Admin_ExistsPolicyTemplateName: - return "Admin_ExistsPolicyTemplateName" - case Admin_ExtractParameters: - return "Admin_ExtractParameters" - case Admin_AddPermittedPolicyTemplatesForOrganization: - return "Admin_AddPermittedPolicyTemplatesForOrganization" - case Admin_DeletePermittedPolicyTemplatesForOrganization: - return "Admin_DeletePermittedPolicyTemplatesForOrganization" - case ListStackPolicyStatus: - return "ListStackPolicyStatus" - case GetStackPolicyTemplateStatus: - return "GetStackPolicyTemplateStatus" - case UpdateStackPolicyTemplateStatus: - return "UpdateStackPolicyTemplateStatus" - case GetMandatoryPolicies: - return "GetMandatoryPolicies" - case SetMandatoryPolicies: - return "SetMandatoryPolicies" - case GetPolicyStatistics: - return "GetPolicyStatistics" - case ListPolicy: - return "ListPolicy" - case CreatePolicy: - return "CreatePolicy" - case DeletePolicy: - return "DeletePolicy" - case GetPolicy: - return "GetPolicy" - case UpdatePolicy: - return "UpdatePolicy" - case UpdatePolicyTargetClusters: - return "UpdatePolicyTargetClusters" - case ExistsPolicyName: - return "ExistsPolicyName" - case ExistsPolicyResourceName: - return "ExistsPolicyResourceName" - case GetPolicyEdit: - return "GetPolicyEdit" - case AddPoliciesForStack: - return "AddPoliciesForStack" - case DeletePoliciesForStack: - return "DeletePoliciesForStack" - case StackPolicyStatistics: - return "StackPolicyStatistics" - case ListPolicyTemplate: - return "ListPolicyTemplate" - case CreatePolicyTemplate: - return "CreatePolicyTemplate" - case DeletePolicyTemplate: - return "DeletePolicyTemplate" - case GetPolicyTemplate: - return "GetPolicyTemplate" - case UpdatePolicyTemplate: - return "UpdatePolicyTemplate" - case GetPolicyTemplateDeploy: - return "GetPolicyTemplateDeploy" - case ListPolicyTemplateStatistics: - return "ListPolicyTemplateStatistics" - case ListPolicyTemplateVersions: - return "ListPolicyTemplateVersions" - case CreatePolicyTemplateVersion: - return "CreatePolicyTemplateVersion" - case DeletePolicyTemplateVersion: - return "DeletePolicyTemplateVersion" - case GetPolicyTemplateVersion: - return "GetPolicyTemplateVersion" - case ExistsPolicyTemplateKind: - return "ExistsPolicyTemplateKind" - case ExistsPolicyTemplateName: - return "ExistsPolicyTemplateName" - case ExtractParameters: - return "ExtractParameters" - case ListPolicyTemplateExample: - return "ListPolicyTemplateExample" - case GetPolicyTemplateExample: - return "GetPolicyTemplateExample" - case UpdatePolicyTemplateExample: - return "UpdatePolicyTemplateExample" - case DeletePolicyTemplateExample: - return "DeletePolicyTemplateExample" - case CompileRego: - return "CompileRego" - default: - return "" +var MapWithName = reverseApiMap() + +func reverseApiMap() map[string]Endpoint { + m := make(map[string]Endpoint) + for k, v := range MapWithEndpoint { + m[v.Name] = k } + return m } + +func (e Endpoint) String() string { + return MapWithEndpoint[e].Name +} + func GetEndpoint(name string) Endpoint { - switch name { - case "Login": - return Login - case "Logout": - return Logout - case "RefreshToken": - return RefreshToken - case "FindId": - return FindId - case "FindPassword": - return FindPassword - case "VerifyIdentityForLostId": - return VerifyIdentityForLostId - case "VerifyIdentityForLostPassword": - return VerifyIdentityForLostPassword - case "VerifyToken": - return VerifyToken - case "CreateUser": - return CreateUser - case "ListUser": - return ListUser - case "GetUser": - return GetUser - case "DeleteUser": - return DeleteUser - case "UpdateUsers": - return UpdateUsers - case "UpdateUser": - return UpdateUser - case "ResetPassword": - return ResetPassword - case "CheckId": - return CheckId - case "CheckEmail": - return CheckEmail - case "GetPermissionsByAccountId": - return GetPermissionsByAccountId - case "GetMyProfile": - return GetMyProfile - case "UpdateMyProfile": - return UpdateMyProfile - case "UpdateMyPassword": - return UpdateMyPassword - case "RenewPasswordExpiredDate": - return RenewPasswordExpiredDate - case "DeleteMyProfile": - return DeleteMyProfile - case "Admin_CreateOrganization": - return Admin_CreateOrganization - case "Admin_DeleteOrganization": - return Admin_DeleteOrganization - case "GetOrganizations": - return GetOrganizations - case "GetOrganization": - return GetOrganization - case "CheckOrganizationName": - return CheckOrganizationName - case "UpdateOrganization": - return UpdateOrganization - case "UpdatePrimaryCluster": - return UpdatePrimaryCluster - case "CreateCluster": - return CreateCluster - case "GetClusters": - return GetClusters - case "ImportCluster": - return ImportCluster - case "GetCluster": - return GetCluster - case "DeleteCluster": - return DeleteCluster - case "GetClusterSiteValues": - return GetClusterSiteValues - case "InstallCluster": - return InstallCluster - case "CreateBootstrapKubeconfig": - return CreateBootstrapKubeconfig - case "GetBootstrapKubeconfig": - return GetBootstrapKubeconfig - case "GetNodes": - return GetNodes - case "CreateAppgroup": - return CreateAppgroup - case "GetAppgroups": - return GetAppgroups - case "GetAppgroup": - return GetAppgroup - case "DeleteAppgroup": - return DeleteAppgroup - case "GetApplications": - return GetApplications - case "CreateApplication": - return CreateApplication - case "GetAppServeAppTasksByAppId": - return GetAppServeAppTasksByAppId - case "GetAppServeAppTaskDetail": - return GetAppServeAppTaskDetail - case "CreateAppServeApp": - return CreateAppServeApp - case "GetAppServeApps": - return GetAppServeApps - case "GetNumOfAppsOnStack": - return GetNumOfAppsOnStack - case "GetAppServeApp": - return GetAppServeApp - case "GetAppServeAppLatestTask": - return GetAppServeAppLatestTask - case "IsAppServeAppExist": - return IsAppServeAppExist - case "IsAppServeAppNameExist": - return IsAppServeAppNameExist - case "DeleteAppServeApp": - return DeleteAppServeApp - case "UpdateAppServeApp": - return UpdateAppServeApp - case "UpdateAppServeAppStatus": - return UpdateAppServeAppStatus - case "UpdateAppServeAppEndpoint": - return UpdateAppServeAppEndpoint - case "RollbackAppServeApp": - return RollbackAppServeApp - case "GetCloudAccounts": - return GetCloudAccounts - case "CreateCloudAccount": - return CreateCloudAccount - case "CheckCloudAccountName": - return CheckCloudAccountName - case "CheckAwsAccountId": - return CheckAwsAccountId - case "GetCloudAccount": - return GetCloudAccount - case "UpdateCloudAccount": - return UpdateCloudAccount - case "DeleteCloudAccount": - return DeleteCloudAccount - case "DeleteForceCloudAccount": - return DeleteForceCloudAccount - case "GetResourceQuota": - return GetResourceQuota - case "Admin_GetStackTemplates": - return Admin_GetStackTemplates - case "Admin_GetStackTemplate": - return Admin_GetStackTemplate - case "Admin_GetStackTemplateServices": - return Admin_GetStackTemplateServices - case "Admin_GetStackTemplateTemplateIds": - return Admin_GetStackTemplateTemplateIds - case "Admin_CreateStackTemplate": - return Admin_CreateStackTemplate - case "Admin_UpdateStackTemplate": - return Admin_UpdateStackTemplate - case "Admin_DeleteStackTemplate": - return Admin_DeleteStackTemplate - case "Admin_UpdateStackTemplateOrganizations": - return Admin_UpdateStackTemplateOrganizations - case "Admin_CheckStackTemplateName": - return Admin_CheckStackTemplateName - case "GetOrganizationStackTemplates": - return GetOrganizationStackTemplates - case "GetOrganizationStackTemplate": - return GetOrganizationStackTemplate - case "AddOrganizationStackTemplates": - return AddOrganizationStackTemplates - case "RemoveOrganizationStackTemplates": - return RemoveOrganizationStackTemplates - case "CreateDashboard": - return CreateDashboard - case "GetDashboard": - return GetDashboard - case "UpdateDashboard": - return UpdateDashboard - case "GetChartsDashboard": - return GetChartsDashboard - case "GetChartDashboard": - return GetChartDashboard - case "GetStacksDashboard": - return GetStacksDashboard - case "GetResourcesDashboard": - return GetResourcesDashboard - case "GetPolicyStatusDashboard": - return GetPolicyStatusDashboard - case "GetPolicyUpdateDashboard": - return GetPolicyUpdateDashboard - case "GetPolicyEnforcementDashboard": - return GetPolicyEnforcementDashboard - case "GetPolicyViolationDashboard": - return GetPolicyViolationDashboard - case "GetPolicyViolationLogDashboard": - return GetPolicyViolationLogDashboard - case "GetPolicyStatisticsDashboard": - return GetPolicyStatisticsDashboard - case "GetWorkloadDashboard": - return GetWorkloadDashboard - case "GetPolicyViolationTop5Dashboard": - return GetPolicyViolationTop5Dashboard - case "Admin_CreateSystemNotificationTemplate": - return Admin_CreateSystemNotificationTemplate - case "Admin_UpdateSystemNotificationTemplate": - return Admin_UpdateSystemNotificationTemplate - case "Admin_DeleteSystemNotificationTemplate": - return Admin_DeleteSystemNotificationTemplate - case "Admin_GetSystemNotificationTemplates": - return Admin_GetSystemNotificationTemplates - case "Admin_GetSystemNotificationTemplate": - return Admin_GetSystemNotificationTemplate - case "Admin_CheckSystemNotificationTemplateName": - return Admin_CheckSystemNotificationTemplateName - case "GetOrganizationSystemNotificationTemplates": - return GetOrganizationSystemNotificationTemplates - case "GetOrganizationSystemNotificationTemplate": - return GetOrganizationSystemNotificationTemplate - case "AddOrganizationSystemNotificationTemplates": - return AddOrganizationSystemNotificationTemplates - case "RemoveOrganizationSystemNotificationTemplates": - return RemoveOrganizationSystemNotificationTemplates - case "CreateSystemNotificationRule": - return CreateSystemNotificationRule - case "GetSystemNotificationRules": - return GetSystemNotificationRules - case "GetSystemNotificationRule": - return GetSystemNotificationRule - case "CheckSystemNotificationRuleName": - return CheckSystemNotificationRuleName - case "DeleteSystemNotificationRule": - return DeleteSystemNotificationRule - case "UpdateSystemNotificationRule": - return UpdateSystemNotificationRule - case "MakeDefaultSystemNotificationRules": - return MakeDefaultSystemNotificationRules - case "CreateSystemNotification": - return CreateSystemNotification - case "GetSystemNotifications": - return GetSystemNotifications - case "GetSystemNotification": - return GetSystemNotification - case "DeleteSystemNotification": - return DeleteSystemNotification - case "UpdateSystemNotification": - return UpdateSystemNotification - case "CreateSystemNotificationAction": - return CreateSystemNotificationAction - case "GetPolicyNotifications": - return GetPolicyNotifications - case "GetPolicyNotification": - return GetPolicyNotification - case "GetStacks": - return GetStacks - case "CreateStack": - return CreateStack - case "CheckStackName": - return CheckStackName - case "GetStack": - return GetStack - case "UpdateStack": - return UpdateStack - case "DeleteStack": - return DeleteStack - case "GetStackKubeConfig": - return GetStackKubeConfig - case "GetStackStatus": - return GetStackStatus - case "SetFavoriteStack": - return SetFavoriteStack - case "DeleteFavoriteStack": - return DeleteFavoriteStack - case "InstallStack": - return InstallStack - case "CreateProject": - return CreateProject - case "GetProjectRoles": - return GetProjectRoles - case "GetProjectRole": - return GetProjectRole - case "GetProjects": - return GetProjects - case "GetProject": - return GetProject - case "UpdateProject": - return UpdateProject - case "DeleteProject": - return DeleteProject - case "AddProjectMember": - return AddProjectMember - case "GetProjectMember": - return GetProjectMember - case "GetProjectMembers": - return GetProjectMembers - case "RemoveProjectMember": - return RemoveProjectMember - case "UpdateProjectMemberRole": - return UpdateProjectMemberRole - case "CreateProjectNamespace": - return CreateProjectNamespace - case "GetProjectNamespaces": - return GetProjectNamespaces - case "GetProjectNamespace": - return GetProjectNamespace - case "UpdateProjectNamespace": - return UpdateProjectNamespace - case "DeleteProjectNamespace": - return DeleteProjectNamespace - case "SetFavoriteProject": - return SetFavoriteProject - case "SetFavoriteProjectNamespace": - return SetFavoriteProjectNamespace - case "UnSetFavoriteProject": - return UnSetFavoriteProject - case "UnSetFavoriteProjectNamespace": - return UnSetFavoriteProjectNamespace - case "GetProjectKubeconfig": - return GetProjectKubeconfig - case "GetProjectNamespaceK8sResources": - return GetProjectNamespaceK8sResources - case "GetProjectNamespaceKubeconfig": - return GetProjectNamespaceKubeconfig - case "GetAudits": - return GetAudits - case "GetAudit": - return GetAudit - case "DeleteAudit": - return DeleteAudit - case "CreateTksRole": - return CreateTksRole - case "ListTksRoles": - return ListTksRoles - case "GetTksRole": - return GetTksRole - case "DeleteTksRole": - return DeleteTksRole - case "UpdateTksRole": - return UpdateTksRole - case "GetPermissionsByRoleId": - return GetPermissionsByRoleId - case "UpdatePermissionsByRoleId": - return UpdatePermissionsByRoleId - case "IsRoleNameExisted": - return IsRoleNameExisted - case "AppendUsersToRole": - return AppendUsersToRole - case "GetUsersInRoleId": - return GetUsersInRoleId - case "RemoveUsersFromRole": - return RemoveUsersFromRole - case "GetPermissionTemplates": - return GetPermissionTemplates - case "Admin_CreateUser": - return Admin_CreateUser - case "Admin_ListUser": - return Admin_ListUser - case "Admin_GetUser": - return Admin_GetUser - case "Admin_DeleteUser": - return Admin_DeleteUser - case "Admin_UpdateUser": - return Admin_UpdateUser - case "Admin_ListTksRoles": - return Admin_ListTksRoles - case "Admin_GetTksRole": - return Admin_GetTksRole - case "Admin_GetProjects": - return Admin_GetProjects - case "Admin_ListPolicyTemplate": - return Admin_ListPolicyTemplate - case "Admin_CreatePolicyTemplate": - return Admin_CreatePolicyTemplate - case "Admin_DeletePolicyTemplate": - return Admin_DeletePolicyTemplate - case "Admin_GetPolicyTemplate": - return Admin_GetPolicyTemplate - case "Admin_UpdatePolicyTemplate": - return Admin_UpdatePolicyTemplate - case "Admin_GetPolicyTemplateDeploy": - return Admin_GetPolicyTemplateDeploy - case "Admin_ListPolicyTemplateStatistics": - return Admin_ListPolicyTemplateStatistics - case "Admin_ListPolicyTemplateVersions": - return Admin_ListPolicyTemplateVersions - case "Admin_CreatePolicyTemplateVersion": - return Admin_CreatePolicyTemplateVersion - case "Admin_DeletePolicyTemplateVersion": - return Admin_DeletePolicyTemplateVersion - case "Admin_GetPolicyTemplateVersion": - return Admin_GetPolicyTemplateVersion - case "Admin_ExistsPolicyTemplateKind": - return Admin_ExistsPolicyTemplateKind - case "Admin_ExistsPolicyTemplateName": - return Admin_ExistsPolicyTemplateName - case "Admin_ExtractParameters": - return Admin_ExtractParameters - case "Admin_AddPermittedPolicyTemplatesForOrganization": - return Admin_AddPermittedPolicyTemplatesForOrganization - case "Admin_DeletePermittedPolicyTemplatesForOrganization": - return Admin_DeletePermittedPolicyTemplatesForOrganization - case "ListStackPolicyStatus": - return ListStackPolicyStatus - case "GetStackPolicyTemplateStatus": - return GetStackPolicyTemplateStatus - case "UpdateStackPolicyTemplateStatus": - return UpdateStackPolicyTemplateStatus - case "GetMandatoryPolicies": - return GetMandatoryPolicies - case "SetMandatoryPolicies": - return SetMandatoryPolicies - case "GetPolicyStatistics": - return GetPolicyStatistics - case "ListPolicy": - return ListPolicy - case "CreatePolicy": - return CreatePolicy - case "DeletePolicy": - return DeletePolicy - case "GetPolicy": - return GetPolicy - case "UpdatePolicy": - return UpdatePolicy - case "UpdatePolicyTargetClusters": - return UpdatePolicyTargetClusters - case "ExistsPolicyName": - return ExistsPolicyName - case "ExistsPolicyResourceName": - return ExistsPolicyResourceName - case "GetPolicyEdit": - return GetPolicyEdit - case "AddPoliciesForStack": - return AddPoliciesForStack - case "DeletePoliciesForStack": - return DeletePoliciesForStack - case "StackPolicyStatistics": - return StackPolicyStatistics - case "ListPolicyTemplate": - return ListPolicyTemplate - case "CreatePolicyTemplate": - return CreatePolicyTemplate - case "DeletePolicyTemplate": - return DeletePolicyTemplate - case "GetPolicyTemplate": - return GetPolicyTemplate - case "UpdatePolicyTemplate": - return UpdatePolicyTemplate - case "GetPolicyTemplateDeploy": - return GetPolicyTemplateDeploy - case "ListPolicyTemplateStatistics": - return ListPolicyTemplateStatistics - case "ListPolicyTemplateVersions": - return ListPolicyTemplateVersions - case "CreatePolicyTemplateVersion": - return CreatePolicyTemplateVersion - case "DeletePolicyTemplateVersion": - return DeletePolicyTemplateVersion - case "GetPolicyTemplateVersion": - return GetPolicyTemplateVersion - case "ExistsPolicyTemplateKind": - return ExistsPolicyTemplateKind - case "ExistsPolicyTemplateName": - return ExistsPolicyTemplateName - case "ExtractParameters": - return ExtractParameters - case "ListPolicyTemplateExample": - return ListPolicyTemplateExample - case "GetPolicyTemplateExample": - return GetPolicyTemplateExample - case "UpdatePolicyTemplateExample": - return UpdatePolicyTemplateExample - case "DeletePolicyTemplateExample": - return DeletePolicyTemplateExample - case "CompileRego": - return CompileRego - default: - return -1 - } + return MapWithName[name] } + diff --git a/internal/delivery/http/endpoint.go b/internal/delivery/http/endpoint.go new file mode 100644 index 00000000..34a90b74 --- /dev/null +++ b/internal/delivery/http/endpoint.go @@ -0,0 +1,59 @@ +package http + +import ( + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/usecase" + "github.com/openinfradev/tks-api/pkg/domain" + "net/http" +) + +type IEndpointHandler interface { + ListEndpoint(w http.ResponseWriter, r *http.Request) +} + +type EndpointHandler struct { + endpointUsecase usecase.IEndpointUsecase +} + +func NewEndpointHandler(usecase usecase.Usecase) *EndpointHandler { + return &EndpointHandler{ + endpointUsecase: usecase.Endpoint, + } +} + +// ListEndpoint godoc +// +// @Tags Endpoint +// @Summary List Endpoints +// @Description List Endpoints +// @Accept json +// @Produce json +// @Success 200 {object} domain.ListEndpointResponse +// @Router /admin/endpoints [get] +// @Security JWT +func (h EndpointHandler) ListEndpoint(w http.ResponseWriter, r *http.Request) { + urlParams := r.URL.Query() + pg := pagination.NewPagination(&urlParams) + + endpoints, err := h.endpointUsecase.ListEndpoints(r.Context(), pg) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + var out domain.ListEndpointResponse + + for _, endpoint := range endpoints { + out.Endpoints = append(out.Endpoints, convertEndpointToDomain(endpoint)) + } + + ResponseJSON(w, r, http.StatusOK, out) +} + +func convertEndpointToDomain(endpoint *model.Endpoint) domain.EndpointResponse { + return domain.EndpointResponse{ + Name: endpoint.Name, + Group: endpoint.Group, + } +} diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index 3ad7798f..f2771fae 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -56,9 +56,7 @@ func convertModelToPermissionTemplateResponse(ctx context.Context, permission *m permissionResponse.Key = permission.Key permissionResponse.Name = permission.Name - if permission.IsAllowed != nil { - permissionResponse.IsAllowed = permission.IsAllowed - } + permissionResponse.EdgeKey = permission.EdgeKey for _, child := range permission.Children { permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionTemplateResponse(ctx, child)) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 1ff872be..1883e6f7 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -348,10 +348,6 @@ func convertModelToPermissionResponse(ctx context.Context, permission *model.Per permissionResponse.ID = &permission.ID } - for _, endpoint := range permission.Endpoints { - permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint)) - } - for _, child := range permission.Children { permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child)) } diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 189232ec..74f4717f 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -78,7 +78,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han dto := model.Audit{ OrganizationId: organizationId, OrganizationName: u.Organization.Name, - Group: internalApi.ApiMap[endpoint].Group, + Group: internalApi.MapWithEndpoint[endpoint].Group, Message: message, Description: description, ClientIP: GetClientIpAddress(w, r), diff --git a/internal/middleware/auth/authorizer/organizationFilter.go b/internal/middleware/auth/authorizer/organizationFilter.go index bcd9f925..86e8715a 100644 --- a/internal/middleware/auth/authorizer/organizationFilter.go +++ b/internal/middleware/auth/authorizer/organizationFilter.go @@ -29,11 +29,13 @@ func OrganizationFilter(handler http.Handler, repo repository.Repository) http.H if !ok { log.Warn(r.Context(), "OrganizationFilter: organizationId not found. Passing through unsafely.") handler.ServeHTTP(w, r) + return } if requestedOrganization != requestUserInfo.GetOrganizationId() { log.Debugf(r.Context(), "OrganizationFilter: requestedOrganization: %s, userOrganization: %s", requestedOrganization, requestUserInfo.GetOrganizationId()) internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return } handler.ServeHTTP(w, r) diff --git a/internal/model/end-point.go b/internal/model/endpoint.go similarity index 100% rename from internal/model/end-point.go rename to internal/model/endpoint.go diff --git a/internal/model/permission-endpoint.go b/internal/model/permission-endpoint.go new file mode 100644 index 00000000..b7fe0653 --- /dev/null +++ b/internal/model/permission-endpoint.go @@ -0,0 +1,435 @@ +package model + +import ( + "github.com/openinfradev/tks-api/internal/delivery/api" + "gorm.io/gorm" + "sort" +) + +type PermissionEndpoint struct { + EdgeKey string `gorm:"primaryKey;type:text;"` + EndpointName string `gorm:"primaryKey;type:text;"` + + Permission Permission `gorm:"foreignKey:EdgeKey;references:EdgeKey"` + Endpoint Endpoint `gorm:"foreignKey:EndpointName;references:Name"` +} + +var ( + // map[EdgeKey][]Endpoints + edgeKeyEndpointMap = map[string][]Endpoint{ + TopDashboardKey + "-" + MiddleDashboardKey + "-" + OperationRead: endpointObjects( + api.GetDashboard, + api.GetChartsDashboard, + api.GetChartDashboard, + api.GetStacksDashboard, + api.GetResourcesDashboard, + ), + TopDashboardKey + "-" + MiddleDashboardKey + "-" + OperationUpdate: endpointObjects( + api.CreateDashboard, + api.UpdateDashboard, + ), + + TopStackKey + "-" + MiddleStackKey + "-" + OperationRead: endpointObjects( + api.GetStacks, + api.GetStack, + api.CheckStackName, + api.GetStackStatus, + api.GetStackKubeConfig, + api.SetFavoriteStack, + api.DeleteFavoriteStack, + + // Cluster + api.GetCluster, + api.GetClusters, + api.GetClusterSiteValues, + api.GetBootstrapKubeconfig, + api.GetNodes, + + // AppGroup + api.GetAppgroups, + api.GetAppgroup, + api.GetApplications, + ), + + TopStackKey + "-" + MiddleStackKey + "-" + OperationCreate: endpointObjects( + api.CreateStack, + api.InstallStack, + + // Cluster + api.CreateBootstrapKubeconfig, + api.GetBootstrapKubeconfig, + api.GetNodes, + ), + TopStackKey + "-" + MiddleStackKey + "-" + OperationUpdate: endpointObjects( + api.UpdateStack, + ), + TopStackKey + "-" + MiddleStackKey + "-" + OperationDelete: endpointObjects( + // Stack + api.DeleteStack, + + // Cluster + api.DeleteCluster, + + // AppGroup + api.DeleteAppgroup, + ), + TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationRead: endpointObjects( + // PolicyTemplate + api.Admin_ListPolicyTemplate, + api.Admin_GetPolicyTemplate, + api.Admin_GetPolicyTemplateDeploy, + api.Admin_ListPolicyTemplateStatistics, + api.Admin_ListPolicyTemplateVersions, + api.Admin_GetPolicyTemplateVersion, + api.Admin_ExistsPolicyTemplateName, + api.Admin_ExistsPolicyTemplateKind, + + // StackPolicyStatus + api.ListStackPolicyStatus, + api.GetStackPolicyTemplateStatus, + + // Policy + api.GetMandatoryPolicies, + api.ListPolicy, + api.GetPolicy, + api.ExistsPolicyName, + + // OrganizationPolicyTemplate + api.ListPolicyTemplate, + api.GetPolicyTemplate, + api.GetPolicyTemplateDeploy, + api.ListPolicyTemplateStatistics, + api.ListPolicyTemplateVersions, + api.GetPolicyTemplateVersion, + api.ExistsPolicyTemplateKind, + api.ExistsPolicyTemplateName, + + // PolicyTemplateExample + api.ListPolicyTemplateExample, + api.GetPolicyTemplateExample, + ), + TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationCreate: endpointObjects( + // PolicyTemplate + api.Admin_CreatePolicyTemplate, + api.Admin_CreatePolicyTemplateVersion, + + // Policy + api.SetMandatoryPolicies, + api.CreatePolicy, + + // OrganizationPolicyTemplate + api.CreatePolicyTemplate, + api.CreatePolicyTemplateVersion, + ), + TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationUpdate: endpointObjects( + // PolicyTemplate + api.Admin_UpdatePolicyTemplate, + + // ClusterPolicyStatus + api.UpdateStackPolicyTemplateStatus, + + // Policy + api.UpdatePolicy, + api.UpdatePolicyTargetClusters, + + // OrganizationPolicyTemplate + api.UpdatePolicyTemplate, + + // PolicyTemplateExample + api.UpdatePolicyTemplateExample, + ), + + TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationDelete: endpointObjects( + api.Admin_DeletePolicyTemplate, + api.Admin_DeletePolicyTemplateVersion, + + // Policy + api.DeletePolicy, + + // OrganizationPolicyTemplate + api.DeletePolicyTemplate, + api.DeletePolicyTemplateVersion, + + // PolicyTemplateExample + api.DeletePolicyTemplateExample, + ), + TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationRead: endpointObjects( + api.GetSystemNotification, + api.GetSystemNotifications, + ), + TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationUpdate: endpointObjects( + api.UpdateSystemNotification, + api.CreateSystemNotificationAction, + ), + TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationDownload: endpointObjects(), + + TopProjectKey + "-" + MiddleProjectKey + "-" + OperationRead: endpointObjects( + api.GetProjects, + api.GetProject, + api.GetProjectKubeconfig, + ), + TopProjectKey + "-" + MiddleProjectKey + "-" + OperationCreate: endpointObjects( + api.CreateProject, + ), TopProjectKey + "-" + MiddleProjectKey + "-" + OperationUpdate: endpointObjects( + api.UpdateProject, + ), + TopProjectKey + "-" + MiddleProjectKey + "-" + OperationDelete: endpointObjects( + api.DeleteProject, + ), + TopProjectKey + "-" + MiddleProjectCommonConfigurationKey + "-" + OperationRead: endpointObjects( + api.GetProjects, + api.GetProject, + + api.GetProjectRoles, + api.GetProjectRole, + ), + TopProjectKey + "-" + MiddleProjectCommonConfigurationKey + "-" + OperationUpdate: endpointObjects( + api.UpdateProject, + ), + TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationRead: endpointObjects( + api.GetProjectMembers, + api.GetProjectMember, + api.GetProjectRoles, + api.GetProjectRole, + ), + TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationCreate: endpointObjects( + api.AddProjectMember, + ), + TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationUpdate: endpointObjects( + api.UpdateProjectMemberRole, + ), + TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationDelete: endpointObjects( + api.RemoveProjectMember, + ), + TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationRead: endpointObjects( + api.GetProjectNamespaces, + api.GetProjectNamespace, + api.GetProjectNamespaceK8sResources, + ), + TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationCreate: endpointObjects( + api.CreateProjectNamespace, + ), + TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationUpdate: endpointObjects( + api.UpdateProjectNamespace, + ), + TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationDelete: endpointObjects( + api.DeleteProjectNamespace, + ), + TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationRead: endpointObjects( + api.GetAppServeApps, + api.GetAppServeApp, + api.GetNumOfAppsOnStack, + api.GetAppServeAppLatestTask, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.GetAppServeAppTaskDetail, + api.GetAppServeAppTasksByAppId, + ), + TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationCreate: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationUpdate: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), + TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationDelete: endpointObjects( + api.DeleteAppServeApp, + ), + TopConfigurationKey + "-" + MiddleConfigurationKey + "-" + OperationRead: endpointObjects(), + TopConfigurationKey + "-" + MiddleConfigurationKey + "-" + OperationUpdate: endpointObjects(), + TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationRead: endpointObjects( + api.GetCloudAccounts, + api.GetCloudAccount, + api.CheckCloudAccountName, + api.CheckAwsAccountId, + api.GetResourceQuota, + ), + TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationCreate: endpointObjects( + api.CreateCloudAccount, + ), + TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationUpdate: endpointObjects( + api.UpdateCloudAccount, + ), + TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationDelete: endpointObjects( + api.DeleteCloudAccount, + api.DeleteForceCloudAccount, + ), + TopConfigurationKey + "-" + MiddleConfigurationProjectKey + "-" + OperationRead: endpointObjects(), + TopConfigurationKey + "-" + MiddleConfigurationProjectKey + "-" + OperationCreate: endpointObjects(), + TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationRead: endpointObjects( + api.ListUser, + api.GetUser, + api.CheckId, + api.CheckEmail, + api.GetPermissionsByAccountId, + ), + TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationCreate: endpointObjects( + api.CreateUser, + ), + TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationUpdate: endpointObjects( + api.UpdateUser, + api.ResetPassword, + ), + TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationDelete: endpointObjects( + api.DeleteUser, + ), + TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationRead: endpointObjects( + api.ListTksRoles, + api.GetTksRole, + api.GetPermissionsByRoleId, + api.GetPermissionTemplates, + ), + TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationCreate: endpointObjects( + api.CreateTksRole, + ), + TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationUpdate: endpointObjects( + api.UpdateTksRole, + api.UpdatePermissionsByRoleId, + ), + TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationDelete: endpointObjects( + api.DeleteTksRole, + ), + TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationRead: endpointObjects( + api.GetSystemNotificationRules, + api.GetSystemNotificationRule, + ), + TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationCreate: endpointObjects( + api.CreateSystemNotificationRule, + ), + TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationUpdate: endpointObjects( + api.UpdateSystemNotificationRule, + ), + TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationDelete: endpointObjects( + api.DeleteSystemNotificationRule, + ), + CommonKey: endpointObjects( + // Auth + api.Login, + api.Logout, + api.RefreshToken, + api.FindId, + api.FindPassword, + api.VerifyIdentityForLostId, + api.VerifyIdentityForLostPassword, + api.VerifyToken, + + // User + api.GetUser, + api.GetPermissionsByAccountId, + + // MyProfile + api.GetMyProfile, + api.UpdateMyProfile, + api.UpdateMyPassword, + api.RenewPasswordExpiredDate, + api.DeleteMyProfile, + + // Organization + api.GetOrganization, + + // Role + api.GetPermissionsByRoleId, + + // Utiliy + api.CompileRego, + ), + } +) + +// ForceSyncToLatestPermissionEndpointMapping is used to sync the permission endpoint mapping to the latest version. +func ForceSyncToLatestPermissionEndpointMapping(db *gorm.DB, permissionSet *PermissionSet) error { + var storedPermissionEndpoints []PermissionEndpoint + var storedEdgeKeyEndpointMaps = make(map[string][]Endpoint) + if err := db.Find(&storedPermissionEndpoints).Error; err != nil { + return err + } + for _, pe := range storedPermissionEndpoints { + storedEdgeKeyEndpointMaps[pe.EdgeKey] = append(storedEdgeKeyEndpointMaps[pe.EdgeKey], pe.Endpoint) + } + + var shouldInsertEdgeKeyEndpointMaps, shouldReplaceEdgeKeyEndpointMaps map[string][]Endpoint + shouldReplaceEdgeKeyEndpointMaps = make(map[string][]Endpoint) + shouldInsertEdgeKeyEndpointMaps = edgeKeyEndpointMap + + for edgeKey, endpoints := range storedEdgeKeyEndpointMaps { + if compareEndpointArrays(endpoints, edgeKeyEndpointMap[edgeKey]) { + delete(shouldInsertEdgeKeyEndpointMaps, edgeKey) + } else { + shouldReplaceEdgeKeyEndpointMaps[edgeKey] = endpoints + } + } + + for edgeKey, endpoints := range shouldInsertEdgeKeyEndpointMaps { + for _, endpoint := range endpoints { + if err := db.Create(&PermissionEndpoint{ + EdgeKey: edgeKey, + EndpointName: endpoint.Name, + }).Error; err != nil { + return err + } + } + } + + for edgeKey, endpoints := range shouldReplaceEdgeKeyEndpointMaps { + if err := db.Where("edge_key = ?", edgeKey).Delete(&PermissionEndpoint{}).Error; err != nil { + return err + } + for _, endpoint := range endpoints { + if err := db.Create(&PermissionEndpoint{ + EdgeKey: edgeKey, + EndpointName: endpoint.Name, + }).Error; err != nil { + return err + } + } + } + + return nil +} + +// Compare two arrays of Endpoint objects +func compareEndpointArrays(a, b []Endpoint) bool { + if len(a) != len(b) { + return false + } + + // sort the arrays + sort.Slice(a, func(i, j int) bool { + return a[i].Name < a[j].Name + }) + + sort.Slice(b, func(i, j int) bool { + return b[i].Name < b[j].Name + }) + + // compare the arrays + for i := range a { + if a[i] != b[i] { + return false + } + } + + return true +} + +func endpointObjects(eps ...api.Endpoint) []Endpoint { + var result []Endpoint + for _, ep := range eps { + result = append(result, Endpoint{ + Name: api.MapWithEndpoint[ep].Name, + Group: api.MapWithEndpoint[ep].Group, + }) + } + return result +} diff --git a/internal/model/permission.go b/internal/model/permission.go index cc9f25e6..a84fa777 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -2,7 +2,6 @@ package model import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/helper" "gorm.io/gorm" ) @@ -54,19 +53,22 @@ const ( MiddleConfigurationUserKey = "CONFIGURATION-USER" MiddleConfigurationRoleKey = "CONFIGURATION-ROLE" MiddleConfigurationSystemNotificationKey = "CONFIGURATION-SYSTEM_NOTIFICATION" + CommonKey = "COMMON" ) type Permission struct { gorm.Model - ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` - Name string `json:"name"` - Key string `gorm:"type:text;" json:"key,omitempty"` + ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` + Name string `json:"name"` + Key string `gorm:"type:text;" json:"key,omitempty"` + EdgeKey *string `gorm:"type:text;"` IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` RoleID *string `json:"role_id,omitempty"` Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` - Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` + Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;joinForeignKey:EdgeKey;joinReferences:EndpointName;" json:"endpoints,omitempty"` + //PermissionEndpoint []*PermissionEndpoint `gorm:"foreignKey:EdgeKey;references:EdgeKey;"` // omit empty ParentID *uuid.UUID `json:"parent_id,omitempty"` @@ -82,7 +84,8 @@ type PermissionSet struct { Notification *Permission `gorm:"-:all" json:"notification,omitempty"` Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` Common *Permission `gorm:"-:all" json:"common,omitempty"` - Admin *Permission `gorm:"-:all" json:"admin,omitempty"` + // ToDo: Need to consider whether to use Admin Permission + //Admin *Permission `gorm:"-:all" json:"admin,omitempty"` } func NewDefaultPermissionSet() *PermissionSet { @@ -94,13 +97,13 @@ func NewDefaultPermissionSet() *PermissionSet { Notification: newNotification(), Configuration: newConfiguration(), Common: newCommon(), - Admin: nil, + //Admin: nil, } } func NewAdminPermissionSet() *PermissionSet { return &PermissionSet{ - Admin: newAdmin(), + //Admin: newAdmin(), Dashboard: newDashboard(), Stack: newStack(), Policy: newPolicy(), @@ -126,17 +129,6 @@ func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func( return edgePermissions } -func endpointObjects(eps ...api.Endpoint) []*Endpoint { - var result []*Endpoint - for _, ep := range eps { - result = append(result, &Endpoint{ - Name: api.ApiMap[ep].Name, - Group: api.ApiMap[ep].Group, - }) - } - return result -} - func newDashboard() *Permission { dashboard := &Permission{ ID: uuid.New(), @@ -152,24 +144,15 @@ func newDashboard() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopDashboardKey + "-" + MiddleDashboardKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetDashboard, - api.GetChartsDashboard, - api.GetChartDashboard, - api.GetStacksDashboard, - api.GetResourcesDashboard, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopDashboardKey + "-" + MiddleDashboardKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateDashboard, - api.UpdateDashboard, - ), }, }, }, @@ -194,70 +177,29 @@ func newStack() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopStackKey + "-" + MiddleStackKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - // Stack - api.GetStacks, - api.GetStack, - api.CheckStackName, - api.GetStackStatus, - api.GetStackKubeConfig, - api.SetFavoriteStack, - api.DeleteFavoriteStack, - - // Cluster - api.GetCluster, - api.GetClusters, - api.GetClusterSiteValues, - api.GetBootstrapKubeconfig, - api.GetNodes, - - // AppGroup - api.GetAppgroups, - api.GetAppgroup, - api.GetApplications, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopStackKey + "-" + MiddleStackKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - // Stack - api.CreateStack, - api.InstallStack, - - // Cluster - api.CreateBootstrapKubeconfig, - api.GetBootstrapKubeconfig, - api.GetNodes, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopStackKey + "-" + MiddleStackKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateStack, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopStackKey + "-" + MiddleStackKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - // Stack - api.DeleteStack, - - // Cluster - api.DeleteCluster, - - // AppGroup - api.DeleteAppgroup, - ), }, }, }, @@ -282,105 +224,29 @@ func newPolicy() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - // PolicyTemplate - api.Admin_ListPolicyTemplate, - api.Admin_GetPolicyTemplate, - api.Admin_GetPolicyTemplateDeploy, - api.Admin_ListPolicyTemplateStatistics, - api.Admin_ListPolicyTemplateVersions, - api.Admin_GetPolicyTemplateVersion, - api.Admin_ExistsPolicyTemplateName, - api.Admin_ExistsPolicyTemplateKind, - - // StackPolicyStatus - api.ListStackPolicyStatus, - api.GetStackPolicyTemplateStatus, - - // Policy - api.GetMandatoryPolicies, - api.ListPolicy, - api.GetPolicy, - api.ExistsPolicyName, - - // OrganizationPolicyTemplate - api.ListPolicyTemplate, - api.GetPolicyTemplate, - api.GetPolicyTemplateDeploy, - api.ListPolicyTemplateStatistics, - api.ListPolicyTemplateVersions, - api.GetPolicyTemplateVersion, - api.ExistsPolicyTemplateKind, - api.ExistsPolicyTemplateName, - - // PolicyTemplateExample - api.ListPolicyTemplateExample, - api.GetPolicyTemplateExample, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - // PolicyTemplate - api.Admin_CreatePolicyTemplate, - api.Admin_CreatePolicyTemplateVersion, - - // Policy - api.SetMandatoryPolicies, - api.CreatePolicy, - - // OrganizationPolicyTemplate - api.CreatePolicyTemplate, - api.CreatePolicyTemplateVersion, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - // PolicyTemplate - api.Admin_UpdatePolicyTemplate, - - // ClusterPolicyStatus - api.UpdateStackPolicyTemplateStatus, - - // Policy - api.UpdatePolicy, - api.UpdatePolicyTargetClusters, - - // OrganizationPolicyTemplate - api.UpdatePolicyTemplate, - - // PolicyTemplateExample - api.UpdatePolicyTemplateExample, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - // PolicyTemplate - api.Admin_DeletePolicyTemplate, - api.Admin_DeletePolicyTemplateVersion, - - // Policy - api.DeletePolicy, - - // OrganizationPolicyTemplate - api.DeletePolicyTemplate, - api.DeletePolicyTemplateVersion, - - // PolicyTemplateExample - api.DeletePolicyTemplateExample, - ), }, }, }, @@ -405,26 +271,21 @@ func newNotification() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetSystemNotification, - api.GetSystemNotifications, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateSystemNotification, - api.CreateSystemNotificationAction, - ), }, { ID: uuid.New(), Name: "다운로드", Key: OperationDownload, + EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationDownload), IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -439,6 +300,7 @@ func newNotification() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddlePolicyNotificationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -446,6 +308,7 @@ func newNotification() *Permission { ID: uuid.New(), Name: "다운로드", Key: OperationDownload, + EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddlePolicyNotificationKey + "-" + OperationDownload), IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -472,39 +335,29 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, - api.GetProjectKubeconfig, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateProject, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProject, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProject, - ), }, }, }, @@ -517,23 +370,15 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectCommonConfigurationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjects, - api.GetProject, - - api.GetProjectRoles, - api.GetProjectRole, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectCommonConfigurationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProject, - ), }, }, }, @@ -546,40 +391,29 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjectMembers, - api.GetProjectMember, - api.GetProjectRoles, - api.GetProjectRole, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.AddProjectMember, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProjectMemberRole, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.RemoveProjectMember, - ), }, }, }, @@ -592,39 +426,29 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetProjectNamespaces, - api.GetProjectNamespace, - api.GetProjectNamespaceK8sResources, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateProjectNamespace, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateProjectNamespace, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteProjectNamespace, - ), }, }, }, @@ -637,56 +461,29 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetAppServeApps, - api.GetAppServeApp, - api.GetNumOfAppsOnStack, - api.GetAppServeAppLatestTask, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.GetAppServeAppTaskDetail, - api.GetAppServeAppTasksByAppId, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteAppServeApp, - ), }, }, }, @@ -711,12 +508,14 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), }, }, @@ -730,42 +529,29 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetCloudAccounts, - api.GetCloudAccount, - api.CheckCloudAccountName, - api.CheckAwsAccountId, - api.GetResourceQuota, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateCloudAccount, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateCloudAccount, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteCloudAccount, - api.DeleteForceCloudAccount, - ), }, }, }, @@ -778,12 +564,14 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationProjectKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationProjectKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), }, }, @@ -797,42 +585,29 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.ListUser, - api.GetUser, - api.CheckId, - api.CheckEmail, - api.GetPermissionsByAccountId, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateUser, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateUser, - api.ResetPassword, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteUser, - ), }, }, }, @@ -845,41 +620,29 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.ListTksRoles, - api.GetTksRole, - api.GetPermissionsByRoleId, - api.GetPermissionTemplates, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateTksRole, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateTksRole, - api.UpdatePermissionsByRoleId, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteTksRole, - ), }, }, }, @@ -892,38 +655,29 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.GetSystemNotificationRules, - api.GetSystemNotificationRule, - ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.CreateSystemNotificationRule, - ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.UpdateSystemNotificationRule, - ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, + EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), - Endpoints: endpointObjects( - api.DeleteSystemNotificationRule, - ), }, }, }, @@ -938,100 +692,72 @@ func newCommon() *Permission { ID: uuid.New(), Name: "공통", IsAllowed: helper.BoolP(true), - Endpoints: endpointObjects( - // Auth - api.Login, - api.Logout, - api.RefreshToken, - api.FindId, - api.FindPassword, - api.VerifyIdentityForLostId, - api.VerifyIdentityForLostPassword, - api.VerifyToken, - - // User - api.GetUser, - api.GetPermissionsByAccountId, - - // MyProfile - api.GetMyProfile, - api.UpdateMyProfile, - api.UpdateMyPassword, - api.RenewPasswordExpiredDate, - api.DeleteMyProfile, - - // Organization - api.GetOrganization, - - // Role - api.GetPermissionsByRoleId, - - // Utiliy - api.CompileRego, - ), + Key: CommonKey, + EdgeKey: helper.StringP(CommonKey), } return common } -func newAdmin() *Permission { - admin := &Permission{ - ID: uuid.New(), - Name: "관리자", - IsAllowed: helper.BoolP(true), - Endpoints: endpointObjects( - // Organization - api.Admin_CreateOrganization, - api.Admin_DeleteOrganization, - api.UpdateOrganization, - api.GetOrganization, - api.GetOrganizations, - api.UpdatePrimaryCluster, - api.CheckOrganizationName, - - // User - api.ResetPassword, - api.CheckId, - api.CheckEmail, - - // StackTemplate - api.Admin_GetStackTemplates, - api.Admin_GetStackTemplate, - api.Admin_GetStackTemplateServices, - api.Admin_CreateStackTemplate, - api.Admin_UpdateStackTemplate, - api.Admin_DeleteStackTemplate, - api.Admin_UpdateStackTemplateOrganizations, - api.Admin_CheckStackTemplateName, - - // Admin - api.Admin_GetUser, - api.Admin_ListUser, - api.Admin_CreateUser, - api.Admin_UpdateUser, - api.Admin_DeleteUser, - api.Admin_GetSystemNotificationTemplate, - api.Admin_CreateSystemNotificationTemplate, - api.Admin_ListUser, - api.Admin_GetTksRole, - api.Admin_GetProjects, - api.Admin_UpdateSystemNotificationTemplate, - api.Admin_ListTksRoles, - api.Admin_GetSystemNotificationTemplates, - - // Audit - api.GetAudits, - api.GetAudit, - api.DeleteAudit, - - api.CreateSystemNotification, - api.DeleteSystemNotification, - ), - } - - return admin -} +//func newAdmin() *Permission { +// admin := &Permission{ +// ID: uuid.New(), +// Name: "관리자", +// IsAllowed: helper.BoolP(true), +// EdgeKey: helper.StringP("admin"), +// Endpoints: endpointObjects( +// // Organization +// api.Admin_CreateOrganization, +// api.Admin_DeleteOrganization, +// api.UpdateOrganization, +// api.GetOrganization, +// api.GetOrganizations, +// api.UpdatePrimaryCluster, +// api.CheckOrganizationName, +// +// // User +// api.ResetPassword, +// api.CheckId, +// api.CheckEmail, +// +// // StackTemplate +// api.Admin_GetStackTemplates, +// api.Admin_GetStackTemplate, +// api.Admin_GetStackTemplateServices, +// api.Admin_CreateStackTemplate, +// api.Admin_UpdateStackTemplate, +// api.Admin_DeleteStackTemplate, +// api.Admin_UpdateStackTemplateOrganizations, +// api.Admin_CheckStackTemplateName, +// +// // Admin +// api.Admin_GetUser, +// api.Admin_ListUser, +// api.Admin_CreateUser, +// api.Admin_UpdateUser, +// api.Admin_DeleteUser, +// api.Admin_GetSystemNotificationTemplate, +// api.Admin_CreateSystemNotificationTemplate, +// api.Admin_ListUser, +// api.Admin_GetTksRole, +// api.Admin_GetProjects, +// api.Admin_UpdateSystemNotificationTemplate, +// api.Admin_ListTksRoles, +// api.Admin_GetSystemNotificationTemplates, +// +// // Audit +// api.GetAudits, +// api.GetAudit, +// api.DeleteAudit, +// +// api.CreateSystemNotification, +// api.DeleteSystemNotification, +// ), +// } +// +// return admin +//} func (p *PermissionSet) SetAllowedPermissionSet() { edgePermissions := make([]*Permission, 0) diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 22a7d6bb..807c2525 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -14,6 +14,7 @@ type IPermissionRepository interface { Get(ctx context.Context, id uuid.UUID) (*model.Permission, error) Delete(ctx context.Context, id uuid.UUID) error Update(ctx context.Context, permission *model.Permission) error + EdgeKeyOverwrite(ctx context.Context, permission *model.Permission) error } type PermissionRepository struct { @@ -82,3 +83,7 @@ func (r PermissionRepository) Update(ctx context.Context, p *model.Permission) e // update on is_allowed return r.db.WithContext(ctx).Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error } + +func (r PermissionRepository) EdgeKeyOverwrite(ctx context.Context, p *model.Permission) error { + return r.db.WithContext(ctx).Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"edge_key": p.EdgeKey}).Error +} diff --git a/internal/route/route.go b/internal/route/route.go index 56e2500e..2b9eb1b6 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -81,6 +81,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Audit: usecase.NewAuditUsecase(repoFactory), Role: usecase.NewRoleUsecase(repoFactory, kc), Permission: usecase.NewPermissionUsecase(repoFactory), + Endpoint: usecase.NewEndpointUsecase(repoFactory), PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), Policy: usecase.NewPolicyUsecase(repoFactory), } @@ -318,6 +319,9 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa permissionHandler := delivery.NewPermissionHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) + endpointHandler := delivery.NewEndpointHandler(usecaseFactory) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/endpoints", customMiddleware.Handle(internalApi.GetEndpoints, http.HandlerFunc(endpointHandler.ListEndpoint))).Methods(http.MethodGet) + policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.Admin_CreatePolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_CreatePolicyTemplate))).Methods(http.MethodPost) diff --git a/internal/usecase/endpoint.go b/internal/usecase/endpoint.go new file mode 100644 index 00000000..726042ca --- /dev/null +++ b/internal/usecase/endpoint.go @@ -0,0 +1,26 @@ +package usecase + +import ( + "context" + "github.com/openinfradev/tks-api/internal/model" + "github.com/openinfradev/tks-api/internal/pagination" + "github.com/openinfradev/tks-api/internal/repository" +) + +type IEndpointUsecase interface { + ListEndpoints(ctx context.Context, pg *pagination.Pagination) ([]*model.Endpoint, error) +} + +type EndpointUsecase struct { + repo repository.IEndpointRepository +} + +func NewEndpointUsecase(repo repository.Repository) *EndpointUsecase { + return &EndpointUsecase{ + repo: repo.Endpoint, + } +} + +func (e EndpointUsecase) ListEndpoints(ctx context.Context, pg *pagination.Pagination) ([]*model.Endpoint, error) { + return e.repo.List(ctx, pg) +} diff --git a/internal/usecase/role.go b/internal/usecase/role.go index 7b181c93..40f29201 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -6,6 +6,7 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/log" ) type IRoleUsecase interface { @@ -15,11 +16,14 @@ type IRoleUsecase interface { DeleteTksRole(ctx context.Context, organizationId string, id string) error UpdateTksRole(ctx context.Context, role *model.Role) error IsRoleNameExisted(ctx context.Context, organizationId string, roleName string) (bool, error) + SyncOldVersions(ctx context.Context) error } type RoleUsecase struct { - repo repository.IRoleRepository - kc keycloak.IKeycloak + repo repository.IRoleRepository + kc keycloak.IKeycloak + orgRepo repository.IOrganizationRepository + permissionRepo repository.IPermissionRepository } func NewRoleUsecase(repo repository.Repository, kc keycloak.IKeycloak) *RoleUsecase { @@ -97,3 +101,193 @@ func (r RoleUsecase) IsRoleNameExisted(ctx context.Context, organizationId strin return false, nil } + +func (r RoleUsecase) SyncOldVersions(ctx context.Context) error { + // Get all organizations + orgs, _ := r.orgRepo.Fetch(ctx, nil) + for _, org := range *orgs { + roles, _ := r.repo.ListTksRoles(ctx, org.ID, nil) + for _, role := range roles { + storedPermissionSet := &model.PermissionSet{} + + permissionList, err := r.permissionRepo.List(ctx, role.ID) + + if err != nil { + return err + } + for _, permission := range permissionList { + switch permission.Name { + case string(model.DashBoardPermission): + storedPermissionSet.Dashboard = permission + log.Debugf(ctx, "Dashboard Permission Set : %+v", storedPermissionSet.Dashboard) + case string(model.StackPermission): + storedPermissionSet.Stack = permission + log.Debugf(ctx, "Stack Permission Set : %+v", storedPermissionSet.Stack) + case string(model.PolicyPermission): + storedPermissionSet.Policy = permission + log.Debugf(ctx, "Policy Permission Set : %+v", storedPermissionSet.Policy) + case string(model.ProjectPermission): + storedPermissionSet.ProjectManagement = permission + log.Debugf(ctx, "Project Permission Set : %+v", storedPermissionSet.ProjectManagement) + case string(model.NotificationPermission): + storedPermissionSet.Notification = permission + log.Debugf(ctx, "Notification Permission Set : %+v", storedPermissionSet.Notification) + case string(model.ConfigurationPermission): + storedPermissionSet.Configuration = permission + log.Debugf(ctx, "Configuration Permission Set : %+v", storedPermissionSet.Configuration) + } + } + + // tmp + t := model.NewDefaultPermissionSet() + var overwritePermissions []*model.Permission + overwritePermissions = make([]*model.Permission, 0) + + // dashboard + storedPermissionSet.Dashboard.Children[0].Children[0].EdgeKey = t.Dashboard.Children[0].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Dashboard.Children[0].Children[0]) + storedPermissionSet.Dashboard.Children[0].Children[1].EdgeKey = t.Dashboard.Children[0].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Dashboard.Children[0].Children[1]) + + // stack + storedPermissionSet.Stack.Children[0].Children[0].EdgeKey = t.Stack.Children[0].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Stack.Children[0].Children[0]) + storedPermissionSet.Stack.Children[0].Children[1].EdgeKey = t.Stack.Children[0].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Stack.Children[0].Children[1]) + storedPermissionSet.Stack.Children[0].Children[2].EdgeKey = t.Stack.Children[0].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Stack.Children[0].Children[2]) + storedPermissionSet.Stack.Children[0].Children[3].EdgeKey = t.Stack.Children[0].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Stack.Children[0].Children[3]) + + // policy + storedPermissionSet.Policy.Children[0].Children[0].EdgeKey = t.Policy.Children[0].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Policy.Children[0].Children[0]) + storedPermissionSet.Policy.Children[0].Children[1].EdgeKey = t.Policy.Children[0].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Policy.Children[0].Children[1]) + storedPermissionSet.Policy.Children[0].Children[2].EdgeKey = t.Policy.Children[0].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Policy.Children[0].Children[2]) + storedPermissionSet.Policy.Children[0].Children[3].EdgeKey = t.Policy.Children[0].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Policy.Children[0].Children[3]) + + // notification + storedPermissionSet.Notification.Children[0].Children[0].EdgeKey = t.Notification.Children[0].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[0].Children[0]) + storedPermissionSet.Notification.Children[0].Children[1].EdgeKey = t.Notification.Children[0].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[0].Children[1]) + storedPermissionSet.Notification.Children[0].Children[2].EdgeKey = t.Notification.Children[0].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[0].Children[2]) + storedPermissionSet.Notification.Children[1].Children[0].EdgeKey = t.Notification.Children[1].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[1].Children[0]) + storedPermissionSet.Notification.Children[1].Children[1].EdgeKey = t.Notification.Children[1].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[1].Children[1]) + + // project + // 1depth + storedPermissionSet.ProjectManagement.Children[0].Children[0].EdgeKey = t.ProjectManagement.Children[0].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[0].Children[0]) + storedPermissionSet.ProjectManagement.Children[0].Children[1].EdgeKey = t.ProjectManagement.Children[0].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[0].Children[1]) + storedPermissionSet.ProjectManagement.Children[0].Children[2].EdgeKey = t.ProjectManagement.Children[0].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[0].Children[2]) + storedPermissionSet.ProjectManagement.Children[0].Children[3].EdgeKey = t.ProjectManagement.Children[0].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[0].Children[3]) + + // 2depth + storedPermissionSet.ProjectManagement.Children[1].Children[0].EdgeKey = t.ProjectManagement.Children[1].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[1].Children[0]) + storedPermissionSet.ProjectManagement.Children[1].Children[1].EdgeKey = t.ProjectManagement.Children[1].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[1].Children[1]) + + // 3depth + storedPermissionSet.ProjectManagement.Children[2].Children[0].EdgeKey = t.ProjectManagement.Children[2].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[2].Children[0]) + storedPermissionSet.ProjectManagement.Children[2].Children[1].EdgeKey = t.ProjectManagement.Children[2].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[2].Children[1]) + storedPermissionSet.ProjectManagement.Children[2].Children[2].EdgeKey = t.ProjectManagement.Children[2].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[2].Children[2]) + storedPermissionSet.ProjectManagement.Children[2].Children[3].EdgeKey = t.ProjectManagement.Children[2].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[2].Children[3]) + + // 4depth + storedPermissionSet.ProjectManagement.Children[3].Children[0].EdgeKey = t.ProjectManagement.Children[3].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[3].Children[0]) + storedPermissionSet.ProjectManagement.Children[3].Children[1].EdgeKey = t.ProjectManagement.Children[3].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[3].Children[1]) + storedPermissionSet.ProjectManagement.Children[3].Children[2].EdgeKey = t.ProjectManagement.Children[3].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[3].Children[2]) + storedPermissionSet.ProjectManagement.Children[3].Children[3].EdgeKey = t.ProjectManagement.Children[3].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[3].Children[3]) + + // 5depth + storedPermissionSet.ProjectManagement.Children[4].Children[0].EdgeKey = t.ProjectManagement.Children[4].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[4].Children[0]) + storedPermissionSet.ProjectManagement.Children[4].Children[1].EdgeKey = t.ProjectManagement.Children[4].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[4].Children[1]) + storedPermissionSet.ProjectManagement.Children[4].Children[2].EdgeKey = t.ProjectManagement.Children[4].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[4].Children[2]) + storedPermissionSet.ProjectManagement.Children[4].Children[3].EdgeKey = t.ProjectManagement.Children[4].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[4].Children[3]) + + // configuration + storedPermissionSet.Configuration.Children[0].Children[0].EdgeKey = t.Configuration.Children[0].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[0].Children[0]) + storedPermissionSet.Configuration.Children[0].Children[1].EdgeKey = t.Configuration.Children[0].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[0].Children[1]) + + // 2depth + storedPermissionSet.Configuration.Children[1].Children[0].EdgeKey = t.Configuration.Children[1].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[1].Children[0]) + storedPermissionSet.Configuration.Children[1].Children[1].EdgeKey = t.Configuration.Children[1].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[1].Children[1]) + storedPermissionSet.Configuration.Children[1].Children[2].EdgeKey = t.Configuration.Children[1].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[1].Children[2]) + storedPermissionSet.Configuration.Children[1].Children[3].EdgeKey = t.Configuration.Children[1].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[1].Children[3]) + + // 3depth + storedPermissionSet.Configuration.Children[2].Children[0].EdgeKey = t.Configuration.Children[2].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[2].Children[0]) + storedPermissionSet.Configuration.Children[2].Children[1].EdgeKey = t.Configuration.Children[2].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[2].Children[1]) + + // 4depth + storedPermissionSet.Configuration.Children[3].Children[0].EdgeKey = t.Configuration.Children[3].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[3].Children[0]) + storedPermissionSet.Configuration.Children[3].Children[1].EdgeKey = t.Configuration.Children[3].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[3].Children[1]) + storedPermissionSet.Configuration.Children[3].Children[2].EdgeKey = t.Configuration.Children[3].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[3].Children[2]) + storedPermissionSet.Configuration.Children[3].Children[3].EdgeKey = t.Configuration.Children[3].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[3].Children[3]) + + // 5depth + storedPermissionSet.Configuration.Children[4].Children[0].EdgeKey = t.Configuration.Children[4].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[4].Children[0]) + storedPermissionSet.Configuration.Children[4].Children[1].EdgeKey = t.Configuration.Children[4].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[4].Children[1]) + storedPermissionSet.Configuration.Children[4].Children[2].EdgeKey = t.Configuration.Children[4].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[4].Children[2]) + storedPermissionSet.Configuration.Children[4].Children[3].EdgeKey = t.Configuration.Children[4].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[4].Children[3]) + + // 6depth + storedPermissionSet.Configuration.Children[5].Children[0].EdgeKey = t.Configuration.Children[5].Children[0].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[5].Children[0]) + storedPermissionSet.Configuration.Children[5].Children[1].EdgeKey = t.Configuration.Children[5].Children[1].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[5].Children[1]) + storedPermissionSet.Configuration.Children[5].Children[2].EdgeKey = t.Configuration.Children[5].Children[2].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[5].Children[2]) + storedPermissionSet.Configuration.Children[5].Children[3].EdgeKey = t.Configuration.Children[5].Children[3].EdgeKey + overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[5].Children[3]) + + for _, permission := range overwritePermissions { + if err = r.permissionRepo.EdgeKeyOverwrite(ctx, permission); err != nil { + return err + } + } + log.Debugf(ctx, "Dashboard EdgeKey Overwrite Success") + } + } + + return nil +} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index 46302b69..cb580b9d 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -17,6 +17,7 @@ type Usecase struct { Project IProjectUsecase Role IRoleUsecase Permission IPermissionUsecase + Endpoint IEndpointUsecase Audit IAuditUsecase PolicyTemplate IPolicyTemplateUsecase Policy IPolicyUsecase diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index 33acdc92..b8ca18ee 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -4,3 +4,7 @@ type EndpointResponse struct { Name string `json:"name"` Group string `json:"group"` } + +type ListEndpointResponse struct { + Endpoints []EndpointResponse `json:"endpoints"` +} diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index 3ae4805c..a1a2e490 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -19,10 +19,10 @@ type GetPermissionTemplatesResponse struct { //} type TemplateResponse struct { - Name string `json:"name"` - Key string `json:"key"` - IsAllowed *bool `json:"isAllowed,omitempty"` - Children []*TemplateResponse `json:"children,omitempty"` + Name string `json:"name"` + Key string `json:"key"` + EdgeKey *string `json:"edgeKey,omitempty"` + Children []*TemplateResponse `json:"children,omitempty"` } type GetPermissionsByRoleIdResponse struct { @@ -44,7 +44,6 @@ type PermissionResponse struct { Name string `json:"name"` Key string `json:"key"` IsAllowed *bool `json:"isAllowed,omitempty"` - Endpoints []*EndpointResponse `json:"endpoints,omitempty"` Children []*PermissionResponse `json:"children,omitempty"` } @@ -76,3 +75,6 @@ type MergePermissionResponse struct { IsAllowed *bool `json:"isAllowed,omitempty"` Children []*MergePermissionResponse `json:"children,omitempty"` } + +type GetPermissionEdgeKeysResponse struct { +} From 20903bc32f9a61120b55dc3e81bfe9be232ef74b Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 2 May 2024 14:32:30 +0900 Subject: [PATCH 412/502] lint fix --- internal/delivery/http/role.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 1883e6f7..b43769af 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -355,15 +355,6 @@ func convertModelToPermissionResponse(ctx context.Context, permission *model.Per return &permissionResponse } -func convertModelToEndpointResponse(_ context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { - var endpointResponse domain.EndpointResponse - - endpointResponse.Name = endpoint.Name - endpointResponse.Group = endpoint.Group - - return &endpointResponse -} - // UpdatePermissionsByRoleId godoc // // @Tags Roles From 723337d6262cfee9d2f1f2c966f837bd285db67c Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 2 May 2024 15:06:20 +0900 Subject: [PATCH 413/502] add get endpoints of permission --- internal/delivery/api/endpoint.go | 3 +- .../delivery/api/generated_endpoints.go.go | 939 +++++++++--------- internal/delivery/http/permission.go | 44 + .../auth/authorizer/adminApiFilter.go | 2 +- internal/repository/permission.go | 11 + internal/route/route.go | 3 +- internal/usecase/permission.go | 15 + pkg/domain/permission.go | 4 + pkg/httpErrors/errorCode.go | 3 + 9 files changed, 551 insertions(+), 473 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index d632c86b..c0747230 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -219,9 +219,10 @@ const ( // Permission GetPermissionTemplates + GetEndpointsByPermissionId // Endpoint - GetEndpoints + Admin_GetEndpoints // Admin_User Admin_CreateUser diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 799fe4fd..e8d61139 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -1,942 +1,942 @@ - // This is generated code. DO NOT EDIT. +// This is generated code. DO NOT EDIT. package api var MapWithEndpoint = map[Endpoint]EndpointInfo{ - Login: { - Name: "Login", + Login: { + Name: "Login", Group: "Auth", }, - Logout: { - Name: "Logout", + Logout: { + Name: "Logout", Group: "Auth", }, - RefreshToken: { - Name: "RefreshToken", + RefreshToken: { + Name: "RefreshToken", Group: "Auth", }, - FindId: { - Name: "FindId", + FindId: { + Name: "FindId", Group: "Auth", }, - FindPassword: { - Name: "FindPassword", + FindPassword: { + Name: "FindPassword", Group: "Auth", }, - VerifyIdentityForLostId: { - Name: "VerifyIdentityForLostId", + VerifyIdentityForLostId: { + Name: "VerifyIdentityForLostId", Group: "Auth", }, - VerifyIdentityForLostPassword: { - Name: "VerifyIdentityForLostPassword", + VerifyIdentityForLostPassword: { + Name: "VerifyIdentityForLostPassword", Group: "Auth", }, - VerifyToken: { - Name: "VerifyToken", + VerifyToken: { + Name: "VerifyToken", Group: "Auth", }, - CreateUser: { - Name: "CreateUser", + CreateUser: { + Name: "CreateUser", Group: "User", }, - ListUser: { - Name: "ListUser", + ListUser: { + Name: "ListUser", Group: "User", }, - GetUser: { - Name: "GetUser", + GetUser: { + Name: "GetUser", Group: "User", }, - DeleteUser: { - Name: "DeleteUser", + DeleteUser: { + Name: "DeleteUser", Group: "User", }, - UpdateUsers: { - Name: "UpdateUsers", + UpdateUsers: { + Name: "UpdateUsers", Group: "User", }, - UpdateUser: { - Name: "UpdateUser", + UpdateUser: { + Name: "UpdateUser", Group: "User", }, - ResetPassword: { - Name: "ResetPassword", + ResetPassword: { + Name: "ResetPassword", Group: "User", }, - CheckId: { - Name: "CheckId", + CheckId: { + Name: "CheckId", Group: "User", }, - CheckEmail: { - Name: "CheckEmail", + CheckEmail: { + Name: "CheckEmail", Group: "User", }, - GetPermissionsByAccountId: { - Name: "GetPermissionsByAccountId", + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", Group: "User", }, - GetMyProfile: { - Name: "GetMyProfile", + GetMyProfile: { + Name: "GetMyProfile", Group: "MyProfile", }, - UpdateMyProfile: { - Name: "UpdateMyProfile", + UpdateMyProfile: { + Name: "UpdateMyProfile", Group: "MyProfile", }, - UpdateMyPassword: { - Name: "UpdateMyPassword", + UpdateMyPassword: { + Name: "UpdateMyPassword", Group: "MyProfile", }, - RenewPasswordExpiredDate: { - Name: "RenewPasswordExpiredDate", + RenewPasswordExpiredDate: { + Name: "RenewPasswordExpiredDate", Group: "MyProfile", }, - DeleteMyProfile: { - Name: "DeleteMyProfile", + DeleteMyProfile: { + Name: "DeleteMyProfile", Group: "MyProfile", }, - Admin_CreateOrganization: { - Name: "Admin_CreateOrganization", + Admin_CreateOrganization: { + Name: "Admin_CreateOrganization", Group: "Organization", }, - Admin_DeleteOrganization: { - Name: "Admin_DeleteOrganization", + Admin_DeleteOrganization: { + Name: "Admin_DeleteOrganization", Group: "Organization", }, - GetOrganizations: { - Name: "GetOrganizations", + GetOrganizations: { + Name: "GetOrganizations", Group: "Organization", }, - GetOrganization: { - Name: "GetOrganization", + GetOrganization: { + Name: "GetOrganization", Group: "Organization", }, - CheckOrganizationName: { - Name: "CheckOrganizationName", + CheckOrganizationName: { + Name: "CheckOrganizationName", Group: "Organization", }, - UpdateOrganization: { - Name: "UpdateOrganization", + UpdateOrganization: { + Name: "UpdateOrganization", Group: "Organization", }, - UpdatePrimaryCluster: { - Name: "UpdatePrimaryCluster", + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", Group: "Organization", }, - CreateCluster: { - Name: "CreateCluster", + CreateCluster: { + Name: "CreateCluster", Group: "Cluster", }, - GetClusters: { - Name: "GetClusters", + GetClusters: { + Name: "GetClusters", Group: "Cluster", }, - ImportCluster: { - Name: "ImportCluster", + ImportCluster: { + Name: "ImportCluster", Group: "Cluster", }, - GetCluster: { - Name: "GetCluster", + GetCluster: { + Name: "GetCluster", Group: "Cluster", }, - DeleteCluster: { - Name: "DeleteCluster", + DeleteCluster: { + Name: "DeleteCluster", Group: "Cluster", }, - GetClusterSiteValues: { - Name: "GetClusterSiteValues", + GetClusterSiteValues: { + Name: "GetClusterSiteValues", Group: "Cluster", }, - InstallCluster: { - Name: "InstallCluster", + InstallCluster: { + Name: "InstallCluster", Group: "Cluster", }, - CreateBootstrapKubeconfig: { - Name: "CreateBootstrapKubeconfig", + CreateBootstrapKubeconfig: { + Name: "CreateBootstrapKubeconfig", Group: "Cluster", }, - GetBootstrapKubeconfig: { - Name: "GetBootstrapKubeconfig", + GetBootstrapKubeconfig: { + Name: "GetBootstrapKubeconfig", Group: "Cluster", }, - GetNodes: { - Name: "GetNodes", + GetNodes: { + Name: "GetNodes", Group: "Cluster", }, - CreateAppgroup: { - Name: "CreateAppgroup", + CreateAppgroup: { + Name: "CreateAppgroup", Group: "Appgroup", }, - GetAppgroups: { - Name: "GetAppgroups", + GetAppgroups: { + Name: "GetAppgroups", Group: "Appgroup", }, - GetAppgroup: { - Name: "GetAppgroup", + GetAppgroup: { + Name: "GetAppgroup", Group: "Appgroup", }, - DeleteAppgroup: { - Name: "DeleteAppgroup", + DeleteAppgroup: { + Name: "DeleteAppgroup", Group: "Appgroup", }, - GetApplications: { - Name: "GetApplications", + GetApplications: { + Name: "GetApplications", Group: "Appgroup", }, - CreateApplication: { - Name: "CreateApplication", + CreateApplication: { + Name: "CreateApplication", Group: "Appgroup", }, - GetAppServeAppTasksByAppId: { - Name: "GetAppServeAppTasksByAppId", + GetAppServeAppTasksByAppId: { + Name: "GetAppServeAppTasksByAppId", Group: "AppServeApp", }, - GetAppServeAppTaskDetail: { - Name: "GetAppServeAppTaskDetail", + GetAppServeAppTaskDetail: { + Name: "GetAppServeAppTaskDetail", Group: "AppServeApp", }, - CreateAppServeApp: { - Name: "CreateAppServeApp", + CreateAppServeApp: { + Name: "CreateAppServeApp", Group: "AppServeApp", }, - GetAppServeApps: { - Name: "GetAppServeApps", + GetAppServeApps: { + Name: "GetAppServeApps", Group: "AppServeApp", }, - GetNumOfAppsOnStack: { - Name: "GetNumOfAppsOnStack", + GetNumOfAppsOnStack: { + Name: "GetNumOfAppsOnStack", Group: "AppServeApp", }, - GetAppServeApp: { - Name: "GetAppServeApp", + GetAppServeApp: { + Name: "GetAppServeApp", Group: "AppServeApp", }, - GetAppServeAppLatestTask: { - Name: "GetAppServeAppLatestTask", + GetAppServeAppLatestTask: { + Name: "GetAppServeAppLatestTask", Group: "AppServeApp", }, - IsAppServeAppExist: { - Name: "IsAppServeAppExist", + IsAppServeAppExist: { + Name: "IsAppServeAppExist", Group: "AppServeApp", }, - IsAppServeAppNameExist: { - Name: "IsAppServeAppNameExist", + IsAppServeAppNameExist: { + Name: "IsAppServeAppNameExist", Group: "AppServeApp", }, - DeleteAppServeApp: { - Name: "DeleteAppServeApp", + DeleteAppServeApp: { + Name: "DeleteAppServeApp", Group: "AppServeApp", }, - UpdateAppServeApp: { - Name: "UpdateAppServeApp", + UpdateAppServeApp: { + Name: "UpdateAppServeApp", Group: "AppServeApp", }, - UpdateAppServeAppStatus: { - Name: "UpdateAppServeAppStatus", + UpdateAppServeAppStatus: { + Name: "UpdateAppServeAppStatus", Group: "AppServeApp", }, - UpdateAppServeAppEndpoint: { - Name: "UpdateAppServeAppEndpoint", + UpdateAppServeAppEndpoint: { + Name: "UpdateAppServeAppEndpoint", Group: "AppServeApp", }, - RollbackAppServeApp: { - Name: "RollbackAppServeApp", + RollbackAppServeApp: { + Name: "RollbackAppServeApp", Group: "AppServeApp", }, - GetCloudAccounts: { - Name: "GetCloudAccounts", + GetCloudAccounts: { + Name: "GetCloudAccounts", Group: "CloudAccount", }, - CreateCloudAccount: { - Name: "CreateCloudAccount", + CreateCloudAccount: { + Name: "CreateCloudAccount", Group: "CloudAccount", }, - CheckCloudAccountName: { - Name: "CheckCloudAccountName", + CheckCloudAccountName: { + Name: "CheckCloudAccountName", Group: "CloudAccount", }, - CheckAwsAccountId: { - Name: "CheckAwsAccountId", + CheckAwsAccountId: { + Name: "CheckAwsAccountId", Group: "CloudAccount", }, - GetCloudAccount: { - Name: "GetCloudAccount", + GetCloudAccount: { + Name: "GetCloudAccount", Group: "CloudAccount", }, - UpdateCloudAccount: { - Name: "UpdateCloudAccount", + UpdateCloudAccount: { + Name: "UpdateCloudAccount", Group: "CloudAccount", }, - DeleteCloudAccount: { - Name: "DeleteCloudAccount", + DeleteCloudAccount: { + Name: "DeleteCloudAccount", Group: "CloudAccount", }, - DeleteForceCloudAccount: { - Name: "DeleteForceCloudAccount", + DeleteForceCloudAccount: { + Name: "DeleteForceCloudAccount", Group: "CloudAccount", }, - GetResourceQuota: { - Name: "GetResourceQuota", + GetResourceQuota: { + Name: "GetResourceQuota", Group: "CloudAccount", }, - Admin_GetStackTemplates: { - Name: "Admin_GetStackTemplates", + Admin_GetStackTemplates: { + Name: "Admin_GetStackTemplates", Group: "StackTemplate", }, - Admin_GetStackTemplate: { - Name: "Admin_GetStackTemplate", + Admin_GetStackTemplate: { + Name: "Admin_GetStackTemplate", Group: "StackTemplate", }, - Admin_GetStackTemplateServices: { - Name: "Admin_GetStackTemplateServices", + Admin_GetStackTemplateServices: { + Name: "Admin_GetStackTemplateServices", Group: "StackTemplate", }, - Admin_GetStackTemplateTemplateIds: { - Name: "Admin_GetStackTemplateTemplateIds", + Admin_GetStackTemplateTemplateIds: { + Name: "Admin_GetStackTemplateTemplateIds", Group: "StackTemplate", }, - Admin_CreateStackTemplate: { - Name: "Admin_CreateStackTemplate", + Admin_CreateStackTemplate: { + Name: "Admin_CreateStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplate: { - Name: "Admin_UpdateStackTemplate", + Admin_UpdateStackTemplate: { + Name: "Admin_UpdateStackTemplate", Group: "StackTemplate", }, - Admin_DeleteStackTemplate: { - Name: "Admin_DeleteStackTemplate", + Admin_DeleteStackTemplate: { + Name: "Admin_DeleteStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplateOrganizations: { - Name: "Admin_UpdateStackTemplateOrganizations", + Admin_UpdateStackTemplateOrganizations: { + Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, - Admin_CheckStackTemplateName: { - Name: "Admin_CheckStackTemplateName", + Admin_CheckStackTemplateName: { + Name: "Admin_CheckStackTemplateName", Group: "StackTemplate", }, - GetOrganizationStackTemplates: { - Name: "GetOrganizationStackTemplates", + GetOrganizationStackTemplates: { + Name: "GetOrganizationStackTemplates", Group: "StackTemplate", }, - GetOrganizationStackTemplate: { - Name: "GetOrganizationStackTemplate", + GetOrganizationStackTemplate: { + Name: "GetOrganizationStackTemplate", Group: "StackTemplate", }, - AddOrganizationStackTemplates: { - Name: "AddOrganizationStackTemplates", + AddOrganizationStackTemplates: { + Name: "AddOrganizationStackTemplates", Group: "StackTemplate", }, - RemoveOrganizationStackTemplates: { - Name: "RemoveOrganizationStackTemplates", + RemoveOrganizationStackTemplates: { + Name: "RemoveOrganizationStackTemplates", Group: "StackTemplate", }, - CreateDashboard: { - Name: "CreateDashboard", + CreateDashboard: { + Name: "CreateDashboard", Group: "Dashboard", }, - GetDashboard: { - Name: "GetDashboard", + GetDashboard: { + Name: "GetDashboard", Group: "Dashboard", }, - UpdateDashboard: { - Name: "UpdateDashboard", + UpdateDashboard: { + Name: "UpdateDashboard", Group: "Dashboard", }, - GetChartsDashboard: { - Name: "GetChartsDashboard", + GetChartsDashboard: { + Name: "GetChartsDashboard", Group: "Dashboard", }, - GetChartDashboard: { - Name: "GetChartDashboard", + GetChartDashboard: { + Name: "GetChartDashboard", Group: "Dashboard", }, - GetStacksDashboard: { - Name: "GetStacksDashboard", + GetStacksDashboard: { + Name: "GetStacksDashboard", Group: "Dashboard", }, - GetResourcesDashboard: { - Name: "GetResourcesDashboard", + GetResourcesDashboard: { + Name: "GetResourcesDashboard", Group: "Dashboard", }, - GetPolicyStatusDashboard: { - Name: "GetPolicyStatusDashboard", + GetPolicyStatusDashboard: { + Name: "GetPolicyStatusDashboard", Group: "Dashboard", }, - GetPolicyUpdateDashboard: { - Name: "GetPolicyUpdateDashboard", + GetPolicyUpdateDashboard: { + Name: "GetPolicyUpdateDashboard", Group: "Dashboard", }, - GetPolicyEnforcementDashboard: { - Name: "GetPolicyEnforcementDashboard", + GetPolicyEnforcementDashboard: { + Name: "GetPolicyEnforcementDashboard", Group: "Dashboard", }, - GetPolicyViolationDashboard: { - Name: "GetPolicyViolationDashboard", + GetPolicyViolationDashboard: { + Name: "GetPolicyViolationDashboard", Group: "Dashboard", }, - GetPolicyViolationLogDashboard: { - Name: "GetPolicyViolationLogDashboard", + GetPolicyViolationLogDashboard: { + Name: "GetPolicyViolationLogDashboard", Group: "Dashboard", }, - GetPolicyStatisticsDashboard: { - Name: "GetPolicyStatisticsDashboard", + GetPolicyStatisticsDashboard: { + Name: "GetPolicyStatisticsDashboard", Group: "Dashboard", }, - GetWorkloadDashboard: { - Name: "GetWorkloadDashboard", + GetWorkloadDashboard: { + Name: "GetWorkloadDashboard", Group: "Dashboard", }, - GetPolicyViolationTop5Dashboard: { - Name: "GetPolicyViolationTop5Dashboard", + GetPolicyViolationTop5Dashboard: { + Name: "GetPolicyViolationTop5Dashboard", Group: "Dashboard", }, - Admin_CreateSystemNotificationTemplate: { - Name: "Admin_CreateSystemNotificationTemplate", + Admin_CreateSystemNotificationTemplate: { + Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_UpdateSystemNotificationTemplate: { - Name: "Admin_UpdateSystemNotificationTemplate", + Admin_UpdateSystemNotificationTemplate: { + Name: "Admin_UpdateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_DeleteSystemNotificationTemplate: { - Name: "Admin_DeleteSystemNotificationTemplate", + Admin_DeleteSystemNotificationTemplate: { + Name: "Admin_DeleteSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplates: { - Name: "Admin_GetSystemNotificationTemplates", + Admin_GetSystemNotificationTemplates: { + Name: "Admin_GetSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplate: { - Name: "Admin_GetSystemNotificationTemplate", + Admin_GetSystemNotificationTemplate: { + Name: "Admin_GetSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_CheckSystemNotificationTemplateName: { - Name: "Admin_CheckSystemNotificationTemplateName", + Admin_CheckSystemNotificationTemplateName: { + Name: "Admin_CheckSystemNotificationTemplateName", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplates: { - Name: "GetOrganizationSystemNotificationTemplates", + GetOrganizationSystemNotificationTemplates: { + Name: "GetOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplate: { - Name: "GetOrganizationSystemNotificationTemplate", + GetOrganizationSystemNotificationTemplate: { + Name: "GetOrganizationSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - AddOrganizationSystemNotificationTemplates: { - Name: "AddOrganizationSystemNotificationTemplates", + AddOrganizationSystemNotificationTemplates: { + Name: "AddOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - RemoveOrganizationSystemNotificationTemplates: { - Name: "RemoveOrganizationSystemNotificationTemplates", + RemoveOrganizationSystemNotificationTemplates: { + Name: "RemoveOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - CreateSystemNotificationRule: { - Name: "CreateSystemNotificationRule", + CreateSystemNotificationRule: { + Name: "CreateSystemNotificationRule", Group: "SystemNotificationRule", }, - GetSystemNotificationRules: { - Name: "GetSystemNotificationRules", + GetSystemNotificationRules: { + Name: "GetSystemNotificationRules", Group: "SystemNotificationRule", }, - GetSystemNotificationRule: { - Name: "GetSystemNotificationRule", + GetSystemNotificationRule: { + Name: "GetSystemNotificationRule", Group: "SystemNotificationRule", }, - CheckSystemNotificationRuleName: { - Name: "CheckSystemNotificationRuleName", + CheckSystemNotificationRuleName: { + Name: "CheckSystemNotificationRuleName", Group: "SystemNotificationRule", }, - DeleteSystemNotificationRule: { - Name: "DeleteSystemNotificationRule", + DeleteSystemNotificationRule: { + Name: "DeleteSystemNotificationRule", Group: "SystemNotificationRule", }, - UpdateSystemNotificationRule: { - Name: "UpdateSystemNotificationRule", + UpdateSystemNotificationRule: { + Name: "UpdateSystemNotificationRule", Group: "SystemNotificationRule", }, - MakeDefaultSystemNotificationRules: { - Name: "MakeDefaultSystemNotificationRules", + MakeDefaultSystemNotificationRules: { + Name: "MakeDefaultSystemNotificationRules", Group: "SystemNotificationRule", }, - CreateSystemNotification: { - Name: "CreateSystemNotification", + CreateSystemNotification: { + Name: "CreateSystemNotification", Group: "SystemNotification", }, - GetSystemNotifications: { - Name: "GetSystemNotifications", + GetSystemNotifications: { + Name: "GetSystemNotifications", Group: "SystemNotification", }, - GetSystemNotification: { - Name: "GetSystemNotification", + GetSystemNotification: { + Name: "GetSystemNotification", Group: "SystemNotification", }, - DeleteSystemNotification: { - Name: "DeleteSystemNotification", + DeleteSystemNotification: { + Name: "DeleteSystemNotification", Group: "SystemNotification", }, - UpdateSystemNotification: { - Name: "UpdateSystemNotification", + UpdateSystemNotification: { + Name: "UpdateSystemNotification", Group: "SystemNotification", }, - CreateSystemNotificationAction: { - Name: "CreateSystemNotificationAction", + CreateSystemNotificationAction: { + Name: "CreateSystemNotificationAction", Group: "SystemNotification", }, - GetPolicyNotifications: { - Name: "GetPolicyNotifications", + GetPolicyNotifications: { + Name: "GetPolicyNotifications", Group: "PolicyNotification", }, - GetPolicyNotification: { - Name: "GetPolicyNotification", + GetPolicyNotification: { + Name: "GetPolicyNotification", Group: "PolicyNotification", }, - CreateStack: { - Name: "CreateStack", + CreateStack: { + Name: "CreateStack", Group: "Stack", }, - GetStacks: { - Name: "GetStacks", + GetStacks: { + Name: "GetStacks", Group: "Stack", }, - GetStack: { - Name: "GetStack", + GetStack: { + Name: "GetStack", Group: "Stack", }, - UpdateStack: { - Name: "UpdateStack", + UpdateStack: { + Name: "UpdateStack", Group: "Stack", }, - DeleteStack: { - Name: "DeleteStack", + DeleteStack: { + Name: "DeleteStack", Group: "Stack", }, - CheckStackName: { - Name: "CheckStackName", + CheckStackName: { + Name: "CheckStackName", Group: "Stack", }, - GetStackStatus: { - Name: "GetStackStatus", + GetStackStatus: { + Name: "GetStackStatus", Group: "Stack", }, - GetStackKubeConfig: { - Name: "GetStackKubeConfig", + GetStackKubeConfig: { + Name: "GetStackKubeConfig", Group: "Stack", }, - SetFavoriteStack: { - Name: "SetFavoriteStack", + SetFavoriteStack: { + Name: "SetFavoriteStack", Group: "Stack", }, - DeleteFavoriteStack: { - Name: "DeleteFavoriteStack", + DeleteFavoriteStack: { + Name: "DeleteFavoriteStack", Group: "Stack", }, - InstallStack: { - Name: "InstallStack", + InstallStack: { + Name: "InstallStack", Group: "Stack", }, - CreateProject: { - Name: "CreateProject", + CreateProject: { + Name: "CreateProject", Group: "Project", }, - GetProjectRoles: { - Name: "GetProjectRoles", + GetProjectRoles: { + Name: "GetProjectRoles", Group: "Project", }, - GetProjectRole: { - Name: "GetProjectRole", + GetProjectRole: { + Name: "GetProjectRole", Group: "Project", }, - GetProjects: { - Name: "GetProjects", + GetProjects: { + Name: "GetProjects", Group: "Project", }, - GetProject: { - Name: "GetProject", + GetProject: { + Name: "GetProject", Group: "Project", }, - UpdateProject: { - Name: "UpdateProject", + UpdateProject: { + Name: "UpdateProject", Group: "Project", }, - DeleteProject: { - Name: "DeleteProject", + DeleteProject: { + Name: "DeleteProject", Group: "Project", }, - AddProjectMember: { - Name: "AddProjectMember", + AddProjectMember: { + Name: "AddProjectMember", Group: "Project", }, - GetProjectMember: { - Name: "GetProjectMember", + GetProjectMember: { + Name: "GetProjectMember", Group: "Project", }, - GetProjectMembers: { - Name: "GetProjectMembers", + GetProjectMembers: { + Name: "GetProjectMembers", Group: "Project", }, - RemoveProjectMember: { - Name: "RemoveProjectMember", + RemoveProjectMember: { + Name: "RemoveProjectMember", Group: "Project", }, - UpdateProjectMemberRole: { - Name: "UpdateProjectMemberRole", + UpdateProjectMemberRole: { + Name: "UpdateProjectMemberRole", Group: "Project", }, - CreateProjectNamespace: { - Name: "CreateProjectNamespace", + CreateProjectNamespace: { + Name: "CreateProjectNamespace", Group: "Project", }, - GetProjectNamespaces: { - Name: "GetProjectNamespaces", + GetProjectNamespaces: { + Name: "GetProjectNamespaces", Group: "Project", }, - GetProjectNamespace: { - Name: "GetProjectNamespace", + GetProjectNamespace: { + Name: "GetProjectNamespace", Group: "Project", }, - UpdateProjectNamespace: { - Name: "UpdateProjectNamespace", + UpdateProjectNamespace: { + Name: "UpdateProjectNamespace", Group: "Project", }, - DeleteProjectNamespace: { - Name: "DeleteProjectNamespace", + DeleteProjectNamespace: { + Name: "DeleteProjectNamespace", Group: "Project", }, - SetFavoriteProject: { - Name: "SetFavoriteProject", + SetFavoriteProject: { + Name: "SetFavoriteProject", Group: "Project", }, - SetFavoriteProjectNamespace: { - Name: "SetFavoriteProjectNamespace", + SetFavoriteProjectNamespace: { + Name: "SetFavoriteProjectNamespace", Group: "Project", }, - UnSetFavoriteProject: { - Name: "UnSetFavoriteProject", + UnSetFavoriteProject: { + Name: "UnSetFavoriteProject", Group: "Project", }, - UnSetFavoriteProjectNamespace: { - Name: "UnSetFavoriteProjectNamespace", + UnSetFavoriteProjectNamespace: { + Name: "UnSetFavoriteProjectNamespace", Group: "Project", }, - GetProjectKubeconfig: { - Name: "GetProjectKubeconfig", + GetProjectKubeconfig: { + Name: "GetProjectKubeconfig", Group: "Project", }, - GetProjectNamespaceK8sResources: { - Name: "GetProjectNamespaceK8sResources", + GetProjectNamespaceK8sResources: { + Name: "GetProjectNamespaceK8sResources", Group: "Project", }, - GetProjectNamespaceKubeconfig: { - Name: "GetProjectNamespaceKubeconfig", + GetProjectNamespaceKubeconfig: { + Name: "GetProjectNamespaceKubeconfig", Group: "Project", }, - GetAudits: { - Name: "GetAudits", + GetAudits: { + Name: "GetAudits", Group: "Audit", }, - GetAudit: { - Name: "GetAudit", + GetAudit: { + Name: "GetAudit", Group: "Audit", }, - DeleteAudit: { - Name: "DeleteAudit", + DeleteAudit: { + Name: "DeleteAudit", Group: "Audit", }, - CreateTksRole: { - Name: "CreateTksRole", + CreateTksRole: { + Name: "CreateTksRole", Group: "Role", }, - ListTksRoles: { - Name: "ListTksRoles", + ListTksRoles: { + Name: "ListTksRoles", Group: "Role", }, - GetTksRole: { - Name: "GetTksRole", + GetTksRole: { + Name: "GetTksRole", Group: "Role", }, - DeleteTksRole: { - Name: "DeleteTksRole", + DeleteTksRole: { + Name: "DeleteTksRole", Group: "Role", }, - UpdateTksRole: { - Name: "UpdateTksRole", + UpdateTksRole: { + Name: "UpdateTksRole", Group: "Role", }, - GetPermissionsByRoleId: { - Name: "GetPermissionsByRoleId", + GetPermissionsByRoleId: { + Name: "GetPermissionsByRoleId", Group: "Role", }, - UpdatePermissionsByRoleId: { - Name: "UpdatePermissionsByRoleId", + UpdatePermissionsByRoleId: { + Name: "UpdatePermissionsByRoleId", Group: "Role", }, - IsRoleNameExisted: { - Name: "IsRoleNameExisted", + IsRoleNameExisted: { + Name: "IsRoleNameExisted", Group: "Role", }, - AppendUsersToRole: { - Name: "AppendUsersToRole", + AppendUsersToRole: { + Name: "AppendUsersToRole", Group: "Role", }, - GetUsersInRoleId: { - Name: "GetUsersInRoleId", + GetUsersInRoleId: { + Name: "GetUsersInRoleId", Group: "Role", }, - RemoveUsersFromRole: { - Name: "RemoveUsersFromRole", + RemoveUsersFromRole: { + Name: "RemoveUsersFromRole", Group: "Role", }, - GetPermissionTemplates: { - Name: "GetPermissionTemplates", + GetPermissionTemplates: { + Name: "GetPermissionTemplates", Group: "Permission", }, - GetEndpoints: { - Name: "GetEndpoints", + Admin_GetEndpoints: { + Name: "Admin_GetEndpoints", Group: "Endpoint", }, - Admin_CreateUser: { - Name: "Admin_CreateUser", + Admin_CreateUser: { + Name: "Admin_CreateUser", Group: "Admin_User", }, - Admin_ListUser: { - Name: "Admin_ListUser", + Admin_ListUser: { + Name: "Admin_ListUser", Group: "Admin_User", }, - Admin_GetUser: { - Name: "Admin_GetUser", + Admin_GetUser: { + Name: "Admin_GetUser", Group: "Admin_User", }, - Admin_DeleteUser: { - Name: "Admin_DeleteUser", + Admin_DeleteUser: { + Name: "Admin_DeleteUser", Group: "Admin_User", }, - Admin_UpdateUser: { - Name: "Admin_UpdateUser", + Admin_UpdateUser: { + Name: "Admin_UpdateUser", Group: "Admin_User", }, - Admin_ListTksRoles: { - Name: "Admin_ListTksRoles", + Admin_ListTksRoles: { + Name: "Admin_ListTksRoles", Group: "Admin Role", }, - Admin_GetTksRole: { - Name: "Admin_GetTksRole", + Admin_GetTksRole: { + Name: "Admin_GetTksRole", Group: "Admin Role", }, - Admin_GetProjects: { - Name: "Admin_GetProjects", + Admin_GetProjects: { + Name: "Admin_GetProjects", Group: "Admin Project", }, - Admin_ListPolicyTemplate: { - Name: "Admin_ListPolicyTemplate", + Admin_ListPolicyTemplate: { + Name: "Admin_ListPolicyTemplate", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplate: { - Name: "Admin_CreatePolicyTemplate", + Admin_CreatePolicyTemplate: { + Name: "Admin_CreatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplate: { - Name: "Admin_DeletePolicyTemplate", + Admin_DeletePolicyTemplate: { + Name: "Admin_DeletePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplate: { - Name: "Admin_GetPolicyTemplate", + Admin_GetPolicyTemplate: { + Name: "Admin_GetPolicyTemplate", Group: "PolicyTemplate", }, - Admin_UpdatePolicyTemplate: { - Name: "Admin_UpdatePolicyTemplate", + Admin_UpdatePolicyTemplate: { + Name: "Admin_UpdatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateDeploy: { - Name: "Admin_GetPolicyTemplateDeploy", + Admin_GetPolicyTemplateDeploy: { + Name: "Admin_GetPolicyTemplateDeploy", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateStatistics: { - Name: "Admin_ListPolicyTemplateStatistics", + Admin_ListPolicyTemplateStatistics: { + Name: "Admin_ListPolicyTemplateStatistics", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateVersions: { - Name: "Admin_ListPolicyTemplateVersions", + Admin_ListPolicyTemplateVersions: { + Name: "Admin_ListPolicyTemplateVersions", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplateVersion: { - Name: "Admin_CreatePolicyTemplateVersion", + Admin_CreatePolicyTemplateVersion: { + Name: "Admin_CreatePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplateVersion: { - Name: "Admin_DeletePolicyTemplateVersion", + Admin_DeletePolicyTemplateVersion: { + Name: "Admin_DeletePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateVersion: { - Name: "Admin_GetPolicyTemplateVersion", + Admin_GetPolicyTemplateVersion: { + Name: "Admin_GetPolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateKind: { - Name: "Admin_ExistsPolicyTemplateKind", + Admin_ExistsPolicyTemplateKind: { + Name: "Admin_ExistsPolicyTemplateKind", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateName: { - Name: "Admin_ExistsPolicyTemplateName", + Admin_ExistsPolicyTemplateName: { + Name: "Admin_ExistsPolicyTemplateName", Group: "PolicyTemplate", }, - Admin_ExtractParameters: { - Name: "Admin_ExtractParameters", + Admin_ExtractParameters: { + Name: "Admin_ExtractParameters", Group: "PolicyTemplate", }, - Admin_AddPermittedPolicyTemplatesForOrganization: { - Name: "Admin_AddPermittedPolicyTemplatesForOrganization", + Admin_AddPermittedPolicyTemplatesForOrganization: { + Name: "Admin_AddPermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - Admin_DeletePermittedPolicyTemplatesForOrganization: { - Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", + Admin_DeletePermittedPolicyTemplatesForOrganization: { + Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - ListStackPolicyStatus: { - Name: "ListStackPolicyStatus", + ListStackPolicyStatus: { + Name: "ListStackPolicyStatus", Group: "StackPolicyStatus", }, - GetStackPolicyTemplateStatus: { - Name: "GetStackPolicyTemplateStatus", + GetStackPolicyTemplateStatus: { + Name: "GetStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - UpdateStackPolicyTemplateStatus: { - Name: "UpdateStackPolicyTemplateStatus", + UpdateStackPolicyTemplateStatus: { + Name: "UpdateStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - GetMandatoryPolicies: { - Name: "GetMandatoryPolicies", + GetMandatoryPolicies: { + Name: "GetMandatoryPolicies", Group: "Policy", }, - SetMandatoryPolicies: { - Name: "SetMandatoryPolicies", + SetMandatoryPolicies: { + Name: "SetMandatoryPolicies", Group: "Policy", }, - GetPolicyStatistics: { - Name: "GetPolicyStatistics", + GetPolicyStatistics: { + Name: "GetPolicyStatistics", Group: "Policy", }, - ListPolicy: { - Name: "ListPolicy", + ListPolicy: { + Name: "ListPolicy", Group: "Policy", }, - CreatePolicy: { - Name: "CreatePolicy", + CreatePolicy: { + Name: "CreatePolicy", Group: "Policy", }, - DeletePolicy: { - Name: "DeletePolicy", + DeletePolicy: { + Name: "DeletePolicy", Group: "Policy", }, - GetPolicy: { - Name: "GetPolicy", + GetPolicy: { + Name: "GetPolicy", Group: "Policy", }, - UpdatePolicy: { - Name: "UpdatePolicy", + UpdatePolicy: { + Name: "UpdatePolicy", Group: "Policy", }, - UpdatePolicyTargetClusters: { - Name: "UpdatePolicyTargetClusters", + UpdatePolicyTargetClusters: { + Name: "UpdatePolicyTargetClusters", Group: "Policy", }, - ExistsPolicyName: { - Name: "ExistsPolicyName", + ExistsPolicyName: { + Name: "ExistsPolicyName", Group: "Policy", }, - ExistsPolicyResourceName: { - Name: "ExistsPolicyResourceName", + ExistsPolicyResourceName: { + Name: "ExistsPolicyResourceName", Group: "Policy", }, - GetPolicyEdit: { - Name: "GetPolicyEdit", + GetPolicyEdit: { + Name: "GetPolicyEdit", Group: "Policy", }, - AddPoliciesForStack: { - Name: "AddPoliciesForStack", + AddPoliciesForStack: { + Name: "AddPoliciesForStack", Group: "Policy", }, - DeletePoliciesForStack: { - Name: "DeletePoliciesForStack", + DeletePoliciesForStack: { + Name: "DeletePoliciesForStack", Group: "Policy", }, - StackPolicyStatistics: { - Name: "StackPolicyStatistics", + StackPolicyStatistics: { + Name: "StackPolicyStatistics", Group: "Policy", }, - ListPolicyTemplate: { - Name: "ListPolicyTemplate", + ListPolicyTemplate: { + Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplate: { - Name: "CreatePolicyTemplate", + CreatePolicyTemplate: { + Name: "CreatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplate: { - Name: "DeletePolicyTemplate", + DeletePolicyTemplate: { + Name: "DeletePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplate: { - Name: "GetPolicyTemplate", + GetPolicyTemplate: { + Name: "GetPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - UpdatePolicyTemplate: { - Name: "UpdatePolicyTemplate", + UpdatePolicyTemplate: { + Name: "UpdatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateDeploy: { - Name: "GetPolicyTemplateDeploy", + GetPolicyTemplateDeploy: { + Name: "GetPolicyTemplateDeploy", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateStatistics: { - Name: "ListPolicyTemplateStatistics", + ListPolicyTemplateStatistics: { + Name: "ListPolicyTemplateStatistics", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateVersions: { - Name: "ListPolicyTemplateVersions", + ListPolicyTemplateVersions: { + Name: "ListPolicyTemplateVersions", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplateVersion: { - Name: "CreatePolicyTemplateVersion", + CreatePolicyTemplateVersion: { + Name: "CreatePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplateVersion: { - Name: "DeletePolicyTemplateVersion", + DeletePolicyTemplateVersion: { + Name: "DeletePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateVersion: { - Name: "GetPolicyTemplateVersion", + GetPolicyTemplateVersion: { + Name: "GetPolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateKind: { - Name: "ExistsPolicyTemplateKind", + ExistsPolicyTemplateKind: { + Name: "ExistsPolicyTemplateKind", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateName: { - Name: "ExistsPolicyTemplateName", + ExistsPolicyTemplateName: { + Name: "ExistsPolicyTemplateName", Group: "OrganizationPolicyTemplate", }, - ExtractParameters: { - Name: "ExtractParameters", + ExtractParameters: { + Name: "ExtractParameters", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateExample: { - Name: "ListPolicyTemplateExample", + ListPolicyTemplateExample: { + Name: "ListPolicyTemplateExample", Group: "PolicyTemplateExample", }, - GetPolicyTemplateExample: { - Name: "GetPolicyTemplateExample", + GetPolicyTemplateExample: { + Name: "GetPolicyTemplateExample", Group: "PolicyTemplateExample", }, - UpdatePolicyTemplateExample: { - Name: "UpdatePolicyTemplateExample", + UpdatePolicyTemplateExample: { + Name: "UpdatePolicyTemplateExample", Group: "PolicyTemplateExample", }, - DeletePolicyTemplateExample: { - Name: "DeletePolicyTemplateExample", + DeletePolicyTemplateExample: { + Name: "DeletePolicyTemplateExample", Group: "PolicyTemplateExample", }, - CompileRego: { - Name: "CompileRego", + CompileRego: { + Name: "CompileRego", Group: "Utility", }, } @@ -957,4 +957,3 @@ func (e Endpoint) String() string { func GetEndpoint(name string) Endpoint { return MapWithName[name] } - diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index f2771fae..f3b8ed25 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -2,6 +2,10 @@ package http import ( "context" + "fmt" + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/pkg/httpErrors" "net/http" "github.com/openinfradev/tks-api/internal/model" @@ -11,6 +15,7 @@ import ( type IPermissionHandler interface { GetPermissionTemplates(w http.ResponseWriter, r *http.Request) + GetEndpoints(w http.ResponseWriter, r *http.Request) } type PermissionHandler struct { @@ -64,3 +69,42 @@ func convertModelToPermissionTemplateResponse(ctx context.Context, permission *m return &permissionResponse } + +// GetEndpoints godoc +// +// @Tags Permission +// @Summary Get Endpoints +// @Description Get Endpoints +// @Accept json +// @Produce json +// @Success 200 {object} domain.GetEndpointsResponse +// @Router /permissions/{permissionId}/endpoints [get] +// @Security JWT +func (h PermissionHandler) GetEndpoints(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + permissionId, ok := vars["permissionId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("permissionId not found"), "PE_INVALID_PERMISSIONID", "permissionId not found")) + return + } + + permissionUuid, err := uuid.Parse(permissionId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("permissionId is invalid"), "PE_INVALID_PERMISSIONID", "permissionId is invalid")) + return + } + + endpoints, err := h.permissionUsecase.GetEndpointsByPermissionId(r.Context(), permissionUuid) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "PE_GET_ENDPOINTS_FAILED", "Failed to get endpoints")) + return + } + + var out domain.GetEndpointsResponse + out.Endpoints = make([]domain.EndpointResponse, 0) + for _, endpoint := range endpoints { + out.Endpoints = append(out.Endpoints, convertEndpointToDomain(endpoint)) + } + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/middleware/auth/authorizer/adminApiFilter.go b/internal/middleware/auth/authorizer/adminApiFilter.go index e19fcf22..2fb006f9 100644 --- a/internal/middleware/auth/authorizer/adminApiFilter.go +++ b/internal/middleware/auth/authorizer/adminApiFilter.go @@ -26,7 +26,7 @@ func AdminApiFilter(handler http.Handler, repo repository.Repository) http.Handl if strings.HasPrefix(endpointInfo.String(), "Admin_") { if requestUserInfo.GetOrganizationId() != "master" { - internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "A_INVALID_TOKEN", "Not allowed access to admin api")) return } } diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 807c2525..3d394b22 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -15,6 +15,7 @@ type IPermissionRepository interface { Delete(ctx context.Context, id uuid.UUID) error Update(ctx context.Context, permission *model.Permission) error EdgeKeyOverwrite(ctx context.Context, permission *model.Permission) error + GetEndpointsByPermissionId(ctx context.Context, permissionId uuid.UUID) (*model.Permission, error) } type PermissionRepository struct { @@ -87,3 +88,13 @@ func (r PermissionRepository) Update(ctx context.Context, p *model.Permission) e func (r PermissionRepository) EdgeKeyOverwrite(ctx context.Context, p *model.Permission) error { return r.db.WithContext(ctx).Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"edge_key": p.EdgeKey}).Error } + +func (r PermissionRepository) GetEndpointsByPermissionId(ctx context.Context, permissionId uuid.UUID) (*model.Permission, error) { + var permission *model.Permission + err := r.db.WithContext(ctx).Preload("Permission_endpoints").First(&permission, "id = ?", permissionId).Error + if err != nil { + return nil, err + } + + return permission, nil +} diff --git a/internal/route/route.go b/internal/route/route.go index 2b9eb1b6..aa557fae 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -318,9 +318,10 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa permissionHandler := delivery.NewPermissionHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/permissions/{permissionId}/endpoints", customMiddleware.Handle(internalApi.GetEndpointsByPermissionId, http.HandlerFunc(permissionHandler.GetEndpoints))).Methods(http.MethodGet) endpointHandler := delivery.NewEndpointHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/endpoints", customMiddleware.Handle(internalApi.GetEndpoints, http.HandlerFunc(endpointHandler.ListEndpoint))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/endpoints", customMiddleware.Handle(internalApi.Admin_GetEndpoints, http.HandlerFunc(endpointHandler.ListEndpoint))).Methods(http.MethodGet) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplate))).Methods(http.MethodGet) diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index 532e723c..bd6b1fc2 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -17,6 +17,7 @@ type IPermissionUsecase interface { GetUserPermissionSet(ctx context.Context) *model.PermissionSet UpdatePermission(ctx context.Context, permission *model.Permission) error MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet + GetEndpointsByPermissionId(ctx context.Context, permissionId uuid.UUID) ([]*model.Endpoint, error) } type PermissionUsecase struct { @@ -133,6 +134,20 @@ func (p PermissionUsecase) GetUserPermissionSet(ctx context.Context) *model.Perm return permissionSet } +func (p PermissionUsecase) GetEndpointsByPermissionId(ctx context.Context, permissionId uuid.UUID) ([]*model.Endpoint, error) { + permission, err := p.repo.GetEndpointsByPermissionId(ctx, permissionId) + if err != nil { + return nil, err + } + + endpoints := make([]*model.Endpoint, 0) + for _, e := range permission.Endpoints { + endpoints = append(endpoints, e) + } + + return endpoints, nil +} + func (p PermissionUsecase) MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet { var out *model.PermissionSet for i, ps := range permissionSet { diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index a1a2e490..3d8ab656 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -78,3 +78,7 @@ type MergePermissionResponse struct { type GetPermissionEdgeKeysResponse struct { } + +type GetEndpointsResponse struct { + Endpoints []EndpointResponse `json:"endpoints"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 21fb3510..3b7efb98 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -146,6 +146,9 @@ var errorMap = map[ErrorCode]string{ "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", "P_INVALID_POLICY_PARAMETER": "정책 파라미터가 템플릿의 파라미터 스키마에 유효하지 않습니다. 파라미터를 확인하세요.", + + // Permission + "PE_INVALID_PERMISSIONID": "유효하지 않은 권한 아이디입니다. 권한 아이디를 확인하세요.", } func (m ErrorCode) GetText() string { From fab0cdf407db8f378f11c67bf09c7cee19d693e0 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 2 May 2024 16:33:35 +0900 Subject: [PATCH 414/502] bugfix. fix ordering of auto migration --- internal/database/database.go | 15 +++++++++++---- internal/model/permission-endpoint.go | 4 ++++ internal/model/permission.go | 2 -- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/internal/database/database.go b/internal/database/database.go index 44f7f095..23c04070 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -63,7 +63,6 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&model.CacheEmailCode{}, &model.ExpiredTokenTime{}, &model.Role{}, - &model.PermissionEndpoint{}, &model.CloudAccount{}, &model.StackTemplate{}, &model.Organization{}, @@ -78,10 +77,8 @@ func migrateSchema(db *gorm.DB) error { &model.SystemNotificationAction{}, &model.SystemNotificationMetricParameter{}, &model.SystemNotificationTemplate{}, - &model.SystemNotificationCondition{}, &model.SystemNotificationRule{}, - &model.Permission{}, - &model.Endpoint{}, + &model.SystemNotificationCondition{}, &model.Project{}, &model.ProjectMember{}, &model.ProjectNamespace{}, @@ -94,6 +91,16 @@ func migrateSchema(db *gorm.DB) error { ); err != nil { return err } + + if err := db.AutoMigrate(&model.Permission{}); err != nil { + return err + } + if err := db.AutoMigrate(&model.Endpoint{}); err != nil { + return err + } + if err := db.AutoMigrate(&model.PermissionEndpoint{}); err != nil { + return err + } return nil } diff --git a/internal/model/permission-endpoint.go b/internal/model/permission-endpoint.go index b7fe0653..10fc3d4f 100644 --- a/internal/model/permission-endpoint.go +++ b/internal/model/permission-endpoint.go @@ -14,6 +14,10 @@ type PermissionEndpoint struct { Endpoint Endpoint `gorm:"foreignKey:EndpointName;references:Name"` } +func (PermissionEndpoint) TableName() string { + return "permission_endpoints" +} + var ( // map[EdgeKey][]Endpoints edgeKeyEndpointMap = map[string][]Endpoint{ diff --git a/internal/model/permission.go b/internal/model/permission.go index a84fa777..0e17b7e8 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -68,8 +68,6 @@ type Permission struct { RoleID *string `json:"role_id,omitempty"` Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;joinForeignKey:EdgeKey;joinReferences:EndpointName;" json:"endpoints,omitempty"` - //PermissionEndpoint []*PermissionEndpoint `gorm:"foreignKey:EdgeKey;references:EdgeKey;"` - // omit empty ParentID *uuid.UUID `json:"parent_id,omitempty"` Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` From 9e7492c64405f3f7c1347b5e63360503953e3842 Mon Sep 17 00:00:00 2001 From: ktkfree Date: Thu, 2 May 2024 17:06:35 +0900 Subject: [PATCH 415/502] Revert "bugfix. fix ordering of auto migration" --- internal/database/database.go | 15 ++++----------- internal/model/permission-endpoint.go | 4 ---- internal/model/permission.go | 2 ++ 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/internal/database/database.go b/internal/database/database.go index 23c04070..44f7f095 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -63,6 +63,7 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&model.CacheEmailCode{}, &model.ExpiredTokenTime{}, &model.Role{}, + &model.PermissionEndpoint{}, &model.CloudAccount{}, &model.StackTemplate{}, &model.Organization{}, @@ -77,8 +78,10 @@ func migrateSchema(db *gorm.DB) error { &model.SystemNotificationAction{}, &model.SystemNotificationMetricParameter{}, &model.SystemNotificationTemplate{}, - &model.SystemNotificationRule{}, &model.SystemNotificationCondition{}, + &model.SystemNotificationRule{}, + &model.Permission{}, + &model.Endpoint{}, &model.Project{}, &model.ProjectMember{}, &model.ProjectNamespace{}, @@ -91,16 +94,6 @@ func migrateSchema(db *gorm.DB) error { ); err != nil { return err } - - if err := db.AutoMigrate(&model.Permission{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.Endpoint{}); err != nil { - return err - } - if err := db.AutoMigrate(&model.PermissionEndpoint{}); err != nil { - return err - } return nil } diff --git a/internal/model/permission-endpoint.go b/internal/model/permission-endpoint.go index 10fc3d4f..b7fe0653 100644 --- a/internal/model/permission-endpoint.go +++ b/internal/model/permission-endpoint.go @@ -14,10 +14,6 @@ type PermissionEndpoint struct { Endpoint Endpoint `gorm:"foreignKey:EndpointName;references:Name"` } -func (PermissionEndpoint) TableName() string { - return "permission_endpoints" -} - var ( // map[EdgeKey][]Endpoints edgeKeyEndpointMap = map[string][]Endpoint{ diff --git a/internal/model/permission.go b/internal/model/permission.go index 0e17b7e8..a84fa777 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -68,6 +68,8 @@ type Permission struct { RoleID *string `json:"role_id,omitempty"` Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;joinForeignKey:EdgeKey;joinReferences:EndpointName;" json:"endpoints,omitempty"` + //PermissionEndpoint []*PermissionEndpoint `gorm:"foreignKey:EdgeKey;references:EdgeKey;"` + // omit empty ParentID *uuid.UUID `json:"parent_id,omitempty"` Parent *Permission `gorm:"foreignKey:ParentID;references:ID;" json:"parent,omitempty"` From ae3fa7812ba5eb38ab70126ea1fd08ffa93040a2 Mon Sep 17 00:00:00 2001 From: ktkfree Date: Thu, 2 May 2024 17:07:33 +0900 Subject: [PATCH 416/502] =?UTF-8?q?Revert=20"Permission-API=20Endpoint=20m?= =?UTF-8?q?apping=20=EA=B0=9C=EC=84=A0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hack/endpoint-codegen.go | 104 +- internal/database/database.go | 3 +- internal/delivery/api/endpoint.go | 10 +- .../delivery/api/endpoints_permission_test.go | 3 +- .../delivery/api/generated_endpoints.go.go | 1893 ++++++++++++----- internal/delivery/http/endpoint.go | 59 - internal/delivery/http/organization.go | 2 +- internal/delivery/http/permission.go | 48 +- internal/delivery/http/role.go | 13 + internal/middleware/audit/audit.go | 2 +- .../auth/authorizer/adminApiFilter.go | 36 - .../middleware/auth/authorizer/authorizer.go | 1 - .../auth/authorizer/organizationFilter.go | 43 - internal/middleware/auth/authorizer/rbac.go | 130 +- internal/model/{endpoint.go => end-point.go} | 0 internal/model/permission-endpoint.go | 435 ---- internal/model/permission.go | 526 +++-- internal/repository/permission.go | 16 - internal/route/route.go | 5 - internal/usecase/endpoint.go | 26 - internal/usecase/permission.go | 15 - internal/usecase/role.go | 198 +- internal/usecase/usecase.go | 1 - pkg/domain/endpoint.go | 4 - pkg/domain/permission.go | 16 +- pkg/httpErrors/errorCode.go | 3 - 26 files changed, 2006 insertions(+), 1586 deletions(-) delete mode 100644 internal/delivery/http/endpoint.go delete mode 100644 internal/middleware/auth/authorizer/adminApiFilter.go delete mode 100644 internal/middleware/auth/authorizer/organizationFilter.go rename internal/model/{endpoint.go => end-point.go} (100%) delete mode 100644 internal/model/permission-endpoint.go delete mode 100644 internal/usecase/endpoint.go diff --git a/hack/endpoint-codegen.go b/hack/endpoint-codegen.go index fc48fee4..354082b3 100644 --- a/hack/endpoint-codegen.go +++ b/hack/endpoint-codegen.go @@ -36,7 +36,7 @@ package api //) //` -const apiMapTemplateStr = `var MapWithEndpoint = map[Endpoint]EndpointInfo{ +const apiMapTemplateStr = `var ApiMap = map[Endpoint]EndpointInfo{ {{- range .}} {{.Name}}: { Name: "{{.Name}}", @@ -46,51 +46,30 @@ const apiMapTemplateStr = `var MapWithEndpoint = map[Endpoint]EndpointInfo{ } ` -const restCodeTemplateStr = `var MapWithName = reverseApiMap() - -func reverseApiMap() map[string]Endpoint { - m := make(map[string]Endpoint) - for k, v := range MapWithEndpoint { - m[v.Name] = k +const stringFunctionTemplateStr = `func (e Endpoint) String() string { + switch e { +{{- range .}} + case {{.Name}}: + return "{{.Name}}" +{{- end}} + default: + return "" } - return m -} - -func (e Endpoint) String() string { - return MapWithEndpoint[e].Name } +` -func GetEndpoint(name string) Endpoint { - return MapWithName[name] +const getEndpointFunctionTemplateStr = `func GetEndpoint(name string) Endpoint { + switch name { +{{- range .}} + case "{{.Name}}": + return {{.Name}} +{{- end}} + default: + return -1 + } } - ` -// -//const stringFunctionTemplateStr = `func (e Endpoint) String() string { -// switch e { -//{{- range .}} -// case {{.Name}}: -// return "{{.Name}}" -//{{- end}} -// default: -// return "" -// } -//} -//` -// -//const getEndpointFunctionTemplateStr = `func GetEndpoint(name string) Endpoint { -// switch name { -//{{- range .}} -// case "{{.Name}}": -// return {{.Name}} -//{{- end}} -// default: -// return -1 -// } -//} -//` - func main() { fset := token.NewFileSet() node, err := parser.ParseFile(fset, endpointFilePath, nil, parser.ParseComments) @@ -178,42 +157,31 @@ func main() { log.Fatalf("failed to execute template: %v", err) } - restCodeTemplate := template.New("restCode") - restCodeTemplate, err = restCodeTemplate.Parse(restCodeTemplateStr) + // contents for stringFunction + stringFunctionTemplate := template.New("stringFunction") + stringFunctionTemplate, err = stringFunctionTemplate.Parse(stringFunctionTemplateStr) if err != nil { log.Fatalf("failed to parse template: %v", err) } - var restCode bytes.Buffer - if err := restCodeTemplate.Execute(&restCode, nil); err != nil { + var stringFunctionCode bytes.Buffer + if err := stringFunctionTemplate.Execute(&stringFunctionCode, endpoints); err != nil { + log.Fatalf("failed to execute template: %v", err) + } + + // contents for getEndpointFunction + getEndpointFunctionTemplate := template.New("getEndpointFunction") + getEndpointFunctionTemplate, err = getEndpointFunctionTemplate.Parse(getEndpointFunctionTemplateStr) + if err != nil { + log.Fatalf("failed to parse template: %v", err) + } + var getEndpointFunctionCode bytes.Buffer + if err := getEndpointFunctionTemplate.Execute(&getEndpointFunctionCode, endpoints); err != nil { log.Fatalf("failed to execute template: %v", err) } - // - //// contents for stringFunction - //stringFunctionTemplate := template.New("stringFunction") - //stringFunctionTemplate, err = stringFunctionTemplate.Parse(stringFunctionTemplateStr) - //if err != nil { - // log.Fatalf("failed to parse template: %v", err) - //} - //var stringFunctionCode bytes.Buffer - //if err := stringFunctionTemplate.Execute(&stringFunctionCode, endpoints); err != nil { - // log.Fatalf("failed to execute template: %v", err) - //} - // - //// contents for getEndpointFunction - //getEndpointFunctionTemplate := template.New("getEndpointFunction") - //getEndpointFunctionTemplate, err = getEndpointFunctionTemplate.Parse(getEndpointFunctionTemplateStr) - //if err != nil { - // log.Fatalf("failed to parse template: %v", err) - //} - //var getEndpointFunctionCode bytes.Buffer - //if err := getEndpointFunctionTemplate.Execute(&getEndpointFunctionCode, endpoints); err != nil { - // log.Fatalf("failed to execute template: %v", err) - //} // replace original file(endpointFilePath) with new contents //contents := indexCode.String() + endpointCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() - //contents := indexCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() - contents := indexCode.String() + apiMapCode.String() + restCode.String() + contents := indexCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() newFilePath := strings.Replace(endpointFilePath, "endpoint", "generated_endpoints.go", 1) if err := ioutil.WriteFile(newFilePath, []byte(contents), 0644); err != nil { diff --git a/internal/database/database.go b/internal/database/database.go index 44f7f095..9fcb1a37 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -63,7 +63,6 @@ func migrateSchema(db *gorm.DB) error { if err := db.AutoMigrate(&model.CacheEmailCode{}, &model.ExpiredTokenTime{}, &model.Role{}, - &model.PermissionEndpoint{}, &model.CloudAccount{}, &model.StackTemplate{}, &model.Organization{}, @@ -132,7 +131,7 @@ func EnsureDefaultRows(db *gorm.DB) error { for _, ep := range eps { storedEps[ep.Name] = struct{}{} } - for _, ep := range api.MapWithEndpoint { + for _, ep := range api.ApiMap { if _, ok := storedEps[ep.Name]; !ok { if err := repoFactory.Endpoint.Create(ctx, &model.Endpoint{ Name: ep.Name, diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index c0747230..c847c189 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -161,14 +161,14 @@ const ( GetPolicyNotification // Stack - CreateStack // 스택관리/생성 GetStacks // 스택관리/조회 + CreateStack // 스택관리/생성 + CheckStackName // 스택관리/조회 GetStack // 스택관리/조회 UpdateStack // 스택관리/수정 DeleteStack // 스택관리/삭제 - CheckStackName // 스택관리/조회 - GetStackStatus // 스택관리/조회 GetStackKubeConfig // 스택관리/조회 + GetStackStatus // 스택관리/조회 SetFavoriteStack // 스택관리/조회 DeleteFavoriteStack // 스택관리/조회 InstallStack // 스택관리 / 조회 @@ -219,10 +219,6 @@ const ( // Permission GetPermissionTemplates - GetEndpointsByPermissionId - - // Endpoint - Admin_GetEndpoints // Admin_User Admin_CreateUser diff --git a/internal/delivery/api/endpoints_permission_test.go b/internal/delivery/api/endpoints_permission_test.go index a4ba98bf..b012f456 100644 --- a/internal/delivery/api/endpoints_permission_test.go +++ b/internal/delivery/api/endpoints_permission_test.go @@ -8,7 +8,7 @@ import ( func TestEndpointsUsage(t *testing.T) { var allEndpoints []string - for _, v := range api.MapWithEndpoint { + for _, v := range api.ApiMap { allEndpoints = append(allEndpoints, v.Name) } //allEndpoints := []Endpoint{ @@ -26,6 +26,7 @@ func TestEndpointsUsage(t *testing.T) { ps.Stack, ps.Policy, ps.Common, + ps.Admin, } leafPermissions := make([]*model.Permission, 0) diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index e8d61139..937cb4d0 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -1,959 +1,1882 @@ -// This is generated code. DO NOT EDIT. + // This is generated code. DO NOT EDIT. package api -var MapWithEndpoint = map[Endpoint]EndpointInfo{ - Login: { - Name: "Login", +var ApiMap = map[Endpoint]EndpointInfo{ + Login: { + Name: "Login", Group: "Auth", }, - Logout: { - Name: "Logout", + Logout: { + Name: "Logout", Group: "Auth", }, - RefreshToken: { - Name: "RefreshToken", + RefreshToken: { + Name: "RefreshToken", Group: "Auth", }, - FindId: { - Name: "FindId", + FindId: { + Name: "FindId", Group: "Auth", }, - FindPassword: { - Name: "FindPassword", + FindPassword: { + Name: "FindPassword", Group: "Auth", }, - VerifyIdentityForLostId: { - Name: "VerifyIdentityForLostId", + VerifyIdentityForLostId: { + Name: "VerifyIdentityForLostId", Group: "Auth", }, - VerifyIdentityForLostPassword: { - Name: "VerifyIdentityForLostPassword", + VerifyIdentityForLostPassword: { + Name: "VerifyIdentityForLostPassword", Group: "Auth", }, - VerifyToken: { - Name: "VerifyToken", + VerifyToken: { + Name: "VerifyToken", Group: "Auth", }, - CreateUser: { - Name: "CreateUser", + CreateUser: { + Name: "CreateUser", Group: "User", }, - ListUser: { - Name: "ListUser", + ListUser: { + Name: "ListUser", Group: "User", }, - GetUser: { - Name: "GetUser", + GetUser: { + Name: "GetUser", Group: "User", }, - DeleteUser: { - Name: "DeleteUser", + DeleteUser: { + Name: "DeleteUser", Group: "User", }, - UpdateUsers: { - Name: "UpdateUsers", + UpdateUsers: { + Name: "UpdateUsers", Group: "User", }, - UpdateUser: { - Name: "UpdateUser", + UpdateUser: { + Name: "UpdateUser", Group: "User", }, - ResetPassword: { - Name: "ResetPassword", + ResetPassword: { + Name: "ResetPassword", Group: "User", }, - CheckId: { - Name: "CheckId", + CheckId: { + Name: "CheckId", Group: "User", }, - CheckEmail: { - Name: "CheckEmail", + CheckEmail: { + Name: "CheckEmail", Group: "User", }, - GetPermissionsByAccountId: { - Name: "GetPermissionsByAccountId", + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", Group: "User", }, - GetMyProfile: { - Name: "GetMyProfile", + GetMyProfile: { + Name: "GetMyProfile", Group: "MyProfile", }, - UpdateMyProfile: { - Name: "UpdateMyProfile", + UpdateMyProfile: { + Name: "UpdateMyProfile", Group: "MyProfile", }, - UpdateMyPassword: { - Name: "UpdateMyPassword", + UpdateMyPassword: { + Name: "UpdateMyPassword", Group: "MyProfile", }, - RenewPasswordExpiredDate: { - Name: "RenewPasswordExpiredDate", + RenewPasswordExpiredDate: { + Name: "RenewPasswordExpiredDate", Group: "MyProfile", }, - DeleteMyProfile: { - Name: "DeleteMyProfile", + DeleteMyProfile: { + Name: "DeleteMyProfile", Group: "MyProfile", }, - Admin_CreateOrganization: { - Name: "Admin_CreateOrganization", + Admin_CreateOrganization: { + Name: "Admin_CreateOrganization", Group: "Organization", }, - Admin_DeleteOrganization: { - Name: "Admin_DeleteOrganization", + Admin_DeleteOrganization: { + Name: "Admin_DeleteOrganization", Group: "Organization", }, - GetOrganizations: { - Name: "GetOrganizations", + GetOrganizations: { + Name: "GetOrganizations", Group: "Organization", }, - GetOrganization: { - Name: "GetOrganization", + GetOrganization: { + Name: "GetOrganization", Group: "Organization", }, - CheckOrganizationName: { - Name: "CheckOrganizationName", + CheckOrganizationName: { + Name: "CheckOrganizationName", Group: "Organization", }, - UpdateOrganization: { - Name: "UpdateOrganization", + UpdateOrganization: { + Name: "UpdateOrganization", Group: "Organization", }, - UpdatePrimaryCluster: { - Name: "UpdatePrimaryCluster", + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", Group: "Organization", }, - CreateCluster: { - Name: "CreateCluster", + CreateCluster: { + Name: "CreateCluster", Group: "Cluster", }, - GetClusters: { - Name: "GetClusters", + GetClusters: { + Name: "GetClusters", Group: "Cluster", }, - ImportCluster: { - Name: "ImportCluster", + ImportCluster: { + Name: "ImportCluster", Group: "Cluster", }, - GetCluster: { - Name: "GetCluster", + GetCluster: { + Name: "GetCluster", Group: "Cluster", }, - DeleteCluster: { - Name: "DeleteCluster", + DeleteCluster: { + Name: "DeleteCluster", Group: "Cluster", }, - GetClusterSiteValues: { - Name: "GetClusterSiteValues", + GetClusterSiteValues: { + Name: "GetClusterSiteValues", Group: "Cluster", }, - InstallCluster: { - Name: "InstallCluster", + InstallCluster: { + Name: "InstallCluster", Group: "Cluster", }, - CreateBootstrapKubeconfig: { - Name: "CreateBootstrapKubeconfig", + CreateBootstrapKubeconfig: { + Name: "CreateBootstrapKubeconfig", Group: "Cluster", }, - GetBootstrapKubeconfig: { - Name: "GetBootstrapKubeconfig", + GetBootstrapKubeconfig: { + Name: "GetBootstrapKubeconfig", Group: "Cluster", }, - GetNodes: { - Name: "GetNodes", + GetNodes: { + Name: "GetNodes", Group: "Cluster", }, - CreateAppgroup: { - Name: "CreateAppgroup", + CreateAppgroup: { + Name: "CreateAppgroup", Group: "Appgroup", }, - GetAppgroups: { - Name: "GetAppgroups", + GetAppgroups: { + Name: "GetAppgroups", Group: "Appgroup", }, - GetAppgroup: { - Name: "GetAppgroup", + GetAppgroup: { + Name: "GetAppgroup", Group: "Appgroup", }, - DeleteAppgroup: { - Name: "DeleteAppgroup", + DeleteAppgroup: { + Name: "DeleteAppgroup", Group: "Appgroup", }, - GetApplications: { - Name: "GetApplications", + GetApplications: { + Name: "GetApplications", Group: "Appgroup", }, - CreateApplication: { - Name: "CreateApplication", + CreateApplication: { + Name: "CreateApplication", Group: "Appgroup", }, - GetAppServeAppTasksByAppId: { - Name: "GetAppServeAppTasksByAppId", + GetAppServeAppTasksByAppId: { + Name: "GetAppServeAppTasksByAppId", Group: "AppServeApp", }, - GetAppServeAppTaskDetail: { - Name: "GetAppServeAppTaskDetail", + GetAppServeAppTaskDetail: { + Name: "GetAppServeAppTaskDetail", Group: "AppServeApp", }, - CreateAppServeApp: { - Name: "CreateAppServeApp", + CreateAppServeApp: { + Name: "CreateAppServeApp", Group: "AppServeApp", }, - GetAppServeApps: { - Name: "GetAppServeApps", + GetAppServeApps: { + Name: "GetAppServeApps", Group: "AppServeApp", }, - GetNumOfAppsOnStack: { - Name: "GetNumOfAppsOnStack", + GetNumOfAppsOnStack: { + Name: "GetNumOfAppsOnStack", Group: "AppServeApp", }, - GetAppServeApp: { - Name: "GetAppServeApp", + GetAppServeApp: { + Name: "GetAppServeApp", Group: "AppServeApp", }, - GetAppServeAppLatestTask: { - Name: "GetAppServeAppLatestTask", + GetAppServeAppLatestTask: { + Name: "GetAppServeAppLatestTask", Group: "AppServeApp", }, - IsAppServeAppExist: { - Name: "IsAppServeAppExist", + IsAppServeAppExist: { + Name: "IsAppServeAppExist", Group: "AppServeApp", }, - IsAppServeAppNameExist: { - Name: "IsAppServeAppNameExist", + IsAppServeAppNameExist: { + Name: "IsAppServeAppNameExist", Group: "AppServeApp", }, - DeleteAppServeApp: { - Name: "DeleteAppServeApp", + DeleteAppServeApp: { + Name: "DeleteAppServeApp", Group: "AppServeApp", }, - UpdateAppServeApp: { - Name: "UpdateAppServeApp", + UpdateAppServeApp: { + Name: "UpdateAppServeApp", Group: "AppServeApp", }, - UpdateAppServeAppStatus: { - Name: "UpdateAppServeAppStatus", + UpdateAppServeAppStatus: { + Name: "UpdateAppServeAppStatus", Group: "AppServeApp", }, - UpdateAppServeAppEndpoint: { - Name: "UpdateAppServeAppEndpoint", + UpdateAppServeAppEndpoint: { + Name: "UpdateAppServeAppEndpoint", Group: "AppServeApp", }, - RollbackAppServeApp: { - Name: "RollbackAppServeApp", + RollbackAppServeApp: { + Name: "RollbackAppServeApp", Group: "AppServeApp", }, - GetCloudAccounts: { - Name: "GetCloudAccounts", + GetCloudAccounts: { + Name: "GetCloudAccounts", Group: "CloudAccount", }, - CreateCloudAccount: { - Name: "CreateCloudAccount", + CreateCloudAccount: { + Name: "CreateCloudAccount", Group: "CloudAccount", }, - CheckCloudAccountName: { - Name: "CheckCloudAccountName", + CheckCloudAccountName: { + Name: "CheckCloudAccountName", Group: "CloudAccount", }, - CheckAwsAccountId: { - Name: "CheckAwsAccountId", + CheckAwsAccountId: { + Name: "CheckAwsAccountId", Group: "CloudAccount", }, - GetCloudAccount: { - Name: "GetCloudAccount", + GetCloudAccount: { + Name: "GetCloudAccount", Group: "CloudAccount", }, - UpdateCloudAccount: { - Name: "UpdateCloudAccount", + UpdateCloudAccount: { + Name: "UpdateCloudAccount", Group: "CloudAccount", }, - DeleteCloudAccount: { - Name: "DeleteCloudAccount", + DeleteCloudAccount: { + Name: "DeleteCloudAccount", Group: "CloudAccount", }, - DeleteForceCloudAccount: { - Name: "DeleteForceCloudAccount", + DeleteForceCloudAccount: { + Name: "DeleteForceCloudAccount", Group: "CloudAccount", }, - GetResourceQuota: { - Name: "GetResourceQuota", + GetResourceQuota: { + Name: "GetResourceQuota", Group: "CloudAccount", }, - Admin_GetStackTemplates: { - Name: "Admin_GetStackTemplates", + Admin_GetStackTemplates: { + Name: "Admin_GetStackTemplates", Group: "StackTemplate", }, - Admin_GetStackTemplate: { - Name: "Admin_GetStackTemplate", + Admin_GetStackTemplate: { + Name: "Admin_GetStackTemplate", Group: "StackTemplate", }, - Admin_GetStackTemplateServices: { - Name: "Admin_GetStackTemplateServices", + Admin_GetStackTemplateServices: { + Name: "Admin_GetStackTemplateServices", Group: "StackTemplate", }, - Admin_GetStackTemplateTemplateIds: { - Name: "Admin_GetStackTemplateTemplateIds", + Admin_GetStackTemplateTemplateIds: { + Name: "Admin_GetStackTemplateTemplateIds", Group: "StackTemplate", }, - Admin_CreateStackTemplate: { - Name: "Admin_CreateStackTemplate", + Admin_CreateStackTemplate: { + Name: "Admin_CreateStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplate: { - Name: "Admin_UpdateStackTemplate", + Admin_UpdateStackTemplate: { + Name: "Admin_UpdateStackTemplate", Group: "StackTemplate", }, - Admin_DeleteStackTemplate: { - Name: "Admin_DeleteStackTemplate", + Admin_DeleteStackTemplate: { + Name: "Admin_DeleteStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplateOrganizations: { - Name: "Admin_UpdateStackTemplateOrganizations", + Admin_UpdateStackTemplateOrganizations: { + Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, - Admin_CheckStackTemplateName: { - Name: "Admin_CheckStackTemplateName", + Admin_CheckStackTemplateName: { + Name: "Admin_CheckStackTemplateName", Group: "StackTemplate", }, - GetOrganizationStackTemplates: { - Name: "GetOrganizationStackTemplates", + GetOrganizationStackTemplates: { + Name: "GetOrganizationStackTemplates", Group: "StackTemplate", }, - GetOrganizationStackTemplate: { - Name: "GetOrganizationStackTemplate", + GetOrganizationStackTemplate: { + Name: "GetOrganizationStackTemplate", Group: "StackTemplate", }, - AddOrganizationStackTemplates: { - Name: "AddOrganizationStackTemplates", + AddOrganizationStackTemplates: { + Name: "AddOrganizationStackTemplates", Group: "StackTemplate", }, - RemoveOrganizationStackTemplates: { - Name: "RemoveOrganizationStackTemplates", + RemoveOrganizationStackTemplates: { + Name: "RemoveOrganizationStackTemplates", Group: "StackTemplate", }, - CreateDashboard: { - Name: "CreateDashboard", + CreateDashboard: { + Name: "CreateDashboard", Group: "Dashboard", }, - GetDashboard: { - Name: "GetDashboard", + GetDashboard: { + Name: "GetDashboard", Group: "Dashboard", }, - UpdateDashboard: { - Name: "UpdateDashboard", + UpdateDashboard: { + Name: "UpdateDashboard", Group: "Dashboard", }, - GetChartsDashboard: { - Name: "GetChartsDashboard", + GetChartsDashboard: { + Name: "GetChartsDashboard", Group: "Dashboard", }, - GetChartDashboard: { - Name: "GetChartDashboard", + GetChartDashboard: { + Name: "GetChartDashboard", Group: "Dashboard", }, - GetStacksDashboard: { - Name: "GetStacksDashboard", + GetStacksDashboard: { + Name: "GetStacksDashboard", Group: "Dashboard", }, - GetResourcesDashboard: { - Name: "GetResourcesDashboard", + GetResourcesDashboard: { + Name: "GetResourcesDashboard", Group: "Dashboard", }, - GetPolicyStatusDashboard: { - Name: "GetPolicyStatusDashboard", + GetPolicyStatusDashboard: { + Name: "GetPolicyStatusDashboard", Group: "Dashboard", }, - GetPolicyUpdateDashboard: { - Name: "GetPolicyUpdateDashboard", + GetPolicyUpdateDashboard: { + Name: "GetPolicyUpdateDashboard", Group: "Dashboard", }, - GetPolicyEnforcementDashboard: { - Name: "GetPolicyEnforcementDashboard", + GetPolicyEnforcementDashboard: { + Name: "GetPolicyEnforcementDashboard", Group: "Dashboard", }, - GetPolicyViolationDashboard: { - Name: "GetPolicyViolationDashboard", + GetPolicyViolationDashboard: { + Name: "GetPolicyViolationDashboard", Group: "Dashboard", }, - GetPolicyViolationLogDashboard: { - Name: "GetPolicyViolationLogDashboard", + GetPolicyViolationLogDashboard: { + Name: "GetPolicyViolationLogDashboard", Group: "Dashboard", }, - GetPolicyStatisticsDashboard: { - Name: "GetPolicyStatisticsDashboard", + GetPolicyStatisticsDashboard: { + Name: "GetPolicyStatisticsDashboard", Group: "Dashboard", }, - GetWorkloadDashboard: { - Name: "GetWorkloadDashboard", + GetWorkloadDashboard: { + Name: "GetWorkloadDashboard", Group: "Dashboard", }, - GetPolicyViolationTop5Dashboard: { - Name: "GetPolicyViolationTop5Dashboard", + GetPolicyViolationTop5Dashboard: { + Name: "GetPolicyViolationTop5Dashboard", Group: "Dashboard", }, - Admin_CreateSystemNotificationTemplate: { - Name: "Admin_CreateSystemNotificationTemplate", + Admin_CreateSystemNotificationTemplate: { + Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_UpdateSystemNotificationTemplate: { - Name: "Admin_UpdateSystemNotificationTemplate", + Admin_UpdateSystemNotificationTemplate: { + Name: "Admin_UpdateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_DeleteSystemNotificationTemplate: { - Name: "Admin_DeleteSystemNotificationTemplate", + Admin_DeleteSystemNotificationTemplate: { + Name: "Admin_DeleteSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplates: { - Name: "Admin_GetSystemNotificationTemplates", + Admin_GetSystemNotificationTemplates: { + Name: "Admin_GetSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplate: { - Name: "Admin_GetSystemNotificationTemplate", + Admin_GetSystemNotificationTemplate: { + Name: "Admin_GetSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_CheckSystemNotificationTemplateName: { - Name: "Admin_CheckSystemNotificationTemplateName", + Admin_CheckSystemNotificationTemplateName: { + Name: "Admin_CheckSystemNotificationTemplateName", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplates: { - Name: "GetOrganizationSystemNotificationTemplates", + GetOrganizationSystemNotificationTemplates: { + Name: "GetOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplate: { - Name: "GetOrganizationSystemNotificationTemplate", + GetOrganizationSystemNotificationTemplate: { + Name: "GetOrganizationSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - AddOrganizationSystemNotificationTemplates: { - Name: "AddOrganizationSystemNotificationTemplates", + AddOrganizationSystemNotificationTemplates: { + Name: "AddOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - RemoveOrganizationSystemNotificationTemplates: { - Name: "RemoveOrganizationSystemNotificationTemplates", + RemoveOrganizationSystemNotificationTemplates: { + Name: "RemoveOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - CreateSystemNotificationRule: { - Name: "CreateSystemNotificationRule", + CreateSystemNotificationRule: { + Name: "CreateSystemNotificationRule", Group: "SystemNotificationRule", }, - GetSystemNotificationRules: { - Name: "GetSystemNotificationRules", + GetSystemNotificationRules: { + Name: "GetSystemNotificationRules", Group: "SystemNotificationRule", }, - GetSystemNotificationRule: { - Name: "GetSystemNotificationRule", + GetSystemNotificationRule: { + Name: "GetSystemNotificationRule", Group: "SystemNotificationRule", }, - CheckSystemNotificationRuleName: { - Name: "CheckSystemNotificationRuleName", + CheckSystemNotificationRuleName: { + Name: "CheckSystemNotificationRuleName", Group: "SystemNotificationRule", }, - DeleteSystemNotificationRule: { - Name: "DeleteSystemNotificationRule", + DeleteSystemNotificationRule: { + Name: "DeleteSystemNotificationRule", Group: "SystemNotificationRule", }, - UpdateSystemNotificationRule: { - Name: "UpdateSystemNotificationRule", + UpdateSystemNotificationRule: { + Name: "UpdateSystemNotificationRule", Group: "SystemNotificationRule", }, - MakeDefaultSystemNotificationRules: { - Name: "MakeDefaultSystemNotificationRules", + MakeDefaultSystemNotificationRules: { + Name: "MakeDefaultSystemNotificationRules", Group: "SystemNotificationRule", }, - CreateSystemNotification: { - Name: "CreateSystemNotification", + CreateSystemNotification: { + Name: "CreateSystemNotification", Group: "SystemNotification", }, - GetSystemNotifications: { - Name: "GetSystemNotifications", + GetSystemNotifications: { + Name: "GetSystemNotifications", Group: "SystemNotification", }, - GetSystemNotification: { - Name: "GetSystemNotification", + GetSystemNotification: { + Name: "GetSystemNotification", Group: "SystemNotification", }, - DeleteSystemNotification: { - Name: "DeleteSystemNotification", + DeleteSystemNotification: { + Name: "DeleteSystemNotification", Group: "SystemNotification", }, - UpdateSystemNotification: { - Name: "UpdateSystemNotification", + UpdateSystemNotification: { + Name: "UpdateSystemNotification", Group: "SystemNotification", }, - CreateSystemNotificationAction: { - Name: "CreateSystemNotificationAction", + CreateSystemNotificationAction: { + Name: "CreateSystemNotificationAction", Group: "SystemNotification", }, - GetPolicyNotifications: { - Name: "GetPolicyNotifications", + GetPolicyNotifications: { + Name: "GetPolicyNotifications", Group: "PolicyNotification", }, - GetPolicyNotification: { - Name: "GetPolicyNotification", + GetPolicyNotification: { + Name: "GetPolicyNotification", Group: "PolicyNotification", }, - CreateStack: { - Name: "CreateStack", + GetStacks: { + Name: "GetStacks", Group: "Stack", }, - GetStacks: { - Name: "GetStacks", + CreateStack: { + Name: "CreateStack", Group: "Stack", }, - GetStack: { - Name: "GetStack", + CheckStackName: { + Name: "CheckStackName", Group: "Stack", }, - UpdateStack: { - Name: "UpdateStack", + GetStack: { + Name: "GetStack", Group: "Stack", }, - DeleteStack: { - Name: "DeleteStack", + UpdateStack: { + Name: "UpdateStack", Group: "Stack", }, - CheckStackName: { - Name: "CheckStackName", + DeleteStack: { + Name: "DeleteStack", Group: "Stack", }, - GetStackStatus: { - Name: "GetStackStatus", + GetStackKubeConfig: { + Name: "GetStackKubeConfig", Group: "Stack", }, - GetStackKubeConfig: { - Name: "GetStackKubeConfig", + GetStackStatus: { + Name: "GetStackStatus", Group: "Stack", }, - SetFavoriteStack: { - Name: "SetFavoriteStack", + SetFavoriteStack: { + Name: "SetFavoriteStack", Group: "Stack", }, - DeleteFavoriteStack: { - Name: "DeleteFavoriteStack", + DeleteFavoriteStack: { + Name: "DeleteFavoriteStack", Group: "Stack", }, - InstallStack: { - Name: "InstallStack", + InstallStack: { + Name: "InstallStack", Group: "Stack", }, - CreateProject: { - Name: "CreateProject", + CreateProject: { + Name: "CreateProject", Group: "Project", }, - GetProjectRoles: { - Name: "GetProjectRoles", + GetProjectRoles: { + Name: "GetProjectRoles", Group: "Project", }, - GetProjectRole: { - Name: "GetProjectRole", + GetProjectRole: { + Name: "GetProjectRole", Group: "Project", }, - GetProjects: { - Name: "GetProjects", + GetProjects: { + Name: "GetProjects", Group: "Project", }, - GetProject: { - Name: "GetProject", + GetProject: { + Name: "GetProject", Group: "Project", }, - UpdateProject: { - Name: "UpdateProject", + UpdateProject: { + Name: "UpdateProject", Group: "Project", }, - DeleteProject: { - Name: "DeleteProject", + DeleteProject: { + Name: "DeleteProject", Group: "Project", }, - AddProjectMember: { - Name: "AddProjectMember", + AddProjectMember: { + Name: "AddProjectMember", Group: "Project", }, - GetProjectMember: { - Name: "GetProjectMember", + GetProjectMember: { + Name: "GetProjectMember", Group: "Project", }, - GetProjectMembers: { - Name: "GetProjectMembers", + GetProjectMembers: { + Name: "GetProjectMembers", Group: "Project", }, - RemoveProjectMember: { - Name: "RemoveProjectMember", + RemoveProjectMember: { + Name: "RemoveProjectMember", Group: "Project", }, - UpdateProjectMemberRole: { - Name: "UpdateProjectMemberRole", + UpdateProjectMemberRole: { + Name: "UpdateProjectMemberRole", Group: "Project", }, - CreateProjectNamespace: { - Name: "CreateProjectNamespace", + CreateProjectNamespace: { + Name: "CreateProjectNamespace", Group: "Project", }, - GetProjectNamespaces: { - Name: "GetProjectNamespaces", + GetProjectNamespaces: { + Name: "GetProjectNamespaces", Group: "Project", }, - GetProjectNamespace: { - Name: "GetProjectNamespace", + GetProjectNamespace: { + Name: "GetProjectNamespace", Group: "Project", }, - UpdateProjectNamespace: { - Name: "UpdateProjectNamespace", + UpdateProjectNamespace: { + Name: "UpdateProjectNamespace", Group: "Project", }, - DeleteProjectNamespace: { - Name: "DeleteProjectNamespace", + DeleteProjectNamespace: { + Name: "DeleteProjectNamespace", Group: "Project", }, - SetFavoriteProject: { - Name: "SetFavoriteProject", + SetFavoriteProject: { + Name: "SetFavoriteProject", Group: "Project", }, - SetFavoriteProjectNamespace: { - Name: "SetFavoriteProjectNamespace", + SetFavoriteProjectNamespace: { + Name: "SetFavoriteProjectNamespace", Group: "Project", }, - UnSetFavoriteProject: { - Name: "UnSetFavoriteProject", + UnSetFavoriteProject: { + Name: "UnSetFavoriteProject", Group: "Project", }, - UnSetFavoriteProjectNamespace: { - Name: "UnSetFavoriteProjectNamespace", + UnSetFavoriteProjectNamespace: { + Name: "UnSetFavoriteProjectNamespace", Group: "Project", }, - GetProjectKubeconfig: { - Name: "GetProjectKubeconfig", + GetProjectKubeconfig: { + Name: "GetProjectKubeconfig", Group: "Project", }, - GetProjectNamespaceK8sResources: { - Name: "GetProjectNamespaceK8sResources", + GetProjectNamespaceK8sResources: { + Name: "GetProjectNamespaceK8sResources", Group: "Project", }, - GetProjectNamespaceKubeconfig: { - Name: "GetProjectNamespaceKubeconfig", + GetProjectNamespaceKubeconfig: { + Name: "GetProjectNamespaceKubeconfig", Group: "Project", }, - GetAudits: { - Name: "GetAudits", + GetAudits: { + Name: "GetAudits", Group: "Audit", }, - GetAudit: { - Name: "GetAudit", + GetAudit: { + Name: "GetAudit", Group: "Audit", }, - DeleteAudit: { - Name: "DeleteAudit", + DeleteAudit: { + Name: "DeleteAudit", Group: "Audit", }, - CreateTksRole: { - Name: "CreateTksRole", + CreateTksRole: { + Name: "CreateTksRole", Group: "Role", }, - ListTksRoles: { - Name: "ListTksRoles", + ListTksRoles: { + Name: "ListTksRoles", Group: "Role", }, - GetTksRole: { - Name: "GetTksRole", + GetTksRole: { + Name: "GetTksRole", Group: "Role", }, - DeleteTksRole: { - Name: "DeleteTksRole", + DeleteTksRole: { + Name: "DeleteTksRole", Group: "Role", }, - UpdateTksRole: { - Name: "UpdateTksRole", + UpdateTksRole: { + Name: "UpdateTksRole", Group: "Role", }, - GetPermissionsByRoleId: { - Name: "GetPermissionsByRoleId", + GetPermissionsByRoleId: { + Name: "GetPermissionsByRoleId", Group: "Role", }, - UpdatePermissionsByRoleId: { - Name: "UpdatePermissionsByRoleId", + UpdatePermissionsByRoleId: { + Name: "UpdatePermissionsByRoleId", Group: "Role", }, - IsRoleNameExisted: { - Name: "IsRoleNameExisted", + IsRoleNameExisted: { + Name: "IsRoleNameExisted", Group: "Role", }, - AppendUsersToRole: { - Name: "AppendUsersToRole", + AppendUsersToRole: { + Name: "AppendUsersToRole", Group: "Role", }, - GetUsersInRoleId: { - Name: "GetUsersInRoleId", + GetUsersInRoleId: { + Name: "GetUsersInRoleId", Group: "Role", }, - RemoveUsersFromRole: { - Name: "RemoveUsersFromRole", + RemoveUsersFromRole: { + Name: "RemoveUsersFromRole", Group: "Role", }, - GetPermissionTemplates: { - Name: "GetPermissionTemplates", + GetPermissionTemplates: { + Name: "GetPermissionTemplates", Group: "Permission", }, - Admin_GetEndpoints: { - Name: "Admin_GetEndpoints", - Group: "Endpoint", - }, - Admin_CreateUser: { - Name: "Admin_CreateUser", + Admin_CreateUser: { + Name: "Admin_CreateUser", Group: "Admin_User", }, - Admin_ListUser: { - Name: "Admin_ListUser", + Admin_ListUser: { + Name: "Admin_ListUser", Group: "Admin_User", }, - Admin_GetUser: { - Name: "Admin_GetUser", + Admin_GetUser: { + Name: "Admin_GetUser", Group: "Admin_User", }, - Admin_DeleteUser: { - Name: "Admin_DeleteUser", + Admin_DeleteUser: { + Name: "Admin_DeleteUser", Group: "Admin_User", }, - Admin_UpdateUser: { - Name: "Admin_UpdateUser", + Admin_UpdateUser: { + Name: "Admin_UpdateUser", Group: "Admin_User", }, - Admin_ListTksRoles: { - Name: "Admin_ListTksRoles", + Admin_ListTksRoles: { + Name: "Admin_ListTksRoles", Group: "Admin Role", }, - Admin_GetTksRole: { - Name: "Admin_GetTksRole", + Admin_GetTksRole: { + Name: "Admin_GetTksRole", Group: "Admin Role", }, - Admin_GetProjects: { - Name: "Admin_GetProjects", + Admin_GetProjects: { + Name: "Admin_GetProjects", Group: "Admin Project", }, - Admin_ListPolicyTemplate: { - Name: "Admin_ListPolicyTemplate", + Admin_ListPolicyTemplate: { + Name: "Admin_ListPolicyTemplate", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplate: { - Name: "Admin_CreatePolicyTemplate", + Admin_CreatePolicyTemplate: { + Name: "Admin_CreatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplate: { - Name: "Admin_DeletePolicyTemplate", + Admin_DeletePolicyTemplate: { + Name: "Admin_DeletePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplate: { - Name: "Admin_GetPolicyTemplate", + Admin_GetPolicyTemplate: { + Name: "Admin_GetPolicyTemplate", Group: "PolicyTemplate", }, - Admin_UpdatePolicyTemplate: { - Name: "Admin_UpdatePolicyTemplate", + Admin_UpdatePolicyTemplate: { + Name: "Admin_UpdatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateDeploy: { - Name: "Admin_GetPolicyTemplateDeploy", + Admin_GetPolicyTemplateDeploy: { + Name: "Admin_GetPolicyTemplateDeploy", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateStatistics: { - Name: "Admin_ListPolicyTemplateStatistics", + Admin_ListPolicyTemplateStatistics: { + Name: "Admin_ListPolicyTemplateStatistics", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateVersions: { - Name: "Admin_ListPolicyTemplateVersions", + Admin_ListPolicyTemplateVersions: { + Name: "Admin_ListPolicyTemplateVersions", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplateVersion: { - Name: "Admin_CreatePolicyTemplateVersion", + Admin_CreatePolicyTemplateVersion: { + Name: "Admin_CreatePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplateVersion: { - Name: "Admin_DeletePolicyTemplateVersion", + Admin_DeletePolicyTemplateVersion: { + Name: "Admin_DeletePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateVersion: { - Name: "Admin_GetPolicyTemplateVersion", + Admin_GetPolicyTemplateVersion: { + Name: "Admin_GetPolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateKind: { - Name: "Admin_ExistsPolicyTemplateKind", + Admin_ExistsPolicyTemplateKind: { + Name: "Admin_ExistsPolicyTemplateKind", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateName: { - Name: "Admin_ExistsPolicyTemplateName", + Admin_ExistsPolicyTemplateName: { + Name: "Admin_ExistsPolicyTemplateName", Group: "PolicyTemplate", }, - Admin_ExtractParameters: { - Name: "Admin_ExtractParameters", + Admin_ExtractParameters: { + Name: "Admin_ExtractParameters", Group: "PolicyTemplate", }, - Admin_AddPermittedPolicyTemplatesForOrganization: { - Name: "Admin_AddPermittedPolicyTemplatesForOrganization", + Admin_AddPermittedPolicyTemplatesForOrganization: { + Name: "Admin_AddPermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - Admin_DeletePermittedPolicyTemplatesForOrganization: { - Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", + Admin_DeletePermittedPolicyTemplatesForOrganization: { + Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - ListStackPolicyStatus: { - Name: "ListStackPolicyStatus", + ListStackPolicyStatus: { + Name: "ListStackPolicyStatus", Group: "StackPolicyStatus", }, - GetStackPolicyTemplateStatus: { - Name: "GetStackPolicyTemplateStatus", + GetStackPolicyTemplateStatus: { + Name: "GetStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - UpdateStackPolicyTemplateStatus: { - Name: "UpdateStackPolicyTemplateStatus", + UpdateStackPolicyTemplateStatus: { + Name: "UpdateStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - GetMandatoryPolicies: { - Name: "GetMandatoryPolicies", + GetMandatoryPolicies: { + Name: "GetMandatoryPolicies", Group: "Policy", }, - SetMandatoryPolicies: { - Name: "SetMandatoryPolicies", + SetMandatoryPolicies: { + Name: "SetMandatoryPolicies", Group: "Policy", }, - GetPolicyStatistics: { - Name: "GetPolicyStatistics", + GetPolicyStatistics: { + Name: "GetPolicyStatistics", Group: "Policy", }, - ListPolicy: { - Name: "ListPolicy", + ListPolicy: { + Name: "ListPolicy", Group: "Policy", }, - CreatePolicy: { - Name: "CreatePolicy", + CreatePolicy: { + Name: "CreatePolicy", Group: "Policy", }, - DeletePolicy: { - Name: "DeletePolicy", + DeletePolicy: { + Name: "DeletePolicy", Group: "Policy", }, - GetPolicy: { - Name: "GetPolicy", + GetPolicy: { + Name: "GetPolicy", Group: "Policy", }, - UpdatePolicy: { - Name: "UpdatePolicy", + UpdatePolicy: { + Name: "UpdatePolicy", Group: "Policy", }, - UpdatePolicyTargetClusters: { - Name: "UpdatePolicyTargetClusters", + UpdatePolicyTargetClusters: { + Name: "UpdatePolicyTargetClusters", Group: "Policy", }, - ExistsPolicyName: { - Name: "ExistsPolicyName", + ExistsPolicyName: { + Name: "ExistsPolicyName", Group: "Policy", }, - ExistsPolicyResourceName: { - Name: "ExistsPolicyResourceName", + ExistsPolicyResourceName: { + Name: "ExistsPolicyResourceName", Group: "Policy", }, - GetPolicyEdit: { - Name: "GetPolicyEdit", + GetPolicyEdit: { + Name: "GetPolicyEdit", Group: "Policy", }, - AddPoliciesForStack: { - Name: "AddPoliciesForStack", + AddPoliciesForStack: { + Name: "AddPoliciesForStack", Group: "Policy", }, - DeletePoliciesForStack: { - Name: "DeletePoliciesForStack", + DeletePoliciesForStack: { + Name: "DeletePoliciesForStack", Group: "Policy", }, - StackPolicyStatistics: { - Name: "StackPolicyStatistics", + StackPolicyStatistics: { + Name: "StackPolicyStatistics", Group: "Policy", }, - ListPolicyTemplate: { - Name: "ListPolicyTemplate", + ListPolicyTemplate: { + Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplate: { - Name: "CreatePolicyTemplate", + CreatePolicyTemplate: { + Name: "CreatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplate: { - Name: "DeletePolicyTemplate", + DeletePolicyTemplate: { + Name: "DeletePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplate: { - Name: "GetPolicyTemplate", + GetPolicyTemplate: { + Name: "GetPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - UpdatePolicyTemplate: { - Name: "UpdatePolicyTemplate", + UpdatePolicyTemplate: { + Name: "UpdatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateDeploy: { - Name: "GetPolicyTemplateDeploy", + GetPolicyTemplateDeploy: { + Name: "GetPolicyTemplateDeploy", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateStatistics: { - Name: "ListPolicyTemplateStatistics", + ListPolicyTemplateStatistics: { + Name: "ListPolicyTemplateStatistics", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateVersions: { - Name: "ListPolicyTemplateVersions", + ListPolicyTemplateVersions: { + Name: "ListPolicyTemplateVersions", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplateVersion: { - Name: "CreatePolicyTemplateVersion", + CreatePolicyTemplateVersion: { + Name: "CreatePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplateVersion: { - Name: "DeletePolicyTemplateVersion", + DeletePolicyTemplateVersion: { + Name: "DeletePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateVersion: { - Name: "GetPolicyTemplateVersion", + GetPolicyTemplateVersion: { + Name: "GetPolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateKind: { - Name: "ExistsPolicyTemplateKind", + ExistsPolicyTemplateKind: { + Name: "ExistsPolicyTemplateKind", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateName: { - Name: "ExistsPolicyTemplateName", + ExistsPolicyTemplateName: { + Name: "ExistsPolicyTemplateName", Group: "OrganizationPolicyTemplate", }, - ExtractParameters: { - Name: "ExtractParameters", + ExtractParameters: { + Name: "ExtractParameters", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateExample: { - Name: "ListPolicyTemplateExample", + ListPolicyTemplateExample: { + Name: "ListPolicyTemplateExample", Group: "PolicyTemplateExample", }, - GetPolicyTemplateExample: { - Name: "GetPolicyTemplateExample", + GetPolicyTemplateExample: { + Name: "GetPolicyTemplateExample", Group: "PolicyTemplateExample", }, - UpdatePolicyTemplateExample: { - Name: "UpdatePolicyTemplateExample", + UpdatePolicyTemplateExample: { + Name: "UpdatePolicyTemplateExample", Group: "PolicyTemplateExample", }, - DeletePolicyTemplateExample: { - Name: "DeletePolicyTemplateExample", + DeletePolicyTemplateExample: { + Name: "DeletePolicyTemplateExample", Group: "PolicyTemplateExample", }, - CompileRego: { - Name: "CompileRego", + CompileRego: { + Name: "CompileRego", Group: "Utility", }, } -var MapWithName = reverseApiMap() - -func reverseApiMap() map[string]Endpoint { - m := make(map[string]Endpoint) - for k, v := range MapWithEndpoint { - m[v.Name] = k - } - return m -} - func (e Endpoint) String() string { - return MapWithEndpoint[e].Name + switch e { + case Login: + return "Login" + case Logout: + return "Logout" + case RefreshToken: + return "RefreshToken" + case FindId: + return "FindId" + case FindPassword: + return "FindPassword" + case VerifyIdentityForLostId: + return "VerifyIdentityForLostId" + case VerifyIdentityForLostPassword: + return "VerifyIdentityForLostPassword" + case VerifyToken: + return "VerifyToken" + case CreateUser: + return "CreateUser" + case ListUser: + return "ListUser" + case GetUser: + return "GetUser" + case DeleteUser: + return "DeleteUser" + case UpdateUsers: + return "UpdateUsers" + case UpdateUser: + return "UpdateUser" + case ResetPassword: + return "ResetPassword" + case CheckId: + return "CheckId" + case CheckEmail: + return "CheckEmail" + case GetPermissionsByAccountId: + return "GetPermissionsByAccountId" + case GetMyProfile: + return "GetMyProfile" + case UpdateMyProfile: + return "UpdateMyProfile" + case UpdateMyPassword: + return "UpdateMyPassword" + case RenewPasswordExpiredDate: + return "RenewPasswordExpiredDate" + case DeleteMyProfile: + return "DeleteMyProfile" + case Admin_CreateOrganization: + return "Admin_CreateOrganization" + case Admin_DeleteOrganization: + return "Admin_DeleteOrganization" + case GetOrganizations: + return "GetOrganizations" + case GetOrganization: + return "GetOrganization" + case CheckOrganizationName: + return "CheckOrganizationName" + case UpdateOrganization: + return "UpdateOrganization" + case UpdatePrimaryCluster: + return "UpdatePrimaryCluster" + case CreateCluster: + return "CreateCluster" + case GetClusters: + return "GetClusters" + case ImportCluster: + return "ImportCluster" + case GetCluster: + return "GetCluster" + case DeleteCluster: + return "DeleteCluster" + case GetClusterSiteValues: + return "GetClusterSiteValues" + case InstallCluster: + return "InstallCluster" + case CreateBootstrapKubeconfig: + return "CreateBootstrapKubeconfig" + case GetBootstrapKubeconfig: + return "GetBootstrapKubeconfig" + case GetNodes: + return "GetNodes" + case CreateAppgroup: + return "CreateAppgroup" + case GetAppgroups: + return "GetAppgroups" + case GetAppgroup: + return "GetAppgroup" + case DeleteAppgroup: + return "DeleteAppgroup" + case GetApplications: + return "GetApplications" + case CreateApplication: + return "CreateApplication" + case GetAppServeAppTasksByAppId: + return "GetAppServeAppTasksByAppId" + case GetAppServeAppTaskDetail: + return "GetAppServeAppTaskDetail" + case CreateAppServeApp: + return "CreateAppServeApp" + case GetAppServeApps: + return "GetAppServeApps" + case GetNumOfAppsOnStack: + return "GetNumOfAppsOnStack" + case GetAppServeApp: + return "GetAppServeApp" + case GetAppServeAppLatestTask: + return "GetAppServeAppLatestTask" + case IsAppServeAppExist: + return "IsAppServeAppExist" + case IsAppServeAppNameExist: + return "IsAppServeAppNameExist" + case DeleteAppServeApp: + return "DeleteAppServeApp" + case UpdateAppServeApp: + return "UpdateAppServeApp" + case UpdateAppServeAppStatus: + return "UpdateAppServeAppStatus" + case UpdateAppServeAppEndpoint: + return "UpdateAppServeAppEndpoint" + case RollbackAppServeApp: + return "RollbackAppServeApp" + case GetCloudAccounts: + return "GetCloudAccounts" + case CreateCloudAccount: + return "CreateCloudAccount" + case CheckCloudAccountName: + return "CheckCloudAccountName" + case CheckAwsAccountId: + return "CheckAwsAccountId" + case GetCloudAccount: + return "GetCloudAccount" + case UpdateCloudAccount: + return "UpdateCloudAccount" + case DeleteCloudAccount: + return "DeleteCloudAccount" + case DeleteForceCloudAccount: + return "DeleteForceCloudAccount" + case GetResourceQuota: + return "GetResourceQuota" + case Admin_GetStackTemplates: + return "Admin_GetStackTemplates" + case Admin_GetStackTemplate: + return "Admin_GetStackTemplate" + case Admin_GetStackTemplateServices: + return "Admin_GetStackTemplateServices" + case Admin_GetStackTemplateTemplateIds: + return "Admin_GetStackTemplateTemplateIds" + case Admin_CreateStackTemplate: + return "Admin_CreateStackTemplate" + case Admin_UpdateStackTemplate: + return "Admin_UpdateStackTemplate" + case Admin_DeleteStackTemplate: + return "Admin_DeleteStackTemplate" + case Admin_UpdateStackTemplateOrganizations: + return "Admin_UpdateStackTemplateOrganizations" + case Admin_CheckStackTemplateName: + return "Admin_CheckStackTemplateName" + case GetOrganizationStackTemplates: + return "GetOrganizationStackTemplates" + case GetOrganizationStackTemplate: + return "GetOrganizationStackTemplate" + case AddOrganizationStackTemplates: + return "AddOrganizationStackTemplates" + case RemoveOrganizationStackTemplates: + return "RemoveOrganizationStackTemplates" + case CreateDashboard: + return "CreateDashboard" + case GetDashboard: + return "GetDashboard" + case UpdateDashboard: + return "UpdateDashboard" + case GetChartsDashboard: + return "GetChartsDashboard" + case GetChartDashboard: + return "GetChartDashboard" + case GetStacksDashboard: + return "GetStacksDashboard" + case GetResourcesDashboard: + return "GetResourcesDashboard" + case GetPolicyStatusDashboard: + return "GetPolicyStatusDashboard" + case GetPolicyUpdateDashboard: + return "GetPolicyUpdateDashboard" + case GetPolicyEnforcementDashboard: + return "GetPolicyEnforcementDashboard" + case GetPolicyViolationDashboard: + return "GetPolicyViolationDashboard" + case GetPolicyViolationLogDashboard: + return "GetPolicyViolationLogDashboard" + case GetPolicyStatisticsDashboard: + return "GetPolicyStatisticsDashboard" + case GetWorkloadDashboard: + return "GetWorkloadDashboard" + case GetPolicyViolationTop5Dashboard: + return "GetPolicyViolationTop5Dashboard" + case Admin_CreateSystemNotificationTemplate: + return "Admin_CreateSystemNotificationTemplate" + case Admin_UpdateSystemNotificationTemplate: + return "Admin_UpdateSystemNotificationTemplate" + case Admin_DeleteSystemNotificationTemplate: + return "Admin_DeleteSystemNotificationTemplate" + case Admin_GetSystemNotificationTemplates: + return "Admin_GetSystemNotificationTemplates" + case Admin_GetSystemNotificationTemplate: + return "Admin_GetSystemNotificationTemplate" + case Admin_CheckSystemNotificationTemplateName: + return "Admin_CheckSystemNotificationTemplateName" + case GetOrganizationSystemNotificationTemplates: + return "GetOrganizationSystemNotificationTemplates" + case GetOrganizationSystemNotificationTemplate: + return "GetOrganizationSystemNotificationTemplate" + case AddOrganizationSystemNotificationTemplates: + return "AddOrganizationSystemNotificationTemplates" + case RemoveOrganizationSystemNotificationTemplates: + return "RemoveOrganizationSystemNotificationTemplates" + case CreateSystemNotificationRule: + return "CreateSystemNotificationRule" + case GetSystemNotificationRules: + return "GetSystemNotificationRules" + case GetSystemNotificationRule: + return "GetSystemNotificationRule" + case CheckSystemNotificationRuleName: + return "CheckSystemNotificationRuleName" + case DeleteSystemNotificationRule: + return "DeleteSystemNotificationRule" + case UpdateSystemNotificationRule: + return "UpdateSystemNotificationRule" + case MakeDefaultSystemNotificationRules: + return "MakeDefaultSystemNotificationRules" + case CreateSystemNotification: + return "CreateSystemNotification" + case GetSystemNotifications: + return "GetSystemNotifications" + case GetSystemNotification: + return "GetSystemNotification" + case DeleteSystemNotification: + return "DeleteSystemNotification" + case UpdateSystemNotification: + return "UpdateSystemNotification" + case CreateSystemNotificationAction: + return "CreateSystemNotificationAction" + case GetPolicyNotifications: + return "GetPolicyNotifications" + case GetPolicyNotification: + return "GetPolicyNotification" + case GetStacks: + return "GetStacks" + case CreateStack: + return "CreateStack" + case CheckStackName: + return "CheckStackName" + case GetStack: + return "GetStack" + case UpdateStack: + return "UpdateStack" + case DeleteStack: + return "DeleteStack" + case GetStackKubeConfig: + return "GetStackKubeConfig" + case GetStackStatus: + return "GetStackStatus" + case SetFavoriteStack: + return "SetFavoriteStack" + case DeleteFavoriteStack: + return "DeleteFavoriteStack" + case InstallStack: + return "InstallStack" + case CreateProject: + return "CreateProject" + case GetProjectRoles: + return "GetProjectRoles" + case GetProjectRole: + return "GetProjectRole" + case GetProjects: + return "GetProjects" + case GetProject: + return "GetProject" + case UpdateProject: + return "UpdateProject" + case DeleteProject: + return "DeleteProject" + case AddProjectMember: + return "AddProjectMember" + case GetProjectMember: + return "GetProjectMember" + case GetProjectMembers: + return "GetProjectMembers" + case RemoveProjectMember: + return "RemoveProjectMember" + case UpdateProjectMemberRole: + return "UpdateProjectMemberRole" + case CreateProjectNamespace: + return "CreateProjectNamespace" + case GetProjectNamespaces: + return "GetProjectNamespaces" + case GetProjectNamespace: + return "GetProjectNamespace" + case UpdateProjectNamespace: + return "UpdateProjectNamespace" + case DeleteProjectNamespace: + return "DeleteProjectNamespace" + case SetFavoriteProject: + return "SetFavoriteProject" + case SetFavoriteProjectNamespace: + return "SetFavoriteProjectNamespace" + case UnSetFavoriteProject: + return "UnSetFavoriteProject" + case UnSetFavoriteProjectNamespace: + return "UnSetFavoriteProjectNamespace" + case GetProjectKubeconfig: + return "GetProjectKubeconfig" + case GetProjectNamespaceK8sResources: + return "GetProjectNamespaceK8sResources" + case GetProjectNamespaceKubeconfig: + return "GetProjectNamespaceKubeconfig" + case GetAudits: + return "GetAudits" + case GetAudit: + return "GetAudit" + case DeleteAudit: + return "DeleteAudit" + case CreateTksRole: + return "CreateTksRole" + case ListTksRoles: + return "ListTksRoles" + case GetTksRole: + return "GetTksRole" + case DeleteTksRole: + return "DeleteTksRole" + case UpdateTksRole: + return "UpdateTksRole" + case GetPermissionsByRoleId: + return "GetPermissionsByRoleId" + case UpdatePermissionsByRoleId: + return "UpdatePermissionsByRoleId" + case IsRoleNameExisted: + return "IsRoleNameExisted" + case AppendUsersToRole: + return "AppendUsersToRole" + case GetUsersInRoleId: + return "GetUsersInRoleId" + case RemoveUsersFromRole: + return "RemoveUsersFromRole" + case GetPermissionTemplates: + return "GetPermissionTemplates" + case Admin_CreateUser: + return "Admin_CreateUser" + case Admin_ListUser: + return "Admin_ListUser" + case Admin_GetUser: + return "Admin_GetUser" + case Admin_DeleteUser: + return "Admin_DeleteUser" + case Admin_UpdateUser: + return "Admin_UpdateUser" + case Admin_ListTksRoles: + return "Admin_ListTksRoles" + case Admin_GetTksRole: + return "Admin_GetTksRole" + case Admin_GetProjects: + return "Admin_GetProjects" + case Admin_ListPolicyTemplate: + return "Admin_ListPolicyTemplate" + case Admin_CreatePolicyTemplate: + return "Admin_CreatePolicyTemplate" + case Admin_DeletePolicyTemplate: + return "Admin_DeletePolicyTemplate" + case Admin_GetPolicyTemplate: + return "Admin_GetPolicyTemplate" + case Admin_UpdatePolicyTemplate: + return "Admin_UpdatePolicyTemplate" + case Admin_GetPolicyTemplateDeploy: + return "Admin_GetPolicyTemplateDeploy" + case Admin_ListPolicyTemplateStatistics: + return "Admin_ListPolicyTemplateStatistics" + case Admin_ListPolicyTemplateVersions: + return "Admin_ListPolicyTemplateVersions" + case Admin_CreatePolicyTemplateVersion: + return "Admin_CreatePolicyTemplateVersion" + case Admin_DeletePolicyTemplateVersion: + return "Admin_DeletePolicyTemplateVersion" + case Admin_GetPolicyTemplateVersion: + return "Admin_GetPolicyTemplateVersion" + case Admin_ExistsPolicyTemplateKind: + return "Admin_ExistsPolicyTemplateKind" + case Admin_ExistsPolicyTemplateName: + return "Admin_ExistsPolicyTemplateName" + case Admin_ExtractParameters: + return "Admin_ExtractParameters" + case Admin_AddPermittedPolicyTemplatesForOrganization: + return "Admin_AddPermittedPolicyTemplatesForOrganization" + case Admin_DeletePermittedPolicyTemplatesForOrganization: + return "Admin_DeletePermittedPolicyTemplatesForOrganization" + case ListStackPolicyStatus: + return "ListStackPolicyStatus" + case GetStackPolicyTemplateStatus: + return "GetStackPolicyTemplateStatus" + case UpdateStackPolicyTemplateStatus: + return "UpdateStackPolicyTemplateStatus" + case GetMandatoryPolicies: + return "GetMandatoryPolicies" + case SetMandatoryPolicies: + return "SetMandatoryPolicies" + case GetPolicyStatistics: + return "GetPolicyStatistics" + case ListPolicy: + return "ListPolicy" + case CreatePolicy: + return "CreatePolicy" + case DeletePolicy: + return "DeletePolicy" + case GetPolicy: + return "GetPolicy" + case UpdatePolicy: + return "UpdatePolicy" + case UpdatePolicyTargetClusters: + return "UpdatePolicyTargetClusters" + case ExistsPolicyName: + return "ExistsPolicyName" + case ExistsPolicyResourceName: + return "ExistsPolicyResourceName" + case GetPolicyEdit: + return "GetPolicyEdit" + case AddPoliciesForStack: + return "AddPoliciesForStack" + case DeletePoliciesForStack: + return "DeletePoliciesForStack" + case StackPolicyStatistics: + return "StackPolicyStatistics" + case ListPolicyTemplate: + return "ListPolicyTemplate" + case CreatePolicyTemplate: + return "CreatePolicyTemplate" + case DeletePolicyTemplate: + return "DeletePolicyTemplate" + case GetPolicyTemplate: + return "GetPolicyTemplate" + case UpdatePolicyTemplate: + return "UpdatePolicyTemplate" + case GetPolicyTemplateDeploy: + return "GetPolicyTemplateDeploy" + case ListPolicyTemplateStatistics: + return "ListPolicyTemplateStatistics" + case ListPolicyTemplateVersions: + return "ListPolicyTemplateVersions" + case CreatePolicyTemplateVersion: + return "CreatePolicyTemplateVersion" + case DeletePolicyTemplateVersion: + return "DeletePolicyTemplateVersion" + case GetPolicyTemplateVersion: + return "GetPolicyTemplateVersion" + case ExistsPolicyTemplateKind: + return "ExistsPolicyTemplateKind" + case ExistsPolicyTemplateName: + return "ExistsPolicyTemplateName" + case ExtractParameters: + return "ExtractParameters" + case ListPolicyTemplateExample: + return "ListPolicyTemplateExample" + case GetPolicyTemplateExample: + return "GetPolicyTemplateExample" + case UpdatePolicyTemplateExample: + return "UpdatePolicyTemplateExample" + case DeletePolicyTemplateExample: + return "DeletePolicyTemplateExample" + case CompileRego: + return "CompileRego" + default: + return "" + } } - func GetEndpoint(name string) Endpoint { - return MapWithName[name] + switch name { + case "Login": + return Login + case "Logout": + return Logout + case "RefreshToken": + return RefreshToken + case "FindId": + return FindId + case "FindPassword": + return FindPassword + case "VerifyIdentityForLostId": + return VerifyIdentityForLostId + case "VerifyIdentityForLostPassword": + return VerifyIdentityForLostPassword + case "VerifyToken": + return VerifyToken + case "CreateUser": + return CreateUser + case "ListUser": + return ListUser + case "GetUser": + return GetUser + case "DeleteUser": + return DeleteUser + case "UpdateUsers": + return UpdateUsers + case "UpdateUser": + return UpdateUser + case "ResetPassword": + return ResetPassword + case "CheckId": + return CheckId + case "CheckEmail": + return CheckEmail + case "GetPermissionsByAccountId": + return GetPermissionsByAccountId + case "GetMyProfile": + return GetMyProfile + case "UpdateMyProfile": + return UpdateMyProfile + case "UpdateMyPassword": + return UpdateMyPassword + case "RenewPasswordExpiredDate": + return RenewPasswordExpiredDate + case "DeleteMyProfile": + return DeleteMyProfile + case "Admin_CreateOrganization": + return Admin_CreateOrganization + case "Admin_DeleteOrganization": + return Admin_DeleteOrganization + case "GetOrganizations": + return GetOrganizations + case "GetOrganization": + return GetOrganization + case "CheckOrganizationName": + return CheckOrganizationName + case "UpdateOrganization": + return UpdateOrganization + case "UpdatePrimaryCluster": + return UpdatePrimaryCluster + case "CreateCluster": + return CreateCluster + case "GetClusters": + return GetClusters + case "ImportCluster": + return ImportCluster + case "GetCluster": + return GetCluster + case "DeleteCluster": + return DeleteCluster + case "GetClusterSiteValues": + return GetClusterSiteValues + case "InstallCluster": + return InstallCluster + case "CreateBootstrapKubeconfig": + return CreateBootstrapKubeconfig + case "GetBootstrapKubeconfig": + return GetBootstrapKubeconfig + case "GetNodes": + return GetNodes + case "CreateAppgroup": + return CreateAppgroup + case "GetAppgroups": + return GetAppgroups + case "GetAppgroup": + return GetAppgroup + case "DeleteAppgroup": + return DeleteAppgroup + case "GetApplications": + return GetApplications + case "CreateApplication": + return CreateApplication + case "GetAppServeAppTasksByAppId": + return GetAppServeAppTasksByAppId + case "GetAppServeAppTaskDetail": + return GetAppServeAppTaskDetail + case "CreateAppServeApp": + return CreateAppServeApp + case "GetAppServeApps": + return GetAppServeApps + case "GetNumOfAppsOnStack": + return GetNumOfAppsOnStack + case "GetAppServeApp": + return GetAppServeApp + case "GetAppServeAppLatestTask": + return GetAppServeAppLatestTask + case "IsAppServeAppExist": + return IsAppServeAppExist + case "IsAppServeAppNameExist": + return IsAppServeAppNameExist + case "DeleteAppServeApp": + return DeleteAppServeApp + case "UpdateAppServeApp": + return UpdateAppServeApp + case "UpdateAppServeAppStatus": + return UpdateAppServeAppStatus + case "UpdateAppServeAppEndpoint": + return UpdateAppServeAppEndpoint + case "RollbackAppServeApp": + return RollbackAppServeApp + case "GetCloudAccounts": + return GetCloudAccounts + case "CreateCloudAccount": + return CreateCloudAccount + case "CheckCloudAccountName": + return CheckCloudAccountName + case "CheckAwsAccountId": + return CheckAwsAccountId + case "GetCloudAccount": + return GetCloudAccount + case "UpdateCloudAccount": + return UpdateCloudAccount + case "DeleteCloudAccount": + return DeleteCloudAccount + case "DeleteForceCloudAccount": + return DeleteForceCloudAccount + case "GetResourceQuota": + return GetResourceQuota + case "Admin_GetStackTemplates": + return Admin_GetStackTemplates + case "Admin_GetStackTemplate": + return Admin_GetStackTemplate + case "Admin_GetStackTemplateServices": + return Admin_GetStackTemplateServices + case "Admin_GetStackTemplateTemplateIds": + return Admin_GetStackTemplateTemplateIds + case "Admin_CreateStackTemplate": + return Admin_CreateStackTemplate + case "Admin_UpdateStackTemplate": + return Admin_UpdateStackTemplate + case "Admin_DeleteStackTemplate": + return Admin_DeleteStackTemplate + case "Admin_UpdateStackTemplateOrganizations": + return Admin_UpdateStackTemplateOrganizations + case "Admin_CheckStackTemplateName": + return Admin_CheckStackTemplateName + case "GetOrganizationStackTemplates": + return GetOrganizationStackTemplates + case "GetOrganizationStackTemplate": + return GetOrganizationStackTemplate + case "AddOrganizationStackTemplates": + return AddOrganizationStackTemplates + case "RemoveOrganizationStackTemplates": + return RemoveOrganizationStackTemplates + case "CreateDashboard": + return CreateDashboard + case "GetDashboard": + return GetDashboard + case "UpdateDashboard": + return UpdateDashboard + case "GetChartsDashboard": + return GetChartsDashboard + case "GetChartDashboard": + return GetChartDashboard + case "GetStacksDashboard": + return GetStacksDashboard + case "GetResourcesDashboard": + return GetResourcesDashboard + case "GetPolicyStatusDashboard": + return GetPolicyStatusDashboard + case "GetPolicyUpdateDashboard": + return GetPolicyUpdateDashboard + case "GetPolicyEnforcementDashboard": + return GetPolicyEnforcementDashboard + case "GetPolicyViolationDashboard": + return GetPolicyViolationDashboard + case "GetPolicyViolationLogDashboard": + return GetPolicyViolationLogDashboard + case "GetPolicyStatisticsDashboard": + return GetPolicyStatisticsDashboard + case "GetWorkloadDashboard": + return GetWorkloadDashboard + case "GetPolicyViolationTop5Dashboard": + return GetPolicyViolationTop5Dashboard + case "Admin_CreateSystemNotificationTemplate": + return Admin_CreateSystemNotificationTemplate + case "Admin_UpdateSystemNotificationTemplate": + return Admin_UpdateSystemNotificationTemplate + case "Admin_DeleteSystemNotificationTemplate": + return Admin_DeleteSystemNotificationTemplate + case "Admin_GetSystemNotificationTemplates": + return Admin_GetSystemNotificationTemplates + case "Admin_GetSystemNotificationTemplate": + return Admin_GetSystemNotificationTemplate + case "Admin_CheckSystemNotificationTemplateName": + return Admin_CheckSystemNotificationTemplateName + case "GetOrganizationSystemNotificationTemplates": + return GetOrganizationSystemNotificationTemplates + case "GetOrganizationSystemNotificationTemplate": + return GetOrganizationSystemNotificationTemplate + case "AddOrganizationSystemNotificationTemplates": + return AddOrganizationSystemNotificationTemplates + case "RemoveOrganizationSystemNotificationTemplates": + return RemoveOrganizationSystemNotificationTemplates + case "CreateSystemNotificationRule": + return CreateSystemNotificationRule + case "GetSystemNotificationRules": + return GetSystemNotificationRules + case "GetSystemNotificationRule": + return GetSystemNotificationRule + case "CheckSystemNotificationRuleName": + return CheckSystemNotificationRuleName + case "DeleteSystemNotificationRule": + return DeleteSystemNotificationRule + case "UpdateSystemNotificationRule": + return UpdateSystemNotificationRule + case "MakeDefaultSystemNotificationRules": + return MakeDefaultSystemNotificationRules + case "CreateSystemNotification": + return CreateSystemNotification + case "GetSystemNotifications": + return GetSystemNotifications + case "GetSystemNotification": + return GetSystemNotification + case "DeleteSystemNotification": + return DeleteSystemNotification + case "UpdateSystemNotification": + return UpdateSystemNotification + case "CreateSystemNotificationAction": + return CreateSystemNotificationAction + case "GetPolicyNotifications": + return GetPolicyNotifications + case "GetPolicyNotification": + return GetPolicyNotification + case "GetStacks": + return GetStacks + case "CreateStack": + return CreateStack + case "CheckStackName": + return CheckStackName + case "GetStack": + return GetStack + case "UpdateStack": + return UpdateStack + case "DeleteStack": + return DeleteStack + case "GetStackKubeConfig": + return GetStackKubeConfig + case "GetStackStatus": + return GetStackStatus + case "SetFavoriteStack": + return SetFavoriteStack + case "DeleteFavoriteStack": + return DeleteFavoriteStack + case "InstallStack": + return InstallStack + case "CreateProject": + return CreateProject + case "GetProjectRoles": + return GetProjectRoles + case "GetProjectRole": + return GetProjectRole + case "GetProjects": + return GetProjects + case "GetProject": + return GetProject + case "UpdateProject": + return UpdateProject + case "DeleteProject": + return DeleteProject + case "AddProjectMember": + return AddProjectMember + case "GetProjectMember": + return GetProjectMember + case "GetProjectMembers": + return GetProjectMembers + case "RemoveProjectMember": + return RemoveProjectMember + case "UpdateProjectMemberRole": + return UpdateProjectMemberRole + case "CreateProjectNamespace": + return CreateProjectNamespace + case "GetProjectNamespaces": + return GetProjectNamespaces + case "GetProjectNamespace": + return GetProjectNamespace + case "UpdateProjectNamespace": + return UpdateProjectNamespace + case "DeleteProjectNamespace": + return DeleteProjectNamespace + case "SetFavoriteProject": + return SetFavoriteProject + case "SetFavoriteProjectNamespace": + return SetFavoriteProjectNamespace + case "UnSetFavoriteProject": + return UnSetFavoriteProject + case "UnSetFavoriteProjectNamespace": + return UnSetFavoriteProjectNamespace + case "GetProjectKubeconfig": + return GetProjectKubeconfig + case "GetProjectNamespaceK8sResources": + return GetProjectNamespaceK8sResources + case "GetProjectNamespaceKubeconfig": + return GetProjectNamespaceKubeconfig + case "GetAudits": + return GetAudits + case "GetAudit": + return GetAudit + case "DeleteAudit": + return DeleteAudit + case "CreateTksRole": + return CreateTksRole + case "ListTksRoles": + return ListTksRoles + case "GetTksRole": + return GetTksRole + case "DeleteTksRole": + return DeleteTksRole + case "UpdateTksRole": + return UpdateTksRole + case "GetPermissionsByRoleId": + return GetPermissionsByRoleId + case "UpdatePermissionsByRoleId": + return UpdatePermissionsByRoleId + case "IsRoleNameExisted": + return IsRoleNameExisted + case "AppendUsersToRole": + return AppendUsersToRole + case "GetUsersInRoleId": + return GetUsersInRoleId + case "RemoveUsersFromRole": + return RemoveUsersFromRole + case "GetPermissionTemplates": + return GetPermissionTemplates + case "Admin_CreateUser": + return Admin_CreateUser + case "Admin_ListUser": + return Admin_ListUser + case "Admin_GetUser": + return Admin_GetUser + case "Admin_DeleteUser": + return Admin_DeleteUser + case "Admin_UpdateUser": + return Admin_UpdateUser + case "Admin_ListTksRoles": + return Admin_ListTksRoles + case "Admin_GetTksRole": + return Admin_GetTksRole + case "Admin_GetProjects": + return Admin_GetProjects + case "Admin_ListPolicyTemplate": + return Admin_ListPolicyTemplate + case "Admin_CreatePolicyTemplate": + return Admin_CreatePolicyTemplate + case "Admin_DeletePolicyTemplate": + return Admin_DeletePolicyTemplate + case "Admin_GetPolicyTemplate": + return Admin_GetPolicyTemplate + case "Admin_UpdatePolicyTemplate": + return Admin_UpdatePolicyTemplate + case "Admin_GetPolicyTemplateDeploy": + return Admin_GetPolicyTemplateDeploy + case "Admin_ListPolicyTemplateStatistics": + return Admin_ListPolicyTemplateStatistics + case "Admin_ListPolicyTemplateVersions": + return Admin_ListPolicyTemplateVersions + case "Admin_CreatePolicyTemplateVersion": + return Admin_CreatePolicyTemplateVersion + case "Admin_DeletePolicyTemplateVersion": + return Admin_DeletePolicyTemplateVersion + case "Admin_GetPolicyTemplateVersion": + return Admin_GetPolicyTemplateVersion + case "Admin_ExistsPolicyTemplateKind": + return Admin_ExistsPolicyTemplateKind + case "Admin_ExistsPolicyTemplateName": + return Admin_ExistsPolicyTemplateName + case "Admin_ExtractParameters": + return Admin_ExtractParameters + case "Admin_AddPermittedPolicyTemplatesForOrganization": + return Admin_AddPermittedPolicyTemplatesForOrganization + case "Admin_DeletePermittedPolicyTemplatesForOrganization": + return Admin_DeletePermittedPolicyTemplatesForOrganization + case "ListStackPolicyStatus": + return ListStackPolicyStatus + case "GetStackPolicyTemplateStatus": + return GetStackPolicyTemplateStatus + case "UpdateStackPolicyTemplateStatus": + return UpdateStackPolicyTemplateStatus + case "GetMandatoryPolicies": + return GetMandatoryPolicies + case "SetMandatoryPolicies": + return SetMandatoryPolicies + case "GetPolicyStatistics": + return GetPolicyStatistics + case "ListPolicy": + return ListPolicy + case "CreatePolicy": + return CreatePolicy + case "DeletePolicy": + return DeletePolicy + case "GetPolicy": + return GetPolicy + case "UpdatePolicy": + return UpdatePolicy + case "UpdatePolicyTargetClusters": + return UpdatePolicyTargetClusters + case "ExistsPolicyName": + return ExistsPolicyName + case "ExistsPolicyResourceName": + return ExistsPolicyResourceName + case "GetPolicyEdit": + return GetPolicyEdit + case "AddPoliciesForStack": + return AddPoliciesForStack + case "DeletePoliciesForStack": + return DeletePoliciesForStack + case "StackPolicyStatistics": + return StackPolicyStatistics + case "ListPolicyTemplate": + return ListPolicyTemplate + case "CreatePolicyTemplate": + return CreatePolicyTemplate + case "DeletePolicyTemplate": + return DeletePolicyTemplate + case "GetPolicyTemplate": + return GetPolicyTemplate + case "UpdatePolicyTemplate": + return UpdatePolicyTemplate + case "GetPolicyTemplateDeploy": + return GetPolicyTemplateDeploy + case "ListPolicyTemplateStatistics": + return ListPolicyTemplateStatistics + case "ListPolicyTemplateVersions": + return ListPolicyTemplateVersions + case "CreatePolicyTemplateVersion": + return CreatePolicyTemplateVersion + case "DeletePolicyTemplateVersion": + return DeletePolicyTemplateVersion + case "GetPolicyTemplateVersion": + return GetPolicyTemplateVersion + case "ExistsPolicyTemplateKind": + return ExistsPolicyTemplateKind + case "ExistsPolicyTemplateName": + return ExistsPolicyTemplateName + case "ExtractParameters": + return ExtractParameters + case "ListPolicyTemplateExample": + return ListPolicyTemplateExample + case "GetPolicyTemplateExample": + return GetPolicyTemplateExample + case "UpdatePolicyTemplateExample": + return UpdatePolicyTemplateExample + case "DeletePolicyTemplateExample": + return DeletePolicyTemplateExample + case "CompileRego": + return CompileRego + default: + return -1 + } } diff --git a/internal/delivery/http/endpoint.go b/internal/delivery/http/endpoint.go deleted file mode 100644 index 34a90b74..00000000 --- a/internal/delivery/http/endpoint.go +++ /dev/null @@ -1,59 +0,0 @@ -package http - -import ( - "github.com/openinfradev/tks-api/internal/model" - "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/usecase" - "github.com/openinfradev/tks-api/pkg/domain" - "net/http" -) - -type IEndpointHandler interface { - ListEndpoint(w http.ResponseWriter, r *http.Request) -} - -type EndpointHandler struct { - endpointUsecase usecase.IEndpointUsecase -} - -func NewEndpointHandler(usecase usecase.Usecase) *EndpointHandler { - return &EndpointHandler{ - endpointUsecase: usecase.Endpoint, - } -} - -// ListEndpoint godoc -// -// @Tags Endpoint -// @Summary List Endpoints -// @Description List Endpoints -// @Accept json -// @Produce json -// @Success 200 {object} domain.ListEndpointResponse -// @Router /admin/endpoints [get] -// @Security JWT -func (h EndpointHandler) ListEndpoint(w http.ResponseWriter, r *http.Request) { - urlParams := r.URL.Query() - pg := pagination.NewPagination(&urlParams) - - endpoints, err := h.endpointUsecase.ListEndpoints(r.Context(), pg) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - var out domain.ListEndpointResponse - - for _, endpoint := range endpoints { - out.Endpoints = append(out.Endpoints, convertEndpointToDomain(endpoint)) - } - - ResponseJSON(w, r, http.StatusOK, out) -} - -func convertEndpointToDomain(endpoint *model.Endpoint) domain.EndpointResponse { - return domain.EndpointResponse{ - Name: endpoint.Name, - Group: endpoint.Group, - } -} diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 6549554a..524e78ae 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -34,7 +34,7 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { } } -// Admin_CreateOrganization CreateOrganization godoc +// CreateOrganization godoc // // @Tags Organizations // @Summary Create organization in Admin portal diff --git a/internal/delivery/http/permission.go b/internal/delivery/http/permission.go index f3b8ed25..3ad7798f 100644 --- a/internal/delivery/http/permission.go +++ b/internal/delivery/http/permission.go @@ -2,10 +2,6 @@ package http import ( "context" - "fmt" - "github.com/google/uuid" - "github.com/gorilla/mux" - "github.com/openinfradev/tks-api/pkg/httpErrors" "net/http" "github.com/openinfradev/tks-api/internal/model" @@ -15,7 +11,6 @@ import ( type IPermissionHandler interface { GetPermissionTemplates(w http.ResponseWriter, r *http.Request) - GetEndpoints(w http.ResponseWriter, r *http.Request) } type PermissionHandler struct { @@ -61,7 +56,9 @@ func convertModelToPermissionTemplateResponse(ctx context.Context, permission *m permissionResponse.Key = permission.Key permissionResponse.Name = permission.Name - permissionResponse.EdgeKey = permission.EdgeKey + if permission.IsAllowed != nil { + permissionResponse.IsAllowed = permission.IsAllowed + } for _, child := range permission.Children { permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionTemplateResponse(ctx, child)) @@ -69,42 +66,3 @@ func convertModelToPermissionTemplateResponse(ctx context.Context, permission *m return &permissionResponse } - -// GetEndpoints godoc -// -// @Tags Permission -// @Summary Get Endpoints -// @Description Get Endpoints -// @Accept json -// @Produce json -// @Success 200 {object} domain.GetEndpointsResponse -// @Router /permissions/{permissionId}/endpoints [get] -// @Security JWT -func (h PermissionHandler) GetEndpoints(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - permissionId, ok := vars["permissionId"] - if !ok { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("permissionId not found"), "PE_INVALID_PERMISSIONID", "permissionId not found")) - return - } - - permissionUuid, err := uuid.Parse(permissionId) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("permissionId is invalid"), "PE_INVALID_PERMISSIONID", "permissionId is invalid")) - return - } - - endpoints, err := h.permissionUsecase.GetEndpointsByPermissionId(r.Context(), permissionUuid) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "PE_GET_ENDPOINTS_FAILED", "Failed to get endpoints")) - return - } - - var out domain.GetEndpointsResponse - out.Endpoints = make([]domain.EndpointResponse, 0) - for _, endpoint := range endpoints { - out.Endpoints = append(out.Endpoints, convertEndpointToDomain(endpoint)) - } - - ResponseJSON(w, r, http.StatusOK, out) -} diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index b43769af..1ff872be 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -348,6 +348,10 @@ func convertModelToPermissionResponse(ctx context.Context, permission *model.Per permissionResponse.ID = &permission.ID } + for _, endpoint := range permission.Endpoints { + permissionResponse.Endpoints = append(permissionResponse.Endpoints, convertModelToEndpointResponse(ctx, endpoint)) + } + for _, child := range permission.Children { permissionResponse.Children = append(permissionResponse.Children, convertModelToPermissionResponse(ctx, child)) } @@ -355,6 +359,15 @@ func convertModelToPermissionResponse(ctx context.Context, permission *model.Per return &permissionResponse } +func convertModelToEndpointResponse(_ context.Context, endpoint *model.Endpoint) *domain.EndpointResponse { + var endpointResponse domain.EndpointResponse + + endpointResponse.Name = endpoint.Name + endpointResponse.Group = endpoint.Group + + return &endpointResponse +} + // UpdatePermissionsByRoleId godoc // // @Tags Roles diff --git a/internal/middleware/audit/audit.go b/internal/middleware/audit/audit.go index 74f4717f..189232ec 100644 --- a/internal/middleware/audit/audit.go +++ b/internal/middleware/audit/audit.go @@ -78,7 +78,7 @@ func (a *defaultAudit) WithAudit(endpoint internalApi.Endpoint, handler http.Han dto := model.Audit{ OrganizationId: organizationId, OrganizationName: u.Organization.Name, - Group: internalApi.MapWithEndpoint[endpoint].Group, + Group: internalApi.ApiMap[endpoint].Group, Message: message, Description: description, ClientIP: GetClientIpAddress(w, r), diff --git a/internal/middleware/auth/authorizer/adminApiFilter.go b/internal/middleware/auth/authorizer/adminApiFilter.go deleted file mode 100644 index 2fb006f9..00000000 --- a/internal/middleware/auth/authorizer/adminApiFilter.go +++ /dev/null @@ -1,36 +0,0 @@ -package authorizer - -import ( - "fmt" - internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/httpErrors" - "net/http" - "strings" -) - -func AdminApiFilter(handler http.Handler, repo repository.Repository) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) - return - } - - endpointInfo, ok := request.EndpointFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) - return - } - - if strings.HasPrefix(endpointInfo.String(), "Admin_") { - if requestUserInfo.GetOrganizationId() != "master" { - internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "A_INVALID_TOKEN", "Not allowed access to admin api")) - return - } - } - - handler.ServeHTTP(w, r) - }) -} diff --git a/internal/middleware/auth/authorizer/authorizer.go b/internal/middleware/auth/authorizer/authorizer.go index dc0b830d..1ce71727 100644 --- a/internal/middleware/auth/authorizer/authorizer.go +++ b/internal/middleware/auth/authorizer/authorizer.go @@ -22,7 +22,6 @@ func NewDefaultAuthorization(repo repository.Repository) *defaultAuthorization { //d.addFilters(RBACFilter) //d.addFilters(RBACFilterWithEndpoint) d.addFilters(AdminApiFilter) - d.addFilters(OrganizationFilter) return d } diff --git a/internal/middleware/auth/authorizer/organizationFilter.go b/internal/middleware/auth/authorizer/organizationFilter.go deleted file mode 100644 index 86e8715a..00000000 --- a/internal/middleware/auth/authorizer/organizationFilter.go +++ /dev/null @@ -1,43 +0,0 @@ -package authorizer - -import ( - "fmt" - "github.com/gorilla/mux" - internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" - "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/httpErrors" - "github.com/openinfradev/tks-api/pkg/log" - "net/http" -) - -func OrganizationFilter(handler http.Handler, repo repository.Repository) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - requestUserInfo, ok := request.UserFrom(r.Context()) - if !ok { - internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) - return - } - - if requestUserInfo.GetOrganizationId() != "" && requestUserInfo.GetOrganizationId() == "master" { - handler.ServeHTTP(w, r) - return - } - - vars := mux.Vars(r) - requestedOrganization, ok := vars["organizationId"] - if !ok { - log.Warn(r.Context(), "OrganizationFilter: organizationId not found. Passing through unsafely.") - handler.ServeHTTP(w, r) - return - } - - if requestedOrganization != requestUserInfo.GetOrganizationId() { - log.Debugf(r.Context(), "OrganizationFilter: requestedOrganization: %s, userOrganization: %s", requestedOrganization, requestUserInfo.GetOrganizationId()) - internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) - return - } - - handler.ServeHTTP(w, r) - }) -} diff --git a/internal/middleware/auth/authorizer/rbac.go b/internal/middleware/auth/authorizer/rbac.go index 996379fc..9813558e 100644 --- a/internal/middleware/auth/authorizer/rbac.go +++ b/internal/middleware/auth/authorizer/rbac.go @@ -1,10 +1,62 @@ package authorizer import ( - "github.com/openinfradev/tks-api/internal/repository" + "fmt" "net/http" + "strings" + + "github.com/gorilla/mux" + "github.com/openinfradev/tks-api/internal" + internalHttp "github.com/openinfradev/tks-api/internal/delivery/http" + "github.com/openinfradev/tks-api/internal/middleware/auth/request" + "github.com/openinfradev/tks-api/internal/repository" + "github.com/openinfradev/tks-api/pkg/httpErrors" + "github.com/openinfradev/tks-api/pkg/log" ) +func RBACFilter(handler http.Handler, repo repository.Repository) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + return + } + organizationRole := requestUserInfo.GetRoleOrganizationMapping()[requestUserInfo.GetOrganizationId()] + + // TODO: 추후 tks-admin role 수정 필요 + if organizationRole == "tks-admin" { + handler.ServeHTTP(w, r) + return + } + + vars := mux.Vars(r) + // Organization Filter + if organizationRole == "admin" || organizationRole == "user" { + if orgId, ok := vars["organizationId"]; ok { + if orgId != requestUserInfo.GetOrganizationId() { + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return + } + } else { + log.Warn(r.Context(), "RBACFilter: organizationId not found. Passing through unsafely.") + } + } + + // User Resource Filter + if strings.HasPrefix(r.URL.Path, internal.API_PREFIX+internal.API_VERSION+"/organizations/"+requestUserInfo.GetOrganizationId()+"/user") { + switch r.Method { + case http.MethodPost, http.MethodPut, http.MethodDelete: + if organizationRole != "admin" { + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return + } + } + } + + handler.ServeHTTP(w, r) + }) +} + func RBACFilterWithEndpoint(handler http.Handler, repo repository.Repository) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { //requestEndpointInfo, ok := request.EndpointFrom(r.Context()) @@ -39,3 +91,79 @@ func RBACFilterWithEndpoint(handler http.Handler, repo repository.Repository) ht handler.ServeHTTP(w, r) }) } + +func AdminApiFilter(handler http.Handler, repo repository.Repository) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + return + } + + endpointInfo, ok := request.EndpointFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("endpoint not found"), "", "")) + return + } + + if strings.HasPrefix(endpointInfo.String(), "Admin") { + if requestUserInfo.GetOrganizationId() != "master" { + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return + } + } + + handler.ServeHTTP(w, r) + }) +} + +func RequestOrganizationValidationFilter(handler http.Handler, repo repository.Repository) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requestUserInfo, ok := request.UserFrom(r.Context()) + if !ok { + internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("user not found"), "", "")) + return + } + + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + //internalHttp.ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("organizationId not found"), "", "")) + //return + log.Warn(r.Context(), "RequestOrganizationValidationFilter: organizationId not found. Passing through unsafely.") + } + if organizationId != requestUserInfo.GetOrganizationId() { + internalHttp.ErrorJSON(w, r, httpErrors.NewForbiddenError(fmt.Errorf("permission denied"), "", "")) + return + } + + handler.ServeHTTP(w, r) + }) +} + +//type pair struct { +// regexp string +// method string +//} +// +//var LeaderPair = []pair{ +// {`/organizations/o[A-Za-z0-9]{8}/projects(?:\?.*)?$`, http.MethodPost}, +// {`/organizations/o[A-Za-z0-9]{8}/projects(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodPut}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodDelete}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members(?:\?.*)?$`, http.MethodPost}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(?:\?.*)?$`, http.MethodDelete}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/members/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/role(?:\?.*)?$`, http.MethodPut}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace(?:\?.*)?$`, http.MethodPost}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace/n[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodGet}, +// {`/organizations/o[A-Za-z0-9]{8}/projects/p[A-Za-z0-9]{8}/namespace/n[A-Za-z0-9]{8}(?:\?.*)?$`, http.MethodDelete}, +//} +//var roleApiMapper = make(map[string][]pair) +// +//func projectFilter(url string, method string, userInfo user.Info) bool { +// +// return true +//} diff --git a/internal/model/endpoint.go b/internal/model/end-point.go similarity index 100% rename from internal/model/endpoint.go rename to internal/model/end-point.go diff --git a/internal/model/permission-endpoint.go b/internal/model/permission-endpoint.go deleted file mode 100644 index b7fe0653..00000000 --- a/internal/model/permission-endpoint.go +++ /dev/null @@ -1,435 +0,0 @@ -package model - -import ( - "github.com/openinfradev/tks-api/internal/delivery/api" - "gorm.io/gorm" - "sort" -) - -type PermissionEndpoint struct { - EdgeKey string `gorm:"primaryKey;type:text;"` - EndpointName string `gorm:"primaryKey;type:text;"` - - Permission Permission `gorm:"foreignKey:EdgeKey;references:EdgeKey"` - Endpoint Endpoint `gorm:"foreignKey:EndpointName;references:Name"` -} - -var ( - // map[EdgeKey][]Endpoints - edgeKeyEndpointMap = map[string][]Endpoint{ - TopDashboardKey + "-" + MiddleDashboardKey + "-" + OperationRead: endpointObjects( - api.GetDashboard, - api.GetChartsDashboard, - api.GetChartDashboard, - api.GetStacksDashboard, - api.GetResourcesDashboard, - ), - TopDashboardKey + "-" + MiddleDashboardKey + "-" + OperationUpdate: endpointObjects( - api.CreateDashboard, - api.UpdateDashboard, - ), - - TopStackKey + "-" + MiddleStackKey + "-" + OperationRead: endpointObjects( - api.GetStacks, - api.GetStack, - api.CheckStackName, - api.GetStackStatus, - api.GetStackKubeConfig, - api.SetFavoriteStack, - api.DeleteFavoriteStack, - - // Cluster - api.GetCluster, - api.GetClusters, - api.GetClusterSiteValues, - api.GetBootstrapKubeconfig, - api.GetNodes, - - // AppGroup - api.GetAppgroups, - api.GetAppgroup, - api.GetApplications, - ), - - TopStackKey + "-" + MiddleStackKey + "-" + OperationCreate: endpointObjects( - api.CreateStack, - api.InstallStack, - - // Cluster - api.CreateBootstrapKubeconfig, - api.GetBootstrapKubeconfig, - api.GetNodes, - ), - TopStackKey + "-" + MiddleStackKey + "-" + OperationUpdate: endpointObjects( - api.UpdateStack, - ), - TopStackKey + "-" + MiddleStackKey + "-" + OperationDelete: endpointObjects( - // Stack - api.DeleteStack, - - // Cluster - api.DeleteCluster, - - // AppGroup - api.DeleteAppgroup, - ), - TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationRead: endpointObjects( - // PolicyTemplate - api.Admin_ListPolicyTemplate, - api.Admin_GetPolicyTemplate, - api.Admin_GetPolicyTemplateDeploy, - api.Admin_ListPolicyTemplateStatistics, - api.Admin_ListPolicyTemplateVersions, - api.Admin_GetPolicyTemplateVersion, - api.Admin_ExistsPolicyTemplateName, - api.Admin_ExistsPolicyTemplateKind, - - // StackPolicyStatus - api.ListStackPolicyStatus, - api.GetStackPolicyTemplateStatus, - - // Policy - api.GetMandatoryPolicies, - api.ListPolicy, - api.GetPolicy, - api.ExistsPolicyName, - - // OrganizationPolicyTemplate - api.ListPolicyTemplate, - api.GetPolicyTemplate, - api.GetPolicyTemplateDeploy, - api.ListPolicyTemplateStatistics, - api.ListPolicyTemplateVersions, - api.GetPolicyTemplateVersion, - api.ExistsPolicyTemplateKind, - api.ExistsPolicyTemplateName, - - // PolicyTemplateExample - api.ListPolicyTemplateExample, - api.GetPolicyTemplateExample, - ), - TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationCreate: endpointObjects( - // PolicyTemplate - api.Admin_CreatePolicyTemplate, - api.Admin_CreatePolicyTemplateVersion, - - // Policy - api.SetMandatoryPolicies, - api.CreatePolicy, - - // OrganizationPolicyTemplate - api.CreatePolicyTemplate, - api.CreatePolicyTemplateVersion, - ), - TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationUpdate: endpointObjects( - // PolicyTemplate - api.Admin_UpdatePolicyTemplate, - - // ClusterPolicyStatus - api.UpdateStackPolicyTemplateStatus, - - // Policy - api.UpdatePolicy, - api.UpdatePolicyTargetClusters, - - // OrganizationPolicyTemplate - api.UpdatePolicyTemplate, - - // PolicyTemplateExample - api.UpdatePolicyTemplateExample, - ), - - TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationDelete: endpointObjects( - api.Admin_DeletePolicyTemplate, - api.Admin_DeletePolicyTemplateVersion, - - // Policy - api.DeletePolicy, - - // OrganizationPolicyTemplate - api.DeletePolicyTemplate, - api.DeletePolicyTemplateVersion, - - // PolicyTemplateExample - api.DeletePolicyTemplateExample, - ), - TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationRead: endpointObjects( - api.GetSystemNotification, - api.GetSystemNotifications, - ), - TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationUpdate: endpointObjects( - api.UpdateSystemNotification, - api.CreateSystemNotificationAction, - ), - TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationDownload: endpointObjects(), - - TopProjectKey + "-" + MiddleProjectKey + "-" + OperationRead: endpointObjects( - api.GetProjects, - api.GetProject, - api.GetProjectKubeconfig, - ), - TopProjectKey + "-" + MiddleProjectKey + "-" + OperationCreate: endpointObjects( - api.CreateProject, - ), TopProjectKey + "-" + MiddleProjectKey + "-" + OperationUpdate: endpointObjects( - api.UpdateProject, - ), - TopProjectKey + "-" + MiddleProjectKey + "-" + OperationDelete: endpointObjects( - api.DeleteProject, - ), - TopProjectKey + "-" + MiddleProjectCommonConfigurationKey + "-" + OperationRead: endpointObjects( - api.GetProjects, - api.GetProject, - - api.GetProjectRoles, - api.GetProjectRole, - ), - TopProjectKey + "-" + MiddleProjectCommonConfigurationKey + "-" + OperationUpdate: endpointObjects( - api.UpdateProject, - ), - TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationRead: endpointObjects( - api.GetProjectMembers, - api.GetProjectMember, - api.GetProjectRoles, - api.GetProjectRole, - ), - TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationCreate: endpointObjects( - api.AddProjectMember, - ), - TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationUpdate: endpointObjects( - api.UpdateProjectMemberRole, - ), - TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationDelete: endpointObjects( - api.RemoveProjectMember, - ), - TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationRead: endpointObjects( - api.GetProjectNamespaces, - api.GetProjectNamespace, - api.GetProjectNamespaceK8sResources, - ), - TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationCreate: endpointObjects( - api.CreateProjectNamespace, - ), - TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationUpdate: endpointObjects( - api.UpdateProjectNamespace, - ), - TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationDelete: endpointObjects( - api.DeleteProjectNamespace, - ), - TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationRead: endpointObjects( - api.GetAppServeApps, - api.GetAppServeApp, - api.GetNumOfAppsOnStack, - api.GetAppServeAppLatestTask, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.GetAppServeAppTaskDetail, - api.GetAppServeAppTasksByAppId, - ), - TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationCreate: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), - TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationUpdate: endpointObjects( - api.CreateAppServeApp, - api.IsAppServeAppExist, - api.IsAppServeAppNameExist, - api.UpdateAppServeApp, - api.UpdateAppServeAppEndpoint, - api.UpdateAppServeAppStatus, - api.RollbackAppServeApp, - ), - TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationDelete: endpointObjects( - api.DeleteAppServeApp, - ), - TopConfigurationKey + "-" + MiddleConfigurationKey + "-" + OperationRead: endpointObjects(), - TopConfigurationKey + "-" + MiddleConfigurationKey + "-" + OperationUpdate: endpointObjects(), - TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationRead: endpointObjects( - api.GetCloudAccounts, - api.GetCloudAccount, - api.CheckCloudAccountName, - api.CheckAwsAccountId, - api.GetResourceQuota, - ), - TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationCreate: endpointObjects( - api.CreateCloudAccount, - ), - TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationUpdate: endpointObjects( - api.UpdateCloudAccount, - ), - TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationDelete: endpointObjects( - api.DeleteCloudAccount, - api.DeleteForceCloudAccount, - ), - TopConfigurationKey + "-" + MiddleConfigurationProjectKey + "-" + OperationRead: endpointObjects(), - TopConfigurationKey + "-" + MiddleConfigurationProjectKey + "-" + OperationCreate: endpointObjects(), - TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationRead: endpointObjects( - api.ListUser, - api.GetUser, - api.CheckId, - api.CheckEmail, - api.GetPermissionsByAccountId, - ), - TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationCreate: endpointObjects( - api.CreateUser, - ), - TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationUpdate: endpointObjects( - api.UpdateUser, - api.ResetPassword, - ), - TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationDelete: endpointObjects( - api.DeleteUser, - ), - TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationRead: endpointObjects( - api.ListTksRoles, - api.GetTksRole, - api.GetPermissionsByRoleId, - api.GetPermissionTemplates, - ), - TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationCreate: endpointObjects( - api.CreateTksRole, - ), - TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationUpdate: endpointObjects( - api.UpdateTksRole, - api.UpdatePermissionsByRoleId, - ), - TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationDelete: endpointObjects( - api.DeleteTksRole, - ), - TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationRead: endpointObjects( - api.GetSystemNotificationRules, - api.GetSystemNotificationRule, - ), - TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationCreate: endpointObjects( - api.CreateSystemNotificationRule, - ), - TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationUpdate: endpointObjects( - api.UpdateSystemNotificationRule, - ), - TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationDelete: endpointObjects( - api.DeleteSystemNotificationRule, - ), - CommonKey: endpointObjects( - // Auth - api.Login, - api.Logout, - api.RefreshToken, - api.FindId, - api.FindPassword, - api.VerifyIdentityForLostId, - api.VerifyIdentityForLostPassword, - api.VerifyToken, - - // User - api.GetUser, - api.GetPermissionsByAccountId, - - // MyProfile - api.GetMyProfile, - api.UpdateMyProfile, - api.UpdateMyPassword, - api.RenewPasswordExpiredDate, - api.DeleteMyProfile, - - // Organization - api.GetOrganization, - - // Role - api.GetPermissionsByRoleId, - - // Utiliy - api.CompileRego, - ), - } -) - -// ForceSyncToLatestPermissionEndpointMapping is used to sync the permission endpoint mapping to the latest version. -func ForceSyncToLatestPermissionEndpointMapping(db *gorm.DB, permissionSet *PermissionSet) error { - var storedPermissionEndpoints []PermissionEndpoint - var storedEdgeKeyEndpointMaps = make(map[string][]Endpoint) - if err := db.Find(&storedPermissionEndpoints).Error; err != nil { - return err - } - for _, pe := range storedPermissionEndpoints { - storedEdgeKeyEndpointMaps[pe.EdgeKey] = append(storedEdgeKeyEndpointMaps[pe.EdgeKey], pe.Endpoint) - } - - var shouldInsertEdgeKeyEndpointMaps, shouldReplaceEdgeKeyEndpointMaps map[string][]Endpoint - shouldReplaceEdgeKeyEndpointMaps = make(map[string][]Endpoint) - shouldInsertEdgeKeyEndpointMaps = edgeKeyEndpointMap - - for edgeKey, endpoints := range storedEdgeKeyEndpointMaps { - if compareEndpointArrays(endpoints, edgeKeyEndpointMap[edgeKey]) { - delete(shouldInsertEdgeKeyEndpointMaps, edgeKey) - } else { - shouldReplaceEdgeKeyEndpointMaps[edgeKey] = endpoints - } - } - - for edgeKey, endpoints := range shouldInsertEdgeKeyEndpointMaps { - for _, endpoint := range endpoints { - if err := db.Create(&PermissionEndpoint{ - EdgeKey: edgeKey, - EndpointName: endpoint.Name, - }).Error; err != nil { - return err - } - } - } - - for edgeKey, endpoints := range shouldReplaceEdgeKeyEndpointMaps { - if err := db.Where("edge_key = ?", edgeKey).Delete(&PermissionEndpoint{}).Error; err != nil { - return err - } - for _, endpoint := range endpoints { - if err := db.Create(&PermissionEndpoint{ - EdgeKey: edgeKey, - EndpointName: endpoint.Name, - }).Error; err != nil { - return err - } - } - } - - return nil -} - -// Compare two arrays of Endpoint objects -func compareEndpointArrays(a, b []Endpoint) bool { - if len(a) != len(b) { - return false - } - - // sort the arrays - sort.Slice(a, func(i, j int) bool { - return a[i].Name < a[j].Name - }) - - sort.Slice(b, func(i, j int) bool { - return b[i].Name < b[j].Name - }) - - // compare the arrays - for i := range a { - if a[i] != b[i] { - return false - } - } - - return true -} - -func endpointObjects(eps ...api.Endpoint) []Endpoint { - var result []Endpoint - for _, ep := range eps { - result = append(result, Endpoint{ - Name: api.MapWithEndpoint[ep].Name, - Group: api.MapWithEndpoint[ep].Group, - }) - } - return result -} diff --git a/internal/model/permission.go b/internal/model/permission.go index a84fa777..4c395c85 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -2,6 +2,7 @@ package model import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/delivery/api" "github.com/openinfradev/tks-api/internal/helper" "gorm.io/gorm" ) @@ -53,22 +54,19 @@ const ( MiddleConfigurationUserKey = "CONFIGURATION-USER" MiddleConfigurationRoleKey = "CONFIGURATION-ROLE" MiddleConfigurationSystemNotificationKey = "CONFIGURATION-SYSTEM_NOTIFICATION" - CommonKey = "COMMON" ) type Permission struct { gorm.Model - ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` - Name string `json:"name"` - Key string `gorm:"type:text;" json:"key,omitempty"` - EdgeKey *string `gorm:"type:text;"` + ID uuid.UUID `gorm:"primarykey;type:uuid;" json:"ID"` + Name string `json:"name"` + Key string `gorm:"type:text;" json:"key,omitempty"` IsAllowed *bool `gorm:"type:boolean;" json:"is_allowed,omitempty"` RoleID *string `json:"role_id,omitempty"` Role *Role `gorm:"foreignKey:RoleID;references:ID;" json:"role,omitempty"` - Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;joinForeignKey:EdgeKey;joinReferences:EndpointName;" json:"endpoints,omitempty"` - //PermissionEndpoint []*PermissionEndpoint `gorm:"foreignKey:EdgeKey;references:EdgeKey;"` + Endpoints []*Endpoint `gorm:"many2many:permission_endpoints;" json:"endpoints,omitempty"` // omit empty ParentID *uuid.UUID `json:"parent_id,omitempty"` @@ -84,8 +82,7 @@ type PermissionSet struct { Notification *Permission `gorm:"-:all" json:"notification,omitempty"` Configuration *Permission `gorm:"-:all" json:"configuration,omitempty"` Common *Permission `gorm:"-:all" json:"common,omitempty"` - // ToDo: Need to consider whether to use Admin Permission - //Admin *Permission `gorm:"-:all" json:"admin,omitempty"` + Admin *Permission `gorm:"-:all" json:"admin,omitempty"` } func NewDefaultPermissionSet() *PermissionSet { @@ -97,13 +94,13 @@ func NewDefaultPermissionSet() *PermissionSet { Notification: newNotification(), Configuration: newConfiguration(), Common: newCommon(), - //Admin: nil, + Admin: nil, } } func NewAdminPermissionSet() *PermissionSet { return &PermissionSet{ - //Admin: newAdmin(), + Admin: newAdmin(), Dashboard: newDashboard(), Stack: newStack(), Policy: newPolicy(), @@ -129,6 +126,17 @@ func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func( return edgePermissions } +func endpointObjects(eps ...api.Endpoint) []*Endpoint { + var result []*Endpoint + for _, ep := range eps { + result = append(result, &Endpoint{ + Name: api.ApiMap[ep].Name, + Group: api.ApiMap[ep].Group, + }) + } + return result +} + func newDashboard() *Permission { dashboard := &Permission{ ID: uuid.New(), @@ -144,14 +152,18 @@ func newDashboard() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopDashboardKey + "-" + MiddleDashboardKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetChartsDashboard, + api.GetChartDashboard, + api.GetStacksDashboard, + api.GetResourcesDashboard, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopDashboardKey + "-" + MiddleDashboardKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), }, }, @@ -177,29 +189,74 @@ func newStack() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopStackKey + "-" + MiddleStackKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetStacks, + api.GetStack, + api.CheckStackName, + api.GetStackStatus, + api.GetStackKubeConfig, + + api.SetFavoriteStack, + api.DeleteFavoriteStack, + + // Cluster + api.GetCluster, + api.GetClusters, + api.GetClusterSiteValues, + api.GetBootstrapKubeconfig, + api.GetNodes, + + // AppGroup + api.GetAppgroups, + api.GetAppgroup, + api.GetApplications, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopStackKey + "-" + MiddleStackKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateStack, + api.InstallStack, + api.CreateAppgroup, + + // Cluster + api.CreateCluster, + api.ImportCluster, + api.InstallCluster, + api.CreateBootstrapKubeconfig, + + // AppGroup + api.CreateAppgroup, + api.CreateApplication, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopStackKey + "-" + MiddleStackKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateStack, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopStackKey + "-" + MiddleStackKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteStack, + + // Cluster + api.DeleteCluster, + + // AppGroup + api.DeleteAppgroup, + ), }, }, }, @@ -224,29 +281,105 @@ func newPolicy() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.Admin_ListPolicyTemplate, + api.Admin_GetPolicyTemplate, + api.Admin_GetPolicyTemplateDeploy, + api.Admin_ListPolicyTemplateStatistics, + api.Admin_ListPolicyTemplateVersions, + api.Admin_GetPolicyTemplateVersion, + api.Admin_ExistsPolicyTemplateName, + api.Admin_ExistsPolicyTemplateKind, + + // StackPolicyStatus + api.ListStackPolicyStatus, + api.GetStackPolicyTemplateStatus, + + // Policy + api.GetMandatoryPolicies, + api.ListPolicy, + api.GetPolicy, + api.ExistsPolicyName, + + // OrganizationPolicyTemplate + api.ListPolicyTemplate, + api.GetPolicyTemplate, + api.GetPolicyTemplateDeploy, + api.ListPolicyTemplateStatistics, + api.ListPolicyTemplateVersions, + api.GetPolicyTemplateVersion, + api.ExistsPolicyTemplateKind, + api.ExistsPolicyTemplateName, + + // PolicyTemplateExample + api.ListPolicyTemplateExample, + api.GetPolicyTemplateExample, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.Admin_CreatePolicyTemplate, + api.Admin_CreatePolicyTemplateVersion, + + // Policy + api.SetMandatoryPolicies, + api.CreatePolicy, + + // OrganizationPolicyTemplate + api.CreatePolicyTemplate, + api.CreatePolicyTemplateVersion, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.Admin_UpdatePolicyTemplate, + + // ClusterPolicyStatus + api.UpdateStackPolicyTemplateStatus, + + // Policy + api.UpdatePolicy, + api.UpdatePolicyTargetClusters, + + // OrganizationPolicyTemplate + api.UpdatePolicyTemplate, + + // PolicyTemplateExample + api.UpdatePolicyTemplateExample, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopPolicyKey + "-" + MiddlePolicyKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + // PolicyTemplate + api.Admin_DeletePolicyTemplate, + api.Admin_DeletePolicyTemplateVersion, + + // Policy + api.DeletePolicy, + + // OrganizationPolicyTemplate + api.DeletePolicyTemplate, + api.DeletePolicyTemplateVersion, + + // PolicyTemplateExample + api.DeletePolicyTemplateExample, + ), }, }, }, @@ -271,21 +404,26 @@ func newNotification() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetSystemNotification, + api.GetSystemNotifications, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateSystemNotification, + api.CreateSystemNotificationAction, + ), }, { ID: uuid.New(), Name: "다운로드", Key: OperationDownload, - EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddleNotificationKey + "-" + OperationDownload), IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -300,7 +438,6 @@ func newNotification() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddlePolicyNotificationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -308,7 +445,6 @@ func newNotification() *Permission { ID: uuid.New(), Name: "다운로드", Key: OperationDownload, - EdgeKey: helper.StringP(TopNotificationKey + "-" + MiddlePolicyNotificationKey + "-" + OperationDownload), IsAllowed: helper.BoolP(false), Children: []*Permission{}, }, @@ -335,29 +471,39 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + api.GetProjectKubeconfig, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProject, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProject, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProject, + ), }, }, }, @@ -370,15 +516,23 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectCommonConfigurationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjects, + api.GetProject, + + api.GetProjectRoles, + api.GetProjectRole, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectCommonConfigurationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProject, + ), }, }, }, @@ -391,29 +545,40 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectMembers, + api.GetProjectMember, + api.GetProjectRoles, + api.GetProjectRole, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.AddProjectMember, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProjectMemberRole, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectMemberConfigurationKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.RemoveProjectMember, + ), }, }, }, @@ -426,29 +591,39 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetProjectNamespaces, + api.GetProjectNamespace, + api.GetProjectNamespaceK8sResources, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateProjectNamespace, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateProjectNamespace, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectNamespaceKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteProjectNamespace, + ), }, }, }, @@ -461,29 +636,56 @@ func newProject() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetAppServeApps, + api.GetAppServeApp, + api.GetNumOfAppsOnStack, + api.GetAppServeAppLatestTask, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.GetAppServeAppTaskDetail, + api.GetAppServeAppTasksByAppId, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateAppServeApp, + api.IsAppServeAppExist, + api.IsAppServeAppNameExist, + api.UpdateAppServeApp, + api.UpdateAppServeAppEndpoint, + api.UpdateAppServeAppStatus, + api.RollbackAppServeApp, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopProjectKey + "-" + MiddleProjectAppServeKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteAppServeApp, + ), }, }, }, @@ -508,14 +710,12 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), }, }, @@ -529,29 +729,42 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetCloudAccounts, + api.GetCloudAccount, + api.CheckCloudAccountName, + api.CheckAwsAccountId, + api.GetResourceQuota, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateCloudAccount, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateCloudAccount, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationCloudAccountKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteCloudAccount, + api.DeleteForceCloudAccount, + ), }, }, }, @@ -564,14 +777,12 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationProjectKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationProjectKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), }, }, @@ -585,29 +796,43 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.ListUser, + api.GetUser, + api.CheckId, + api.CheckEmail, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateUser, + api.CheckId, + api.CheckEmail, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateUser, + api.ResetPassword, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationUserKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteUser, + ), }, }, }, @@ -620,29 +845,41 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.ListTksRoles, + api.GetTksRole, + api.GetPermissionsByRoleId, + api.GetPermissionTemplates, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateTksRole, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateTksRole, + api.UpdatePermissionsByRoleId, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationRoleKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteTksRole, + ), }, }, }, @@ -655,29 +892,38 @@ func newConfiguration() *Permission { ID: uuid.New(), Name: "조회", Key: OperationRead, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationRead), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.GetSystemNotificationRules, + api.GetSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "생성", Key: OperationCreate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationCreate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.CreateSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "수정", Key: OperationUpdate, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationUpdate), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.UpdateSystemNotificationRule, + ), }, { ID: uuid.New(), Name: "삭제", Key: OperationDelete, - EdgeKey: helper.StringP(TopConfigurationKey + "-" + MiddleConfigurationSystemNotificationKey + "-" + OperationDelete), IsAllowed: helper.BoolP(false), + Endpoints: endpointObjects( + api.DeleteSystemNotificationRule, + ), }, }, }, @@ -692,72 +938,104 @@ func newCommon() *Permission { ID: uuid.New(), Name: "공통", IsAllowed: helper.BoolP(true), - Key: CommonKey, - EdgeKey: helper.StringP(CommonKey), + Endpoints: endpointObjects( + // Auth + api.Login, + api.Logout, + api.RefreshToken, + api.FindId, + api.FindPassword, + api.VerifyIdentityForLostId, + api.VerifyIdentityForLostPassword, + api.VerifyToken, + + // Stack + api.SetFavoriteStack, + api.DeleteFavoriteStack, + + // Project + api.SetFavoriteProject, + api.SetFavoriteProjectNamespace, + api.UnSetFavoriteProject, + api.UnSetFavoriteProjectNamespace, + + // MyProfile + api.GetMyProfile, + api.UpdateMyProfile, + api.UpdateMyPassword, + api.RenewPasswordExpiredDate, + api.DeleteMyProfile, + + // StackTemplate + api.GetOrganizationStackTemplates, + api.GetOrganizationStackTemplate, + + // Utiliy + api.CompileRego, + ), } return common } -//func newAdmin() *Permission { -// admin := &Permission{ -// ID: uuid.New(), -// Name: "관리자", -// IsAllowed: helper.BoolP(true), -// EdgeKey: helper.StringP("admin"), -// Endpoints: endpointObjects( -// // Organization -// api.Admin_CreateOrganization, -// api.Admin_DeleteOrganization, -// api.UpdateOrganization, -// api.GetOrganization, -// api.GetOrganizations, -// api.UpdatePrimaryCluster, -// api.CheckOrganizationName, -// -// // User -// api.ResetPassword, -// api.CheckId, -// api.CheckEmail, -// -// // StackTemplate -// api.Admin_GetStackTemplates, -// api.Admin_GetStackTemplate, -// api.Admin_GetStackTemplateServices, -// api.Admin_CreateStackTemplate, -// api.Admin_UpdateStackTemplate, -// api.Admin_DeleteStackTemplate, -// api.Admin_UpdateStackTemplateOrganizations, -// api.Admin_CheckStackTemplateName, -// -// // Admin -// api.Admin_GetUser, -// api.Admin_ListUser, -// api.Admin_CreateUser, -// api.Admin_UpdateUser, -// api.Admin_DeleteUser, -// api.Admin_GetSystemNotificationTemplate, -// api.Admin_CreateSystemNotificationTemplate, -// api.Admin_ListUser, -// api.Admin_GetTksRole, -// api.Admin_GetProjects, -// api.Admin_UpdateSystemNotificationTemplate, -// api.Admin_ListTksRoles, -// api.Admin_GetSystemNotificationTemplates, -// -// // Audit -// api.GetAudits, -// api.GetAudit, -// api.DeleteAudit, -// -// api.CreateSystemNotification, -// api.DeleteSystemNotification, -// ), -// } -// -// return admin -//} +func newAdmin() *Permission { + admin := &Permission{ + ID: uuid.New(), + Name: "관리자", + IsAllowed: helper.BoolP(true), + Endpoints: endpointObjects( + // Organization + api.Admin_CreateOrganization, + api.Admin_DeleteOrganization, + api.UpdateOrganization, + api.GetOrganization, + api.GetOrganizations, + api.UpdatePrimaryCluster, + api.CheckOrganizationName, + + // User + api.ResetPassword, + api.CheckId, + api.CheckEmail, + + // StackTemplate + api.Admin_GetStackTemplates, + api.Admin_GetStackTemplate, + api.Admin_GetStackTemplateServices, + api.Admin_CreateStackTemplate, + api.Admin_UpdateStackTemplate, + api.Admin_DeleteStackTemplate, + api.Admin_UpdateStackTemplateOrganizations, + api.Admin_CheckStackTemplateName, + + // Admin + api.Admin_GetUser, + api.Admin_ListUser, + api.Admin_CreateUser, + api.Admin_UpdateUser, + api.Admin_DeleteUser, + api.Admin_GetSystemNotificationTemplate, + api.Admin_CreateSystemNotificationTemplate, + api.Admin_ListUser, + api.Admin_GetTksRole, + api.Admin_GetProjects, + api.Admin_UpdateSystemNotificationTemplate, + api.Admin_ListTksRoles, + api.Admin_GetSystemNotificationTemplates, + + // Audit + api.GetAudits, + api.GetAudit, + api.DeleteAudit, + + api.CreateSystemNotification, + api.DeleteSystemNotification, + ), + } + + return admin +} func (p *PermissionSet) SetAllowedPermissionSet() { edgePermissions := make([]*Permission, 0) diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 3d394b22..22a7d6bb 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -14,8 +14,6 @@ type IPermissionRepository interface { Get(ctx context.Context, id uuid.UUID) (*model.Permission, error) Delete(ctx context.Context, id uuid.UUID) error Update(ctx context.Context, permission *model.Permission) error - EdgeKeyOverwrite(ctx context.Context, permission *model.Permission) error - GetEndpointsByPermissionId(ctx context.Context, permissionId uuid.UUID) (*model.Permission, error) } type PermissionRepository struct { @@ -84,17 +82,3 @@ func (r PermissionRepository) Update(ctx context.Context, p *model.Permission) e // update on is_allowed return r.db.WithContext(ctx).Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"is_allowed": p.IsAllowed}).Error } - -func (r PermissionRepository) EdgeKeyOverwrite(ctx context.Context, p *model.Permission) error { - return r.db.WithContext(ctx).Model(&model.Permission{}).Where("id = ?", p.ID).Updates(map[string]interface{}{"edge_key": p.EdgeKey}).Error -} - -func (r PermissionRepository) GetEndpointsByPermissionId(ctx context.Context, permissionId uuid.UUID) (*model.Permission, error) { - var permission *model.Permission - err := r.db.WithContext(ctx).Preload("Permission_endpoints").First(&permission, "id = ?", permissionId).Error - if err != nil { - return nil, err - } - - return permission, nil -} diff --git a/internal/route/route.go b/internal/route/route.go index aa557fae..56e2500e 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -81,7 +81,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa Audit: usecase.NewAuditUsecase(repoFactory), Role: usecase.NewRoleUsecase(repoFactory, kc), Permission: usecase.NewPermissionUsecase(repoFactory), - Endpoint: usecase.NewEndpointUsecase(repoFactory), PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), Policy: usecase.NewPolicyUsecase(repoFactory), } @@ -318,10 +317,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa permissionHandler := delivery.NewPermissionHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/permissions/templates", customMiddleware.Handle(internalApi.GetPermissionTemplates, http.HandlerFunc(permissionHandler.GetPermissionTemplates))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/permissions/{permissionId}/endpoints", customMiddleware.Handle(internalApi.GetEndpointsByPermissionId, http.HandlerFunc(permissionHandler.GetEndpoints))).Methods(http.MethodGet) - - endpointHandler := delivery.NewEndpointHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/endpoints", customMiddleware.Handle(internalApi.Admin_GetEndpoints, http.HandlerFunc(endpointHandler.ListEndpoint))).Methods(http.MethodGet) policyTemplateHandler := delivery.NewPolicyTemplateHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/policy-templates", customMiddleware.Handle(internalApi.Admin_ListPolicyTemplate, http.HandlerFunc(policyTemplateHandler.Admin_ListPolicyTemplate))).Methods(http.MethodGet) diff --git a/internal/usecase/endpoint.go b/internal/usecase/endpoint.go deleted file mode 100644 index 726042ca..00000000 --- a/internal/usecase/endpoint.go +++ /dev/null @@ -1,26 +0,0 @@ -package usecase - -import ( - "context" - "github.com/openinfradev/tks-api/internal/model" - "github.com/openinfradev/tks-api/internal/pagination" - "github.com/openinfradev/tks-api/internal/repository" -) - -type IEndpointUsecase interface { - ListEndpoints(ctx context.Context, pg *pagination.Pagination) ([]*model.Endpoint, error) -} - -type EndpointUsecase struct { - repo repository.IEndpointRepository -} - -func NewEndpointUsecase(repo repository.Repository) *EndpointUsecase { - return &EndpointUsecase{ - repo: repo.Endpoint, - } -} - -func (e EndpointUsecase) ListEndpoints(ctx context.Context, pg *pagination.Pagination) ([]*model.Endpoint, error) { - return e.repo.List(ctx, pg) -} diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index bd6b1fc2..532e723c 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -17,7 +17,6 @@ type IPermissionUsecase interface { GetUserPermissionSet(ctx context.Context) *model.PermissionSet UpdatePermission(ctx context.Context, permission *model.Permission) error MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet - GetEndpointsByPermissionId(ctx context.Context, permissionId uuid.UUID) ([]*model.Endpoint, error) } type PermissionUsecase struct { @@ -134,20 +133,6 @@ func (p PermissionUsecase) GetUserPermissionSet(ctx context.Context) *model.Perm return permissionSet } -func (p PermissionUsecase) GetEndpointsByPermissionId(ctx context.Context, permissionId uuid.UUID) ([]*model.Endpoint, error) { - permission, err := p.repo.GetEndpointsByPermissionId(ctx, permissionId) - if err != nil { - return nil, err - } - - endpoints := make([]*model.Endpoint, 0) - for _, e := range permission.Endpoints { - endpoints = append(endpoints, e) - } - - return endpoints, nil -} - func (p PermissionUsecase) MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet { var out *model.PermissionSet for i, ps := range permissionSet { diff --git a/internal/usecase/role.go b/internal/usecase/role.go index 40f29201..7b181c93 100644 --- a/internal/usecase/role.go +++ b/internal/usecase/role.go @@ -6,7 +6,6 @@ import ( "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" - "github.com/openinfradev/tks-api/pkg/log" ) type IRoleUsecase interface { @@ -16,14 +15,11 @@ type IRoleUsecase interface { DeleteTksRole(ctx context.Context, organizationId string, id string) error UpdateTksRole(ctx context.Context, role *model.Role) error IsRoleNameExisted(ctx context.Context, organizationId string, roleName string) (bool, error) - SyncOldVersions(ctx context.Context) error } type RoleUsecase struct { - repo repository.IRoleRepository - kc keycloak.IKeycloak - orgRepo repository.IOrganizationRepository - permissionRepo repository.IPermissionRepository + repo repository.IRoleRepository + kc keycloak.IKeycloak } func NewRoleUsecase(repo repository.Repository, kc keycloak.IKeycloak) *RoleUsecase { @@ -101,193 +97,3 @@ func (r RoleUsecase) IsRoleNameExisted(ctx context.Context, organizationId strin return false, nil } - -func (r RoleUsecase) SyncOldVersions(ctx context.Context) error { - // Get all organizations - orgs, _ := r.orgRepo.Fetch(ctx, nil) - for _, org := range *orgs { - roles, _ := r.repo.ListTksRoles(ctx, org.ID, nil) - for _, role := range roles { - storedPermissionSet := &model.PermissionSet{} - - permissionList, err := r.permissionRepo.List(ctx, role.ID) - - if err != nil { - return err - } - for _, permission := range permissionList { - switch permission.Name { - case string(model.DashBoardPermission): - storedPermissionSet.Dashboard = permission - log.Debugf(ctx, "Dashboard Permission Set : %+v", storedPermissionSet.Dashboard) - case string(model.StackPermission): - storedPermissionSet.Stack = permission - log.Debugf(ctx, "Stack Permission Set : %+v", storedPermissionSet.Stack) - case string(model.PolicyPermission): - storedPermissionSet.Policy = permission - log.Debugf(ctx, "Policy Permission Set : %+v", storedPermissionSet.Policy) - case string(model.ProjectPermission): - storedPermissionSet.ProjectManagement = permission - log.Debugf(ctx, "Project Permission Set : %+v", storedPermissionSet.ProjectManagement) - case string(model.NotificationPermission): - storedPermissionSet.Notification = permission - log.Debugf(ctx, "Notification Permission Set : %+v", storedPermissionSet.Notification) - case string(model.ConfigurationPermission): - storedPermissionSet.Configuration = permission - log.Debugf(ctx, "Configuration Permission Set : %+v", storedPermissionSet.Configuration) - } - } - - // tmp - t := model.NewDefaultPermissionSet() - var overwritePermissions []*model.Permission - overwritePermissions = make([]*model.Permission, 0) - - // dashboard - storedPermissionSet.Dashboard.Children[0].Children[0].EdgeKey = t.Dashboard.Children[0].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Dashboard.Children[0].Children[0]) - storedPermissionSet.Dashboard.Children[0].Children[1].EdgeKey = t.Dashboard.Children[0].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Dashboard.Children[0].Children[1]) - - // stack - storedPermissionSet.Stack.Children[0].Children[0].EdgeKey = t.Stack.Children[0].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Stack.Children[0].Children[0]) - storedPermissionSet.Stack.Children[0].Children[1].EdgeKey = t.Stack.Children[0].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Stack.Children[0].Children[1]) - storedPermissionSet.Stack.Children[0].Children[2].EdgeKey = t.Stack.Children[0].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Stack.Children[0].Children[2]) - storedPermissionSet.Stack.Children[0].Children[3].EdgeKey = t.Stack.Children[0].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Stack.Children[0].Children[3]) - - // policy - storedPermissionSet.Policy.Children[0].Children[0].EdgeKey = t.Policy.Children[0].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Policy.Children[0].Children[0]) - storedPermissionSet.Policy.Children[0].Children[1].EdgeKey = t.Policy.Children[0].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Policy.Children[0].Children[1]) - storedPermissionSet.Policy.Children[0].Children[2].EdgeKey = t.Policy.Children[0].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Policy.Children[0].Children[2]) - storedPermissionSet.Policy.Children[0].Children[3].EdgeKey = t.Policy.Children[0].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Policy.Children[0].Children[3]) - - // notification - storedPermissionSet.Notification.Children[0].Children[0].EdgeKey = t.Notification.Children[0].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[0].Children[0]) - storedPermissionSet.Notification.Children[0].Children[1].EdgeKey = t.Notification.Children[0].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[0].Children[1]) - storedPermissionSet.Notification.Children[0].Children[2].EdgeKey = t.Notification.Children[0].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[0].Children[2]) - storedPermissionSet.Notification.Children[1].Children[0].EdgeKey = t.Notification.Children[1].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[1].Children[0]) - storedPermissionSet.Notification.Children[1].Children[1].EdgeKey = t.Notification.Children[1].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Notification.Children[1].Children[1]) - - // project - // 1depth - storedPermissionSet.ProjectManagement.Children[0].Children[0].EdgeKey = t.ProjectManagement.Children[0].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[0].Children[0]) - storedPermissionSet.ProjectManagement.Children[0].Children[1].EdgeKey = t.ProjectManagement.Children[0].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[0].Children[1]) - storedPermissionSet.ProjectManagement.Children[0].Children[2].EdgeKey = t.ProjectManagement.Children[0].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[0].Children[2]) - storedPermissionSet.ProjectManagement.Children[0].Children[3].EdgeKey = t.ProjectManagement.Children[0].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[0].Children[3]) - - // 2depth - storedPermissionSet.ProjectManagement.Children[1].Children[0].EdgeKey = t.ProjectManagement.Children[1].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[1].Children[0]) - storedPermissionSet.ProjectManagement.Children[1].Children[1].EdgeKey = t.ProjectManagement.Children[1].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[1].Children[1]) - - // 3depth - storedPermissionSet.ProjectManagement.Children[2].Children[0].EdgeKey = t.ProjectManagement.Children[2].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[2].Children[0]) - storedPermissionSet.ProjectManagement.Children[2].Children[1].EdgeKey = t.ProjectManagement.Children[2].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[2].Children[1]) - storedPermissionSet.ProjectManagement.Children[2].Children[2].EdgeKey = t.ProjectManagement.Children[2].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[2].Children[2]) - storedPermissionSet.ProjectManagement.Children[2].Children[3].EdgeKey = t.ProjectManagement.Children[2].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[2].Children[3]) - - // 4depth - storedPermissionSet.ProjectManagement.Children[3].Children[0].EdgeKey = t.ProjectManagement.Children[3].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[3].Children[0]) - storedPermissionSet.ProjectManagement.Children[3].Children[1].EdgeKey = t.ProjectManagement.Children[3].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[3].Children[1]) - storedPermissionSet.ProjectManagement.Children[3].Children[2].EdgeKey = t.ProjectManagement.Children[3].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[3].Children[2]) - storedPermissionSet.ProjectManagement.Children[3].Children[3].EdgeKey = t.ProjectManagement.Children[3].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[3].Children[3]) - - // 5depth - storedPermissionSet.ProjectManagement.Children[4].Children[0].EdgeKey = t.ProjectManagement.Children[4].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[4].Children[0]) - storedPermissionSet.ProjectManagement.Children[4].Children[1].EdgeKey = t.ProjectManagement.Children[4].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[4].Children[1]) - storedPermissionSet.ProjectManagement.Children[4].Children[2].EdgeKey = t.ProjectManagement.Children[4].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[4].Children[2]) - storedPermissionSet.ProjectManagement.Children[4].Children[3].EdgeKey = t.ProjectManagement.Children[4].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.ProjectManagement.Children[4].Children[3]) - - // configuration - storedPermissionSet.Configuration.Children[0].Children[0].EdgeKey = t.Configuration.Children[0].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[0].Children[0]) - storedPermissionSet.Configuration.Children[0].Children[1].EdgeKey = t.Configuration.Children[0].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[0].Children[1]) - - // 2depth - storedPermissionSet.Configuration.Children[1].Children[0].EdgeKey = t.Configuration.Children[1].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[1].Children[0]) - storedPermissionSet.Configuration.Children[1].Children[1].EdgeKey = t.Configuration.Children[1].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[1].Children[1]) - storedPermissionSet.Configuration.Children[1].Children[2].EdgeKey = t.Configuration.Children[1].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[1].Children[2]) - storedPermissionSet.Configuration.Children[1].Children[3].EdgeKey = t.Configuration.Children[1].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[1].Children[3]) - - // 3depth - storedPermissionSet.Configuration.Children[2].Children[0].EdgeKey = t.Configuration.Children[2].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[2].Children[0]) - storedPermissionSet.Configuration.Children[2].Children[1].EdgeKey = t.Configuration.Children[2].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[2].Children[1]) - - // 4depth - storedPermissionSet.Configuration.Children[3].Children[0].EdgeKey = t.Configuration.Children[3].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[3].Children[0]) - storedPermissionSet.Configuration.Children[3].Children[1].EdgeKey = t.Configuration.Children[3].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[3].Children[1]) - storedPermissionSet.Configuration.Children[3].Children[2].EdgeKey = t.Configuration.Children[3].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[3].Children[2]) - storedPermissionSet.Configuration.Children[3].Children[3].EdgeKey = t.Configuration.Children[3].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[3].Children[3]) - - // 5depth - storedPermissionSet.Configuration.Children[4].Children[0].EdgeKey = t.Configuration.Children[4].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[4].Children[0]) - storedPermissionSet.Configuration.Children[4].Children[1].EdgeKey = t.Configuration.Children[4].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[4].Children[1]) - storedPermissionSet.Configuration.Children[4].Children[2].EdgeKey = t.Configuration.Children[4].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[4].Children[2]) - storedPermissionSet.Configuration.Children[4].Children[3].EdgeKey = t.Configuration.Children[4].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[4].Children[3]) - - // 6depth - storedPermissionSet.Configuration.Children[5].Children[0].EdgeKey = t.Configuration.Children[5].Children[0].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[5].Children[0]) - storedPermissionSet.Configuration.Children[5].Children[1].EdgeKey = t.Configuration.Children[5].Children[1].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[5].Children[1]) - storedPermissionSet.Configuration.Children[5].Children[2].EdgeKey = t.Configuration.Children[5].Children[2].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[5].Children[2]) - storedPermissionSet.Configuration.Children[5].Children[3].EdgeKey = t.Configuration.Children[5].Children[3].EdgeKey - overwritePermissions = append(overwritePermissions, storedPermissionSet.Configuration.Children[5].Children[3]) - - for _, permission := range overwritePermissions { - if err = r.permissionRepo.EdgeKeyOverwrite(ctx, permission); err != nil { - return err - } - } - log.Debugf(ctx, "Dashboard EdgeKey Overwrite Success") - } - } - - return nil -} diff --git a/internal/usecase/usecase.go b/internal/usecase/usecase.go index cb580b9d..46302b69 100644 --- a/internal/usecase/usecase.go +++ b/internal/usecase/usecase.go @@ -17,7 +17,6 @@ type Usecase struct { Project IProjectUsecase Role IRoleUsecase Permission IPermissionUsecase - Endpoint IEndpointUsecase Audit IAuditUsecase PolicyTemplate IPolicyTemplateUsecase Policy IPolicyUsecase diff --git a/pkg/domain/endpoint.go b/pkg/domain/endpoint.go index b8ca18ee..33acdc92 100644 --- a/pkg/domain/endpoint.go +++ b/pkg/domain/endpoint.go @@ -4,7 +4,3 @@ type EndpointResponse struct { Name string `json:"name"` Group string `json:"group"` } - -type ListEndpointResponse struct { - Endpoints []EndpointResponse `json:"endpoints"` -} diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index 3d8ab656..3ae4805c 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -19,10 +19,10 @@ type GetPermissionTemplatesResponse struct { //} type TemplateResponse struct { - Name string `json:"name"` - Key string `json:"key"` - EdgeKey *string `json:"edgeKey,omitempty"` - Children []*TemplateResponse `json:"children,omitempty"` + Name string `json:"name"` + Key string `json:"key"` + IsAllowed *bool `json:"isAllowed,omitempty"` + Children []*TemplateResponse `json:"children,omitempty"` } type GetPermissionsByRoleIdResponse struct { @@ -44,6 +44,7 @@ type PermissionResponse struct { Name string `json:"name"` Key string `json:"key"` IsAllowed *bool `json:"isAllowed,omitempty"` + Endpoints []*EndpointResponse `json:"endpoints,omitempty"` Children []*PermissionResponse `json:"children,omitempty"` } @@ -75,10 +76,3 @@ type MergePermissionResponse struct { IsAllowed *bool `json:"isAllowed,omitempty"` Children []*MergePermissionResponse `json:"children,omitempty"` } - -type GetPermissionEdgeKeysResponse struct { -} - -type GetEndpointsResponse struct { - Endpoints []EndpointResponse `json:"endpoints"` -} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 3b7efb98..21fb3510 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -146,9 +146,6 @@ var errorMap = map[ErrorCode]string{ "P_CALL_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 호출에 실패했습니다.", "P_FAILED_TO_APPLY_KUBERNETES": "쿠버네티스 클러스터 변경사항 적용에 실패했습니다.", "P_INVALID_POLICY_PARAMETER": "정책 파라미터가 템플릿의 파라미터 스키마에 유효하지 않습니다. 파라미터를 확인하세요.", - - // Permission - "PE_INVALID_PERMISSIONID": "유효하지 않은 권한 아이디입니다. 권한 아이디를 확인하세요.", } func (m ErrorCode) GetText() string { From 5bb763058851f1c1c8672a5ccbde2cc91e858d86 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 3 May 2024 09:49:30 +0900 Subject: [PATCH 417/502] trivial. fix audit when user failed login --- internal/usecase/audit.go | 37 +++++++++++---------------- scripts/init_postgres.sql | 54 +++++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 49 deletions(-) diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index 92c7c97c..d205210c 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -4,7 +4,6 @@ import ( "context" "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/internal/repository" @@ -31,31 +30,25 @@ func NewAuditUsecase(r repository.Repository) IAuditUsecase { } func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { - if dto.UserId == nil || *dto.UserId == uuid.Nil { - userInfo, ok := request.UserFrom(ctx) - if ok { - id := userInfo.GetUserId() - dto.UserId = &id + if dto.UserId != nil && *dto.UserId == uuid.Nil { + user, err := u.userRepo.GetByUuid(ctx, *dto.UserId) + if err != nil { + return auditId, err } - } - - user, err := u.userRepo.GetByUuid(ctx, *dto.UserId) - if err != nil { - return auditId, err - } - userRoles := "" - for i, role := range user.Roles { - if i > 0 { - userRoles = userRoles + "," + userRoles := "" + for i, role := range user.Roles { + if i > 0 { + userRoles = userRoles + "," + } + userRoles = userRoles + role.Name } - userRoles = userRoles + role.Name + dto.OrganizationId = user.Organization.ID + dto.OrganizationName = user.Organization.Name + dto.UserAccountId = user.AccountId + dto.UserName = user.Name + dto.UserRoles = userRoles } - dto.OrganizationId = user.Organization.ID - dto.OrganizationName = user.Organization.Name - dto.UserAccountId = user.AccountId - dto.UserName = user.Name - dto.UserRoles = userRoles auditId, err = u.repo.Create(ctx, dto) if err != nil { diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index ef542216..206cf269 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -20,37 +20,37 @@ insert into policies ( role_id, name, description, c, create_priviledge, u, upda insert into organizations ( id, name, description, created_at, updated_at ) values ( 'master', 'master', 'tks', now(), now() ); ## Users -insert into users ( id, account_id, name, password, organization_id, role_id, created_at, updated_at ) values ( 'bf67de40-ce15-4dc0-b6c2-17f053ca504f', 'admin', 'admin', '$2a$10$Akf03nbLHk93sTtozm35XuINXkJeNX7A1T9o/Pxpg9R2B2PToBPOO', 'master', 'b2b689f0-ceeb-46c2-b280-0bc06896acd1', now(), now() ); +insert into users ( id, account_id, name, organization_id, created_at, updated_at ) values ( 'bf67de40-ce15-4dc0-b6c2-17f053ca504f', 'admin', 'admin', 'master', now(), now() ); ## StackTemplates -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( '49901092-be76-4d4f-94e9-b84525f560b5', 'master', 'AWS Standard (x86)', 'included LMA', 'v1', 'AWS', 'x86', 'aws-reference', 'STANDARD', 'v1.25', 'AWS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( '44d5e76b-63db-4dd0-a16e-11bd3f6054cf', 'master', 'AWS MSA Standard (x86)', 'included LMA, SERVICE MESH', 'v1', 'AWS', 'x86', 'aws-msa-reference', 'MSA', 'v1.25', 'AWS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}, {"name": "MSA", "type": "SERVICE_MESH", "applications": [{"name": "istio", "version": "v1.13.1", "description": "MSA 플랫폼"}, {"name": "jagger", "version": "v2.27.1", "description": "분산 서비스간 트랜잭션 추적을 위한 로깅 플랫폼"}, {"name": "kiali", "version": "v1.45.1", "description": "MSA 통합 모니터링포탈"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( 'fe1d97e0-7428-4be6-9c69-310a88b4ff46', 'master', 'AWS Standard (arm)', 'included LMA', 'v2', 'AWS', 'arm', 'aws-arm-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( '3696cb38-4da0-4235-97eb-b6eb15962bd1', 'master', 'AWS Standard (arm)', 'included LMA, SERVICE_MESH', 'v2', 'AWS', 'arm', 'aws-arm-msa-reference', 'MSA', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}, {"name": "MSA", "type": "SERVICE_MESH", "applications": [{"name": "istio", "version": "v1.13.1", "description": "MSA 플랫폼"}, {"name": "jagger", "version": "v2.27.1", "description": "분산 서비스간 트랜잭션 추적을 위한 로깅 플랫폼"}, {"name": "kiali", "version": "v1.45.1", "description": "MSA 통합 모니터링포탈"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( 'c8a4658d-d5a6-4191-8a91-e26f6aee007f', 'master', 'EKS Standard (x86)', 'included LMA', 'v1', 'AWS', 'x86', 'eks-reference', 'STANDARD', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( '39f18a09-5b94-4772-bdba-e4c32ee002f7', 'master', 'EKS MSA Standard (x86)', 'included LMA, SERVICE MESH', 'v1', 'AWS', 'x86', 'eks-msa-reference', 'MSA', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]},{"name":"MSA","type":"SERVICE_MESH","applications":[{"name":"istio","version":"v1.17.2","description":"MSA 플랫폼"},{"name":"jagger","version":"1.35.0","description":"분산 서비스간 트랜잭션 추적을 위한 플랫폼"},{"name":"kiali","version":"v1.63.0","description":"MSA 구조 및 성능을 볼 수 있는 Dashboard"},{"name":"k8ssandra","version":"1.6.0","description":"분산 서비스간 호출 로그를 저장하는 스토리지"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( '5678bf11-256f-4d2c-a673-f2fedb82de5b', 'master', 'BYOH Standard', 'included LMA', 'v1', 'AWS', 'x86', 'eks-reference', 'STANDARD', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( '92f5e5ce-7ffd-4c3e-aff6-9b7fb03dd881', 'master', 'BYOH MSA Standard', 'included LMA, SERVICE MESH', 'v1', 'AWS', 'x86', 'eks-msa-reference', 'MSA', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]},{"name":"MSA","type":"SERVICE_MESH","applications":[{"name":"istio","version":"v1.17.2","description":"MSA 플랫폼"},{"name":"jagger","version":"1.35.0","description":"분산 서비스간 트랜잭션 추적을 위한 플랫폼"},{"name":"kiali","version":"v1.63.0","description":"MSA 구조 및 성능을 볼 수 있는 Dashboard"},{"name":"k8ssandra","version":"1.6.0","description":"분산 서비스간 호출 로그를 저장하는 스토리지"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '49901092-be76-4d4f-94e9-b84525f560b5', 'AWS Standard (x86)', 'included LMA', 'v1', 'AWS', 'x86', 'aws-reference', 'STANDARD', 'v1.25', 'AWS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '44d5e76b-63db-4dd0-a16e-11bd3f6054cf', 'AWS MSA Standard (x86)', 'included LMA, SERVICE MESH', 'v1', 'AWS', 'x86', 'aws-msa-reference', 'MSA', 'v1.25', 'AWS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}, {"name": "MSA", "type": "SERVICE_MESH", "applications": [{"name": "istio", "version": "v1.13.1", "description": "MSA 플랫폼"}, {"name": "jagger", "version": "v2.27.1", "description": "분산 서비스간 트랜잭션 추적을 위한 로깅 플랫폼"}, {"name": "kiali", "version": "v1.45.1", "description": "MSA 통합 모니터링포탈"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( 'fe1d97e0-7428-4be6-9c69-310a88b4ff46', 'AWS Standard (arm)', 'included LMA', 'v2', 'AWS', 'arm', 'aws-arm-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '3696cb38-4da0-4235-97eb-b6eb15962bd1', 'AWS Standard (arm)', 'included LMA, SERVICE_MESH', 'v2', 'AWS', 'arm', 'aws-arm-msa-reference', 'MSA', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}, {"name": "MSA", "type": "SERVICE_MESH", "applications": [{"name": "istio", "version": "v1.13.1", "description": "MSA 플랫폼"}, {"name": "jagger", "version": "v2.27.1", "description": "분산 서비스간 트랜잭션 추적을 위한 로깅 플랫폼"}, {"name": "kiali", "version": "v1.45.1", "description": "MSA 통합 모니터링포탈"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( 'c8a4658d-d5a6-4191-8a91-e26f6aee007f', 'EKS Standard (x86)', 'included LMA', 'v1', 'AWS', 'x86', 'eks-reference', 'STANDARD', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '39f18a09-5b94-4772-bdba-e4c32ee002f7', 'EKS MSA Standard (x86)', 'included LMA, SERVICE MESH', 'v1', 'AWS', 'x86', 'eks-msa-reference', 'MSA', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]},{"name":"MSA","type":"SERVICE_MESH","applications":[{"name":"istio","version":"v1.17.2","description":"MSA 플랫폼"},{"name":"jagger","version":"1.35.0","description":"분산 서비스간 트랜잭션 추적을 위한 플랫폼"},{"name":"kiali","version":"v1.63.0","description":"MSA 구조 및 성능을 볼 수 있는 Dashboard"},{"name":"k8ssandra","version":"1.6.0","description":"분산 서비스간 호출 로그를 저장하는 스토리지"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '5678bf11-256f-4d2c-a673-f2fedb82de5b', 'BYOH Standard', 'included LMA', 'v1', 'AWS', 'x86', 'eks-reference', 'STANDARD', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '92f5e5ce-7ffd-4c3e-aff6-9b7fb03dd881', 'BYOH MSA Standard', 'included LMA, SERVICE MESH', 'v1', 'AWS', 'x86', 'eks-msa-reference', 'MSA', 'v1.25', 'AWS', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]},{"name":"MSA","type":"SERVICE_MESH","applications":[{"name":"istio","version":"v1.17.2","description":"MSA 플랫폼"},{"name":"jagger","version":"1.35.0","description":"분산 서비스간 트랜잭션 추적을 위한 플랫폼"},{"name":"kiali","version":"v1.63.0","description":"MSA 구조 및 성능을 볼 수 있는 Dashboard"},{"name":"k8ssandra","version":"1.6.0","description":"분산 서비스간 호출 로그를 저장하는 스토리지"}]}]' ); # BTV -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( '2526ec49-28a2-4be9-8d18-2c39fc0993fd', 'master', 'BYOH Admin Standard (BTV)', 'included LMA', 'v1', 'BYOH', 'x86', 'tks-admin', 'STANDARD', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( 'a76b5c97-7d55-46d8-9248-9952bfaff62c', 'master', 'BYOH MSA Standard (BTV SSU)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-ssu-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( 'b5bbd6ea-5bf3-4d88-bb06-4a4c64c73c15', 'master', 'BYOH MSA Standard (BTV SUY)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-suy-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '2526ec49-28a2-4be9-8d18-2c39fc0993fd', 'BYOH Admin Standard (BTV)', 'included LMA', 'v1', 'BYOH', 'x86', 'tks-admin', 'STANDARD', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( 'a76b5c97-7d55-46d8-9248-9952bfaff62c', 'BYOH MSA Standard (BTV SSU)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-ssu-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( 'b5bbd6ea-5bf3-4d88-bb06-4a4c64c73c15', 'BYOH MSA Standard (BTV SUY)', 'included LMA', 'v1', 'BYOH', 'x86', 'byoh-suy-reference', 'MSA', 'v1.25', 'BYOH', now(), now(), '[{"name":"Logging,Monitoring,Alerting","type":"LMA","applications":[{"name":"thanos","version":"0.30.2","description":"다중클러스터의 모니터링 데이터 통합 질의처리"},{"name":"prometheus-stack","version":"v0.66.0","description":"모니터링 데이터 수집/저장 및 질의처리"},{"name":"alertmanager","version":"v0.25.0","description":"알람 처리를 위한 노티피케이션 서비스"},{"name":"loki","version":"2.6.1","description":"로그데이터 저장 및 질의처리"},{"name":"grafana","version":"8.3.3","description":"모니터링/로그 통합대시보드"}]}]' ); # PSNM -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( 'c3396c68-03ec-4d41-991c-69e4a2ac16aa', 'master', 'psnm-backend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-backend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); -insert into stack_templates ( id, organization_id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) -values ( '23b07a65-1cb3-4609-9bba-e88c15e2e192', 'master', 'psnm-frontend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-frontend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( 'c3396c68-03ec-4d41-991c-69e4a2ac16aa', 'psnm-backend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-backend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); +insert into stack_templates ( id, name, description, version, cloud_service, platform, template, template_type, kube_version, kube_type, created_at, updated_at, services ) +values ( '23b07a65-1cb3-4609-9bba-e88c15e2e192', 'psnm-frontend-reference', 'included LMA', 'v1', 'AWS', 'x86', 'psnm-frontend-reference', 'STANDARD', 'v1.25', 'EKS', now(), now(), '[{"name": "Logging,Monitoring,Alerting", "type": "LMA", "applications": [{"name": "prometheus-stack", "version": "v.44.3.1", "description": "통계데이터 제공을 위한 backend 플랫폼"}, {"name": "elastic-system", "version": "v1.8.0", "description": "로그 데이터 적재를 위한 Storage"}, {"name": "alertmanager", "version": "v0.23.0", "description": "Alert 관리를 위한 backend 서비스"}, {"name": "grafana", "version": "v6.50.7", "description": "모니터링 통합 포탈"}]}]' ); ## Projects insert into project_roles ( id, name, description, created_at, updated_at ) values ( 'f4358b4e-adc3-447a-8ad9-c111c4b9a974', 'project-leader', 'project-leader', now(), now() ); From 80fab70c8c587fc6d873c66a0f07a7d73d7dbede Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 3 May 2024 11:05:54 +0900 Subject: [PATCH 418/502] trivial. add byoh test code --- internal/usecase/app-group.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index 37896b64..9d9490d5 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -80,7 +80,8 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do // check cloudAccount tksCloudAccountId := "" - tksObjectStore := "minio" + //tksObjectStore := "minio" // FOR TEST + tksObjectStore := "s3" if cluster.CloudService != domain.CloudService_BYOH { tksObjectStore = "s3" cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, cluster.OrganizationId, nil) @@ -180,7 +181,8 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err // check cloudAccount tksCloudAccountId := "" - tksObjectStore := "minio" + //tksObjectStore := "minio" // FOR TEST + tksObjectStore := "s3" if cluster.CloudService != domain.CloudService_BYOH { tksObjectStore = "s3" cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, cluster.OrganizationId, nil) From 951860bb89f934b4a75b2ef7784a4ea74ea34844 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 3 May 2024 13:24:28 +0900 Subject: [PATCH 419/502] trivial. add api for policy-notification --- api/swagger/docs.go | 137 +++++++++++++++++++++++++++++++++++++-- api/swagger/swagger.json | 137 +++++++++++++++++++++++++++++++++++++-- api/swagger/swagger.yaml | 96 +++++++++++++++++++++++++-- internal/route/route.go | 2 +- 4 files changed, 354 insertions(+), 18 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0f7b8583..43a7daf1 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -4318,7 +4318,7 @@ const docTemplate = `{ "tags": [ "Policy" ], - "summary": "[ExistsPolicyName] 정책 아름 존재 여부 확인", + "summary": "[ExistsPolicyName] 정책 이름 존재 여부 확인", "parameters": [ { "type": "string", @@ -4345,6 +4345,50 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/policies/resource-name/{policyResourceName}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 자원 이름을 가진 정책이 이미 존재하는지 확인한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[ExistsPolicyResourceName] 정책 자원 이름 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 자원 이름(쿠버네티스 배포 시 자원 이름)", + "name": "policyResourceName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, "/organizations/{organizationId}/policies/{policyId}": { "get": { "security": [ @@ -13502,7 +13546,7 @@ const docTemplate = `{ "policyTemplates": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse" } } } @@ -14182,6 +14226,87 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "currentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "kind": { + "type": "string", + "example": "K8sRequiredLabels" + }, + "latestVersion": { + "type": "string", + "example": "v1.0.1" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "type": { + "type": "string", + "enum": [ + "tks", + "organization" + ], + "example": "tks" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse": { "type": "object", "properties": { @@ -15656,10 +15781,6 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { "type": "object", - "required": [ - "enforcementAction", - "policyName" - ], "properties": { "description": { "type": "string" @@ -15840,6 +15961,7 @@ const docTemplate = `{ "required": [ "kubeType", "kubeVersion", + "name", "organizationIds", "platform", "serviceIds", @@ -15863,6 +15985,9 @@ const docTemplate = `{ "kubeVersion": { "type": "string" }, + "name": { + "type": "string" + }, "organizationIds": { "type": "array", "items": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index a11a64b7..6e191c12 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -4312,7 +4312,7 @@ "tags": [ "Policy" ], - "summary": "[ExistsPolicyName] 정책 아름 존재 여부 확인", + "summary": "[ExistsPolicyName] 정책 이름 존재 여부 확인", "parameters": [ { "type": "string", @@ -4339,6 +4339,50 @@ } } }, + "/organizations/{organizationId}/policies/resource-name/{policyResourceName}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "해당 자원 이름을 가진 정책이 이미 존재하는지 확인한다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Policy" + ], + "summary": "[ExistsPolicyResourceName] 정책 자원 이름 존재 여부 확인", + "parameters": [ + { + "type": "string", + "description": "조직 식별자(o로 시작)", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "정책 자원 이름(쿠버네티스 배포 시 자원 이름)", + "name": "policyResourceName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse" + } + } + } + } + }, "/organizations/{organizationId}/policies/{policyId}": { "get": { "security": [ @@ -13496,7 +13540,7 @@ "policyTemplates": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse" } } } @@ -14176,6 +14220,87 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse": { + "type": "object", + "properties": { + "createdAt": { + "type": "string" + }, + "creator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + }, + "currentVersion": { + "type": "string", + "example": "v1.0.1" + }, + "deprecated": { + "type": "boolean", + "example": false + }, + "description": { + "type": "string", + "example": "이 정책은 ..." + }, + "id": { + "type": "string", + "example": "d98ef5f1-4a68-4047-a446-2207787ce3ff" + }, + "kind": { + "type": "string", + "example": "K8sRequiredLabels" + }, + "latestVersion": { + "type": "string", + "example": "v1.0.1" + }, + "libs": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "rego 코드" + ] + }, + "parametersSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef" + } + }, + "rego": { + "type": "string", + "example": "rego 코드" + }, + "severity": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "example": "medium" + }, + "templateName": { + "type": "string", + "example": "필수 Label 검사" + }, + "type": { + "type": "string", + "enum": [ + "tks", + "organization" + ], + "example": "tks" + }, + "updatedAt": { + "type": "string" + }, + "updator": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse": { "type": "object", "properties": { @@ -15650,10 +15775,6 @@ }, "github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyRequest": { "type": "object", - "required": [ - "enforcementAction", - "policyName" - ], "properties": { "description": { "type": "string" @@ -15834,6 +15955,7 @@ "required": [ "kubeType", "kubeVersion", + "name", "organizationIds", "platform", "serviceIds", @@ -15857,6 +15979,9 @@ "kubeVersion": { "type": "string" }, + "name": { + "type": "string" + }, "organizationIds": { "type": "array", "items": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 707c8d93..f595a0b4 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2159,7 +2159,7 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' policyTemplates: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse' type: array type: object github_com_openinfradev_tks-api_pkg_domain.ListPolicyTemplateStatisticsResponse: @@ -2616,6 +2616,64 @@ definitions: usageCount: type: integer type: object + github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse: + properties: + createdAt: + type: string + creator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + currentVersion: + example: v1.0.1 + type: string + deprecated: + example: false + type: boolean + description: + example: 이 정책은 ... + type: string + id: + example: d98ef5f1-4a68-4047-a446-2207787ce3ff + type: string + kind: + example: K8sRequiredLabels + type: string + latestVersion: + example: v1.0.1 + type: string + libs: + example: + - rego 코드 + items: + type: string + type: array + parametersSchema: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ParameterDef' + type: array + rego: + example: rego 코드 + type: string + severity: + enum: + - low + - medium + - high + example: medium + type: string + templateName: + example: 필수 Label 검사 + type: string + type: + enum: + - tks + - organization + example: tks + type: string + updatedAt: + type: string + updator: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + type: object github_com_openinfradev_tks-api_pkg_domain.ProjectDetailResponse: properties: createdAt: @@ -3628,9 +3686,6 @@ definitions: templateId: example: d98ef5f1-4a68-4047-a446-2207787ce3ff type: string - required: - - enforcementAction - - policyName type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePolicyTemplateRequest: properties: @@ -3730,6 +3785,8 @@ definitions: type: string kubeVersion: type: string + name: + type: string organizationIds: items: type: string @@ -3752,6 +3809,7 @@ definitions: required: - kubeType - kubeVersion + - name - organizationIds - platform - serviceIds @@ -7155,7 +7213,35 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' security: - JWT: [] - summary: '[ExistsPolicyName] 정책 아름 존재 여부 확인' + summary: '[ExistsPolicyName] 정책 이름 존재 여부 확인' + tags: + - Policy + /organizations/{organizationId}/policies/resource-name/{policyResourceName}/existence: + get: + consumes: + - application/json + description: 해당 자원 이름을 가진 정책이 이미 존재하는지 확인한다. + parameters: + - description: 조직 식별자(o로 시작) + in: path + name: organizationId + required: true + type: string + - description: 정책 자원 이름(쿠버네티스 배포 시 자원 이름) + in: path + name: policyResourceName + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.CheckExistedResponse' + security: + - JWT: [] + summary: '[ExistsPolicyResourceName] 정책 자원 이름 존재 여부 확인' tags: - Policy /organizations/{organizationId}/policy-notifications: diff --git a/internal/route/route.go b/internal/route/route.go index 56e2500e..537899c9 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -249,7 +249,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa policyNotificationHandler := delivery.NewPolicyNotificationHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-notifications", customMiddleware.Handle(internalApi.GetSystemNotifications, http.HandlerFunc(policyNotificationHandler.GetPolicyNotifications))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-notification", customMiddleware.Handle(internalApi.GetSystemNotification, http.HandlerFunc(policyNotificationHandler.GetPolicyNotification))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/policy-notifications/{policyNotificationId}", customMiddleware.Handle(internalApi.GetSystemNotification, http.HandlerFunc(policyNotificationHandler.GetPolicyNotification))).Methods(http.MethodGet) stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) From ef089bb13abea0b15bca5324218548a145b8da9b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 3 May 2024 13:55:03 +0900 Subject: [PATCH 420/502] trivial. fix typo --- internal/usecase/audit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index d205210c..d7e50b99 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -30,7 +30,7 @@ func NewAuditUsecase(r repository.Repository) IAuditUsecase { } func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { - if dto.UserId != nil && *dto.UserId == uuid.Nil { + if dto.UserId != nil && *dto.UserId != uuid.Nil { user, err := u.userRepo.GetByUuid(ctx, *dto.UserId) if err != nil { return auditId, err From 9aecbd04a2454dc7cad693b2da2548b78746c8fb Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Fri, 3 May 2024 15:25:47 +0900 Subject: [PATCH 421/502] bugfix: return availableRollback value by GetTasks API --- internal/delivery/http/app-serve-app.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index aa29a745..ab127e72 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -481,6 +481,12 @@ func (h *AppServeAppHandler) GetAppServeAppTasksByAppId(w http.ResponseWriter, r var out domain.GetAppServeAppTasksResponse out.AppServeAppTasks = make([]domain.AppServeAppTaskResponse, len(tasks)) for i, task := range tasks { + // Rollbacking to latest task should be blocked. + if i > 0 && strings.Contains(task.Status, "SUCCESS") && task.Status != "ABORT_SUCCESS" && + task.Status != "ROLLBACK_SUCCESS" { + task.AvailableRollback = true + } + if err := serializer.Map(r.Context(), task, &out.AppServeAppTasks[i]); err != nil { log.Info(r.Context(), err) continue From dabc62161fa653addee789235b294365f5a310ab Mon Sep 17 00:00:00 2001 From: Seungkyu Ahn Date: Fri, 3 May 2024 16:00:55 +0900 Subject: [PATCH 422/502] fill in return data after sorting --- internal/repository/policy-template.go | 19 +++ internal/usecase/dashboard.go | 192 +++++++++++++++++++------ 2 files changed, 167 insertions(+), 44 deletions(-) diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index c06a7cae..763e569c 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -37,6 +37,7 @@ type IPolicyTemplateRepository interface { CountTksTemplateByOrganization(ctx context.Context, organizationId string) (count int64, err error) CountOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) CountPolicyFromOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) + GetPolicyTemplateByOrganizationIdOrTKS(ctx context.Context, organizationId string) ([]model.PolicyTemplate, error) } type PolicyTemplateRepository struct { @@ -496,3 +497,21 @@ func (r *PolicyTemplateRepository) GetLatestTemplateVersion(ctx context.Context, return policyTemplateVersion.Version, nil } + +func (r *PolicyTemplateRepository) GetPolicyTemplateByOrganizationIdOrTKS(ctx context.Context, organizationId string) (out []model.PolicyTemplate, err error) { + res := r.db.WithContext(ctx). + Select("id", "type", "template_name"). + Where("organization_id = ? or type = ?", organizationId, "tks"). + Find(&out) + + if res.Error != nil { + if errors.Is(res.Error, gorm.ErrRecordNotFound) { + log.Info(ctx, "Cannot find policytemplate") + return nil, nil + } else { + log.Error(ctx, res.Error) + return nil, res.Error + } + } + return out, nil +} diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index c1bd54d5..31eb3ef6 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -660,28 +660,59 @@ func (u *DashboardUsecase) GetPolicyEnforcement(ctx context.Context, organizatio ClusterId string PolicyTemplate map[string]map[string]int } + dashboardPolicyTemplates := make([]DashboardPolicyTemplate, 0) + + // get clusters from db + dbClusters, err := u.clusterRepo.FetchByOrganizationId(ctx, organizationId, uuid.Nil, nil) + if err != nil { + return nil, err + } + filteredClusters := funk.Filter(dbClusters, func(x model.Cluster) bool { + return x.Status == domain.ClusterStatus_RUNNING + }) + if filteredClusters != nil { + dbPolicyTemplates, err := u.policyTemplateRepo.GetPolicyTemplateByOrganizationIdOrTKS(ctx, organizationId) + if err != nil { + return nil, err + } + for _, cluster := range filteredClusters.([]model.Cluster) { + policyTemplates := make(map[string]map[string]int) + // get policytemplates by cluster + // dbPolicyTemplates = {"K8sAllowedRepos": {"": 0}} + for _, dpt := range dbPolicyTemplates { + if _, ok := policyTemplates[dpt.TemplateName]; !ok { + policyTemplates[dpt.TemplateName] = map[string]int{"": 0} + } + } + dashboardPolicyTemplates = append(dashboardPolicyTemplates, + DashboardPolicyTemplate{ClusterId: cluster.Name, PolicyTemplate: policyTemplates}) + } + } + // get clusters from cr clusters, err := policytemplate.GetTksClusterCRs(ctx, primaryClusterId) if err != nil { log.Error(ctx, "Failed to retrieve policytemplate list ", err) return nil, err } - dashboardPolicyTemplates := make([]DashboardPolicyTemplate, 0) for _, cluster := range clusters { + // policyTemplates = {"K8sAllowedRepos": {"members": 1}} + policyTemplates := make(map[string]map[string]int) + // If the cluster does not have a policytemplate, skip ahead // cluster.Status.Templates = {"K8sAllowedRepos": ["members"]} if cluster.Status.Templates == nil { continue } - // policyTemplates = {"K8sAllowedRepos": {"members": 1}} - policyTemplates := make(map[string]map[string]int) + for templateName, policies := range cluster.Status.Templates { for _, policy := range policies { policyTemplates[templateName] = make(map[string]int) policyTemplates[templateName][policy] = 1 } } + dashboardPolicyTemplates = append(dashboardPolicyTemplates, DashboardPolicyTemplate{ClusterId: cluster.Name, PolicyTemplate: policyTemplates}) } @@ -722,22 +753,39 @@ func (u *DashboardUsecase) GetPolicyEnforcement(ctx context.Context, organizatio } } - // Y축 - var series []domain.UnitNumber - yRequiredData := make([]int, 0) - yOptionalData := make([]int, 0) + // desc sorting by value + type ChartData struct { + Name string + OptionalCount int + RequiredCount int + } + chartData := make([]ChartData, 0) + for key, val := range totalTemplate { + data := ChartData{ + Name: key, + OptionalCount: val.OptionalPolicyCount, + RequiredCount: val.RequiredPolicyCount, + } + chartData = append(chartData, data) + } + sort.Slice(chartData, func(i, j int) bool { + return chartData[i].OptionalCount+chartData[i].RequiredCount > + chartData[j].OptionalCount+chartData[j].RequiredCount + }) // X축 var xAxis *domain.Axis xData := make([]string, 0) - for key, val := range totalTemplate { - // X axis Data - xData = append(xData, key) + // Y축 + var series []domain.UnitNumber + yOptionalData := make([]int, 0) + yRequiredData := make([]int, 0) - // Y axis Data - yOptionalData = append(yOptionalData, val.OptionalPolicyCount) - yRequiredData = append(yRequiredData, val.RequiredPolicyCount) + for _, v := range chartData { + xData = append(xData, v.Name) + yOptionalData = append(yOptionalData, v.OptionalCount) + yRequiredData = append(yRequiredData, v.RequiredCount) } xAxis = &domain.Axis{ @@ -787,25 +835,21 @@ func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationI // totalViolation: {"K8sRequiredLabels": {"violation_enforcement": 2}} totalViolation := make(map[string]map[string]int) - // Y축 - var series []domain.UnitNumber - yDenyData := make([]int, 0) - yWarnData := make([]int, 0) - yDryrunData := make([]int, 0) - - // X축 - var xAxis *domain.Axis - xData := make([]string, 0) + dbPolicyTemplates, err := u.policyTemplateRepo.GetPolicyTemplateByOrganizationIdOrTKS(ctx, organizationId) + if err != nil { + return nil, err + } + for _, dpt := range dbPolicyTemplates { + if _, ok := totalViolation[dpt.TemplateName]; !ok { + totalViolation[dpt.TemplateName] = map[string]int{"": 0} + } + } for _, res := range pm.Data.Result { policyTemplate := res.Metric.Kind if len(res.Metric.Violation) == 0 { continue } - if !slices.Contains(xData, policyTemplate) { - xData = append(xData, policyTemplate) - } - count, err := strconv.Atoi(res.Value[1].(string)) if err != nil { count = 0 @@ -819,10 +863,48 @@ func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationI } } - for _, violations := range totalViolation { - yDenyData = append(yDenyData, violations["deny"]) - yWarnData = append(yWarnData, violations["warn"]) - yDryrunData = append(yDryrunData, violations["dryrun"]) + // desc sorting by value + type ChartData struct { + Name string + DenyCount int + WarnCount int + DryRunCount int + } + chartData := make([]ChartData, 0) + for pt, violations := range totalViolation { + data := ChartData{} + data.Name = pt + if val, ok := violations["deny"]; ok { + data.DenyCount = val + } + if val, ok := violations["warn"]; ok { + data.WarnCount = val + } + if val, ok := violations["dryrun"]; ok { + data.DryRunCount = val + } + chartData = append(chartData, data) + } + sort.Slice(chartData, func(i, j int) bool { + return chartData[i].DenyCount+chartData[i].WarnCount+chartData[i].DryRunCount > + chartData[j].DenyCount+chartData[j].WarnCount+chartData[j].DryRunCount + }) + + // X축 + var xAxis *domain.Axis + xData := make([]string, 0) + + // Y축 + var series []domain.UnitNumber + yDenyData := make([]int, 0) + yWarnData := make([]int, 0) + yDryrunData := make([]int, 0) + + for _, v := range chartData { + xData = append(xData, v.Name) + yDenyData = append(yDenyData, v.DenyCount) + yWarnData = append(yWarnData, v.WarnCount) + yDryrunData = append(yDryrunData, v.DryRunCount) } xAxis = &domain.Axis{ @@ -962,18 +1044,18 @@ func (u *DashboardUsecase) GetPolicyViolationTop5(ctx context.Context, organizat templateNames = append(templateNames, result.Metric.Kind) } - // X축 - var xAxis *domain.Axis - xData := make([]string, 0) - - // Y축 - var series []domain.UnitNumber - yDenyData := make([]int, 0) - yWarnData := make([]int, 0) - yDryrunData := make([]int, 0) - + // desc sorting by value + type ChartData struct { + Name string + DenyCount int + WarnCount int + DryRunCount int + } + chartData := make([]ChartData, 0) for _, templateName := range templateNames { - xData = append(xData, templateName) + //xData = append(xData, templateName) + data := ChartData{} + data.Name = templateName query = fmt.Sprintf("sum by (violation_enforcement) "+ "(opa_scorecard_constraint_violations{taco_cluster='%s', kind='%s'})", clusterIdStr, templateName) @@ -995,9 +1077,31 @@ func (u *DashboardUsecase) GetPolicyViolationTop5(ctx context.Context, organizat dryrunCount, _ = strconv.Atoi(result.Value[1].(string)) } } - yDenyData = append(yDenyData, denyCount) - yWarnData = append(yWarnData, warnCount) - yDryrunData = append(yDryrunData, dryrunCount) + data.DenyCount = denyCount + data.WarnCount = warnCount + data.DryRunCount = dryrunCount + chartData = append(chartData, data) + } + sort.Slice(chartData, func(i, j int) bool { + return chartData[i].DenyCount+chartData[i].WarnCount+chartData[i].DryRunCount > + chartData[j].DenyCount+chartData[j].WarnCount+chartData[j].DryRunCount + }) + + // X축 + var xAxis *domain.Axis + xData := make([]string, 0) + + // Y축 + var series []domain.UnitNumber + yDenyData := make([]int, 0) + yWarnData := make([]int, 0) + yDryrunData := make([]int, 0) + + for _, v := range chartData { + xData = append(xData, v.Name) + yDenyData = append(yDenyData, v.DenyCount) + yWarnData = append(yWarnData, v.WarnCount) + yDryrunData = append(yDryrunData, v.DryRunCount) } xAxis = &domain.Axis{ From 928bd08d400da5166b0204da2d1675affc0f0128 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Fri, 3 May 2024 16:14:36 +0900 Subject: [PATCH 423/502] =?UTF-8?q?gorm=20DB=20=EA=B4=80=EA=B3=84=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=8B=9C=20=EC=A0=9C?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=EA=B0=80=20=EC=95=88=20=EB=90=98?= =?UTF-8?q?=EC=96=B4=20=EC=A4=91=EB=B3=B5=20=EB=A0=88=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=82=BD=EC=9E=85=EC=8B=9C=EB=8F=84=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/repository/policy-template.go | 2 +- internal/repository/policy.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index c06a7cae..248a45af 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -88,7 +88,7 @@ func (r *PolicyTemplateRepository) Update(ctx context.Context, policyTemplateId } if len(updateMap) > 0 { - err = tx.WithContext(ctx).Model(&policyTemplate).Limit(1). + err = tx.WithContext(ctx).Omit("PermittedOrganizations").Model(&policyTemplate).Limit(1). Where("id = ?", policyTemplateId).Where("type = ?", "tks"). Updates(updateMap).Error diff --git a/internal/repository/policy.go b/internal/repository/policy.go index 63be3517..ff995800 100644 --- a/internal/repository/policy.go +++ b/internal/repository/policy.go @@ -87,7 +87,7 @@ func (r *PolicyRepository) Update(ctx context.Context, organizationId string, po } if len(updateMap) > 0 { - err = tx.WithContext(ctx).Model(&policy).Limit(1). + err = tx.WithContext(ctx).Omit("TargetClusters").Model(&policy).Limit(1). Where("id = ?", policyId). Updates(updateMap).Error From 133a7c91921c81d153ac1fcc979b663039d2a077 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 7 May 2024 01:32:04 +0900 Subject: [PATCH 424/502] =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20=EA=B0=9C=EC=84=A0(array=20index=EB=A5=BC?= =?UTF-8?q?=20var=EB=A1=9C=20=EC=B0=B8=EC=A1=B0=20=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/policy-template-rego.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index 1817b47e..de39beb0 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -15,11 +15,13 @@ import ( ) const ( + rego_var_name_pattern = `[[a-zA-Z_][a-zA-Z0-9_]*` input_param_prefix = "input.parameters" - input_extract_pattern = `input(\.parameters|\[\"parameters\"\])((\[\"[\w\-]+\"\])|(\[_\])|(\.\w+))*` //(\.\w+)*` // (\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))*` + input_extract_pattern = `input(\.parameters|\[\"parameters\"\])((\[\"[\w\-]+\"\])|(\[_\])|(\[` + rego_var_name_pattern + `\])|(\.\w+))*` //(\.\w+)*` // (\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))*` // input_extract_pattern = `input\.parameters((\[\".+\"\])?(\.\w+\[\"\w+\"\])|(\.\w+\[\w+\])|(\.\w+))+` obj_get_list_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+), \"([^\"]+)\", \[\]\)` obj_get_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+), \"([^\"]+)\", [^\)]+\)` + ref_by_key_pattern = `\[\"([\w-]+)\"\]` package_name_regex = `package ([\w\.]+)[\n\r]+` import_regex = `import ([\w\.]+)[\n\r]+` ) @@ -28,6 +30,8 @@ var ( input_extract_regex = regexp.MustCompile(input_extract_pattern) obj_get_list_regex = regexp.MustCompile(obj_get_list_pattern) obj_get_regex = regexp.MustCompile(obj_get_pattern) + ref_by_key_regex = regexp.MustCompile(ref_by_key_pattern) + ref_by_var_regex = regexp.MustCompile(`\[` + rego_var_name_pattern + `\]`) array_param_map, capabilities = buildArrayParameterMap() ) @@ -451,8 +455,11 @@ func ExtractParameter(modules map[string]*ast.Module) []*domain.ParameterDef { remainder := inputExpr[len(input_param_prefix):] // 문법 변환: aa["a"]["B"][_]->aa.a.B[_] - regex := regexp.MustCompile(`\[\"([\w-]+)\"\]`) - remainder = regex.ReplaceAllString(remainder, ".${1}") + remainder = ref_by_key_regex.ReplaceAllString(remainder, ".${1}") + + // 문법 변환2: input.parameters.aa[varname]에서 aa는 객체가 아닌 배열이라고 확신할 수 있으므로 + // input.parameters.aa[_]로 변환해도 무방함 + remainder = ref_by_var_regex.ReplaceAllString(remainder, "[_]") params := strings.Split(remainder, ".") From 513fad344b4222a1293309a44fea033e357719ad Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 7 May 2024 10:31:27 +0900 Subject: [PATCH 425/502] trivial. fix marshall error response --- internal/delivery/http/app-serve-app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index ab127e72..70a383ac 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -113,7 +113,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re appReq := domain.CreateAppServeAppRequest{} err := UnmarshalRequestInput(r, &appReq) if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Error while unmarshalling request"), "C_INTERNAL_ERROR", "")) + ErrorJSON(w, r, err) return } From a9a70f448dfca363b604cb4b682679e966ef96c0 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 7 May 2024 10:29:53 +0900 Subject: [PATCH 426/502] feature. implementation calculating resources for namespace --- internal/delivery/http/app-serve-app.go | 2 +- internal/usecase/dashboard.go | 5 ++++ internal/usecase/project.go | 40 ++++++++++++++++++------- internal/validator/validator.go | 5 ++-- pkg/thanos-client/types.go | 1 + 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index ab127e72..70a383ac 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -113,7 +113,7 @@ func (h *AppServeAppHandler) CreateAppServeApp(w http.ResponseWriter, r *http.Re appReq := domain.CreateAppServeAppRequest{} err := UnmarshalRequestInput(r, &appReq) if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Error while unmarshalling request"), "C_INTERNAL_ERROR", "")) + ErrorJSON(w, r, err) return } diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 31eb3ef6..a47f3fae 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -1141,6 +1141,11 @@ func (u *DashboardUsecase) GetThanosClient(ctx context.Context, organizationId s return nil, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } address, port := helper.SplitAddress(ctx, thanosUrl) + + // [TEST] + //address = "http://a93c60de70c794ef39b495976588c989-d7cd29ca75def693.elb.ap-northeast-2.amazonaws.com" + //port = 9090 + client, err := thanos.New(address, port, false, "") if err != nil { return nil, errors.Wrap(err, "failed to create thanos client") diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 80775111..2ad792a4 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -911,19 +911,39 @@ func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, thanosClient tha if err != nil { return out, errors.Wrap(err, fmt.Sprintf("Failed to get cluster : stackId %s", stackId)) } - /* - query := "sum(rate(container_cpu_usage_seconds_total{image!=\"\"}[10m]) ) by (taco_cluster, namespace)" - result, err := thanosClient.Get(ctx, query) - if err != nil { - return out, err + + // sum(rate(container_cpu_usage_seconds_total{taco_cluster=\"$taco_cluster\",image!=\"\"}[$__rate_interval])) by (namespace) + query := fmt.Sprintf("sum(rate(container_cpu_usage_seconds_total{image!=\"\", namespace=\"%s\"}[10m]) ) by (taco_cluster, namespace)", namespace) + result, err := thanosClient.Get(ctx, query) + if err != nil { + return out, err + } + for _, val := range result.Data.Result { + if val.Metric.TacoCluster == stackId.String() { + if val.Metric.Namespace == namespace { + if s, err := strconv.ParseFloat(val.Value[1].(string), 32); err == nil { + out.Cpu = fmt.Sprintf("%0.2f %%", s*100) + } + } } - log.Info(ctx, helper.ModelToJson(result)) + } - */ + // sum(container_memory_working_set_bytes{taco_cluster=\"$taco_cluster\",image!=\"\"}) by (namespace) + query = fmt.Sprintf("sum(container_memory_working_set_bytes{image!=\"\", namespace=\"%s\"}) by (taco_cluster, namespace)", namespace) + result, err = thanosClient.Get(ctx, query) + if err != nil { + return out, err + } + for _, val := range result.Data.Result { + if val.Metric.TacoCluster == stackId.String() { + if val.Metric.Namespace == namespace { + memory, _ := strconv.Atoi(val.Value[1].(string)) + out.Memory = fmt.Sprintf("%d MiB", memory/1024/1024) + } + } + } - out.Cpu = "1.0 %" - out.Memory = "2.0 %" - out.Storage = "3.0 %" + out.Storage = "" return } diff --git a/internal/validator/validator.go b/internal/validator/validator.go index 5d9fd3f7..3a161738 100644 --- a/internal/validator/validator.go +++ b/internal/validator/validator.go @@ -1,6 +1,7 @@ package validator import ( + "context" "regexp" "strings" "unicode/utf8" @@ -10,7 +11,7 @@ import ( validator "github.com/go-playground/validator/v10" en_translations "github.com/go-playground/validator/v10/translations/en" "github.com/openinfradev/tks-api/pkg/domain" - "github.com/opentracing/opentracing-go/log" + "github.com/openinfradev/tks-api/pkg/log" ) const ( @@ -30,7 +31,7 @@ func NewValidator() (*validator.Validate, *ut.UniversalTranslator) { v := validator.New() err := en_translations.RegisterDefaultTranslations(v, trans) if err != nil { - log.Error(err) + log.Error(context.TODO(), err) } // register custom validator diff --git a/pkg/thanos-client/types.go b/pkg/thanos-client/types.go index cffb437a..3d6c7c80 100644 --- a/pkg/thanos-client/types.go +++ b/pkg/thanos-client/types.go @@ -18,6 +18,7 @@ type MetricDataResult struct { type MetricDataResultMetric struct { Name string `json:"__name__"` + Namespace string `json:"namespace,omitempty"` TacoCluster string `json:"taco_cluster"` } From 961248031a4e8f792e0af9f5eee46d44370999fa Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 7 May 2024 10:54:37 +0900 Subject: [PATCH 427/502] app-serving: remove omitempty tag --- internal/model/app-serve-app.go | 62 ++++++++++++++++----------------- pkg/domain/app-serve-app.go | 62 ++++++++++++++++----------------- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go index 0a5e9f77..4d86c603 100644 --- a/internal/model/app-serve-app.go +++ b/internal/model/app-serve-app.go @@ -7,43 +7,43 @@ import ( ) type AppServeApp struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - Name string `gorm:"index" json:"name,omitempty"` // application name - Namespace string `json:"namespace,omitempty"` // application namespace - OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to - ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to - Type string `json:"type,omitempty"` // type (build/deploy/all) - AppType string `json:"appType,omitempty"` // appType (spring/springboot) - EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app - PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment - TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed - TargetClusterName string `gorm:"-:all" json:"targetClusterName,omitempty"` // target cluster name - Status string `gorm:"index" json:"status,omitempty"` // status is status of deployed app - GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app - Description string `json:"description,omitempty"` // description for application + ID string `gorm:"primarykey" json:"id"` + Name string `gorm:"index" json:"name"` // application name + Namespace string `json:"namespace"` // application namespace + OrganizationId string `json:"organizationId"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId"` // project ID which this app belongs to + Type string `json:"type"` // type (build/deploy/all) + AppType string `json:"appType"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId"` // target cluster to which the app is deployed + TargetClusterName string `gorm:"-:all" json:"targetClusterName"` // target cluster name + Status string `gorm:"index" json:"status"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl"` // grafana dashboard URL for deployed app + Description string `json:"description"` // description for application CreatedAt time.Time `gorm:"autoCreateTime:false" json:"createdAt" ` UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` } type AppServeAppTask struct { - ID string `gorm:"primarykey" json:"id,omitempty"` - AppServeAppId string `gorm:"not null" json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to - Version string `json:"version,omitempty"` // application version - Status string `json:"status,omitempty"` // status is app status - Output string `json:"output,omitempty"` // output for task result - ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) - ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app - ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image - Profile string `json:"profile,omitempty"` // java app profile - AppConfig string `json:"appConfig,omitempty"` // java app config - AppSecret string `json:"appSecret,omitempty"` // java app secret - ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app - Port string `json:"port,omitempty"` // java app port - ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod - HelmRevision int32 `gorm:"default:0" json:"helmRevision,omitempty"` // revision of deployed helm release - Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) - RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version + ID string `gorm:"primarykey" json:"id"` + AppServeAppId string `gorm:"not null" json:"appServeAppId"` // ID for appServeApp that this task belongs to + Version string `json:"version"` // application version + Status string `json:"status"` // status is app status + Output string `json:"output"` // output for task result + ArtifactUrl string `json:"artifactUrl"` // URL of java app artifact (Eg, Jar) + ImageUrl string `json:"imageUrl"` // URL of built image for app + ExecutablePath string `json:"executablePath"` // Executable path of app image + Profile string `json:"profile"` // java app profile + AppConfig string `json:"appConfig"` // java app config + AppSecret string `json:"appSecret"` // java app secret + ExtraEnv string `json:"extraEnv"` // env variable list for java app + Port string `json:"port"` // java app port + ResourceSpec string `json:"resourceSpec"` // resource spec of app pod + HelmRevision int32 `gorm:"default:0" json:"helmRevision"` // revision of deployed helm release + Strategy string `json:"strategy"` // deployment strategy (eg, rolling-update) + RollbackVersion string `json:"rollbackVersion"` // rollback target version PvEnabled bool `json:"pvEnabled"` PvStorageClass string `json:"pvStorageClass"` PvAccessMode string `json:"pvAccessMode"` diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index b12c192b..757b877a 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -3,43 +3,43 @@ package domain import "time" type AppServeAppResponse struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` // application name - Namespace string `json:"namespace,omitempty"` // application namespace - OrganizationId string `json:"organizationId,omitempty"` // contractId is a contract ID which this app belongs to - ProjectId string `json:"projectId,omitempty"` // project ID which this app belongs to - Type string `json:"type,omitempty"` // type (build/deploy/all) - AppType string `json:"appType,omitempty"` // appType (spring/springboot) - EndpointUrl string `json:"endpointUrl,omitempty"` // endpoint URL of deployed app - PreviewEndpointUrl string `json:"previewEndpointUrl,omitempty"` // preview svc endpoint URL in B/G deployment - TargetClusterId string `json:"targetClusterId,omitempty"` // target cluster to which the app is deployed - TargetClusterName string `json:"targetClusterName,omitempty"` // target cluster name - Status string `json:"status,omitempty"` // status is status of deployed app - GrafanaUrl string `json:"grafanaUrl,omitempty"` // grafana dashboard URL for deployed app - Description string `json:"description,omitempty"` // description for application + ID string `json:"id"` + Name string `json:"name"` // application name + Namespace string `json:"namespace"` // application namespace + OrganizationId string `json:"organizationId"` // contractId is a contract ID which this app belongs to + ProjectId string `json:"projectId"` // project ID which this app belongs to + Type string `json:"type"` // type (build/deploy/all) + AppType string `json:"appType"` // appType (spring/springboot) + EndpointUrl string `json:"endpointUrl"` // endpoint URL of deployed app + PreviewEndpointUrl string `json:"previewEndpointUrl"` // preview svc endpoint URL in B/G deployment + TargetClusterId string `json:"targetClusterId"` // target cluster to which the app is deployed + TargetClusterName string `json:"targetClusterName"` // target cluster name + Status string `json:"status"` // status is status of deployed app + GrafanaUrl string `json:"grafanaUrl"` // grafana dashboard URL for deployed app + Description string `json:"description"` // description for application CreatedAt time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` } type AppServeAppTaskResponse struct { - ID string `json:"id,omitempty"` - AppServeAppId string `json:"appServeAppId,omitempty"` // ID for appServeApp that this task belongs to - Version string `json:"version,omitempty"` // application version - Status string `json:"status,omitempty"` // status is app status - Output string `json:"output,omitempty"` // output for task result - ArtifactUrl string `json:"artifactUrl,omitempty"` // URL of java app artifact (Eg, Jar) - ImageUrl string `json:"imageUrl,omitempty"` // URL of built image for app - ExecutablePath string `json:"executablePath,omitempty"` // Executable path of app image - Profile string `json:"profile,omitempty"` // java app profile - AppConfig string `json:"appConfig,omitempty"` // java app config - AppSecret string `json:"appSecret,omitempty"` // java app secret - ExtraEnv string `json:"extraEnv,omitempty"` // env variable list for java app - Port string `json:"port,omitempty"` // java app port - ResourceSpec string `json:"resourceSpec,omitempty"` // resource spec of app pod - HelmRevision int32 `json:"helmRevision,omitempty"` // revision of deployed helm release - Strategy string `json:"strategy,omitempty"` // deployment strategy (eg, rolling-update) - RollbackVersion string `json:"rollbackVersion,omitempty"` // rollback target version + ID string `json:"id"` + AppServeAppId string `json:"appServeAppId"` // ID for appServeApp that this task belongs to + Version string `json:"version"` // application version + Status string `json:"status"` // status is app status + Output string `json:"output"` // output for task result + ArtifactUrl string `json:"artifactUrl"` // URL of java app artifact (Eg, Jar) + ImageUrl string `json:"imageUrl"` // URL of built image for app + ExecutablePath string `json:"executablePath"` // Executable path of app image + Profile string `json:"profile"` // java app profile + AppConfig string `json:"appConfig"` // java app config + AppSecret string `json:"appSecret"` // java app secret + ExtraEnv string `json:"extraEnv"` // env variable list for java app + Port string `json:"port"` // java app port + ResourceSpec string `json:"resourceSpec"` // resource spec of app pod + HelmRevision int32 `json:"helmRevision"` // revision of deployed helm release + Strategy string `json:"strategy"` // deployment strategy (eg, rolling-update) + RollbackVersion string `json:"rollbackVersion"` // rollback target version PvEnabled bool `json:"pvEnabled"` PvStorageClass string `json:"pvStorageClass"` PvAccessMode string `json:"pvAccessMode"` From 7a182b7cc663449a902bc34593518f2e8b5f2480 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 7 May 2024 11:02:42 +0900 Subject: [PATCH 428/502] feature. add force deleting logic when the cluster status was invalid --- internal/usecase/stack.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index f3c8621c..e2f576cf 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -419,6 +419,14 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) return httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to get cluster"), "S_FAILED_FETCH_CLUSTER", "") } + // cluster 의 상태가 비정상 상태라면, DB 데이터만 삭제 + if cluster.Status != domain.ClusterStatus_RUNNING && + cluster.Status != domain.ClusterStatus_BOOTSTRAPPING && + cluster.Status != domain.ClusterStatus_INSTALLING && + cluster.Status != domain.ClusterStatus_DELETING { + return u.clusterRepo.Delete(ctx, domain.ClusterId(dto.ID)) + } + // 지우려고 하는 stack 이 primary cluster 라면, organization 내에 cluster 가 자기 자신만 남아있을 경우이다. organizations, err := u.organizationRepo.Fetch(ctx, nil) if err != nil { @@ -464,8 +472,6 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) return httpErrors.NewBadRequestError(fmt.Errorf("existed appServeApps in %s", dto.OrganizationId), "S_FAILED_DELETE_EXISTED_ASA", "") } - // Policy 삭제 - workflow := "tks-stack-delete" workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ From 8326bacdbbeebbbe3619c5a039653754c2cd0e61 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 7 May 2024 11:44:01 +0900 Subject: [PATCH 429/502] bugfix: disable rollback of latest task --- internal/delivery/http/app-serve-app.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 70a383ac..5a76487e 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -574,8 +574,16 @@ func (h *AppServeAppHandler) GetAppServeAppTaskDetail(w http.ResponseWriter, r * return } - // TODO: this should be false for latest task - if strings.Contains(task.Status, "SUCCESS") && task.Status != "ABORT_SUCCESS" && + // Workaround: Compare task ID with latest task ID + // Mark latest task with additional flag later + latestTask, err := h.usecase.GetAppServeAppLatestTask(r.Context(), appId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if taskId == latestTask.ID { + task.AvailableRollback = false + } else if strings.Contains(task.Status, "SUCCESS") && task.Status != "ABORT_SUCCESS" && task.Status != "ROLLBACK_SUCCESS" { task.AvailableRollback = true } From 40e40a682c676b56e8a2f804c14a700af186da72 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 7 May 2024 11:54:09 +0900 Subject: [PATCH 430/502] feature. send email to all members in organization --- internal/usecase/system-notification.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 2ee8b34f..bb8e6f6e 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -118,6 +118,8 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre } } + // [TODO] policy 일 경우 처리 + dto := model.SystemNotification{ OrganizationId: organizationId, Name: systemNotification.Labels.AlertName, @@ -140,7 +142,6 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre continue } - // 사용자가 생성한 알림 if systemNotificationRuleId != nil { rule, err := u.systemNotificationRuleRepo.Get(ctx, *systemNotificationRuleId) if err != nil { @@ -150,9 +151,23 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre if rule.SystemNotificationCondition.EnableEmail { to := []string{} - for _, user := range rule.TargetUsers { - to = append(to, user.Email) + + // 아무것도 지정되어 있지 않다면, organization 전체 대상으로 발송한다. + if rule.TargetUsers == nil || len(rule.TargetUsers) == 0 { + users, err := u.userRepo.List(ctx, u.userRepo.OrganizationFilter(organizationId)) + if err != nil || users == nil { + log.Error(ctx, "Failed to get users ", err) + continue + } + for _, user := range *users { + to = append(to, user.Email) + } + } else { + for _, user := range rule.TargetUsers { + to = append(to, user.Email) + } } + message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, systemNotification.Annotations.Description, to) if err != nil { log.Error(ctx, fmt.Sprintf("Failed to make email content. err : %s", err.Error())) From ae092218df5685b363402198e9aad6815aa627db Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Tue, 7 May 2024 13:56:26 +0900 Subject: [PATCH 431/502] temp-fix: make appserving dashboard not being refreshed for now --- internal/usecase/app-serve-app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index f64506a2..033f3aae 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -223,7 +223,8 @@ func (u *AppServeAppUsecase) GetAppServeAppById(ctx context.Context, appId strin return asa, err } if len(applications) > 0 { - asa.GrafanaUrl = applications[0].Endpoint + "/d/tks_appserving_dashboard/tks-appserving-dashboard?refresh=30s&var-cluster=" + asa.TargetClusterId + "&var-kubernetes_namespace_name=" + asa.Namespace + "&var-kubernetes_pod_name=All&var-kubernetes_container_name=main&var-TopK=10" + // TODO: revert refresh param once the bug is resolved + asa.GrafanaUrl = applications[0].Endpoint + "/d/tks_appserving_dashboard/tks-appserving-dashboard?refresh=30s&var-cluster=" + asa.TargetClusterId + "&var-kubernetes_namespace_name=" + asa.Namespace + "&var-kubernetes_pod_name=All&var-kubernetes_container_name=main&var-TopK=10&refresh=30m" log.Debugf(ctx, "Found grafanaURL: %s", asa.GrafanaUrl) } } From 9148fa6c0989c7882cf4f74475b16ea6c118e8d4 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 7 May 2024 17:27:00 +0900 Subject: [PATCH 432/502] trivial. add attribute to audit --- internal/delivery/http/auth.go | 1 + internal/usecase/audit.go | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/internal/delivery/http/auth.go b/internal/delivery/http/auth.go index 5e8f702a..ee74f5eb 100644 --- a/internal/delivery/http/auth.go +++ b/internal/delivery/http/auth.go @@ -69,6 +69,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { Description: errorResponse.Text(), ClientIP: audit.GetClientIpAddress(w, r), UserId: nil, + UserAccountId: input.AccountId, }) log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) ErrorJSON(w, r, err) diff --git a/internal/usecase/audit.go b/internal/usecase/audit.go index d7e50b99..4e9ec1a3 100644 --- a/internal/usecase/audit.go +++ b/internal/usecase/audit.go @@ -18,18 +18,27 @@ type IAuditUsecase interface { } type AuditUsecase struct { - repo repository.IAuditRepository - userRepo repository.IUserRepository + repo repository.IAuditRepository + userRepo repository.IUserRepository + organizationRepo repository.IOrganizationRepository } func NewAuditUsecase(r repository.Repository) IAuditUsecase { return &AuditUsecase{ - repo: r.Audit, - userRepo: r.User, + repo: r.Audit, + userRepo: r.User, + organizationRepo: r.Organization, } } func (u *AuditUsecase) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { + if dto.OrganizationId != "" { + organization, err := u.organizationRepo.Get(ctx, dto.OrganizationId) + if err == nil { + dto.OrganizationName = organization.Name + } + } + if dto.UserId != nil && *dto.UserId != uuid.Nil { user, err := u.userRepo.GetByUuid(ctx, *dto.UserId) if err != nil { From 79a0a0f3b645550ae21c37dff37beb93e0ce8fbe Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 7 May 2024 17:35:45 +0900 Subject: [PATCH 433/502] minor fix. fix url of kubeconfig --- internal/delivery/http/project.go | 4 ++-- internal/route/route.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 0239e86c..0e5df939 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1708,7 +1708,7 @@ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r * // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} domain.GetProjectKubeconfigResponse -// @Router /organizations/{organizationId}/projects/{projectId}/kubeconfig [get] +// @Router /organizations/{organizationId}/projects/{projectId}/kube-config [get] // @Security JWT func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1864,7 +1864,7 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" // @Success 200 {object} domain.GetProjectNamespaceKubeConfigResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig [get] +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaceKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/internal/route/route.go b/internal/route/route.go index 537899c9..e9edbf12 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -289,8 +289,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateProjectNamespace, http.HandlerFunc(projectHandler.UpdateProjectNamespace))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectNamespaceKubeconfig, http.HandlerFunc(projectHandler.GetProjectNamespaceKubeconfig))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config", customMiddleware.Handle(internalApi.GetProjectNamespaceKubeconfig, http.HandlerFunc(projectHandler.GetProjectNamespaceKubeconfig))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kube-config", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) auditHandler := delivery.NewAuditHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/admin/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) From ed56cfbebef6970f47e0275e173eac3934a358ff Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 8 May 2024 12:51:11 +0900 Subject: [PATCH 434/502] trivial. disable email on default systemnotification --- internal/usecase/system-notification-rule.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 22afda6b..2c737b08 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -213,7 +213,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Severity: "warning", Duration: "3m", Parameter: []byte("[{\"order\": 0, \"value\": \"10\", \"operator\": \"<\"}]"), - EnableEmail: true, + EnableEmail: false, EnablePortal: true, }, TargetUsers: []model.User{}, @@ -239,7 +239,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Severity: "warning", Duration: "3m", Parameter: []byte("[{\"order\": 0, \"value\": \"0.2\", \"operator\": \"<\"}]"), - EnableEmail: true, + EnableEmail: false, EnablePortal: true, }, TargetUsers: []model.User{}, @@ -265,7 +265,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Severity: "critical", Duration: "30m", Parameter: []byte("[{\"order\": 0, \"value\": \"0\", \"operator\": \"<\"}]"), - EnableEmail: true, + EnableEmail: false, EnablePortal: true, }, TargetUsers: []model.User{}, @@ -291,7 +291,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Severity: "critical", Duration: "30m", Parameter: []byte("[{\"order\": 0, \"value\": \"0\", \"operator\": \"<\"}]"), - EnableEmail: true, + EnableEmail: false, EnablePortal: true, }, TargetUsers: []model.User{}, @@ -317,7 +317,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Severity: "critical", Duration: "30m", Parameter: []byte("[{\"order\": 0, \"value\": \"2\", \"operator\": \">\"}]"), - EnableEmail: true, + EnableEmail: false, EnablePortal: true, }, TargetUsers: []model.User{}, @@ -343,7 +343,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Severity: "critical", Duration: "1m", Parameter: []byte("[{\"order\": 0, \"value\": \"1\", \"operator\": \"==\"}]"), - EnableEmail: true, + EnableEmail: false, EnablePortal: true, }, TargetUsers: []model.User{}, @@ -369,7 +369,7 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c Severity: "critical", Duration: "1m", Parameter: []byte("[{\"order\": 0, \"value\": \"1\", \"operator\": \"==\"}]"), - EnableEmail: true, + EnableEmail: false, EnablePortal: true, }, TargetUsers: []model.User{}, From b11633a2afcc0db39f78c6a142900a871d911090 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 8 May 2024 12:57:05 +0900 Subject: [PATCH 435/502] tirivial. fix typo --- scripts/init_postgres.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index 206cf269..a5327374 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -61,7 +61,7 @@ insert into project_roles ( id, name, description, created_at, updated_at ) valu insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) values ('d42d716f-dd2e-429b-897d-b602f6382790', 'node-cpu-high-load', 'node-cpu-high-load', true, 'SYSTEM_NOTIFICATION', '(avg by (taco_cluster, instance) (rate(node_cpu_seconds_total{mode="idle"}[60s])))', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', true, 'SYSTEM_NOTIFICATION', 'node-memory-high-utilization', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)', null, null, now(), now() ); +values ('f11eefa4-5a16-44fc-8dae-4662e7fba023', 'node-memory-high-utilization', 'node-memory-high-utilization', true, 'SYSTEM_NOTIFICATION', '(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) values ('1ec08b58-2fe1-49c5-bbab-3544ec8ce330', 'node-disk-full', 'node-disk-full', true, 'SYSTEM_NOTIFICATION', 'predict_linear(node_filesystem_free_bytes{mountpoint="/"}[6h], 24*3600)', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) From 76621d376ce57aa5b4bae801826e6d494ee545a5 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 9 May 2024 01:49:23 +0900 Subject: [PATCH 436/502] =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0?= =?UTF-8?q?=EB=A5=BC=20=EB=AA=85=EC=8B=9C=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EC=9D=80=20=EC=A0=95=EC=B1=85=EC=9D=84=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/policy-template/policy-operator.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 0626ea11..98c81311 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -24,7 +24,7 @@ func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { return nil } - var params *apiextensionsv1.JSON = nil + var params *apiextensionsv1.JSON = &apiextensionsv1.JSON{Raw: []byte("{}")} var jsonResult map[string]interface{} @@ -86,6 +86,14 @@ func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) * labels[PartOfKey] = PartOfVal labels[TemplateIDLabel] = policyTemplate.ID.String() + var validation *Validation = nil + + if len(policyTemplate.ParametersSchema) > 0 { + validation = &Validation{ + OpenAPIV3Schema: ParamDefsToJSONSchemaProeprties(policyTemplate.ParametersSchema, false), + } + } + return &TKSPolicyTemplate{ TypeMeta: metav1.TypeMeta{ APIVersion: "tkspolicy.openinfradev.github.io/v1", @@ -103,9 +111,7 @@ func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) * Names: Names{ Kind: policyTemplate.Kind, }, - Validation: &Validation{ - OpenAPIV3Schema: ParamDefsToJSONSchemaProeprties(policyTemplate.ParametersSchema, false), - }, + Validation: validation, }, }, Targets: []Target{{ From 4e61ef67d38b23f3f268f7b8623636773e27d85e Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 9 May 2024 10:49:24 +0900 Subject: [PATCH 437/502] trivial. fix typo error --- api/swagger/docs.go | 4 ++-- api/swagger/swagger.json | 4 ++-- api/swagger/swagger.yaml | 4 ++-- pkg/domain/system-notification.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 43a7daf1..4ad92f43 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -6571,7 +6571,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "/organizations/{organizationId}/projects/{projectId}/kube-config": { "get": { "security": [ { @@ -7412,7 +7412,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config": { "get": { "security": [ { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 6e191c12..39a8e616 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -6565,7 +6565,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { + "/organizations/{organizationId}/projects/{projectId}/kube-config": { "get": { "security": [ { @@ -7406,7 +7406,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config": { "get": { "security": [ { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index f595a0b4..e4aa9380 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -8418,7 +8418,7 @@ paths: summary: Check duplicate appServeAppName tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/kubeconfig: + /organizations/{organizationId}/projects/{projectId}/kube-config: get: consumes: - application/json @@ -8965,7 +8965,7 @@ paths: summary: Get k8s resources for project namespace tags: - Projects - /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig: + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config: get: consumes: - application/json diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 8ba0f1e8..ff5d7c31 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -61,7 +61,7 @@ type SystemNotificationRequest struct { AlertType string `json:"alertType"` SystemNotificationRuleId string `json:"systemNotificationRuleId"` PolicyName string `json:"policyName"` - PolicyTemplate string `json:"policyTemplate"` + PolicyTemplateName string `json:"policyTemplateName"` } `json:"annotations"` } From 393902eed7061f05c3d7e441eebf7bdaa10bcb95 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 9 May 2024 11:19:05 +0900 Subject: [PATCH 438/502] feature. add policyName to systemNotification --- internal/model/system-notification.go | 1 + internal/usecase/system-notification.go | 8 ++++++-- pkg/domain/system-notification.go | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go index 26906afe..2be07d47 100644 --- a/internal/model/system-notification.go +++ b/internal/model/system-notification.go @@ -39,6 +39,7 @@ type SystemNotification struct { Read bool `gorm:"-:all"` Readers []User `gorm:"many2many:system_notification_users;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` SystemNotificationRuleId *uuid.UUID + PolicyName string } type SystemNotificationAction struct { diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index bb8e6f6e..451f407e 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -118,8 +118,6 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre } } - // [TODO] policy 일 경우 처리 - dto := model.SystemNotification{ OrganizationId: organizationId, Name: systemNotification.Labels.AlertName, @@ -136,6 +134,10 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre NotificationType: systemNotification.Annotations.AlertType, } + if systemNotification.Annotations.AlertType != "POLICY_NOTIFICATION" { + dto.PolicyName = systemNotification.Annotations.PolicyName + } + _, err = u.repo.Create(ctx, dto) if err != nil { log.Error(ctx, "Failed to create systemNotification ", err) @@ -344,6 +346,8 @@ func (u *SystemNotificationUsecase) makeAdditionalInfo(systemNotification *model break } } + + log.Info(context.TODO(), systemNotification.RawData) } func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, systemNotification domain.SystemNotificationRequest, clusterId domain.ClusterId) (url string) { diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index ff5d7c31..4b7e5b30 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -104,6 +104,7 @@ type SystemNotificationResponse struct { Read bool `json:"read"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` + PolicyName string `json:"policyName"` } type SystemNotificationActionResponse struct { From 6347b5fae673264e66c710c7c590e91f6c1da618 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 9 May 2024 11:22:44 +0900 Subject: [PATCH 439/502] trivial. fix typo; --- internal/usecase/system-notification.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 451f407e..7513826e 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -134,7 +134,7 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre NotificationType: systemNotification.Annotations.AlertType, } - if systemNotification.Annotations.AlertType != "POLICY_NOTIFICATION" { + if systemNotification.Annotations.AlertType == "POLICY_NOTIFICATION" { dto.PolicyName = systemNotification.Annotations.PolicyName } From e9be2eeb13c83c1f65975f8cc329ab2f9e9494bb Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 9 May 2024 11:39:12 +0900 Subject: [PATCH 440/502] bugfix. fix wrong permission merging --- internal/model/permission.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/model/permission.go b/internal/model/permission.go index 4c395c85..3091706a 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -113,13 +113,13 @@ func NewAdminPermissionSet() *PermissionSet { func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { if root.Children == nil || len(root.Children) == 0 { + if f != nil && !(*f)(*root) { + return edgePermissions + } return append(edgePermissions, root) } for _, child := range root.Children { - if f != nil && !(*f)(*child) { - continue - } edgePermissions = GetEdgePermission(child, edgePermissions, f) } From ca5ef68b729027ffc199daf8f9183b1c1464f315 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 9 May 2024 17:11:32 +0900 Subject: [PATCH 441/502] feature. fix minor bugs --- api/swagger/docs.go | 6 ++++++ api/swagger/swagger.json | 6 ++++++ api/swagger/swagger.yaml | 4 ++++ internal/delivery/http/organization.go | 14 ++++++++++++++ internal/middleware/audit/audit-map.go | 20 ++++++++++++++++++++ pkg/domain/organization.go | 5 +++-- scripts/init_postgres.sql | 1 + 7 files changed, 54 insertions(+), 2 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 4ad92f43..42716929 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -15315,6 +15315,9 @@ const docTemplate = `{ "organizationId": { "type": "string" }, + "policyName": { + "type": "string" + }, "processingSec": { "type": "integer" }, @@ -15690,6 +15693,9 @@ const docTemplate = `{ "name" ], "properties": { + "adminAccountId": { + "type": "string" + }, "description": { "type": "string", "maxLength": 100, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 39a8e616..f2faa9d1 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -15309,6 +15309,9 @@ "organizationId": { "type": "string" }, + "policyName": { + "type": "string" + }, "processingSec": { "type": "integer" }, @@ -15684,6 +15687,9 @@ "name" ], "properties": { + "adminAccountId": { + "type": "string" + }, "description": { "type": "string", "maxLength": 100, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index e4aa9380..fe6f2961 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -3345,6 +3345,8 @@ definitions: type: string organizationId: type: string + policyName: + type: string processingSec: type: integer rawData: @@ -3591,6 +3593,8 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.UpdateOrganizationRequest: properties: + adminAccountId: + type: string description: maxLength: 100 minLength: 0 diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 524e78ae..292d73ba 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -356,6 +356,20 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. return } + user, err := h.userUsecase.GetByAccountId(r.Context(), input.AdminAccountId, organizationId) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + err = h.usecase.ChangeAdminId(r.Context(), organizationId, user.ID) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + var out domain.UpdateOrganizationResponse out.ID = res.ID diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index eb6babba..7e1e4f5a 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -165,6 +165,26 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return "시스템알림설정을 삭제하는데 실패하였습니다. ", errorText(ctx, out) } + }, internalApi.CreatePolicyTemplate: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { + input := domain.CreatePolicyTemplateRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(ctx, err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("정책템플릿 [%s]를 생성하였습니다.", input.TemplateName), "" + } else { + return fmt.Sprintf("정책템플릿 [%s]을 생성하는데 실패하였습니다.", input.TemplateName), errorText(ctx, out) + } + }, internalApi.CreatePolicy: func(ctx context.Context, out []byte, in []byte, statusCode int) (message string, description string) { + input := domain.CreatePolicyRequest{} + if err := json.Unmarshal(in, &input); err != nil { + log.Error(ctx, err) + } + if isSuccess(statusCode) { + return fmt.Sprintf("정책 [%s]를 생성하였습니다.", input.PolicyName), "" + } else { + return fmt.Sprintf("정책 [%s]을 생성하는데 실패하였습니다.", input.PolicyName), errorText(ctx, out) + } }, } diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index ef19f12c..46479c4f 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -91,8 +91,9 @@ type ListOrganizationResponse struct { } type UpdateOrganizationRequest struct { - Name string `json:"name" validate:"required,min=1,max=30"` - Description string `json:"description" validate:"omitempty,min=0,max=100"` + Name string `json:"name" validate:"required,min=1,max=30"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` + AdminAccountId string `json:"adminAccountId"` } type UpdateOrganizationResponse struct { diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index a5327374..df183860 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -96,6 +96,7 @@ insert into system_notification_metric_parameters ( "order", system_notification values ( 1, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'POD', '$labels.pod', now(), now() ); insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) values ( 2, '46e9e216-364a-4a3f-9182-85b2c4c34f77', 'NAMESPACE', '$labels.namespace', now(), now() ); +insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) values ( 0, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'STACK', '$labels.taco_cluster', now(), now() ); insert into system_notification_metric_parameters ( "order", system_notification_template_id, key, value, created_at, updated_at ) values ( 1, '7355d0f9-7c14-4f70-92ea-a9868624ff82', 'NAME', '$labels.name', now(), now() ); From 3e9bf39d2b70ae0119cb333e37df980cd3de52f6 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 13 May 2024 17:29:12 +0900 Subject: [PATCH 442/502] trivial. fix messageActionProposal on policy_notifications --- internal/usecase/system-notification.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 7513826e..6a2c577f 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -136,6 +136,13 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre if systemNotification.Annotations.AlertType == "POLICY_NOTIFICATION" { dto.PolicyName = systemNotification.Annotations.PolicyName + if strings.Contains(systemNotification.Labels.AlertName, "policy-audited") { + dto.MessageActionProposal = "감사" + } else if strings.Contains(systemNotification.Labels.AlertName, "policy-blocked") { + dto.MessageActionProposal = "거부" + } else { + dto.MessageActionProposal = "" + } } _, err = u.repo.Create(ctx, dto) @@ -346,8 +353,6 @@ func (u *SystemNotificationUsecase) makeAdditionalInfo(systemNotification *model break } } - - log.Info(context.TODO(), systemNotification.RawData) } func (u *SystemNotificationUsecase) makeGrafanaUrl(ctx context.Context, primaryCluster model.Cluster, systemNotification domain.SystemNotificationRequest, clusterId domain.ClusterId) (url string) { From 6eca2a5993ec6870d7b90334fec2c19b20266c3a Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 14 May 2024 10:06:35 +0900 Subject: [PATCH 443/502] trivial. fix filter for policyNotifications --- internal/delivery/http/policy-notification.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/delivery/http/policy-notification.go b/internal/delivery/http/policy-notification.go index 40122206..12e87db4 100644 --- a/internal/delivery/http/policy-notification.go +++ b/internal/delivery/http/policy-notification.go @@ -58,6 +58,16 @@ func (h *PolicyNotificationHandler) GetPolicyNotifications(w http.ResponseWriter var s domain.SystemNotificationRuleStatus pg.GetFilters()[i].Values[j] = strconv.Itoa(int(s.FromString(value))) } + } else if filter.Column == "message_action_proposal" { + for j, value := range filter.Values { + val := "" + if value == "dryrun" { + val = "감사" + } else { + val = "거부" + } + pg.GetFilters()[i].Values[j] = val + } } } From d5755c219ed99ec545af0320b1fffd2687278143 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 16 May 2024 10:49:47 +0900 Subject: [PATCH 444/502] =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=8F=99?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=EC=84=A4=EC=A0=95=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy-template.go | 6 +- internal/model/policy-template.go | 30 ++++++++- internal/policy-template/kind-map.go | 73 +++++++++++++++++++++ internal/policy-template/kind-util.go | 63 ++++++++++++++++++ internal/policy-template/policy-operator.go | 31 +++++++-- internal/repository/policy-template.go | 26 +++++++- internal/usecase/policy-template.go | 55 +++++++++++++++- pkg/domain/admin/policy-template.go | 14 ++-- pkg/domain/policy-template.go | 23 +++++-- pkg/httpErrors/errorCode.go | 1 + 10 files changed, 297 insertions(+), 25 deletions(-) create mode 100644 internal/policy-template/kind-map.go diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index b43bbc42..4fba4a3a 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -650,7 +650,8 @@ func (h *PolicyTemplateHandler) Admin_CreatePolicyTemplateVersion(w http.Respons input.ExpectedVersion, expectedVersion))) } - createdVersion, err := h.usecase.CreatePolicyTemplateVersion(r.Context(), nil, id, expectedVersion, input.ParametersSchema, input.Rego, input.Libs) + createdVersion, err := h.usecase.CreatePolicyTemplateVersion(r.Context(), nil, id, expectedVersion, input.ParametersSchema, + input.Rego, input.Libs, input.SyncKinds, input.SyncJson) if err != nil { ErrorJSON(w, r, err) @@ -1549,7 +1550,8 @@ func (h *PolicyTemplateHandler) CreatePolicyTemplateVersion(w http.ResponseWrite input.ExpectedVersion, expectedVersion))) } - createdVersion, err := h.usecase.CreatePolicyTemplateVersion(r.Context(), &organizationId, id, expectedVersion, input.ParametersSchema, input.Rego, input.Libs) + createdVersion, err := h.usecase.CreatePolicyTemplateVersion(r.Context(), &organizationId, id, expectedVersion, input.ParametersSchema, + input.Rego, input.Libs, input.SyncKinds, input.SyncJson) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index ca2c28ff..ef9ec66e 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -20,9 +20,11 @@ type PolicyTemplateSupportedVersion struct { PolicyTemplateId uuid.UUID `gorm:"index:template_version,unique"` Version string `gorm:"index:template_version,unique"` - ParameterSchema string `gorm:"type:text"` - Rego string `gorm:"type:text"` - Libs string `gorm:"type:text"` + ParameterSchema string `gorm:"type:text"` + Rego string `gorm:"type:text"` + Libs string `gorm:"type:text"` + SyncKinds *string `gorm:"type:text"` + SyncJson *string `gorm:"type:text"` } type PolicyTemplate struct { @@ -46,6 +48,8 @@ type PolicyTemplate struct { ParametersSchema []*domain.ParameterDef `gorm:"-:all"` Rego string `gorm:"-:all"` Libs []string `gorm:"-:all"` + SyncKinds *[]string `gorm:"-:all"` + SyncJson *string `gorm:"-:all"` PermittedOrganizationIds []string `gorm:"-:all"` CreatorId *uuid.UUID `gorm:"type:uuid"` Creator User `gorm:"foreignKey:CreatorId"` @@ -94,12 +98,25 @@ func (pt *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { pt.Version = "v1.0.0" + var syncKindsString *string = nil + + if pt.SyncKinds != nil { + syncJsonBytes, err := json.Marshal(pt.SyncKinds) + + if err == nil { + syncStr := string(syncJsonBytes) + syncKindsString = &syncStr + } + } + pt.SupportedVersions = []PolicyTemplateSupportedVersion{ { Version: "v1.0.0", ParameterSchema: string(jsonByte), Rego: pt.Rego, Libs: libs, + SyncJson: pt.SyncJson, + SyncKinds: syncKindsString, }, } @@ -112,6 +129,7 @@ func (pt *PolicyTemplate) AfterFind(tx *gorm.DB) (err error) { supportedVersion := pt.SupportedVersions[0] pt.Version = supportedVersion.Version pt.Rego = supportedVersion.Rego + pt.SyncJson = supportedVersion.SyncJson if len(strings.TrimSpace(supportedVersion.Libs)) == 0 { pt.Libs = []string{} @@ -121,6 +139,12 @@ func (pt *PolicyTemplate) AfterFind(tx *gorm.DB) (err error) { // 마찬가지로 에러 무시 _ = json.Unmarshal([]byte(supportedVersion.ParameterSchema), &pt.ParametersSchema) + + if supportedVersion.SyncKinds != nil { + syncKinds := []string{} + _ = json.Unmarshal([]byte(*supportedVersion.SyncKinds), &syncKinds) + pt.SyncKinds = &syncKinds + } } pt.PermittedOrganizationIds = make([]string, len(pt.PermittedOrganizations)) diff --git a/internal/policy-template/kind-map.go b/internal/policy-template/kind-map.go new file mode 100644 index 00000000..ba8ee5f7 --- /dev/null +++ b/internal/policy-template/kind-map.go @@ -0,0 +1,73 @@ +package policytemplate + +import "k8s.io/apimachinery/pkg/runtime/schema" + +var KindMap = map[string]schema.GroupVersionKind{ + "Namespace": {Group: "", Version: "v1", Kind: "Namespace"}, + "StatefulSet": {Group: "apps", Version: "v1", Kind: "StatefulSet"}, + "ClusterIssuer": {Group: "cert-manager.io", Version: "v1", Kind: "ClusterIssuer"}, + "LimitRange": {Group: "", Version: "v1", Kind: "LimitRange"}, + "PodAttachOptions": {Group: "", Version: "v1", Kind: "PodAttachOptions"}, + "PersistentVolume": {Group: "", Version: "v1", Kind: "PersistentVolume"}, + "Pod": {Group: "", Version: "v1", Kind: "Pod"}, + "SubjectAccessReview": {Group: "authorization.k8s.io", Version: "v1", Kind: "SubjectAccessReview"}, + "HorizontalPodAutoscaler": {Group: "autoscaling", Version: "v1", Kind: "HorizontalPodAutoscaler"}, + "PriorityLevelConfiguration": {Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1", Kind: "PriorityLevelConfiguration"}, + "SelfSubjectAccessReview": {Group: "authorization.k8s.io", Version: "v1", Kind: "SelfSubjectAccessReview"}, + "Event": {Group: "events.k8s.io", Version: "v1", Kind: "Event"}, + "Job": {Group: "batch", Version: "v1", Kind: "Job"}, + "Issuer": {Group: "cert-manager.io", Version: "v1", Kind: "Issuer"}, + "Eviction": {Group: "", Version: "v1", Kind: "Eviction"}, + "ConfigMap": {Group: "", Version: "v1", Kind: "ConfigMap"}, + "NodeProxyOptions": {Group: "", Version: "v1", Kind: "NodeProxyOptions"}, + "Node": {Group: "", Version: "v1", Kind: "Node"}, + "CSIDriver": {Group: "storage.k8s.io", Version: "v1", Kind: "CSIDriver"}, + "PriorityClass": {Group: "scheduling.k8s.io", Version: "v1", Kind: "PriorityClass"}, + "ReplicationController": {Group: "", Version: "v1", Kind: "ReplicationController"}, + "ResourceQuota": {Group: "", Version: "v1", Kind: "ResourceQuota"}, + "Ingress": {Group: "networking.k8s.io", Version: "v1", Kind: "Ingress"}, + "ComponentStatus": {Group: "", Version: "v1", Kind: "ComponentStatus"}, + "ReplicaSet": {Group: "apps", Version: "v1", Kind: "ReplicaSet"}, + "RuntimeClass": {Group: "node.k8s.io", Version: "v1", Kind: "RuntimeClass"}, + "PodExecOptions": {Group: "", Version: "v1", Kind: "PodExecOptions"}, + "ServiceProxyOptions": {Group: "", Version: "v1", Kind: "ServiceProxyOptions"}, + "CronJob": {Group: "batch", Version: "v1", Kind: "CronJob"}, + "PersistentVolumeClaim": {Group: "", Version: "v1", Kind: "PersistentVolumeClaim"}, + "Secret": {Group: "", Version: "v1", Kind: "Secret"}, + "ServiceAccount": {Group: "", Version: "v1", Kind: "ServiceAccount"}, + "CertificateSigningRequest": {Group: "certificates.k8s.io", Version: "v1", Kind: "CertificateSigningRequest"}, + "Certificate": {Group: "cert-manager.io", Version: "v1", Kind: "Certificate"}, + "Lease": {Group: "coordination.k8s.io", Version: "v1", Kind: "Lease"}, + "IPPool": {Group: "crd.projectcalico.org", Version: "v1", Kind: "IPPool"}, + "ClusterAnalysisTemplate": {Group: "argoproj.io", Version: "v1alpha1", Kind: "ClusterAnalysisTemplate"}, + "CertificateRequest": {Group: "cert-manager.io", Version: "v1", Kind: "CertificateRequest"}, + "Workflow": {Group: "argoproj.io", Version: "v1alpha1", Kind: "Workflow"}, + "Experiment": {Group: "argoproj.io", Version: "v1alpha1", Kind: "Experiment"}, + "CustomResourceDefinition": {Group: "apiextensions.k8s.io", Version: "v1", Kind: "CustomResourceDefinition"}, + "APIService": {Group: "apiregistration.k8s.io", Version: "v1", Kind: "APIService"}, + "ClusterRoleBinding": {Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}, + "EndpointSlice": {Group: "discovery.k8s.io", Version: "v1", Kind: "EndpointSlice"}, + "CSINode": {Group: "storage.k8s.io", Version: "v1", Kind: "CSINode"}, + "StorageClass": {Group: "storage.k8s.io", Version: "v1", Kind: "StorageClass"}, + "MutatingWebhookConfiguration": {Group: "admissionregistration.k8s.io", Version: "v1", Kind: "MutatingWebhookConfiguration"}, + "Deployment": {Group: "apps", Version: "v1", Kind: "Deployment"}, + "PodProxyOptions": {Group: "", Version: "v1", Kind: "PodProxyOptions"}, + "LocalSubjectAccessReview": {Group: "authorization.k8s.io", Version: "v1", Kind: "LocalSubjectAccessReview"}, + "FlowSchema": {Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1", Kind: "FlowSchema"}, + "Endpoints": {Group: "", Version: "v1", Kind: "Endpoints"}, + "Service": {Group: "", Version: "v1", Kind: "Service"}, + "ControllerRevision": {Group: "apps", Version: "v1", Kind: "ControllerRevision"}, + "DaemonSet": {Group: "apps", Version: "v1", Kind: "DaemonSet"}, + "Role": {Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "Role"}, + "VolumeAttachment": {Group: "storage.k8s.io", Version: "v1", Kind: "VolumeAttachment"}, + "RoleBinding": {Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "RoleBinding"}, + "ClusterTriggerBinding": {Group: "triggers.tekton.dev", Version: "v1beta1", Kind: "ClusterTriggerBinding"}, + "PodDisruptionBudget": {Group: "policy", Version: "v1", Kind: "PodDisruptionBudget"}, + "IngressClass": {Group: "networking.k8s.io", Version: "v1", Kind: "IngressClass"}, + "PodTemplate": {Group: "", Version: "v1", Kind: "PodTemplate"}, + "ClusterRole": {Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole"}, + "SelfSubjectRulesReview": {Group: "authorization.k8s.io", Version: "v1", Kind: "SelfSubjectRulesReview"}, + "ValidatingWebhookConfiguration": {Group: "admissionregistration.k8s.io", Version: "v1", Kind: "ValidatingWebhookConfiguration"}, + "Binding": {Group: "", Version: "v1", Kind: "Binding"}, + "PodPortForwardOptions": {Group: "", Version: "v1", Kind: "PodPortForwardOptions"}, +} diff --git a/internal/policy-template/kind-util.go b/internal/policy-template/kind-util.go index b19a766b..5fe13747 100644 --- a/internal/policy-template/kind-util.go +++ b/internal/policy-template/kind-util.go @@ -1,6 +1,7 @@ package policytemplate import ( + "encoding/json" "fmt" "slices" @@ -92,3 +93,65 @@ func CheckAndNormalizeKinds(kinds []domain.Kinds) ([]domain.Kinds, error) { return result, nil } + +func CheckAndConvertToSyncData(kinds []string) (*[][]domain.CompactGVKEquivalenceSet, error) { + invalid_kinds := []string{} + results := []domain.CompactGVKEquivalenceSet{} + + for _, kind := range kinds { + gvk, ok := KindMap[kind] + + if ok { + results = append(results, domain.CompactGVKEquivalenceSet{ + Groups: []string{gvk.Group}, Versions: []string{gvk.Version}, Kinds: []string{gvk.Kind}, + }) + } else { + invalid_kinds = append(invalid_kinds, kind) + } + } + + if len(invalid_kinds) > 0 { + return nil, fmt.Errorf("invalid kinds %v", invalid_kinds) + } + + return &[][]domain.CompactGVKEquivalenceSet{ + results, + }, nil +} + +func MarshalSyncData(syncData *[][]domain.CompactGVKEquivalenceSet) (string, error) { + result, err := json.MarshalIndent(syncData, "", " ") + + if err != nil { + return "", err + } + + return string(result), nil +} + +func ParseAndCheckSyncData(syncjson string) (*[][]domain.CompactGVKEquivalenceSet, error) { + result := [][]domain.CompactGVKEquivalenceSet{} + err := json.Unmarshal([]byte(syncjson), &result) + + if err != nil { + return nil, err + } + + invalid_kinds := []string{} + + for _, sets := range result { + for _, set := range sets { + for _, kind := range set.Kinds { + if _, ok := KindMap[kind]; !ok { + invalid_kinds = append(invalid_kinds, kind) + } + } + } + } + + if len(invalid_kinds) > 0 { + return nil, fmt.Errorf("invalid kinds %v", invalid_kinds) + } + + return &result, nil +} diff --git a/internal/policy-template/policy-operator.go b/internal/policy-template/policy-operator.go index 98c81311..bb617f05 100644 --- a/internal/policy-template/policy-operator.go +++ b/internal/policy-template/policy-operator.go @@ -12,11 +12,12 @@ import ( ) const ( - PartOfKey = "app.kubernetes.io/part-of" - PartOfVal = "tks-policy-operator" - TksLabelPrefix = "tks/" - PolicyIDLabel = TksLabelPrefix + "policy-id" - TemplateIDLabel = TksLabelPrefix + "policy-template-id" + PartOfKey = "app.kubernetes.io/part-of" + PartOfVal = "tks-policy-operator" + TksLabelPrefix = "tks/" + PolicyIDLabel = TksLabelPrefix + "policy-id" + TemplateIDLabel = TksLabelPrefix + "policy-template-id" + RequireSyncDataAnnotation = "metadata.gatekeeper.sh/requires-sync-data" ) func PolicyToTksPolicyCR(policy *model.Policy) *TKSPolicy { @@ -86,6 +87,21 @@ func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) * labels[PartOfKey] = PartOfVal labels[TemplateIDLabel] = policyTemplate.ID.String() + annotations := map[string]string{} + + if policyTemplate.SyncJson != nil { + annotations[RequireSyncDataAnnotation] = "\"" + *policyTemplate.SyncJson + "\"" + } else if policyTemplate.SyncKinds != nil { + sync, err := CheckAndConvertToSyncData(*policyTemplate.SyncKinds) + + if err == nil { + syncVal, err := MarshalSyncData(sync) + if err == nil { + annotations[RequireSyncDataAnnotation] = "\"" + syncVal + "\"" + } + } + } + var validation *Validation = nil if len(policyTemplate.ParametersSchema) > 0 { @@ -101,8 +117,9 @@ func PolicyTemplateToTksPolicyTemplateCR(policyTemplate *model.PolicyTemplate) * }, ObjectMeta: metav1.ObjectMeta{ - Name: strings.ToLower(policyTemplate.Kind), - Labels: labels, + Name: strings.ToLower(policyTemplate.Kind), + Labels: labels, + Annotations: annotations, }, Spec: TKSPolicyTemplateSpec{ diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 28ea8f16..24dd7df0 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -32,7 +32,8 @@ type IPolicyTemplateRepository interface { ListPolicyTemplateVersions(ctx context.Context, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) GetPolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) DeletePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, version string) (err error) - CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) + CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, + schema []*domain.ParameterDef, rego string, libs []string, syncKinds *[]string, syncJson *string) (version string, err error) GetLatestTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID) (version string, err error) CountTksTemplateByOrganization(ctx context.Context, organizationId string) (count int64, err error) CountOrganizationTemplate(ctx context.Context, organizationId string) (count int64, err error) @@ -435,7 +436,8 @@ func (r *PolicyTemplateRepository) DeletePolicyTemplateVersion(ctx context.Conte }) } -func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) { +func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Context, policyTemplateId uuid.UUID, newVersion string, + schema []*domain.ParameterDef, rego string, libs []string, syncKinds *[]string, syncJson *string) (version string, err error) { var policyTemplateVersion model.PolicyTemplateSupportedVersion res := r.db.WithContext(ctx).Limit(1). Where("policy_template_id = ?", policyTemplateId).Where("version = ?", version). @@ -469,12 +471,32 @@ func (r *PolicyTemplateRepository) CreatePolicyTemplateVersion(ctx context.Conte return "", parseErr } + var syncKindsString *string = nil + + if syncKinds != nil { + syncJsonBytes, err := json.Marshal(syncKinds) + + if err != nil { + parseErr := errors.Errorf("Unable to parse parameter schema: %v", err) + + log.Error(ctx, parseErr) + + return "", parseErr + } + + syncStr := string(syncJsonBytes) + + syncKindsString = &syncStr + } + newPolicyTemplateVersion := &model.PolicyTemplateSupportedVersion{ PolicyTemplateId: policyTemplateId, Version: newVersion, Rego: rego, Libs: libsString, ParameterSchema: string(jsonBytes), + SyncJson: syncJson, + SyncKinds: syncKindsString, } if err := r.db.WithContext(ctx).Create(newPolicyTemplateVersion).Error; err != nil { diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index f54a4f96..3fb66ac6 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -30,7 +30,8 @@ type IPolicyTemplateUsecase interface { GetPolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string) (policyTemplateVersionsReponse *model.PolicyTemplate, err error) ListPolicyTemplateVersions(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID) (policyTemplateVersionsReponse *domain.ListPolicyTemplateVersionsResponse, err error) DeletePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, version string) (err error) - CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) + CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string, + syncKinds *[]string, syncJson *string) (version string, err error) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) @@ -71,6 +72,30 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp return uuid.Nil, httpErrors.NewUnauthorizedError(fmt.Errorf("invalid token"), "A_INVALID_TOKEN", "") } + if dto.SyncKinds != nil && dto.SyncJson != nil { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_INVALID_SYNC", "both sync kinds and json specified") + } + + if dto.SyncKinds != nil { + if _, err := policytemplate.CheckAndConvertToSyncData(*dto.SyncKinds); err != nil { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_INVALID_SYNC", "invalid sync kind") + } + } + + if dto.SyncJson != nil { + result, err := policytemplate.ParseAndCheckSyncData(*dto.SyncJson) + + if err != nil { + return uuid.Nil, httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_INVALID_SYNC", "invalid sync json") + } + + formatted, err := policytemplate.MarshalSyncData(result) + + if err == nil { + dto.SyncJson = &formatted + } + } + if dto.IsTksTemplate() { exists, err := u.repo.ExistByName(ctx, dto.TemplateName) if err == nil && exists { @@ -485,13 +510,37 @@ func (u *PolicyTemplateUsecase) DeletePolicyTemplateVersion(ctx context.Context, return u.repo.DeletePolicyTemplateVersion(ctx, policyTemplateId, version) } -func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string) (version string, err error) { +func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, organizationId *string, policyTemplateId uuid.UUID, newVersion string, schema []*domain.ParameterDef, rego string, libs []string, + syncKinds *[]string, syncJson *string) (version string, err error) { policyTemplate, err := u.repo.GetByID(ctx, policyTemplateId) if err != nil { return "", err } + if syncKinds != nil && syncJson != nil { + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_INVALID_SYNC", "both sync kinds and json specified") + } + + if syncKinds != nil { + if _, err := policytemplate.CheckAndConvertToSyncData(*syncKinds); err != nil { + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_INVALID_SYNC", "invalid sync kind") + } + } + + if syncJson != nil { + result, err := policytemplate.ParseAndCheckSyncData(*syncJson) + if err != nil { + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "PT_INVALID_SYNC", "invalid sync json") + } + + formatted, err := policytemplate.MarshalSyncData(result) + + if err == nil { + syncJson = &formatted + } + } + if policyTemplate == nil { return "", httpErrors.NewBadRequestError(fmt.Errorf( "failed to fetch policy template"), @@ -518,7 +567,7 @@ func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, rego = policytemplate.FormatRegoCode(rego) libs = policytemplate.FormatLibCode(libs) - return u.repo.CreatePolicyTemplateVersion(ctx, policyTemplateId, newVersion, schema, rego, libs) + return u.repo.CreatePolicyTemplateVersion(ctx, policyTemplateId, newVersion, schema, rego, libs, syncKinds, syncJson) } func (u *PolicyTemplateUsecase) RegoCompile(request *domain.RegoCompileRequest, parseParameter bool) (response *domain.RegoCompileResponse, err error) { diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index 1e0867ef..9ce9e483 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -29,6 +29,8 @@ type PolicyTemplateResponse struct { ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` Rego string `json:"rego" example:"rego 코드"` Libs []string `json:"libs" example:"rego 코드"` + SyncKinds *[]string `json:"syncKinds,omitempty" example:"Ingress"` + SyncJson *string `json:"SyncJson,omitempty" example:"[[]]"` PermittedOrganizations []domain.SimpleOrganizationResponse `json:"permittedOrganizations"` } @@ -50,8 +52,10 @@ type CreatePolicyTemplateRequest struct { ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - Rego string `json:"rego" example:"rego 코드" validate:"required"` - Libs []string `json:"libs" example:"rego 코드"` + Rego string `json:"rego" example:"rego 코드" validate:"required"` + Libs []string `json:"libs" example:"rego 코드"` + SyncKinds *[]string `json:"syncKinds,omitempty" example:"Ingress"` + SyncJson *string `json:"SyncJson,omitempty" example:"[[]]"` PermittedOrganizationIds []string `json:"permittedOrganizationIds"` } @@ -100,8 +104,10 @@ type CreatePolicyTemplateVersionRequest struct { ParametersSchema []*domain.ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - Rego string `json:"rego" example:"rego 코드" validate:"required"` - Libs []string `json:"libs" example:"rego 코드"` + Rego string `json:"rego" example:"rego 코드" validate:"required"` + Libs []string `json:"libs" example:"rego 코드"` + SyncKinds *[]string `json:"syncKinds,omitempty" example:"Ingress"` + SyncJson *string `json:"SyncJson,omitempty" example:"[[]]"` } type CreatePolicyTemplateVersionResponse struct { diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index a5200616..835a1225 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -21,6 +21,8 @@ type PolicyTemplateResponse struct { ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` Rego string `json:"rego" example:"rego 코드"` Libs []string `json:"libs" example:"rego 코드"` + SyncKinds *[]string `json:"syncKinds,omitempty" example:"Ingress"` + SyncJson *string `json:"SyncJson,omitempty" example:"[[]]"` } type PolicyTemplateTwoVersionResponse struct { @@ -41,6 +43,8 @@ type PolicyTemplateTwoVersionResponse struct { ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` Rego string `json:"rego" example:"rego 코드"` Libs []string `json:"libs" example:"rego 코드"` + SyncKinds *[]string `json:"syncKinds,omitempty" example:"Ingress"` + SyncJson *string `json:"SyncJson,omitempty" example:"[[]]"` } type SimplePolicyTemplateResponse struct { @@ -60,8 +64,10 @@ type CreatePolicyTemplateRequest struct { ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - Rego string `json:"rego" example:"rego 코드" validate:"required"` - Libs []string `json:"libs" example:"rego 코드"` + Rego string `json:"rego" example:"rego 코드" validate:"required"` + Libs []string `json:"libs" example:"rego 코드"` + SyncKinds *[]string `json:"syncKinds,omitempty" example:"Ingress"` + SyncJson *string `json:"SyncJson,omitempty" example:"[[]]"` PermittedOrganizationIds []string `json:"permittedOrganizationIds"` } @@ -98,8 +104,10 @@ type CreatePolicyTemplateVersionRequest struct { ParametersSchema []*ParameterDef `json:"parametersSchema,omitempty"` // "type: object\nproperties: message:\n type: string\n labels:\n type: array\n items:\n type: object\n properties:\n key:\n type: string\n allowedRegex:\n type: string" - Rego string `json:"rego" example:"rego 코드" validate:"required"` - Libs []string `json:"libs" example:"rego 코드"` + Rego string `json:"rego" example:"rego 코드" validate:"required"` + Libs []string `json:"libs" example:"rego 코드"` + SyncKinds *[]string `json:"syncKinds,omitempty" example:"Ingress"` + SyncJson *string `json:"SyncJson,omitempty" example:"[[]]"` } type CreatePolicyTemplateVersionResponse struct { @@ -198,3 +206,10 @@ type UpdatePoliciesForStackRequest struct { type DeletePoliciesForStackRequest struct { PolicyIds []string `json:"policyIds"` } + +// opa gatekeeper에서 복사 +type CompactGVKEquivalenceSet struct { + Groups []string `json:"groups"` + Versions []string `json:"versions"` + Kinds []string `json:"kinds"` +} diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 21fb3510..2d8319ed 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -133,6 +133,7 @@ var errorMap = map[ErrorCode]string{ "PT_INVALID_REGO_PARSEPARAMETER": "유효하지 않은 Rego 파싱 설정입니다. Rego 파싱 설정을 확인하세요.", "PT_NOT_PERMITTED_ON_TKS_POLICY_TEMPLATE": "tks 템플릿에 대해 해당 동작을 수행할 수 없습니다.", "PT_INVALID_PARAMETER_SCHEMA": "파라미터 스키마에 잘못된 타입이 지정되었습니다.", + "PT_INVALID_SYNC": "잘못된 데이터 동기화 설정입니다. 데이터 동기화 설정을 확인하세요.", // Policy "P_CREATE_ALREADY_EXISTED_NAME": "정첵에 이미 존재하는 이름입니다.", From faf2f8e16bf48b65808c6fd33f0a8e9f67084090 Mon Sep 17 00:00:00 2001 From: donggyu Date: Tue, 14 May 2024 11:11:48 +0900 Subject: [PATCH 445/502] add cluster access control in permission obj --- internal/model/permission.go | 36 ++++++++++++++++++++++++++++++++++-- pkg/domain/permission.go | 27 --------------------------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/internal/model/permission.go b/internal/model/permission.go index 3091706a..507bc1ef 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -24,6 +24,7 @@ const ( ProjectPermission PermissionKind = "프로젝트" NotificationPermission PermissionKind = "알림" ConfigurationPermission PermissionKind = "설정" + ClusterAccessControl PermissionKind = "클러스터 접근 제어" OperationRead = "READ" OperationCreate = "CREATE" @@ -36,6 +37,7 @@ const ( MiddleDashboardKey = "DASHBOARD-DASHBOARD" TopStackKey = "STACK" MiddleStackKey = "STACK-STACK" + MiddleClusterAccessControlKey = "STACK-CLUSTER_ACCESS_CONTROL" TopPolicyKey = "POLICY" MiddlePolicyKey = "POLICY-POLICY" TopNotificationKey = "NOTIFICATION" @@ -260,6 +262,37 @@ func newStack() *Permission { }, }, }, + { + ID: uuid.New(), + Name: "클러스터 접근 제어", + Key: MiddleClusterAccessControlKey, + Children: []*Permission{ + { + ID: uuid.New(), + Name: "조회", + Key: OperationRead, + IsAllowed: helper.BoolP(false), + }, + { + ID: uuid.New(), + Name: "생성", + Key: OperationCreate, + IsAllowed: helper.BoolP(false), + }, + { + ID: uuid.New(), + Name: "수정", + Key: OperationUpdate, + IsAllowed: helper.BoolP(false), + }, + { + ID: uuid.New(), + Name: "삭제", + Key: OperationDelete, + IsAllowed: helper.BoolP(false), + }, + }, + }, }, } @@ -1053,7 +1086,7 @@ func (p *PermissionSet) SetAllowedPermissionSet() { func (p *PermissionSet) SetUserPermissionSet() { f := func(permission Permission) bool { - return permission.Name == "조회" + return permission.Key == OperationRead } edgePermissions := make([]*Permission, 0) edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) @@ -1061,7 +1094,6 @@ func (p *PermissionSet) SetUserPermissionSet() { edgePermissions = append(edgePermissions, GetEdgePermission(p.Policy, edgePermissions, &f)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) - //edgePermissions = append(edgePermissions, GetEdgePermission(p.Configuration, edgePermissions, &f)...) for _, permission := range edgePermissions { permission.IsAllowed = helper.BoolP(true) diff --git a/pkg/domain/permission.go b/pkg/domain/permission.go index 3ae4805c..640c3a11 100644 --- a/pkg/domain/permission.go +++ b/pkg/domain/permission.go @@ -9,15 +9,6 @@ type GetPermissionTemplatesResponse struct { Permissions []*TemplateResponse `json:"permissions"` } -//type PermissionTemplateResponse struct { -// Dashboard *TemplateResponse `json:"dashboard,omitempty"` -// Stack *TemplateResponse `json:"stack,omitempty"` -// Policy *TemplateResponse `json:"policy,omitempty"` -// ProjectManagement *TemplateResponse `json:"project_management,omitempty"` -// Notification *TemplateResponse `json:"notification,omitempty"` -// Configuration *TemplateResponse `json:"configuration,omitempty"` -//} - type TemplateResponse struct { Name string `json:"name"` Key string `json:"key"` @@ -30,15 +21,6 @@ type GetPermissionsByRoleIdResponse struct { Permissions []*PermissionResponse `json:"permissions"` } -//type PermissionSetResponse struct { -// Dashboard *PermissionResponse `json:"dashboard,omitempty"` -// Stack *PermissionResponse `json:"stack,omitempty"` -// Policy *PermissionResponse `json:"policy,omitempty"` -// ProjectManagement *PermissionResponse `json:"project_management,omitempty"` -// Notification *PermissionResponse `json:"notification,omitempty"` -// Configuration *PermissionResponse `json:"configuration,omitempty"` -//} - type PermissionResponse struct { ID *uuid.UUID `json:"ID,omitempty"` Name string `json:"name"` @@ -62,15 +44,6 @@ type GetUsersPermissionsResponse struct { Permissions []*MergePermissionResponse `json:"permissions"` } -//type MergedPermissionSetResponse struct { -// Dashboard *MergePermissionResponse `json:"dashboard,omitempty"` -// Stack *MergePermissionResponse `json:"stack,omitempty"` -// Policy *MergePermissionResponse `json:"policy,omitempty"` -// ProjectManagement *MergePermissionResponse `json:"project_management,omitempty"` -// Notification *MergePermissionResponse `json:"notification,omitempty"` -// Configuration *MergePermissionResponse `json:"configuration,omitempty"` -//} - type MergePermissionResponse struct { Key string `json:"key"` IsAllowed *bool `json:"isAllowed,omitempty"` From da326a007bfdf089c0eb8ad86e939860172c2edc Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 17 May 2024 14:34:07 +0900 Subject: [PATCH 446/502] add cluster admin setting on cluster creation --- internal/delivery/http/stack.go | 72 +++++++++++++++++++++++++++++++-- internal/keycloak/keycloak.go | 65 +++++++++++++++++++++++++++++ internal/usecase/permission.go | 14 ++++++- internal/usecase/stack.go | 56 ++++++++++++++++++++++++- 4 files changed, 201 insertions(+), 6 deletions(-) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 726c3253..dd4b8af6 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -16,14 +16,18 @@ import ( ) type StackHandler struct { - usecase usecase.IStackUsecase - usecasePolicy usecase.IPolicyUsecase + usecase usecase.IStackUsecase + usecasePolicy usecase.IPolicyUsecase + usecaseUser usecase.IUserUsecase + usecasePermission usecase.IPermissionUsecase } func NewStackHandler(h usecase.Usecase) *StackHandler { return &StackHandler{ - usecase: h.Stack, - usecasePolicy: h.Policy, + usecase: h.Stack, + usecasePolicy: h.Policy, + usecaseUser: h.User, + usecasePermission: h.Permission, } } @@ -69,6 +73,66 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { return } + // Binding Users for Stack according to their permissions + // First get all users in the organization + users, err := h.usecaseUser.List(r.Context(), organizationId) + if err != nil { + ErrorJSON(w, r, err) + return + } + // 1. Get all roles assigned to the user and merge the permissions + // 2. Then get the cluster admin permissions for the stack + // 3. Finally, sync the permissions with Keycloak + for _, user := range *users { + var permissionSets []*model.PermissionSet + // 1 step + for _, role := range user.Roles { + permissionSet, err := h.usecasePermission.GetPermissionSetByRoleId(r.Context(), role.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + permissionSets = append(permissionSets, permissionSet) + } + mergedPermissionSet := h.usecasePermission.MergePermissionWithOrOperator(r.Context(), permissionSets...) + + // 2 step + var targetEdgePermissions []*model.Permission + // filter function + f := func(permission model.Permission) bool { + if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { + return true + } + return false + } + edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) + + // 3 step + if len(edgePermissions) > 0 { + var err error + for _, edgePermission := range edgePermissions { + switch edgePermission.Key { + case model.OperationCreate: + err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stackId.String()+"-k8s-api", user.ID.String(), "cluster-admin-create", *edgePermission.IsAllowed) + case model.OperationRead: + err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stackId.String()+"-k8s-api", user.ID.String(), "cluster-admin-read", *edgePermission.IsAllowed) + case model.OperationUpdate: + err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stackId.String()+"-k8s-api", user.ID.String(), "cluster-admin-update", *edgePermission.IsAllowed) + case model.OperationDelete: + err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stackId.String()+"-k8s-api", user.ID.String(), "cluster-admin-delete", *edgePermission.IsAllowed) + } + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + } + } + out := domain.CreateStackResponse{ ID: stackId.String(), } diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 46cd34bd..43d26dda 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -27,6 +27,11 @@ type IKeycloak interface { DeleteRealm(ctx context.Context, organizationId string) error UpdateRealm(ctx context.Context, organizationId string, organizationConfig model.Organization) error + CreateClient(ctx context.Context, organizationId string, clientName string, clientSecret string, redirectURIs *[]string) (string, error) + CreateClientProtocolMapper(ctx context.Context, realm string, clientId string, mapper gocloak.ProtocolMapperRepresentation) (string, error) + CreateClientRole(ctx context.Context, organizationId string, clientId string, roleName string) error + DeleteClient(ctx context.Context, organizationId string, clientName string, ignoreNotFound bool) error + CreateUser(ctx context.Context, organizationId string, user *gocloak.User) (string, error) GetUser(ctx context.Context, organizationId string, userAccountId string) (*gocloak.User, error) GetUsers(ctx context.Context, organizationId string) ([]*gocloak.User, error) @@ -333,6 +338,62 @@ func (k *Keycloak) UpdateRealm(ctx context.Context, organizationId string, organ return nil } +func (k *Keycloak) CreateClient(ctx context.Context, organizationId string, clientName string, clientSecret string, redirectURIs *[]string) (string, error) { + token := k.adminCliToken + clientUUID, err := k.createDefaultClient(ctx, token.AccessToken, organizationId, clientName, clientSecret, redirectURIs) + if err != nil { + return "", err + } + + return clientUUID, nil +} + +func (k *Keycloak) DeleteClient(ctx context.Context, organizationId string, clientName string, ignoreNotFound bool) error { + token := k.adminCliToken + clients, err := k.client.GetClients(context.Background(), token.AccessToken, organizationId, gocloak.GetClientsParams{ + ClientID: &clientName, + }) + if err != nil { + log.Error(ctx, err) + return httpErrors.NewInternalServerError(err, "", "") + } + if len(clients) == 0 { + if ignoreNotFound { + return nil + } + return httpErrors.NewNotFoundError(fmt.Errorf("client not found"), "", "") + } + err = k.client.DeleteClient(context.Background(), token.AccessToken, organizationId, *clients[0].ID) + if err != nil { + return err + } + + return nil +} + +func (k *Keycloak) CreateClientProtocolMapper(ctx context.Context, realm string, clientId string, mapper gocloak.ProtocolMapperRepresentation) (string, error) { + token := k.adminCliToken + mapperId, err := k.client.CreateClientProtocolMapper(context.Background(), token.AccessToken, realm, clientId, mapper) + if err != nil { + return "", err + } + + return mapperId, nil +} + +func (k *Keycloak) CreateClientRole(ctx context.Context, organizationId string, clientId string, roleName string) error { + token := k.adminCliToken + role := gocloak.Role{ + Name: gocloak.StringP(roleName), + } + _, err := k.client.CreateClientRole(context.Background(), token.AccessToken, organizationId, clientId, role) + if err != nil { + return err + } + + return nil +} + func (k *Keycloak) DeleteRealm(ctx context.Context, organizationId string) error { token := k.adminCliToken err := k.client.DeleteRealm(context.Background(), token.AccessToken, organizationId) @@ -839,6 +900,10 @@ func (k *Keycloak) createDefaultClient(ctx context.Context, accessToken string, log.Error(ctx, "Getting Client is failed", err) return "", err } + if clientSecret == "" { + return id, nil + } + client.Secret = gocloak.StringP(clientSecret) err = k.client.UpdateClient(context.Background(), accessToken, realm, *client) if err != nil { diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index 532e723c..2ccf2a4a 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -3,6 +3,7 @@ package usecase import ( "context" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/keycloak" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/repository" "sort" @@ -17,15 +18,18 @@ type IPermissionUsecase interface { GetUserPermissionSet(ctx context.Context) *model.PermissionSet UpdatePermission(ctx context.Context, permission *model.Permission) error MergePermissionWithOrOperator(ctx context.Context, permissionSet ...*model.PermissionSet) *model.PermissionSet + SyncKeycloakWithClusterAdminPermission(ctx context.Context, organizationId string, clientName string, userId string, roleName string, boolean bool) error } type PermissionUsecase struct { repo repository.IPermissionRepository + kc keycloak.IKeycloak } -func NewPermissionUsecase(repo repository.Repository) *PermissionUsecase { +func NewPermissionUsecase(repo repository.Repository, kc keycloak.IKeycloak) *PermissionUsecase { return &PermissionUsecase{ repo: repo.Permission, + kc: kc, } } @@ -192,3 +196,11 @@ func (p PermissionUsecase) sortPermissionRecursive(permission *model.Permission) } } } + +func (p PermissionUsecase) SyncKeycloakWithClusterAdminPermission(ctx context.Context, organizationId string, clientName string, userId string, roleName string, boolean bool) error { + if boolean { + return p.kc.AssignClientRoleToUser(ctx, organizationId, userId, clientName, roleName) + } else { + return p.kc.UnassignClientRoleToUser(ctx, organizationId, userId, clientName, roleName) + } +} diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index e2f576cf..43380301 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -3,6 +3,8 @@ package usecase import ( "context" "fmt" + "github.com/Nerzal/gocloak/v13" + "github.com/openinfradev/tks-api/internal/keycloak" "sort" "strings" "time" @@ -47,9 +49,10 @@ type StackUsecase struct { appServeAppRepo repository.IAppServeAppRepository argo argowf.ArgoClient dashbordUsecase IDashboardUsecase + kc keycloak.IKeycloak } -func NewStackUsecase(r repository.Repository, argoClient argowf.ArgoClient, dashbordUsecase IDashboardUsecase) IStackUsecase { +func NewStackUsecase(r repository.Repository, argoClient argowf.ArgoClient, dashbordUsecase IDashboardUsecase, kc keycloak.IKeycloak) IStackUsecase { return &StackUsecase{ clusterRepo: r.Cluster, appGroupRepo: r.AppGroup, @@ -59,6 +62,7 @@ func NewStackUsecase(r repository.Repository, argoClient argowf.ArgoClient, dash appServeAppRepo: r.AppServeApp, argo: argoClient, dashbordUsecase: dashbordUsecase, + kc: kc, } } @@ -174,6 +178,56 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom } } + // keycloak setting + log.Debugf(ctx, "Create keycloak client for %s", dto.ID) + // Create keycloak client + clientUUID, err := u.kc.CreateClient(ctx, dto.OrganizationId, dto.ID.String()+"-k8s-api", "", nil) + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client for %s", dto.ID) + return "", err + } + // Create keycloak client protocol mapper + _, err = u.kc.CreateClientProtocolMapper(ctx, dto.OrganizationId, clientUUID, gocloak.ProtocolMapperRepresentation{ + Name: gocloak.StringP(dto.ID.String() + "k8s-api"), + Protocol: gocloak.StringP("openid-connect"), + ProtocolMapper: gocloak.StringP("oidc-usermodel-client-role-mapper"), + ConsentRequired: gocloak.BoolP(false), + Config: &map[string]string{ + "usermodel.clientRoleMapping.clientId": dto.ID.String(), + "claim.name": "k8s-role-mapper", + "access.token.claim": "false", + "id.token.claim": "true", + "userinfo.token.claim": "true", + "multivalued": "true", + "jsonType.label": "String", + }, + }) + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client protocol mapper for %s", dto.ID) + return "", err + } + // Create keycloak client role + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-create") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-create", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-read") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-read", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-update") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-update", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-delete") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-delete", dto.ID) + return "", err + } + return dto.ID, nil } From a7e96226dea6e6d7daee747b8659f0c760ce07dd Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 17 May 2024 15:19:40 +0900 Subject: [PATCH 447/502] add cluster admin setting on apppending/removing on the role --- internal/delivery/http/role.go | 130 +++++++++++++++++++++++++++++++- internal/delivery/http/stack.go | 6 +- 2 files changed, 129 insertions(+), 7 deletions(-) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 1ff872be..fccb5259 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -35,6 +35,7 @@ type RoleHandler struct { roleUsecase usecase.IRoleUsecase userUsecase usecase.IUserUsecase permissionUsecase usecase.IPermissionUsecase + stackUsecease usecase.IStackUsecase } func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { @@ -42,6 +43,7 @@ func NewRoleHandler(usecase usecase.Usecase) *RoleHandler { roleUsecase: usecase.Role, permissionUsecase: usecase.Permission, userUsecase: usecase.User, + stackUsecease: usecase.Stack, } } @@ -588,8 +590,8 @@ func (h RoleHandler) AppendUsersToRole(w http.ResponseWriter, r *http.Request) { return } - for _, user := range input.Users { - originUser, err := h.userUsecase.Get(r.Context(), user) + for _, userUuid := range input.Users { + originUser, err := h.userUsecase.Get(r.Context(), userUuid) if err != nil { ErrorJSON(w, r, err) return @@ -607,6 +609,66 @@ func (h RoleHandler) AppendUsersToRole(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, err) return } + + // Binding Users for Stack according to their permissions + // 1-step + // Merge the permissions of the userUuid + var permissionSets []*model.PermissionSet + for _, role := range originUser.Roles { + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + permissionSets = append(permissionSets, permissionSet) + } + mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) + + // 2-step + // Then get the cluster admin permissions for the stack + var targetEdgePermissions []*model.Permission + // filter function + f := func(permission model.Permission) bool { + if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { + return true + } + return false + } + edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) + + // 3-step + // Get all the stacks in the organization + // And sync the permissions with Keycloak + stacks, err := h.stackUsecease.Fetch(r.Context(), organizationId, nil) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for _, stack := range stacks { + if len(edgePermissions) > 0 { + var err error + for _, edgePermission := range edgePermissions { + switch edgePermission.Key { + case model.OperationCreate: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-create", *edgePermission.IsAllowed) + case model.OperationRead: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-read", *edgePermission.IsAllowed) + case model.OperationUpdate: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-update", *edgePermission.IsAllowed) + case model.OperationDelete: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-delete", *edgePermission.IsAllowed) + } + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + } + } } // response @@ -651,8 +713,8 @@ func (h RoleHandler) RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) return } - for _, user := range input.Users { - originUser, err := h.userUsecase.Get(r.Context(), user) + for _, userUuid := range input.Users { + originUser, err := h.userUsecase.Get(r.Context(), userUuid) if err != nil { ErrorJSON(w, r, err) return @@ -675,6 +737,66 @@ func (h RoleHandler) RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) ErrorJSON(w, r, err) return } + + // Binding Users for Stack according to their permissions + // 1-step + // Merge the permissions of the userUuid + var permissionSets []*model.PermissionSet + for _, role := range originUser.Roles { + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + permissionSets = append(permissionSets, permissionSet) + } + mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) + + // 2-step + // Then get the cluster admin permissions for the stack + var targetEdgePermissions []*model.Permission + // filter function + f := func(permission model.Permission) bool { + if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { + return true + } + return false + } + edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) + + // 3-step + // Get all the stacks in the organization + // And sync the permissions with Keycloak + stacks, err := h.stackUsecease.Fetch(r.Context(), organizationId, nil) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for _, stack := range stacks { + if len(edgePermissions) > 0 { + var err error + for _, edgePermission := range edgePermissions { + switch edgePermission.Key { + case model.OperationCreate: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-create", *edgePermission.IsAllowed) + case model.OperationRead: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-read", *edgePermission.IsAllowed) + case model.OperationUpdate: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-update", *edgePermission.IsAllowed) + case model.OperationDelete: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, + stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-delete", *edgePermission.IsAllowed) + } + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + } + } + } } // response diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index dd4b8af6..fe8302b2 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -85,7 +85,7 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { // 3. Finally, sync the permissions with Keycloak for _, user := range *users { var permissionSets []*model.PermissionSet - // 1 step + // 1-step for _, role := range user.Roles { permissionSet, err := h.usecasePermission.GetPermissionSetByRoleId(r.Context(), role.ID) if err != nil { @@ -96,7 +96,7 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { } mergedPermissionSet := h.usecasePermission.MergePermissionWithOrOperator(r.Context(), permissionSets...) - // 2 step + // 2-step var targetEdgePermissions []*model.Permission // filter function f := func(permission model.Permission) bool { @@ -107,7 +107,7 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { } edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) - // 3 step + // 3-step if len(edgePermissions) > 0 { var err error for _, edgePermission := range edgePermissions { From 4320bbce6dd55d424d18bf93555086ca549a98e5 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 17 May 2024 15:46:21 +0900 Subject: [PATCH 448/502] add cluster admin setting on removing on the role --- internal/delivery/http/role.go | 244 +++++++++++++++++++-------------- 1 file changed, 140 insertions(+), 104 deletions(-) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index fccb5259..eb7a5ba8 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -239,12 +239,34 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { organizationId = v } + affectedUsers, err := h.userUsecase.ListUsersByRole(r.Context(), organizationId, roleId, nil) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + // delete role if err := h.roleUsecase.DeleteTksRole(r.Context(), organizationId, roleId); err != nil { ErrorJSON(w, r, err) return } + // Sync ClusterAdmin Permission to Keycloak + for _, user := range *affectedUsers { + stacks, err := h.stackUsecease.Fetch(r.Context(), organizationId, nil) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + stackIds := make([]string, 0) + for _, stack := range stacks { + stackIds = append(stackIds, stack.ID.String()) + } + u := make([]model.User, 0) + u = append(u, user) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, u) + } + // response ResponseJSON(w, r, http.StatusOK, nil) } @@ -384,6 +406,25 @@ func convertModelToEndpointResponse(_ context.Context, endpoint *model.Endpoint) // @Router /organizations/{organizationId}/roles/{roleId}/permissions [put] // @Security JWT func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Request) { + // path parameter + vars := mux.Vars(r) + + var organizationId string + if v, ok := vars["organizationId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + organizationId = v + } + + var roleId string + if v, ok := vars["roleId"]; !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(nil, "", "")) + return + } else { + roleId = v + } + // request input := domain.UpdatePermissionsByRoleIdRequest{} err := UnmarshalRequestInput(r, &input) @@ -392,6 +433,8 @@ func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Re return } + var clusterAdminPermissionChanged bool + for _, permissionResponse := range input.Permissions { var permission model.Permission permission.ID = permissionResponse.ID @@ -401,6 +444,33 @@ func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Re ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } + + if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { + clusterAdminPermissionChanged = true + } + } + + // Sync ClusterAdmin Permission to Keycloak + if clusterAdminPermissionChanged { + users, err := h.userUsecase.ListUsersByRole(r.Context(), organizationId, roleId, nil) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + for _, user := range *users { + stacks, err := h.stackUsecease.Fetch(r.Context(), organizationId, nil) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + stackIds := make([]string, 0) + for _, stack := range stacks { + stackIds = append(stackIds, stack.ID.String()) + } + u := make([]model.User, 0) + u = append(u, user) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, u) + } } ResponseJSON(w, r, http.StatusOK, nil) @@ -610,65 +680,19 @@ func (h RoleHandler) AppendUsersToRole(w http.ResponseWriter, r *http.Request) { return } - // Binding Users for Stack according to their permissions - // 1-step - // Merge the permissions of the userUuid - var permissionSets []*model.PermissionSet - for _, role := range originUser.Roles { - permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - permissionSets = append(permissionSets, permissionSet) - } - mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) - - // 2-step - // Then get the cluster admin permissions for the stack - var targetEdgePermissions []*model.Permission - // filter function - f := func(permission model.Permission) bool { - if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { - return true - } - return false - } - edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) - - // 3-step - // Get all the stacks in the organization - // And sync the permissions with Keycloak + // Sync ClusterAdmin Permission to Keycloak stacks, err := h.stackUsecease.Fetch(r.Context(), organizationId, nil) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } + stackIds := make([]string, 0) for _, stack := range stacks { - if len(edgePermissions) > 0 { - var err error - for _, edgePermission := range edgePermissions { - switch edgePermission.Key { - case model.OperationCreate: - err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-create", *edgePermission.IsAllowed) - case model.OperationRead: - err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-read", *edgePermission.IsAllowed) - case model.OperationUpdate: - err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-update", *edgePermission.IsAllowed) - case model.OperationDelete: - err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-delete", *edgePermission.IsAllowed) - } - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - } - } + stackIds = append(stackIds, stack.ID.String()) } + users := make([]model.User, 0) + users = append(users, *originUser) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, users) } // response @@ -738,65 +762,19 @@ func (h RoleHandler) RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) return } - // Binding Users for Stack according to their permissions - // 1-step - // Merge the permissions of the userUuid - var permissionSets []*model.PermissionSet - for _, role := range originUser.Roles { - permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(r.Context(), role.ID) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - permissionSets = append(permissionSets, permissionSet) - } - mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(r.Context(), permissionSets...) - - // 2-step - // Then get the cluster admin permissions for the stack - var targetEdgePermissions []*model.Permission - // filter function - f := func(permission model.Permission) bool { - if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { - return true - } - return false - } - edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) - - // 3-step - // Get all the stacks in the organization - // And sync the permissions with Keycloak + // Sync ClusterAdmin Permission to Keycloak stacks, err := h.stackUsecease.Fetch(r.Context(), organizationId, nil) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) return } + stackIds := make([]string, 0) for _, stack := range stacks { - if len(edgePermissions) > 0 { - var err error - for _, edgePermission := range edgePermissions { - switch edgePermission.Key { - case model.OperationCreate: - err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-create", *edgePermission.IsAllowed) - case model.OperationRead: - err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-read", *edgePermission.IsAllowed) - case model.OperationUpdate: - err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-update", *edgePermission.IsAllowed) - case model.OperationDelete: - err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stack.ID.String()+"-k8s-api", userUuid.String(), "cluster-admin-delete", *edgePermission.IsAllowed) - } - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - } - } + stackIds = append(stackIds, stack.ID.String()) } + users := make([]model.User, 0) + users = append(users, *originUser) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, users) } // response @@ -862,3 +840,61 @@ func (h RoleHandler) GetUsersInRoleId(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } + +// syncKeycloakWithClusterAdminPermission sync the permissions with Keycloak +func (h RoleHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context, organizationId string, clusterIds []string, users []model.User) error { + for _, user := range users { + // 1-step + // Merge the permissions of the userUuid + var permissionSets []*model.PermissionSet + for _, role := range user.Roles { + permissionSet, err := h.permissionUsecase.GetPermissionSetByRoleId(ctx, role.ID) + if err != nil { + return err + } + permissionSets = append(permissionSets, permissionSet) + } + mergedPermissionSet := h.permissionUsecase.MergePermissionWithOrOperator(ctx, permissionSets...) + + // 2-step + // Then get the cluster admin permissions for the stack + var targetEdgePermissions []*model.Permission + // filter function + f := func(permission model.Permission) bool { + if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { + return true + } + return false + } + edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) + + // 3-step + // sync the permissions with Keycloak + for _, clusterId := range clusterIds { + if len(edgePermissions) > 0 { + var err error + for _, edgePermission := range edgePermissions { + switch edgePermission.Key { + case model.OperationCreate: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-create", *edgePermission.IsAllowed) + case model.OperationRead: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-read", *edgePermission.IsAllowed) + case model.OperationUpdate: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-update", *edgePermission.IsAllowed) + case model.OperationDelete: + err = h.permissionUsecase.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-delete", *edgePermission.IsAllowed) + } + if err != nil { + return err + } + } + } + } + } + + return nil +} From 3b1f78e8507ef8e10b93cca84f6e4bb4dbc69395 Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 17 May 2024 15:59:58 +0900 Subject: [PATCH 449/502] add cluster admin setting on editting user role --- internal/delivery/http/role.go | 19 ++--- internal/delivery/http/stack.go | 119 ++++++++++++++++++-------------- internal/delivery/http/user.go | 79 +++++++++++++++++++++ 3 files changed, 153 insertions(+), 64 deletions(-) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index eb7a5ba8..3958cb0c 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -262,9 +262,7 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { for _, stack := range stacks { stackIds = append(stackIds, stack.ID.String()) } - u := make([]model.User, 0) - u = append(u, user) - err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, u) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{user}) } // response @@ -467,9 +465,7 @@ func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Re for _, stack := range stacks { stackIds = append(stackIds, stack.ID.String()) } - u := make([]model.User, 0) - u = append(u, user) - err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, u) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{user}) } } @@ -690,9 +686,7 @@ func (h RoleHandler) AppendUsersToRole(w http.ResponseWriter, r *http.Request) { for _, stack := range stacks { stackIds = append(stackIds, stack.ID.String()) } - users := make([]model.User, 0) - users = append(users, *originUser) - err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, users) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{*originUser}) } // response @@ -772,9 +766,7 @@ func (h RoleHandler) RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) for _, stack := range stacks { stackIds = append(stackIds, stack.ID.String()) } - users := make([]model.User, 0) - users = append(users, *originUser) - err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, users) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{*originUser}) } // response @@ -842,6 +834,9 @@ func (h RoleHandler) GetUsersInRoleId(w http.ResponseWriter, r *http.Request) { } // syncKeycloakWithClusterAdminPermission sync the permissions with Keycloak +// 1. Get all roles assigned to the user and merge the permissions +// 2. Then get the cluster admin permissions for the stack +// 3. Finally, sync the permissions with Keycloak func (h RoleHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context, organizationId string, clusterIds []string, users []model.User) error { for _, user := range users { // 1-step diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index fe8302b2..dd45c306 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -1,6 +1,7 @@ package http import ( + "context" "encoding/json" "fmt" "net/http" @@ -73,64 +74,17 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { return } - // Binding Users for Stack according to their permissions + // Sync ClusterAdmin Permission to Keycloak // First get all users in the organization users, err := h.usecaseUser.List(r.Context(), organizationId) if err != nil { ErrorJSON(w, r, err) return } - // 1. Get all roles assigned to the user and merge the permissions - // 2. Then get the cluster admin permissions for the stack - // 3. Finally, sync the permissions with Keycloak - for _, user := range *users { - var permissionSets []*model.PermissionSet - // 1-step - for _, role := range user.Roles { - permissionSet, err := h.usecasePermission.GetPermissionSetByRoleId(r.Context(), role.ID) - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - permissionSets = append(permissionSets, permissionSet) - } - mergedPermissionSet := h.usecasePermission.MergePermissionWithOrOperator(r.Context(), permissionSets...) - - // 2-step - var targetEdgePermissions []*model.Permission - // filter function - f := func(permission model.Permission) bool { - if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { - return true - } - return false - } - edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) - - // 3-step - if len(edgePermissions) > 0 { - var err error - for _, edgePermission := range edgePermissions { - switch edgePermission.Key { - case model.OperationCreate: - err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stackId.String()+"-k8s-api", user.ID.String(), "cluster-admin-create", *edgePermission.IsAllowed) - case model.OperationRead: - err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stackId.String()+"-k8s-api", user.ID.String(), "cluster-admin-read", *edgePermission.IsAllowed) - case model.OperationUpdate: - err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stackId.String()+"-k8s-api", user.ID.String(), "cluster-admin-update", *edgePermission.IsAllowed) - case model.OperationDelete: - err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(r.Context(), organizationId, - stackId.String()+"-k8s-api", user.ID.String(), "cluster-admin-delete", *edgePermission.IsAllowed) - } - if err != nil { - ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) - return - } - } - } + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, []string{stackId.String()}, *users) + if err != nil { + ErrorJSON(w, r, err) + return } out := domain.CreateStackResponse{ @@ -543,3 +497,64 @@ func (h *StackHandler) DeleteFavorite(w http.ResponseWriter, r *http.Request) { } ResponseJSON(w, r, http.StatusOK, nil) } + +// syncKeycloakWithClusterAdminPermission sync the permissions with Keycloak +// 1. Get all roles assigned to the user and merge the permissions +// 2. Then get the cluster admin permissions for the stack +// 3. Finally, sync the permissions with Keycloak +func (h StackHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context, organizationId string, clusterIds []string, users []model.User) error { + for _, user := range users { + // 1-step + // Merge the permissions of the userUuid + var permissionSets []*model.PermissionSet + for _, role := range user.Roles { + permissionSet, err := h.usecasePermission.GetPermissionSetByRoleId(ctx, role.ID) + if err != nil { + return err + } + permissionSets = append(permissionSets, permissionSet) + } + mergedPermissionSet := h.usecasePermission.MergePermissionWithOrOperator(ctx, permissionSets...) + + // 2-step + // Then get the cluster admin permissions for the stack + var targetEdgePermissions []*model.Permission + // filter function + f := func(permission model.Permission) bool { + if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { + return true + } + return false + } + edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) + + // 3-step + // sync the permissions with Keycloak + for _, clusterId := range clusterIds { + if len(edgePermissions) > 0 { + var err error + for _, edgePermission := range edgePermissions { + switch edgePermission.Key { + case model.OperationCreate: + err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-create", *edgePermission.IsAllowed) + case model.OperationRead: + err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-read", *edgePermission.IsAllowed) + case model.OperationUpdate: + err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-update", *edgePermission.IsAllowed) + case model.OperationDelete: + err = h.usecasePermission.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-delete", *edgePermission.IsAllowed) + } + if err != nil { + return err + } + } + } + } + } + + return nil +} diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index d106b236..abd088b1 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -45,6 +45,7 @@ type IUserHandler interface { type UserHandler struct { usecase usecase.IUserUsecase authUsecase usecase.IAuthUsecase + stackUsecase usecase.IStackUsecase roleUsecase usecase.IRoleUsecase permissionUsecase usecase.IPermissionUsecase } @@ -55,6 +56,7 @@ func NewUserHandler(h usecase.Usecase) IUserHandler { authUsecase: h.Auth, roleUsecase: h.Role, permissionUsecase: h.Permission, + stackUsecase: h.Stack, } } @@ -348,6 +350,22 @@ func (u UserHandler) Update(w http.ResponseWriter, r *http.Request) { return } + // Sync ClusterAdmin Permission to Keycloak + stacks, err := u.stackUsecase.Fetch(r.Context(), organizationId, nil) + if err != nil { + ErrorJSON(w, r, err) + return + } + stackIds := make([]string, 0) + for _, stack := range stacks { + stackIds = append(stackIds, stack.ID.String()) + } + err = u.syncKeycloakWithClusterAdminPermission(ctx, organizationId, stackIds, []model.User{*resUser}) + if err != nil { + ErrorJSON(w, r, err) + return + } + var out domain.UpdateUserResponse if err = serializer.Map(r.Context(), *resUser, &out.User); err != nil { log.Error(r.Context(), err) @@ -1085,3 +1103,64 @@ func (u UserHandler) Admin_Update(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } + +// syncKeycloakWithClusterAdminPermission sync the permissions with Keycloak +// 1. Get all roles assigned to the user and merge the permissions +// 2. Then get the cluster admin permissions for the stack +// 3. Finally, sync the permissions with Keycloak +func (u UserHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context, organizationId string, clusterIds []string, users []model.User) error { + for _, user := range users { + // 1-step + // Merge the permissions of the userUuid + var permissionSets []*model.PermissionSet + for _, role := range user.Roles { + permissionSet, err := u.permissionUsecase.GetPermissionSetByRoleId(ctx, role.ID) + if err != nil { + return err + } + permissionSets = append(permissionSets, permissionSet) + } + mergedPermissionSet := u.permissionUsecase.MergePermissionWithOrOperator(ctx, permissionSets...) + + // 2-step + // Then get the cluster admin permissions for the stack + var targetEdgePermissions []*model.Permission + // filter function + f := func(permission model.Permission) bool { + if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { + return true + } + return false + } + edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) + + // 3-step + // sync the permissions with Keycloak + for _, clusterId := range clusterIds { + if len(edgePermissions) > 0 { + var err error + for _, edgePermission := range edgePermissions { + switch edgePermission.Key { + case model.OperationCreate: + err = u.permissionUsecase.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-create", *edgePermission.IsAllowed) + case model.OperationRead: + err = u.permissionUsecase.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-read", *edgePermission.IsAllowed) + case model.OperationUpdate: + err = u.permissionUsecase.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-update", *edgePermission.IsAllowed) + case model.OperationDelete: + err = u.permissionUsecase.SyncKeycloakWithClusterAdminPermission(ctx, organizationId, + clusterId+"-k8s-api", user.ID.String(), "cluster-admin-delete", *edgePermission.IsAllowed) + } + if err != nil { + return err + } + } + } + } + } + + return nil +} From c89a1a90dc5de7186f045276332702b12cb16a6b Mon Sep 17 00:00:00 2001 From: donggyu Date: Fri, 17 May 2024 16:21:40 +0900 Subject: [PATCH 450/502] bugfix. --- internal/delivery/http/role.go | 45 ++++++++++++++++++++------ internal/delivery/http/stack.go | 12 +++---- internal/delivery/http/user.go | 45 +++++++++++++++++++++----- internal/keycloak/keycloak.go | 19 +++++++++-- internal/model/permission.go | 12 +++---- internal/route/route.go | 6 ++-- internal/usecase/cluster.go | 56 ++++++++++++++++++++++++++++++++- internal/usecase/permission.go | 1 + internal/usecase/stack.go | 12 +++++-- 9 files changed, 170 insertions(+), 38 deletions(-) diff --git a/internal/delivery/http/role.go b/internal/delivery/http/role.go index 3958cb0c..d0bc9fcb 100644 --- a/internal/delivery/http/role.go +++ b/internal/delivery/http/role.go @@ -252,7 +252,13 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { } // Sync ClusterAdmin Permission to Keycloak - for _, user := range *affectedUsers { + for _, affectedUser := range *affectedUsers { + // remove role from user object + user, err := h.userUsecase.Get(r.Context(), affectedUser.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } stacks, err := h.stackUsecease.Fetch(r.Context(), organizationId, nil) if err != nil { ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) @@ -262,7 +268,11 @@ func (h RoleHandler) DeleteTksRole(w http.ResponseWriter, r *http.Request) { for _, stack := range stacks { stackIds = append(stackIds, stack.ID.String()) } - err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{user}) + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{*user}) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } } // response @@ -443,7 +453,12 @@ func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Re return } - if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { + updatedPermission, err := h.permissionUsecase.GetPermission(r.Context(), permission.ID) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + if updatedPermission.Parent != nil && updatedPermission.Parent.Key == model.MiddleClusterAccessControlKey { clusterAdminPermissionChanged = true } } @@ -466,6 +481,10 @@ func (h RoleHandler) UpdatePermissionsByRoleId(w http.ResponseWriter, r *http.Re stackIds = append(stackIds, stack.ID.String()) } err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{user}) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } } } @@ -687,6 +706,10 @@ func (h RoleHandler) AppendUsersToRole(w http.ResponseWriter, r *http.Request) { stackIds = append(stackIds, stack.ID.String()) } err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{*originUser}) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } } // response @@ -767,6 +790,10 @@ func (h RoleHandler) RemoveUsersFromRole(w http.ResponseWriter, r *http.Request) stackIds = append(stackIds, stack.ID.String()) } err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{*originUser}) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } } // response @@ -854,14 +881,14 @@ func (h RoleHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context, // 2-step // Then get the cluster admin permissions for the stack var targetEdgePermissions []*model.Permission - // filter function - f := func(permission model.Permission) bool { - if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { - return true + + var targetPermission *model.Permission + for _, permission := range mergedPermissionSet.Stack.Children { + if permission.Key == model.MiddleClusterAccessControlKey { + targetPermission = permission } - return false } - edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) + edgePermissions := model.GetEdgePermission(targetPermission, targetEdgePermissions, nil) // 3-step // sync the permissions with Keycloak diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index dd45c306..3a3c5423 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -519,14 +519,14 @@ func (h StackHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context // 2-step // Then get the cluster admin permissions for the stack var targetEdgePermissions []*model.Permission - // filter function - f := func(permission model.Permission) bool { - if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { - return true + + var targetPermission *model.Permission + for _, permission := range mergedPermissionSet.Stack.Children { + if permission.Key == model.MiddleClusterAccessControlKey { + targetPermission = permission } - return false } - edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) + edgePermissions := model.GetEdgePermission(targetPermission, targetEdgePermissions, nil) // 3-step // sync the permissions with Keycloak diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index abd088b1..ea31c7ed 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -119,6 +119,22 @@ func (u UserHandler) Create(w http.ResponseWriter, r *http.Request) { return } + // Sync ClusterAdmin Permission to Keycloak + stacks, err := u.stackUsecase.Fetch(r.Context(), organizationId, nil) + if err != nil { + ErrorJSON(w, r, err) + return + } + stackIds := make([]string, 0) + for _, stack := range stacks { + stackIds = append(stackIds, stack.ID.String()) + } + err = u.syncKeycloakWithClusterAdminPermission(ctx, organizationId, stackIds, []model.User{*resUser}) + if err != nil { + ErrorJSON(w, r, err) + return + } + var out domain.CreateUserResponse if err = serializer.Map(r.Context(), *resUser, &out.User); err != nil { log.Error(r.Context(), err) @@ -941,6 +957,22 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { return } + // Sync ClusterAdmin Permission to Keycloak + stacks, err := u.stackUsecase.Fetch(r.Context(), organizationId, nil) + if err != nil { + ErrorJSON(w, r, err) + return + } + stackIds := make([]string, 0) + for _, stack := range stacks { + stackIds = append(stackIds, stack.ID.String()) + } + err = u.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{*resUser}) + if err != nil { + ErrorJSON(w, r, err) + return + } + var out domain.Admin_CreateUserResponse out.ID = resUser.ID.String() @@ -1125,15 +1157,14 @@ func (u UserHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context, // 2-step // Then get the cluster admin permissions for the stack var targetEdgePermissions []*model.Permission - // filter function - f := func(permission model.Permission) bool { - if permission.Parent != nil && permission.Parent.Key == model.MiddleClusterAccessControlKey { - return true + + var targetPermission *model.Permission + for _, permission := range mergedPermissionSet.Stack.Children { + if permission.Key == model.MiddleClusterAccessControlKey { + targetPermission = permission } - return false } - edgePermissions := model.GetEdgePermission(mergedPermissionSet.Stack, targetEdgePermissions, &f) - + edgePermissions := model.GetEdgePermission(targetPermission, targetEdgePermissions, nil) // 3-step // sync the permissions with Keycloak for _, clusterId := range clusterIds { diff --git a/internal/keycloak/keycloak.go b/internal/keycloak/keycloak.go index 43d26dda..34d614b9 100644 --- a/internal/keycloak/keycloak.go +++ b/internal/keycloak/keycloak.go @@ -884,6 +884,22 @@ func (k *Keycloak) createClientProtocolMapper(ctx context.Context, accessToken s func (k *Keycloak) createDefaultClient(ctx context.Context, accessToken string, realm string, clientId string, clientSecret string, redirectURIs *[]string) (string, error) { + if clientSecret == "" { + id, err := k.client.CreateClient(context.Background(), accessToken, realm, gocloak.Client{ + ClientID: gocloak.StringP(clientId), + DirectAccessGrantsEnabled: gocloak.BoolP(true), + Enabled: gocloak.BoolP(true), + RedirectURIs: redirectURIs, + PublicClient: gocloak.BoolP(true), + }) + if err != nil { + log.Error(ctx, "Creating Client is failed", err) + return "", err + } + + return id, nil + } + id, err := k.client.CreateClient(context.Background(), accessToken, realm, gocloak.Client{ ClientID: gocloak.StringP(clientId), DirectAccessGrantsEnabled: gocloak.BoolP(true), @@ -900,9 +916,6 @@ func (k *Keycloak) createDefaultClient(ctx context.Context, accessToken string, log.Error(ctx, "Getting Client is failed", err) return "", err } - if clientSecret == "" { - return id, nil - } client.Secret = gocloak.StringP(clientSecret) err = k.client.UpdateClient(context.Background(), accessToken, realm, *client) diff --git a/internal/model/permission.go b/internal/model/permission.go index 507bc1ef..be5e3abe 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -113,9 +113,9 @@ func NewAdminPermissionSet() *PermissionSet { } } -func GetEdgePermission(root *Permission, edgePermissions []*Permission, f *func(permission Permission) bool) []*Permission { +func GetEdgePermission(root *Permission, edgePermissions []*Permission, f func(permission Permission) bool) []*Permission { if root.Children == nil || len(root.Children) == 0 { - if f != nil && !(*f)(*root) { + if f != nil && !f(*root) { return edgePermissions } return append(edgePermissions, root) @@ -1090,10 +1090,10 @@ func (p *PermissionSet) SetUserPermissionSet() { } edgePermissions := make([]*Permission, 0) edgePermissions = append(edgePermissions, GetEdgePermission(p.Dashboard, edgePermissions, nil)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Policy, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, &f)...) - edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, &f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Stack, edgePermissions, f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Policy, edgePermissions, f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.ProjectManagement, edgePermissions, f)...) + edgePermissions = append(edgePermissions, GetEdgePermission(p.Notification, edgePermissions, f)...) for _, permission := range edgePermissions { permission.IsAllowed = helper.BoolP(true) diff --git a/internal/route/route.go b/internal/route/route.go index e9edbf12..91073585 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -66,7 +66,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa usecaseFactory := usecase.Usecase{ Auth: usecase.NewAuthUsecase(repoFactory, kc), User: usecase.NewUserUsecase(repoFactory, kc), - Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache), + Cluster: usecase.NewClusterUsecase(repoFactory, argoClient, cache, kc), Organization: usecase.NewOrganizationUsecase(repoFactory, argoClient, kc), AppGroup: usecase.NewAppGroupUsecase(repoFactory, argoClient), AppServeApp: usecase.NewAppServeAppUsecase(repoFactory, argoClient), @@ -76,11 +76,11 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa SystemNotification: usecase.NewSystemNotificationUsecase(repoFactory), SystemNotificationTemplate: usecase.NewSystemNotificationTemplateUsecase(repoFactory), SystemNotificationRule: usecase.NewSystemNotificationRuleUsecase(repoFactory), - Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache)), + Stack: usecase.NewStackUsecase(repoFactory, argoClient, usecase.NewDashboardUsecase(repoFactory, cache), kc), Project: usecase.NewProjectUsecase(repoFactory, kc, argoClient), Audit: usecase.NewAuditUsecase(repoFactory), Role: usecase.NewRoleUsecase(repoFactory, kc), - Permission: usecase.NewPermissionUsecase(repoFactory), + Permission: usecase.NewPermissionUsecase(repoFactory, kc), PolicyTemplate: usecase.NewPolicyTemplateUsecase(repoFactory), Policy: usecase.NewPolicyUsecase(repoFactory), } diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index ce7574e8..3d64f4d8 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -5,6 +5,8 @@ import ( "encoding/base64" "encoding/json" "fmt" + "github.com/Nerzal/gocloak/v13" + "github.com/openinfradev/tks-api/internal/keycloak" "strings" "time" @@ -53,9 +55,10 @@ type ClusterUsecase struct { organizationRepo repository.IOrganizationRepository argo argowf.ArgoClient cache *gcache.Cache + kc keycloak.IKeycloak } -func NewClusterUsecase(r repository.Repository, argoClient argowf.ArgoClient, cache *gcache.Cache) IClusterUsecase { +func NewClusterUsecase(r repository.Repository, argoClient argowf.ArgoClient, cache *gcache.Cache, kc keycloak.IKeycloak) IClusterUsecase { return &ClusterUsecase{ repo: r.Cluster, appGroupRepo: r.AppGroup, @@ -64,6 +67,7 @@ func NewClusterUsecase(r repository.Repository, argoClient argowf.ArgoClient, ca organizationRepo: r.Organization, argo: argoClient, cache: cache, + kc: kc, } } @@ -274,6 +278,56 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster return "", errors.Wrap(err, "Failed to initialize status") } + // keycloak setting + log.Debugf(ctx, "Create keycloak client for %s", dto.ID) + // Create keycloak client + clientUUID, err := u.kc.CreateClient(ctx, dto.OrganizationId, dto.ID.String()+"-k8s-api", "", nil) + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client for %s", dto.ID) + return "", err + } + // Create keycloak client protocol mapper + _, err = u.kc.CreateClientProtocolMapper(ctx, dto.OrganizationId, clientUUID, gocloak.ProtocolMapperRepresentation{ + Name: gocloak.StringP("k8s-role-mapper"), + Protocol: gocloak.StringP("openid-connect"), + ProtocolMapper: gocloak.StringP("oidc-usermodel-client-role-mapper"), + ConsentRequired: gocloak.BoolP(false), + Config: &map[string]string{ + "usermodel.clientRoleMapping.clientId": dto.ID.String() + "-k8s-api", + "claim.name": "groups", + "access.token.claim": "false", + "id.token.claim": "true", + "userinfo.token.claim": "true", + "multivalued": "true", + "jsonType.label": "String", + }, + }) + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client protocol mapper for %s", dto.ID) + return "", err + } + // Create keycloak client role + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-create") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-create", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-read") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-read", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-update") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-update", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-delete") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-delete", dto.ID) + return "", err + } + return clusterId, nil } diff --git a/internal/usecase/permission.go b/internal/usecase/permission.go index 2ccf2a4a..a1e1c7bd 100644 --- a/internal/usecase/permission.go +++ b/internal/usecase/permission.go @@ -11,6 +11,7 @@ import ( type IPermissionUsecase interface { CreatePermissionSet(ctx context.Context, permissionSet *model.PermissionSet) error + GetPermission(ctx context.Context, id uuid.UUID) (*model.Permission, error) GetPermissionSetByRoleId(ctx context.Context, roleId string) (*model.PermissionSet, error) ListPermissions(ctx context.Context, roleId string) ([]*model.Permission, error) SetRoleIdToPermissionSet(ctx context.Context, roleId string, permissionSet *model.PermissionSet) diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 43380301..7279be2c 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -188,13 +188,13 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom } // Create keycloak client protocol mapper _, err = u.kc.CreateClientProtocolMapper(ctx, dto.OrganizationId, clientUUID, gocloak.ProtocolMapperRepresentation{ - Name: gocloak.StringP(dto.ID.String() + "k8s-api"), + Name: gocloak.StringP("k8s-role-mapper"), Protocol: gocloak.StringP("openid-connect"), ProtocolMapper: gocloak.StringP("oidc-usermodel-client-role-mapper"), ConsentRequired: gocloak.BoolP(false), Config: &map[string]string{ - "usermodel.clientRoleMapping.clientId": dto.ID.String(), - "claim.name": "k8s-role-mapper", + "usermodel.clientRoleMapping.clientId": dto.ID.String() + "-k8s-api", + "claim.name": "groups", "access.token.claim": "false", "id.token.claim": "true", "userinfo.token.claim": "true", @@ -568,6 +568,12 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) } } + err = u.kc.DeleteClient(ctx, dto.OrganizationId, dto.ID.String()+"-k8s-api", true) + if err != nil { + log.Error(ctx, err) + return err + } + return nil } From 798cd228dfb17b3234ac6982579a2f8598ce0f02 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Fri, 17 May 2024 14:01:01 +0900 Subject: [PATCH 451/502] app-serving: collect app pod log --- internal/delivery/api/endpoint.go | 1 + internal/delivery/http/app-serve-app.go | 66 +++++++++++++++++++++++++ internal/repository/app-serve-app.go | 22 +++++++-- internal/route/route.go | 1 + internal/usecase/app-serve-app.go | 65 ++++++++++++++++++++++++ pkg/domain/app-serve-app.go | 5 ++ 6 files changed, 157 insertions(+), 3 deletions(-) diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index c847c189..3de1e793 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -76,6 +76,7 @@ const ( GetNumOfAppsOnStack // 프로젝트 관리/앱 서빙/조회 GetAppServeApp // 프로젝트 관리/앱 서빙/조회 GetAppServeAppLatestTask // 프로젝트 관리/앱 서빙/조회 + GetAppServeAppLog // 프로젝트 관리/앱 서빙/조회 IsAppServeAppExist // 프로젝트 관리/앱 서빙/조회 // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 IsAppServeAppNameExist // 프로젝트 관리/앱 서빙/조회 // 프로젝트 관리/앱 서빙/배포 // 프로젝트 관리/앱 서빙/빌드 DeleteAppServeApp // 프로젝트 관리/앱 서빙/삭제 diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index 5a76487e..bfc3390d 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -422,6 +422,72 @@ func (h *AppServeAppHandler) GetNumOfAppsOnStack(w http.ResponseWriter, r *http. ResponseJSON(w, r, http.StatusOK, numApps) } +// GetAppServeAppLog godoc +// +// @Tags AppServeApps +// @Summary Get log and pod status of appServeApp +// @Description Get log and pod status of appServeApp +// @Accept json +// @Produce json +// @Param organizationId path string true "Organization ID" +// @Param projectId path string true "Project ID" +// @Param appId path string true "App ID" +// @Success 200 {object} domain.GetAppServeAppLogResponse +// @Router /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/log [get] +// @Security JWT +func (h *AppServeAppHandler) GetAppServeAppLog(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + organizationId, ok := vars["organizationId"] + fmt.Printf("organizationId = [%v]\n", organizationId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "", "")) + return + } + + projectId, ok := vars["projectId"] + log.Debugf(r.Context(), "projectId = [%v]\n", projectId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid projectId: [%s]", projectId), "C_INVALID_PROJECT_ID", "")) + return + } + + appId, ok := vars["appId"] + fmt.Printf("appId = [%s]\n", appId) + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid appId"), "", "")) + return + } + + // Check if projectId exists + prj, err := h.prjUsecase.GetProject(r.Context(), organizationId, projectId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(fmt.Errorf("Error while checking project record: %s", err), "", "")) + return + } else if prj == nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("projectId not found: %s", projectId), "C_INVALID_PROJECT_ID", "")) + } + + podLog, podStatus, err := h.usecase.GetAppServeAppLog(r.Context(), appId) + if err != nil { + ErrorJSON(w, r, httpErrors.NewInternalServerError(err, "", "")) + return + } + + var out domain.GetAppServeAppLogResponse + // if err := serializer.Map(r.Context(), podLog, &out.Log); err != nil { + // log.Info(r.Context(), err) + // } + out.Log = podLog + + // if err := serializer.Map(r.Context(), podStatus, &out.PodStatus); err != nil { + // log.Info(r.Context(), err) + // } + out.PodStatus = podStatus + + ResponseJSON(w, r, http.StatusOK, out) +} + // GetAppServeAppTasksByAppId godoc // // @Tags AppServeApps diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 2267fd94..dc9fba13 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -21,6 +21,7 @@ type IAppServeAppRepository interface { GetAppServeAppTasksByAppId(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, error) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) + GetClusterIdByAppId(ctx context.Context, appId string) (string, error) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) @@ -55,9 +56,9 @@ func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *mode // Update creates new appServeApp task for existing appServeApp. func (r *AppServeAppRepository) CreateTask(ctx context.Context, task *model.AppServeAppTask, appId string) (string, error) { task.ID = uuid.New().String() - if len(appId) > 0 { - task.AppServeAppId = appId - } + if len(appId) > 0 { + task.AppServeAppId = appId + } res := r.db.WithContext(ctx).Create(task) if res.Error != nil { return "", res.Error @@ -174,6 +175,21 @@ func (r *AppServeAppRepository) GetAppServeAppLatestTask(ctx context.Context, ap return &task, nil } +func (r *AppServeAppRepository) GetClusterIdByAppId(ctx context.Context, appId string) (string, error) { + var app model.AppServeApp + + res := r.db.WithContext(ctx).Where("id = ?", appId).First(&app) + if res.Error != nil { + log.Debug(ctx, res.Error) + return "", res.Error + } + if res.RowsAffected == 0 { + return "", fmt.Errorf("No app with ID %s", appId) + } + + return app.TargetClusterId, nil +} + func (r *AppServeAppRepository) GetNumOfAppsOnStack(ctx context.Context, organizationId string, clusterId string) (int64, error) { var apps []model.AppServeApp diff --git a/internal/route/route.go b/internal/route/route.go index e9edbf12..f8dd46a1 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -166,6 +166,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks", customMiddleware.Handle(internalApi.GetAppServeAppTasksByAppId, http.HandlerFunc(appServeAppHandler.GetAppServeAppTasksByAppId))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/tasks/{taskId}", customMiddleware.Handle(internalApi.GetAppServeAppTaskDetail, http.HandlerFunc(appServeAppHandler.GetAppServeAppTaskDetail))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/latest-task", customMiddleware.Handle(internalApi.GetAppServeAppLatestTask, http.HandlerFunc(appServeAppHandler.GetAppServeAppLatestTask))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/log", customMiddleware.Handle(internalApi.GetAppServeAppLog, http.HandlerFunc(appServeAppHandler.GetAppServeAppLog))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/exist", customMiddleware.Handle(internalApi.IsAppServeAppExist, http.HandlerFunc(appServeAppHandler.IsAppServeAppExist))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/name/{name}/existence", customMiddleware.Handle(internalApi.IsAppServeAppNameExist, http.HandlerFunc(appServeAppHandler.IsAppServeAppNameExist))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}", customMiddleware.Handle(internalApi.DeleteAppServeApp, http.HandlerFunc(appServeAppHandler.DeleteAppServeApp))).Methods(http.MethodDelete) diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 033f3aae..93a74175 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -1,9 +1,11 @@ package usecase import ( + "bytes" "context" "encoding/json" "fmt" + "io" "strconv" "strings" @@ -11,6 +13,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/viper" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/openinfradev/tks-api/internal/model" @@ -27,6 +30,7 @@ type IAppServeAppUsecase interface { CreateAppServeApp(ctx context.Context, app *model.AppServeApp, task *model.AppServeAppTask) (appId string, taskId string, err error) GetAppServeApps(ctx context.Context, organizationId string, projectId string, showAll bool, pg *pagination.Pagination) ([]model.AppServeApp, error) GetAppServeAppById(ctx context.Context, appId string) (*model.AppServeApp, error) + GetAppServeAppLog(ctx context.Context, appId string) (string, string, error) GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) GetAppServeAppTaskById(ctx context.Context, taskId string) (*model.AppServeAppTask, error) GetAppServeAppLatestTask(ctx context.Context, appId string) (*model.AppServeAppTask, error) @@ -233,6 +237,67 @@ func (u *AppServeAppUsecase) GetAppServeAppById(ctx context.Context, appId strin return asa, nil } +func (u *AppServeAppUsecase) GetAppServeAppLog(ctx context.Context, appId string) (string, string, error) { + var logStr string + var podStatus string + + app, err := u.repo.GetAppServeAppById(ctx, appId) + if err != nil { + return "", "", fmt.Errorf("error while getting ASA Info from DB. Err: %s", err) + } + if app == nil { + return "", "", httpErrors.NewNoContentError(fmt.Errorf("the appId doesn't exist"), "", "") + } + + clientset, err := kubernetes.GetClientFromClusterId(ctx, app.TargetClusterId) + if err != nil { + log.Error(ctx, err) + return "", "", err + } + + // Reference: https://github.com/nwaizer/GetPodLogsEfficiently/blob/main/cmd/basicgetlogs/basic.go + + labelStr := fmt.Sprintf("app=%s", app.Name) + pods, err := clientset.CoreV1().Pods(app.Namespace).List(context.TODO(), metav1.ListOptions{ + LabelSelector: labelStr}) + if err != nil { + log.Error(ctx, err) + return "", "", err + } + + for _, pod := range pods.Items { + log.Debugf(ctx, "Processing pod: %s", pod.Name) + + tailLines := int64(50) + + req := clientset.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &corev1.PodLogOptions{ + // name should be "tomcat" for legacy spring app + Container: "main", + TailLines: &tailLines, + }) + + podLogs, err := req.Stream(context.TODO()) + if err != nil { + return "", "", fmt.Errorf("Failed to open pod logs due to: %w", err) + } + defer podLogs.Close() + + buf := new(bytes.Buffer) + _, err = io.Copy(buf, podLogs) + + if err != nil { + return "", "", fmt.Errorf("Failed to decode logs binary input due to: %w", err) + } + + logStr = "`" + buf.String() + "`" + + podStatus = fmt.Sprintf("%s", pod.Status.Phase) + log.Debugf(ctx, "Pod status: %s", pod.Status.Phase) + } + + return logStr, podStatus, nil +} + func (u *AppServeAppUsecase) GetAppServeAppTasks(ctx context.Context, appId string, pg *pagination.Pagination) ([]model.AppServeAppTask, error) { tasks, err := u.repo.GetAppServeAppTasksByAppId(ctx, appId, pg) if err != nil { diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index 757b877a..f7b747ec 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -158,6 +158,11 @@ type GetAppServeAppTaskResponse struct { Stages []StageResponse `json:"stages"` } +type GetAppServeAppLogResponse struct { + Log string `json:"log"` + PodStatus string `json:"podStatus"` +} + type StageResponse struct { Name string `json:"name"` // BUILD (빌드), DEPLOY (배포), PROMOTE (프로모트), ROLLBACK (롤백) Status string `json:"status"` From 42780ba9c84141775c045aedd92cfcb9c8a67fdb Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Mon, 20 May 2024 14:13:15 +0900 Subject: [PATCH 452/502] update swagger docs --- api/swagger/docs.go | 62 ++++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.json | 62 ++++++++++++++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 40 ++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 42716929..8bccf48a 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -6312,6 +6312,57 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/log": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get log and pod status of appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get log and pod status of appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { "post": { "security": [ @@ -12579,6 +12630,17 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse": { + "type": "object", + "properties": { + "log": { + "type": "string" + }, + "podStatus": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index f2faa9d1..67edf19f 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -6306,6 +6306,57 @@ } } }, + "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/log": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get log and pod status of appServeApp", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AppServeApps" + ], + "summary": "Get log and pod status of appServeApp", + "parameters": [ + { + "type": "string", + "description": "Organization ID", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Project ID", + "name": "projectId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "App ID", + "name": "appId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse" + } + } + } + } + }, "/organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback": { "post": { "security": [ @@ -12573,6 +12624,17 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse": { + "type": "object", + "properties": { + "log": { + "type": "string" + }, + "podStatus": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse": { "type": "object", "properties": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index fe6f2961..82c2e66f 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1535,6 +1535,13 @@ definitions: pagination: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PaginationResponse' type: object + github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse: + properties: + log: + type: string + podStatus: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppTaskResponse: properties: appServeApp: @@ -8187,6 +8194,39 @@ paths: summary: Get latest task from appServeApp tags: - AppServeApps + /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/log: + get: + consumes: + - application/json + description: Get log and pod status of appServeApp + parameters: + - description: Organization ID + in: path + name: organizationId + required: true + type: string + - description: Project ID + in: path + name: projectId + required: true + type: string + - description: App ID + in: path + name: appId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse' + security: + - JWT: [] + summary: Get log and pod status of appServeApp + tags: + - AppServeApps /organizations/{organizationId}/projects/{projectId}/app-serve-apps/{appId}/rollback: post: consumes: From eb1f63951573afb4745f45a418825401454cb9fa Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Mon, 20 May 2024 14:17:59 +0900 Subject: [PATCH 453/502] trivial: rename log to podLog --- api/swagger/docs.go | 2 +- api/swagger/swagger.json | 2 +- api/swagger/swagger.yaml | 2 +- internal/delivery/http/app-serve-app.go | 4 ++-- pkg/domain/app-serve-app.go | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 8bccf48a..a3ba31bf 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -12633,7 +12633,7 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse": { "type": "object", "properties": { - "log": { + "podLog": { "type": "string" }, "podStatus": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 67edf19f..c66c556a 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -12627,7 +12627,7 @@ "github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse": { "type": "object", "properties": { - "log": { + "podLog": { "type": "string" }, "podStatus": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 82c2e66f..b48f4c49 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1537,7 +1537,7 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.GetAppServeAppLogResponse: properties: - log: + podLog: type: string podStatus: type: string diff --git a/internal/delivery/http/app-serve-app.go b/internal/delivery/http/app-serve-app.go index bfc3390d..602b098e 100644 --- a/internal/delivery/http/app-serve-app.go +++ b/internal/delivery/http/app-serve-app.go @@ -475,10 +475,10 @@ func (h *AppServeAppHandler) GetAppServeAppLog(w http.ResponseWriter, r *http.Re } var out domain.GetAppServeAppLogResponse - // if err := serializer.Map(r.Context(), podLog, &out.Log); err != nil { + // if err := serializer.Map(r.Context(), podLog, &out.PodLog); err != nil { // log.Info(r.Context(), err) // } - out.Log = podLog + out.PodLog = podLog // if err := serializer.Map(r.Context(), podStatus, &out.PodStatus); err != nil { // log.Info(r.Context(), err) diff --git a/pkg/domain/app-serve-app.go b/pkg/domain/app-serve-app.go index f7b747ec..f6bb1048 100644 --- a/pkg/domain/app-serve-app.go +++ b/pkg/domain/app-serve-app.go @@ -159,7 +159,7 @@ type GetAppServeAppTaskResponse struct { } type GetAppServeAppLogResponse struct { - Log string `json:"log"` + PodLog string `json:"podLog"` PodStatus string `json:"podStatus"` } From 29573116ff7462dc6a5b0419b13ab0291306b53e Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Mon, 20 May 2024 14:32:32 +0900 Subject: [PATCH 454/502] trivial: fix lint error --- internal/usecase/app-serve-app.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index 93a74175..c59b71eb 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -291,8 +291,8 @@ func (u *AppServeAppUsecase) GetAppServeAppLog(ctx context.Context, appId string logStr = "`" + buf.String() + "`" - podStatus = fmt.Sprintf("%s", pod.Status.Phase) - log.Debugf(ctx, "Pod status: %s", pod.Status.Phase) + podStatus = string(pod.Status.Phase) + log.Debugf(ctx, "Pod status: %s", podStatus) } return logStr, podStatus, nil From 16e9faf649e7093dad0abebbf799dd3fb2f498c8 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 21 May 2024 12:00:35 +0900 Subject: [PATCH 455/502] trivial. update validation rule for user & organization --- go.mod | 4 ++-- internal/database/database.go | 2 +- pkg/domain/organization.go | 2 +- pkg/domain/user.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 14113d1d..1f2561f2 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/Nerzal/gocloak/v13 v13.9.0 + github.com/PuerkitoBio/goquery v1.9.1 github.com/aws/aws-sdk-go-v2 v1.25.0 github.com/aws/aws-sdk-go-v2/config v1.27.0 github.com/aws/aws-sdk-go-v2/credentials v1.17.0 @@ -27,7 +28,6 @@ require ( github.com/gorilla/websocket v1.5.1 github.com/iancoleman/strcase v0.3.0 github.com/open-policy-agent/opa v0.62.1 - github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 @@ -59,7 +59,6 @@ require ( github.com/Code-Hex/uniseg v0.2.0 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect - github.com/PuerkitoBio/goquery v1.9.1 // indirect github.com/andybalholm/cascadia v1.3.2 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 // indirect @@ -110,6 +109,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.19.0 // indirect diff --git a/internal/database/database.go b/internal/database/database.go index 9fcb1a37..13aac578 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -77,8 +77,8 @@ func migrateSchema(db *gorm.DB) error { &model.SystemNotificationAction{}, &model.SystemNotificationMetricParameter{}, &model.SystemNotificationTemplate{}, - &model.SystemNotificationCondition{}, &model.SystemNotificationRule{}, + &model.SystemNotificationCondition{}, &model.Permission{}, &model.Endpoint{}, &model.Project{}, diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 46479c4f..c9babe2a 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -73,7 +73,7 @@ type SimpleOrganizationResponse = struct { type CreateOrganizationRequest struct { Name string `json:"name" validate:"required,name"` Description string `json:"description" validate:"omitempty,min=0,max=100"` - AdminAccountId string `json:"adminAccountId" validate:"required"` + AdminAccountId string `json:"adminAccountId" validate:"required,min=0,max=20,alphanum"` AdminName string `json:"adminName" validate:"name"` AdminEmail string `json:"adminEmail" validate:"required,email"` } diff --git a/pkg/domain/user.go b/pkg/domain/user.go index e602d74d..ab5f2112 100644 --- a/pkg/domain/user.go +++ b/pkg/domain/user.go @@ -28,7 +28,7 @@ type UserResponse struct { } type CreateUserRequest struct { - AccountId string `json:"accountId" validate:"required"` + AccountId string `json:"accountId" validate:"required,min=0,max=20,alphanum"` Password string `json:"password" validate:"required"` Name string `json:"name" validate:"name"` Email string `json:"email" validate:"required,email"` From 7b8a304a0b3b5ab7aebadecb767a74f3861b0fbb Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 21 May 2024 14:26:30 +0900 Subject: [PATCH 456/502] trivial. add validation rule when organization creating --- internal/usecase/organization.go | 9 +++++++++ pkg/httpErrors/errorCode.go | 1 + 2 files changed, 10 insertions(+) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 7e5c3d07..ff37e9de 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -64,6 +64,15 @@ func (u *OrganizationUsecase) Create(ctx context.Context, in *model.Organization userId := user.GetUserId() in.CreatorId = &userId + pg := pagination.NewPaginationWithFilter("name", "", "$eq", []string{in.Name}) + organizations, err := u.repo.Fetch(ctx, pg) + if err != nil { + return "", err + } + if organizations != nil && len(*organizations) > 0 { + return "", httpErrors.NewBadRequestError(fmt.Errorf("duplicate organization name"), "O_CREATE_ALREADY_EXISTED_NAME", "") + } + // Create realm in keycloak if organizationId, err = u.kc.CreateRealm(ctx, helper.GenerateOrganizationId()); err != nil { return "", err diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 2d8319ed..a99ff7b1 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -39,6 +39,7 @@ var errorMap = map[ErrorCode]string{ // Organization "O_INVALID_ORGANIZATION_NAME": "조직에 이미 존재하는 이름입니다.", "O_NOT_EXISTED_NAME": "조직이 존재하지 않습니다.", + "O_CREATE_ALREADY_EXISTED_NAME": "이미 존재하는 이름입니다.", "O_FAILED_UPDATE_STACK_TEMPLATES": "조직에 스택템플릿을 설정하는데 실패했습니다", "O_FAILED_UPDATE_POLICY_TEMPLATES": "조직에 정책템플릿을 설정하는데 실패했습니다", "O_FAILED_UPDATE_SYSTEM_NOTIFICATION_TEMPLATES": "조직에 알림템플릿을 설정하는데 실패했습니다", From f14d2a169fd5887c8a038fdad9868ec33882704f Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Tue, 21 May 2024 15:42:37 +0900 Subject: [PATCH 457/502] =?UTF-8?q?=EA=B6=8C=ED=95=9C=EB=B6=80=EC=97=AC?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20tks=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=82=AC=EC=9A=A9=20=EB=B6=88=EA=B0=80?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/model/policy-template.go | 3 +-- internal/repository/policy-template.go | 27 ++------------------------ internal/usecase/policy.go | 4 +--- 3 files changed, 4 insertions(+), 30 deletions(-) diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index ef9ec66e..c4a76f17 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -76,8 +76,7 @@ func (pt *PolicyTemplate) IsPermittedToOrganization(organizationId *string) bool } if pt.IsTksTemplate() { - return len(pt.PermittedOrganizationIds) == 0 || - slices.Contains(pt.PermittedOrganizationIds, *organizationId) + return slices.Contains(pt.PermittedOrganizationIds, *organizationId) } return pt.OrganizationId != nil && *organizationId == *pt.OrganizationId diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 24dd7df0..1071f813 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -131,18 +131,6 @@ func (r *PolicyTemplateRepository) FetchForOrganization(ctx context.Context, org pg = pagination.NewPagination(nil) } - // 다음과 같은 쿼리를 생성해서 tks 템플릿에 대해선 PermittedOrganizations가 비거나, PermittedOrganizations에 해당 organizations이 속하는 템플릿을 찾음 - // organization 템플릿은 organizationId가 매칭되는 것을 찾음, 이를 통해 해당 사용자가 사용할 수 있는 모든 템플릿을 fetch - // select id from policy_templates where - // ( - // type = 'tks' - // and ( - // id not in (select policy_template_id from policy_template_permitted_organizations) -- PermitedOrganizations이 빈 경우, 모두에게 허용 - // or id in (select policy_template_id from policy_template_permitted_organizations organization where organization_id = 'orgid') -- PermitedOrganizations 허용된 경우 - // ) - // ) - // or (type = 'organization' and organization_id='orgid') - subQueryAloowedAll := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id") subQueryMatchId := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id"). Where("organization_id = ?", organizationId) @@ -156,12 +144,7 @@ func (r *PolicyTemplateRepository) FetchForOrganization(ctx context.Context, org Where( // tks 템플릿인 경우 r.db.Where("type = ?", "tks"). - Where( - // permitted_organizations이 비어있거나 - r.db.Where("id not in (?)", subQueryAloowedAll). - Or("id in (?)", subQueryMatchId), - // permitted_organization에 매칭되는 템플릿 아이디가 있거나 - ), + Where("id in (?)", subQueryMatchId), ). Or( // organization 타입 템플릿이면서 organization_id가 매칭 @@ -178,7 +161,6 @@ func (r *PolicyTemplateRepository) FetchForOrganization(ctx context.Context, org } func (r *PolicyTemplateRepository) CountTksTemplateByOrganization(ctx context.Context, organizationId string) (count int64, err error) { - subQueryAloowedAll := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id") subQueryMatchId := r.db.Table("policy_template_permitted_organizations").Select("policy_template_id"). Where("organization_id = ?", organizationId) @@ -187,12 +169,7 @@ func (r *PolicyTemplateRepository) CountTksTemplateByOrganization(ctx context.Co Where( // tks 템플릿인 경우 r.db.Where("type = ?", "tks"). - Where( - // permitted_organizations이 비어있거나 - r.db.Where("id not in (?)", subQueryAloowedAll). - Or("id in (?)", subQueryMatchId), - // permitted_organization에 매칭되는 템플릿 아이디가 있거나 - ), + Where("id in (?)", subQueryMatchId), ).Count(&count).Error return diff --git a/internal/usecase/policy.go b/internal/usecase/policy.go index c5d6f6ba..d9031a2a 100644 --- a/internal/usecase/policy.go +++ b/internal/usecase/policy.go @@ -6,7 +6,6 @@ import ( "fmt" "strings" - mapset "github.com/deckarep/golang-set/v2" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" @@ -508,8 +507,7 @@ func (u *PolicyUsecase) GetMandatoryPolicies(ctx context.Context, organizationId for _, policyTemplate := range policyTemplates { templateId := policyTemplate.ID.String() - if len(policyTemplate.PermittedOrganizationIds) == 0 || - mapset.NewSet(policyTemplate.PermittedOrganizationIds...).Contains(organizationId) { + if slices.Contains(policyTemplate.PermittedOrganizationIds, organizationId) { templateMaps[templateId] = &domain.MandatoryTemplateInfo{ TemplateName: policyTemplate.TemplateName, TemplateId: templateId, From 505e7e9b79f8d0d14fd0d298a6775e473503c766 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 21 May 2024 18:12:37 +0900 Subject: [PATCH 458/502] trivial. fix user filter for organizations --- internal/repository/organization.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/internal/repository/organization.go b/internal/repository/organization.go index 0b53d9bf..9b2340ed 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -2,6 +2,7 @@ package repository import ( "context" + "fmt" "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" @@ -88,13 +89,25 @@ func (r *OrganizationRepository) Fetch(ctx context.Context, pg *pagination.Pagin db := r.db.WithContext(ctx).Preload(clause.Associations).Model(&model.Organization{}) // [TODO] more pretty! + adminQuery := "" for _, filter := range pg.Filters { if filter.Relation == "Admin" { - db = db.Joins("join users on users.id::text = organizations.admin_id::text"). - Where("users.name ilike ?", "%"+filter.Values[0]+"%") - break + if adminQuery != "" { + adminQuery = adminQuery + " OR " + } + + switch filter.Column { + case "name": + adminQuery = adminQuery + fmt.Sprintf("users.name ilike '%%%s%%'", filter.Values[0]) + case "account_id": + adminQuery = adminQuery + fmt.Sprintf("users.account_id ilike '%%%s%%'", filter.Values[0]) + case "email": + adminQuery = adminQuery + fmt.Sprintf("users.email ilike '%%%s%%'", filter.Values[0]) + } } } + db = db.Joins("join users on users.id::text = organizations.admin_id::text"). + Where(adminQuery) _, res := pg.Fetch(db, &out) if res.Error != nil { From a3be5c5244b7441a0edf815cbfc753bc71bebdf7 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 22 May 2024 11:09:14 +0900 Subject: [PATCH 459/502] =?UTF-8?q?bugfix.=20TKS=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=20=EC=83=9D=EC=84=B1=EC=8B=9C=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=98=EB=8A=94=20502=20=EC=97=90=EB=9F=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/user.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/internal/delivery/http/user.go b/internal/delivery/http/user.go index ea31c7ed..d83c8d5f 100644 --- a/internal/delivery/http/user.go +++ b/internal/delivery/http/user.go @@ -967,10 +967,14 @@ func (u UserHandler) Admin_Create(w http.ResponseWriter, r *http.Request) { for _, stack := range stacks { stackIds = append(stackIds, stack.ID.String()) } - err = u.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{*resUser}) - if err != nil { - ErrorJSON(w, r, err) - return + + // 현재 Master Org의 경우 ClusterAdmin 권한과 관련이 없으므로 Skip + if organizationId != "master" { + err = u.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, stackIds, []model.User{*resUser}) + if err != nil { + ErrorJSON(w, r, err) + return + } } var out domain.Admin_CreateUserResponse From a4ba3b9091a951d093a85e5a309eb31898d09677 Mon Sep 17 00:00:00 2001 From: donggyu Date: Wed, 22 May 2024 11:38:10 +0900 Subject: [PATCH 460/502] =?UTF-8?q?bugfix.=20TKS=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=20=EC=83=9D=EC=84=B1=EC=8B=9C=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=9E=84=EC=8B=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/organization.go | 7 +++++++ internal/model/user.go | 2 +- internal/usecase/user.go | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 292d73ba..8674136e 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -140,6 +140,13 @@ func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r return } + err = h.userUsecase.ExpirePassword(r.Context(), admin.ID) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + err = h.usecase.ChangeAdminId(r.Context(), organizationId, admin.ID) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) diff --git a/internal/model/user.go b/internal/model/user.go index dfaa0db7..cd4c5b95 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -23,7 +23,7 @@ type User struct { CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` PasswordUpdatedAt time.Time `json:"passwordUpdatedAt"` - PasswordExpired bool `json:"passwordExpired"` + PasswordExpired bool `gorm:"-:all" json:"passwordExpired"` Email string `json:"email"` Department string `json:"department"` diff --git a/internal/usecase/user.go b/internal/usecase/user.go index 35be8fb9..f8e67c54 100644 --- a/internal/usecase/user.go +++ b/internal/usecase/user.go @@ -34,6 +34,7 @@ type IUserUsecase interface { GetByAccountId(ctx context.Context, accountId string, organizationId string) (*model.User, error) GetByEmail(ctx context.Context, email string, organizationId string) (*model.User, error) SendEmailForTemporaryPassword(ctx context.Context, accountId string, organizationId string, password string) error + ExpirePassword(ctx context.Context, userId uuid.UUID) error UpdateByAccountId(ctx context.Context, user *model.User) (*model.User, error) UpdatePasswordByAccountId(ctx context.Context, accountId string, originPassword string, newPassword string, organizationId string) error @@ -528,6 +529,25 @@ func (u *UserUsecase) ListUsersByRole(ctx context.Context, organizationId string } +func (u *UserUsecase) ExpirePassword(ctx context.Context, userId uuid.UUID) error { + user, err := u.userRepository.GetByUuid(ctx, userId) + if err != nil { + if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { + return httpErrors.NewBadRequestError(fmt.Errorf("user not found"), "U_NO_USER", "") + } + return httpErrors.NewInternalServerError(err, "", "") + } + + err = u.userRepository.UpdatePasswordAt(ctx, userId, user.Organization.ID, true) + if err != nil { + log.Errorf(ctx, "failed to update password expired time: %v", err) + return httpErrors.NewInternalServerError(err, "", "") + } + + return nil + +} + func NewUserUsecase(r repository.Repository, kc keycloak.IKeycloak) IUserUsecase { return &UserUsecase{ authRepository: r.Auth, From 961f9fc4be3d491ece9fdc9848d641f6b4dfc174 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 22 May 2024 16:10:32 +0900 Subject: [PATCH 461/502] trivial. change alarm name to warning from audit --- api/swagger/docs.go | 99 ++++++++++++++++++- api/swagger/swagger.json | 99 ++++++++++++++++++- api/swagger/swagger.yaml | 67 +++++++++++++ internal/delivery/http/policy-notification.go | 2 +- internal/usecase/system-notification-rule.go | 4 +- internal/usecase/system-notification.go | 4 +- pkg/domain/system-notification-template.go | 2 +- scripts/init_postgres.sql | 2 +- 8 files changed, 268 insertions(+), 11 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index a3ba31bf..0fdb70a5 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -11668,7 +11668,9 @@ const docTemplate = `{ ], "properties": { "adminAccountId": { - "type": "string" + "type": "string", + "maxLength": 20, + "minLength": 0 }, "adminEmail": { "type": "string" @@ -11769,6 +11771,10 @@ const docTemplate = `{ "templateName" ], "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "deprecated": { "type": "boolean", "example": false @@ -11815,6 +11821,15 @@ const docTemplate = `{ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -11830,6 +11845,10 @@ const docTemplate = `{ "versionUpType" ], "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "currentVersion": { "type": "string", "example": "v1.0.0" @@ -11857,6 +11876,15 @@ const docTemplate = `{ "type": "string", "example": "rego 코드" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "versionUpType": { "type": "string", "enum": [ @@ -12193,7 +12221,9 @@ const docTemplate = `{ ], "properties": { "accountId": { - "type": "string" + "type": "string", + "maxLength": 20, + "minLength": 0 }, "department": { "type": "string", @@ -14200,6 +14230,10 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse": { "type": "object", "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "createdAt": { "type": "string" }, @@ -14250,6 +14284,15 @@ const docTemplate = `{ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -14291,6 +14334,10 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse": { "type": "object", "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "createdAt": { "type": "string" }, @@ -14349,6 +14396,15 @@ const docTemplate = `{ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -16463,6 +16519,10 @@ const docTemplate = `{ "templateName" ], "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "deprecated": { "type": "boolean", "example": false @@ -16509,6 +16569,15 @@ const docTemplate = `{ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -16524,6 +16593,10 @@ const docTemplate = `{ "versionUpType" ], "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "currentVersion": { "type": "string", "example": "v1.0.0" @@ -16551,6 +16624,15 @@ const docTemplate = `{ "type": "string", "example": "rego 코드" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "versionUpType": { "type": "string", "enum": [ @@ -16704,6 +16786,10 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse": { "type": "object", "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "createdAt": { "type": "string" }, @@ -16760,6 +16846,15 @@ const docTemplate = `{ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index c66c556a..5b7cc574 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -11662,7 +11662,9 @@ ], "properties": { "adminAccountId": { - "type": "string" + "type": "string", + "maxLength": 20, + "minLength": 0 }, "adminEmail": { "type": "string" @@ -11763,6 +11765,10 @@ "templateName" ], "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "deprecated": { "type": "boolean", "example": false @@ -11809,6 +11815,15 @@ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -11824,6 +11839,10 @@ "versionUpType" ], "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "currentVersion": { "type": "string", "example": "v1.0.0" @@ -11851,6 +11870,15 @@ "type": "string", "example": "rego 코드" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "versionUpType": { "type": "string", "enum": [ @@ -12187,7 +12215,9 @@ ], "properties": { "accountId": { - "type": "string" + "type": "string", + "maxLength": 20, + "minLength": 0 }, "department": { "type": "string", @@ -14194,6 +14224,10 @@ "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse": { "type": "object", "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "createdAt": { "type": "string" }, @@ -14244,6 +14278,15 @@ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -14285,6 +14328,10 @@ "github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse": { "type": "object", "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "createdAt": { "type": "string" }, @@ -14343,6 +14390,15 @@ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -16457,6 +16513,10 @@ "templateName" ], "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "deprecated": { "type": "boolean", "example": false @@ -16503,6 +16563,15 @@ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" @@ -16518,6 +16587,10 @@ "versionUpType" ], "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "currentVersion": { "type": "string", "example": "v1.0.0" @@ -16545,6 +16618,15 @@ "type": "string", "example": "rego 코드" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "versionUpType": { "type": "string", "enum": [ @@ -16698,6 +16780,10 @@ "github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse": { "type": "object", "properties": { + "SyncJson": { + "type": "string", + "example": "[[]]" + }, "createdAt": { "type": "string" }, @@ -16754,6 +16840,15 @@ ], "example": "medium" }, + "syncKinds": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "Ingress" + ] + }, "templateName": { "type": "string", "example": "필수 Label 검사" diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index b48f4c49..7b328415 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -881,6 +881,8 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.CreateOrganizationRequest: properties: adminAccountId: + maxLength: 20 + minLength: 0 type: string adminEmail: type: string @@ -951,6 +953,9 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateRequest: properties: + SyncJson: + example: '[[]]' + type: string deprecated: example: false type: boolean @@ -984,6 +989,12 @@ definitions: - high example: medium type: string + syncKinds: + example: + - Ingress + items: + type: string + type: array templateName: example: 필수 Label 검사 type: string @@ -995,6 +1006,9 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.CreatePolicyTemplateVersionRequest: properties: + SyncJson: + example: '[[]]' + type: string currentVersion: example: v1.0.0 type: string @@ -1014,6 +1028,12 @@ definitions: rego: example: rego 코드 type: string + syncKinds: + example: + - Ingress + items: + type: string + type: array versionUpType: enum: - major @@ -1242,6 +1262,8 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.CreateUserRequest: properties: accountId: + maxLength: 20 + minLength: 0 type: string department: maxLength: 50 @@ -2561,6 +2583,9 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse: properties: + SyncJson: + example: '[[]]' + type: string createdAt: type: string creator: @@ -2597,6 +2622,12 @@ definitions: - high example: medium type: string + syncKinds: + example: + - Ingress + items: + type: string + type: array templateName: example: 필수 Label 검사 type: string @@ -2625,6 +2656,9 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse: properties: + SyncJson: + example: '[[]]' + type: string createdAt: type: string creator: @@ -2667,6 +2701,12 @@ definitions: - high example: medium type: string + syncKinds: + example: + - Ingress + items: + type: string + type: array templateName: example: 필수 Label 검사 type: string @@ -4077,6 +4117,9 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateRequest: properties: + SyncJson: + example: '[[]]' + type: string deprecated: example: false type: boolean @@ -4110,6 +4153,12 @@ definitions: - high example: medium type: string + syncKinds: + example: + - Ingress + items: + type: string + type: array templateName: example: 필수 Label 검사 type: string @@ -4121,6 +4170,9 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain_admin.CreatePolicyTemplateVersionRequest: properties: + SyncJson: + example: '[[]]' + type: string currentVersion: example: v1.0.0 type: string @@ -4140,6 +4192,12 @@ definitions: rego: example: rego 코드 type: string + syncKinds: + example: + - Ingress + items: + type: string + type: array versionUpType: enum: - major @@ -4245,6 +4303,9 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain_admin.PolicyTemplateResponse: properties: + SyncJson: + example: '[[]]' + type: string createdAt: type: string creator: @@ -4285,6 +4346,12 @@ definitions: - high example: medium type: string + syncKinds: + example: + - Ingress + items: + type: string + type: array templateName: example: 필수 Label 검사 type: string diff --git a/internal/delivery/http/policy-notification.go b/internal/delivery/http/policy-notification.go index 12e87db4..ee084b39 100644 --- a/internal/delivery/http/policy-notification.go +++ b/internal/delivery/http/policy-notification.go @@ -62,7 +62,7 @@ func (h *PolicyNotificationHandler) GetPolicyNotifications(w http.ResponseWriter for j, value := range filter.Values { val := "" if value == "dryrun" { - val = "감사" + val = "경고" } else { val = "거부" } diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 2c737b08..e3bdef06 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -328,11 +328,11 @@ func (u *SystemNotificationRuleUsecase) MakeDefaultSystemNotificationRules(ctx c CreatorId: organization.AdminId, UpdatorId: organization.AdminId, }) - } else if template.Name == domain.SN_TYPE_POLICY_AUDITED { + } else if template.Name == domain.SN_TYPE_POLICY_WARNING { ruleId := uuid.New() rules = append(rules, model.SystemNotificationRule{ ID: ruleId, - Name: domain.SN_TYPE_POLICY_AUDITED + "-critical", + Name: domain.SN_TYPE_POLICY_WARNING + "-critical", Description: "기본 시스템 알림 - 정책 위반", OrganizationId: organizationId, NotificationType: template.NotificationType, diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 6a2c577f..da75cca3 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -136,8 +136,8 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre if systemNotification.Annotations.AlertType == "POLICY_NOTIFICATION" { dto.PolicyName = systemNotification.Annotations.PolicyName - if strings.Contains(systemNotification.Labels.AlertName, "policy-audited") { - dto.MessageActionProposal = "감사" + if strings.Contains(systemNotification.Labels.AlertName, "policy-warning") { + dto.MessageActionProposal = "경고" } else if strings.Contains(systemNotification.Labels.AlertName, "policy-blocked") { dto.MessageActionProposal = "거부" } else { diff --git a/pkg/domain/system-notification-template.go b/pkg/domain/system-notification-template.go index d2e54fa0..89345d17 100644 --- a/pkg/domain/system-notification-template.go +++ b/pkg/domain/system-notification-template.go @@ -9,7 +9,7 @@ const SN_TYPE_NODE_MEMORY_HIGH_UTILIZATION = "node-memory-high-utilization" const SN_TYPE_NODE_DISK_FULL = "node-disk-full" const SN_TYPE_PVC_FULL = "pvc-full" const SN_TYPE_POD_RESTART_FREQUENTLY = "pod-restart-frequently" -const SN_TYPE_POLICY_AUDITED = "policy-audited" +const SN_TYPE_POLICY_WARNING = "policy-warning" const SN_TYPE_POLICY_BLOCKED = "policy-blocked" const ( diff --git a/scripts/init_postgres.sql b/scripts/init_postgres.sql index df183860..1c1c4ff0 100644 --- a/scripts/init_postgres.sql +++ b/scripts/init_postgres.sql @@ -69,7 +69,7 @@ values ('68dcb92d-91cc-47d0-9b2f-2285d74f157f', 'pvc-full', 'pvc-full', true, 'S insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) values ('46e9e216-364a-4a3f-9182-85b2c4c34f77', 'pod-restart-frequently', 'pod-restart-frequently', true, 'SYSTEM_NOTIFICATION','increase(kube_pod_container_status_restarts_total{namespace!="kube-system"}[60m:])', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) -values ('7355d0f9-7c14-4f70-92ea-a9868624ff82', 'policy-audited', 'policy-audited', true, 'POLICY_NOTIFICATION', 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system", violation_enforcement="warn"}', null, null, now(), now() ); +values ('7355d0f9-7c14-4f70-92ea-a9868624ff82', 'policy-warning', 'policy-warning', true, 'POLICY_NOTIFICATION', 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system", violation_enforcement="warn"}', null, null, now(), now() ); insert into system_notification_templates ( id, name, description, is_system, notification_type, metric_query, creator_id, updator_id, created_at, updated_at ) values ('792ca0c6-b98f-4493-aa17-548de9eb9a4e', 'policy-blocked', 'policy-blocked', true, 'POLICY_NOTIFICATION', 'opa_scorecard_constraint_violations{namespace!="kube-system|taco-system|gatekeeper-system",violation_enforcement=""}', null, null, now(), now() ); From 2d809ca671970261db777d29e6942d013af9d898 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 22 May 2024 17:16:13 +0900 Subject: [PATCH 462/502] trivial. change snr policy type --- internal/delivery/http/policy-notification.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/delivery/http/policy-notification.go b/internal/delivery/http/policy-notification.go index ee084b39..a1763787 100644 --- a/internal/delivery/http/policy-notification.go +++ b/internal/delivery/http/policy-notification.go @@ -61,7 +61,7 @@ func (h *PolicyNotificationHandler) GetPolicyNotifications(w http.ResponseWriter } else if filter.Column == "message_action_proposal" { for j, value := range filter.Values { val := "" - if value == "dryrun" { + if value == "warn" { val = "경고" } else { val = "거부" From 552526b6ad1a7aedffca37841793c0a7eaed261a Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Wed, 22 May 2024 22:25:20 +0900 Subject: [PATCH 463/502] policy guard rule audit bugfix --- internal/policy-template/tksguard-rego.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/policy-template/tksguard-rego.go b/internal/policy-template/tksguard-rego.go index e19a94bc..89830dbc 100644 --- a/internal/policy-template/tksguard-rego.go +++ b/internal/policy-template/tksguard-rego.go @@ -23,7 +23,7 @@ const tks_guard_rego_rulename = ` # Do not delete following line, added by TKS const tks_guard_rego_rulelogic = ` # Do not delete or edit following rule, managed by TKS ___not_tks_triggered_request___ { - not input.review.userInfo + not input.review.userInfo.username } { tks_users := {"kubernetes-admin","system:serviceaccount:kube-system:argocd-manager"} tks_groups := {"system:masters"} From bee0b5a801f9d76f4fe5887d2a39c10ee29c2398 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 23 May 2024 10:05:53 +0900 Subject: [PATCH 464/502] bugfix. make kubeconfig lowercase --- combind-kubeconfig | 4 ++++ pkg/domain/project.go | 2 +- pkg/domain/stack.go | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 combind-kubeconfig diff --git a/combind-kubeconfig b/combind-kubeconfig new file mode 100644 index 00000000..350db35b --- /dev/null +++ b/combind-kubeconfig @@ -0,0 +1,4 @@ +apiVersion: "" +kind: "" +clusters: [] +contexts: [] diff --git a/pkg/domain/project.go b/pkg/domain/project.go index dca4cc91..39f7288c 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -199,5 +199,5 @@ type GetProjectNamespaceResourcesUsageResponse struct { } type GetProjectNamespaceKubeConfigResponse struct { - KubeConfig string `json:"kubeConfig"` + KubeConfig string `json:"kubeconfig"` } diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 90f4f96b..8cbbfec6 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -169,7 +169,7 @@ type CheckStackNameResponse struct { } type GetStackKubeConfigResponse struct { - KubeConfig string `json:"kubeConfig"` + KubeConfig string `json:"kubeconfig"` } type GetStackStatusResponse struct { From bc7860d6e5fef2fe64d0150c4ada74c1b9ce8157 Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 23 May 2024 10:26:36 +0900 Subject: [PATCH 465/502] change kubeConfig / kube-config -> kubeconfig --- api/swagger/docs.go | 16 +- api/swagger/swagger.json | 18 +- api/swagger/swagger.yaml | 16 +- internal/delivery/api/endpoint.go | 2 +- .../delivery/api/generated_endpoints.go.go | 943 +++++++++--------- internal/delivery/http/cluster.go | 6 +- internal/delivery/http/project.go | 10 +- internal/delivery/http/stack.go | 16 +- internal/middleware/auth/role/default.go | 4 +- internal/model/permission.go | 2 +- internal/route/route.go | 6 +- internal/usecase/project.go | 20 +- internal/usecase/stack.go | 9 +- pkg/domain/project.go | 4 +- pkg/domain/stack.go | 4 +- pkg/kubernetes/kubernetes.go | 14 +- pkg/kubernetes/kubernetes_test.go | 8 +- 17 files changed, 549 insertions(+), 549 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0fdb70a5..ccc20eb1 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -7515,7 +7515,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeconfigResponse" } } } @@ -8614,7 +8614,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Get KubeConfig by stack", + "description": "Get Kubeconfig by stack", "consumes": [ "application/json" ], @@ -8624,7 +8624,7 @@ const docTemplate = `{ "tags": [ "Stacks" ], - "summary": "Get KubeConfig by stack", + "summary": "Get Kubeconfig by stack", "parameters": [ { "type": "string", @@ -8645,7 +8645,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeconfigResponse" } } } @@ -13170,10 +13170,10 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeconfigResponse": { "type": "object", "properties": { - "kubeConfig": { + "kubeconfig": { "type": "string" } } @@ -13246,10 +13246,10 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackKubeconfigResponse": { "type": "object", "properties": { - "kubeConfig": { + "kubeconfig": { "type": "string" } } diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 5b7cc574..40c9d30a 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -7509,7 +7509,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeconfigResponse" } } } @@ -8608,7 +8608,7 @@ "JWT": [] } ], - "description": "Get KubeConfig by stack", + "description": "Get Kubeconfig by stack", "consumes": [ "application/json" ], @@ -8618,7 +8618,7 @@ "tags": [ "Stacks" ], - "summary": "Get KubeConfig by stack", + "summary": "Get Kubeconfig by stack", "parameters": [ { "type": "string", @@ -8639,7 +8639,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeconfigResponse" } } } @@ -13164,10 +13164,10 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeconfigResponse": { "type": "object", "properties": { - "kubeConfig": { + "kubeconfig": { "type": "string" } } @@ -13240,10 +13240,10 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse": { + "github_com_openinfradev_tks-api_pkg_domain.GetStackKubeconfigResponse": { "type": "object", "properties": { - "kubeConfig": { + "kubeconfig": { "type": "string" } } @@ -16946,4 +16946,4 @@ "in": "header" } } -} \ No newline at end of file +} diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 7b328415..5541b25d 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1884,9 +1884,9 @@ definitions: k8sResources: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectNamespaceK8sResources' type: object - github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse: + github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeconfigResponse: properties: - kubeConfig: + kubeconfig: type: string type: object github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceResourcesUsageResponse: @@ -1932,9 +1932,9 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectResponse' type: array type: object - github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse: + github_com_openinfradev_tks-api_pkg_domain.GetStackKubeconfigResponse: properties: - kubeConfig: + kubeconfig: type: string type: object github_com_openinfradev_tks-api_pkg_domain.GetStackPolicyTemplateStatusResponse: @@ -9108,7 +9108,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeConfigResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetProjectNamespaceKubeconfigResponse' security: - JWT: [] summary: Get project namespace kubeconfig @@ -9869,7 +9869,7 @@ paths: get: consumes: - application/json - description: Get KubeConfig by stack + description: Get Kubeconfig by stack parameters: - description: organizationId in: path @@ -9887,10 +9887,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeConfigResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackKubeconfigResponse' security: - JWT: [] - summary: Get KubeConfig by stack + summary: Get Kubeconfig by stack tags: - Stacks /organizations/{organizationId}/stacks/{stackId}/policies: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 3de1e793..30280502 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -168,7 +168,7 @@ const ( GetStack // 스택관리/조회 UpdateStack // 스택관리/수정 DeleteStack // 스택관리/삭제 - GetStackKubeConfig // 스택관리/조회 + GetStackKubeconfig // 스택관리/조회 GetStackStatus // 스택관리/조회 SetFavoriteStack // 스택관리/조회 DeleteFavoriteStack // 스택관리/조회 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 937cb4d0..25f0364d 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -1,941 +1,942 @@ - // This is generated code. DO NOT EDIT. +// This is generated code. DO NOT EDIT. package api var ApiMap = map[Endpoint]EndpointInfo{ - Login: { - Name: "Login", + Login: { + Name: "Login", Group: "Auth", }, - Logout: { - Name: "Logout", + Logout: { + Name: "Logout", Group: "Auth", }, - RefreshToken: { - Name: "RefreshToken", + RefreshToken: { + Name: "RefreshToken", Group: "Auth", }, - FindId: { - Name: "FindId", + FindId: { + Name: "FindId", Group: "Auth", }, - FindPassword: { - Name: "FindPassword", + FindPassword: { + Name: "FindPassword", Group: "Auth", }, - VerifyIdentityForLostId: { - Name: "VerifyIdentityForLostId", + VerifyIdentityForLostId: { + Name: "VerifyIdentityForLostId", Group: "Auth", }, - VerifyIdentityForLostPassword: { - Name: "VerifyIdentityForLostPassword", + VerifyIdentityForLostPassword: { + Name: "VerifyIdentityForLostPassword", Group: "Auth", }, - VerifyToken: { - Name: "VerifyToken", + VerifyToken: { + Name: "VerifyToken", Group: "Auth", }, - CreateUser: { - Name: "CreateUser", + CreateUser: { + Name: "CreateUser", Group: "User", }, - ListUser: { - Name: "ListUser", + ListUser: { + Name: "ListUser", Group: "User", }, - GetUser: { - Name: "GetUser", + GetUser: { + Name: "GetUser", Group: "User", }, - DeleteUser: { - Name: "DeleteUser", + DeleteUser: { + Name: "DeleteUser", Group: "User", }, - UpdateUsers: { - Name: "UpdateUsers", + UpdateUsers: { + Name: "UpdateUsers", Group: "User", }, - UpdateUser: { - Name: "UpdateUser", + UpdateUser: { + Name: "UpdateUser", Group: "User", }, - ResetPassword: { - Name: "ResetPassword", + ResetPassword: { + Name: "ResetPassword", Group: "User", }, - CheckId: { - Name: "CheckId", + CheckId: { + Name: "CheckId", Group: "User", }, - CheckEmail: { - Name: "CheckEmail", + CheckEmail: { + Name: "CheckEmail", Group: "User", }, - GetPermissionsByAccountId: { - Name: "GetPermissionsByAccountId", + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", Group: "User", }, - GetMyProfile: { - Name: "GetMyProfile", + GetMyProfile: { + Name: "GetMyProfile", Group: "MyProfile", }, - UpdateMyProfile: { - Name: "UpdateMyProfile", + UpdateMyProfile: { + Name: "UpdateMyProfile", Group: "MyProfile", }, - UpdateMyPassword: { - Name: "UpdateMyPassword", + UpdateMyPassword: { + Name: "UpdateMyPassword", Group: "MyProfile", }, - RenewPasswordExpiredDate: { - Name: "RenewPasswordExpiredDate", + RenewPasswordExpiredDate: { + Name: "RenewPasswordExpiredDate", Group: "MyProfile", }, - DeleteMyProfile: { - Name: "DeleteMyProfile", + DeleteMyProfile: { + Name: "DeleteMyProfile", Group: "MyProfile", }, - Admin_CreateOrganization: { - Name: "Admin_CreateOrganization", + Admin_CreateOrganization: { + Name: "Admin_CreateOrganization", Group: "Organization", }, - Admin_DeleteOrganization: { - Name: "Admin_DeleteOrganization", + Admin_DeleteOrganization: { + Name: "Admin_DeleteOrganization", Group: "Organization", }, - GetOrganizations: { - Name: "GetOrganizations", + GetOrganizations: { + Name: "GetOrganizations", Group: "Organization", }, - GetOrganization: { - Name: "GetOrganization", + GetOrganization: { + Name: "GetOrganization", Group: "Organization", }, - CheckOrganizationName: { - Name: "CheckOrganizationName", + CheckOrganizationName: { + Name: "CheckOrganizationName", Group: "Organization", }, - UpdateOrganization: { - Name: "UpdateOrganization", + UpdateOrganization: { + Name: "UpdateOrganization", Group: "Organization", }, - UpdatePrimaryCluster: { - Name: "UpdatePrimaryCluster", + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", Group: "Organization", }, - CreateCluster: { - Name: "CreateCluster", + CreateCluster: { + Name: "CreateCluster", Group: "Cluster", }, - GetClusters: { - Name: "GetClusters", + GetClusters: { + Name: "GetClusters", Group: "Cluster", }, - ImportCluster: { - Name: "ImportCluster", + ImportCluster: { + Name: "ImportCluster", Group: "Cluster", }, - GetCluster: { - Name: "GetCluster", + GetCluster: { + Name: "GetCluster", Group: "Cluster", }, - DeleteCluster: { - Name: "DeleteCluster", + DeleteCluster: { + Name: "DeleteCluster", Group: "Cluster", }, - GetClusterSiteValues: { - Name: "GetClusterSiteValues", + GetClusterSiteValues: { + Name: "GetClusterSiteValues", Group: "Cluster", }, - InstallCluster: { - Name: "InstallCluster", + InstallCluster: { + Name: "InstallCluster", Group: "Cluster", }, - CreateBootstrapKubeconfig: { - Name: "CreateBootstrapKubeconfig", + CreateBootstrapKubeconfig: { + Name: "CreateBootstrapKubeconfig", Group: "Cluster", }, - GetBootstrapKubeconfig: { - Name: "GetBootstrapKubeconfig", + GetBootstrapKubeconfig: { + Name: "GetBootstrapKubeconfig", Group: "Cluster", }, - GetNodes: { - Name: "GetNodes", + GetNodes: { + Name: "GetNodes", Group: "Cluster", }, - CreateAppgroup: { - Name: "CreateAppgroup", + CreateAppgroup: { + Name: "CreateAppgroup", Group: "Appgroup", }, - GetAppgroups: { - Name: "GetAppgroups", + GetAppgroups: { + Name: "GetAppgroups", Group: "Appgroup", }, - GetAppgroup: { - Name: "GetAppgroup", + GetAppgroup: { + Name: "GetAppgroup", Group: "Appgroup", }, - DeleteAppgroup: { - Name: "DeleteAppgroup", + DeleteAppgroup: { + Name: "DeleteAppgroup", Group: "Appgroup", }, - GetApplications: { - Name: "GetApplications", + GetApplications: { + Name: "GetApplications", Group: "Appgroup", }, - CreateApplication: { - Name: "CreateApplication", + CreateApplication: { + Name: "CreateApplication", Group: "Appgroup", }, - GetAppServeAppTasksByAppId: { - Name: "GetAppServeAppTasksByAppId", + GetAppServeAppTasksByAppId: { + Name: "GetAppServeAppTasksByAppId", Group: "AppServeApp", }, - GetAppServeAppTaskDetail: { - Name: "GetAppServeAppTaskDetail", + GetAppServeAppTaskDetail: { + Name: "GetAppServeAppTaskDetail", Group: "AppServeApp", }, - CreateAppServeApp: { - Name: "CreateAppServeApp", + CreateAppServeApp: { + Name: "CreateAppServeApp", Group: "AppServeApp", }, - GetAppServeApps: { - Name: "GetAppServeApps", + GetAppServeApps: { + Name: "GetAppServeApps", Group: "AppServeApp", }, - GetNumOfAppsOnStack: { - Name: "GetNumOfAppsOnStack", + GetNumOfAppsOnStack: { + Name: "GetNumOfAppsOnStack", Group: "AppServeApp", }, - GetAppServeApp: { - Name: "GetAppServeApp", + GetAppServeApp: { + Name: "GetAppServeApp", Group: "AppServeApp", }, - GetAppServeAppLatestTask: { - Name: "GetAppServeAppLatestTask", + GetAppServeAppLatestTask: { + Name: "GetAppServeAppLatestTask", Group: "AppServeApp", }, - IsAppServeAppExist: { - Name: "IsAppServeAppExist", + IsAppServeAppExist: { + Name: "IsAppServeAppExist", Group: "AppServeApp", }, - IsAppServeAppNameExist: { - Name: "IsAppServeAppNameExist", + IsAppServeAppNameExist: { + Name: "IsAppServeAppNameExist", Group: "AppServeApp", }, - DeleteAppServeApp: { - Name: "DeleteAppServeApp", + DeleteAppServeApp: { + Name: "DeleteAppServeApp", Group: "AppServeApp", }, - UpdateAppServeApp: { - Name: "UpdateAppServeApp", + UpdateAppServeApp: { + Name: "UpdateAppServeApp", Group: "AppServeApp", }, - UpdateAppServeAppStatus: { - Name: "UpdateAppServeAppStatus", + UpdateAppServeAppStatus: { + Name: "UpdateAppServeAppStatus", Group: "AppServeApp", }, - UpdateAppServeAppEndpoint: { - Name: "UpdateAppServeAppEndpoint", + UpdateAppServeAppEndpoint: { + Name: "UpdateAppServeAppEndpoint", Group: "AppServeApp", }, - RollbackAppServeApp: { - Name: "RollbackAppServeApp", + RollbackAppServeApp: { + Name: "RollbackAppServeApp", Group: "AppServeApp", }, - GetCloudAccounts: { - Name: "GetCloudAccounts", + GetCloudAccounts: { + Name: "GetCloudAccounts", Group: "CloudAccount", }, - CreateCloudAccount: { - Name: "CreateCloudAccount", + CreateCloudAccount: { + Name: "CreateCloudAccount", Group: "CloudAccount", }, - CheckCloudAccountName: { - Name: "CheckCloudAccountName", + CheckCloudAccountName: { + Name: "CheckCloudAccountName", Group: "CloudAccount", }, - CheckAwsAccountId: { - Name: "CheckAwsAccountId", + CheckAwsAccountId: { + Name: "CheckAwsAccountId", Group: "CloudAccount", }, - GetCloudAccount: { - Name: "GetCloudAccount", + GetCloudAccount: { + Name: "GetCloudAccount", Group: "CloudAccount", }, - UpdateCloudAccount: { - Name: "UpdateCloudAccount", + UpdateCloudAccount: { + Name: "UpdateCloudAccount", Group: "CloudAccount", }, - DeleteCloudAccount: { - Name: "DeleteCloudAccount", + DeleteCloudAccount: { + Name: "DeleteCloudAccount", Group: "CloudAccount", }, - DeleteForceCloudAccount: { - Name: "DeleteForceCloudAccount", + DeleteForceCloudAccount: { + Name: "DeleteForceCloudAccount", Group: "CloudAccount", }, - GetResourceQuota: { - Name: "GetResourceQuota", + GetResourceQuota: { + Name: "GetResourceQuota", Group: "CloudAccount", }, - Admin_GetStackTemplates: { - Name: "Admin_GetStackTemplates", + Admin_GetStackTemplates: { + Name: "Admin_GetStackTemplates", Group: "StackTemplate", }, - Admin_GetStackTemplate: { - Name: "Admin_GetStackTemplate", + Admin_GetStackTemplate: { + Name: "Admin_GetStackTemplate", Group: "StackTemplate", }, - Admin_GetStackTemplateServices: { - Name: "Admin_GetStackTemplateServices", + Admin_GetStackTemplateServices: { + Name: "Admin_GetStackTemplateServices", Group: "StackTemplate", }, - Admin_GetStackTemplateTemplateIds: { - Name: "Admin_GetStackTemplateTemplateIds", + Admin_GetStackTemplateTemplateIds: { + Name: "Admin_GetStackTemplateTemplateIds", Group: "StackTemplate", }, - Admin_CreateStackTemplate: { - Name: "Admin_CreateStackTemplate", + Admin_CreateStackTemplate: { + Name: "Admin_CreateStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplate: { - Name: "Admin_UpdateStackTemplate", + Admin_UpdateStackTemplate: { + Name: "Admin_UpdateStackTemplate", Group: "StackTemplate", }, - Admin_DeleteStackTemplate: { - Name: "Admin_DeleteStackTemplate", + Admin_DeleteStackTemplate: { + Name: "Admin_DeleteStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplateOrganizations: { - Name: "Admin_UpdateStackTemplateOrganizations", + Admin_UpdateStackTemplateOrganizations: { + Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, - Admin_CheckStackTemplateName: { - Name: "Admin_CheckStackTemplateName", + Admin_CheckStackTemplateName: { + Name: "Admin_CheckStackTemplateName", Group: "StackTemplate", }, - GetOrganizationStackTemplates: { - Name: "GetOrganizationStackTemplates", + GetOrganizationStackTemplates: { + Name: "GetOrganizationStackTemplates", Group: "StackTemplate", }, - GetOrganizationStackTemplate: { - Name: "GetOrganizationStackTemplate", + GetOrganizationStackTemplate: { + Name: "GetOrganizationStackTemplate", Group: "StackTemplate", }, - AddOrganizationStackTemplates: { - Name: "AddOrganizationStackTemplates", + AddOrganizationStackTemplates: { + Name: "AddOrganizationStackTemplates", Group: "StackTemplate", }, - RemoveOrganizationStackTemplates: { - Name: "RemoveOrganizationStackTemplates", + RemoveOrganizationStackTemplates: { + Name: "RemoveOrganizationStackTemplates", Group: "StackTemplate", }, - CreateDashboard: { - Name: "CreateDashboard", + CreateDashboard: { + Name: "CreateDashboard", Group: "Dashboard", }, - GetDashboard: { - Name: "GetDashboard", + GetDashboard: { + Name: "GetDashboard", Group: "Dashboard", }, - UpdateDashboard: { - Name: "UpdateDashboard", + UpdateDashboard: { + Name: "UpdateDashboard", Group: "Dashboard", }, - GetChartsDashboard: { - Name: "GetChartsDashboard", + GetChartsDashboard: { + Name: "GetChartsDashboard", Group: "Dashboard", }, - GetChartDashboard: { - Name: "GetChartDashboard", + GetChartDashboard: { + Name: "GetChartDashboard", Group: "Dashboard", }, - GetStacksDashboard: { - Name: "GetStacksDashboard", + GetStacksDashboard: { + Name: "GetStacksDashboard", Group: "Dashboard", }, - GetResourcesDashboard: { - Name: "GetResourcesDashboard", + GetResourcesDashboard: { + Name: "GetResourcesDashboard", Group: "Dashboard", }, - GetPolicyStatusDashboard: { - Name: "GetPolicyStatusDashboard", + GetPolicyStatusDashboard: { + Name: "GetPolicyStatusDashboard", Group: "Dashboard", }, - GetPolicyUpdateDashboard: { - Name: "GetPolicyUpdateDashboard", + GetPolicyUpdateDashboard: { + Name: "GetPolicyUpdateDashboard", Group: "Dashboard", }, - GetPolicyEnforcementDashboard: { - Name: "GetPolicyEnforcementDashboard", + GetPolicyEnforcementDashboard: { + Name: "GetPolicyEnforcementDashboard", Group: "Dashboard", }, - GetPolicyViolationDashboard: { - Name: "GetPolicyViolationDashboard", + GetPolicyViolationDashboard: { + Name: "GetPolicyViolationDashboard", Group: "Dashboard", }, - GetPolicyViolationLogDashboard: { - Name: "GetPolicyViolationLogDashboard", + GetPolicyViolationLogDashboard: { + Name: "GetPolicyViolationLogDashboard", Group: "Dashboard", }, - GetPolicyStatisticsDashboard: { - Name: "GetPolicyStatisticsDashboard", + GetPolicyStatisticsDashboard: { + Name: "GetPolicyStatisticsDashboard", Group: "Dashboard", }, - GetWorkloadDashboard: { - Name: "GetWorkloadDashboard", + GetWorkloadDashboard: { + Name: "GetWorkloadDashboard", Group: "Dashboard", }, - GetPolicyViolationTop5Dashboard: { - Name: "GetPolicyViolationTop5Dashboard", + GetPolicyViolationTop5Dashboard: { + Name: "GetPolicyViolationTop5Dashboard", Group: "Dashboard", }, - Admin_CreateSystemNotificationTemplate: { - Name: "Admin_CreateSystemNotificationTemplate", + Admin_CreateSystemNotificationTemplate: { + Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_UpdateSystemNotificationTemplate: { - Name: "Admin_UpdateSystemNotificationTemplate", + Admin_UpdateSystemNotificationTemplate: { + Name: "Admin_UpdateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_DeleteSystemNotificationTemplate: { - Name: "Admin_DeleteSystemNotificationTemplate", + Admin_DeleteSystemNotificationTemplate: { + Name: "Admin_DeleteSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplates: { - Name: "Admin_GetSystemNotificationTemplates", + Admin_GetSystemNotificationTemplates: { + Name: "Admin_GetSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplate: { - Name: "Admin_GetSystemNotificationTemplate", + Admin_GetSystemNotificationTemplate: { + Name: "Admin_GetSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_CheckSystemNotificationTemplateName: { - Name: "Admin_CheckSystemNotificationTemplateName", + Admin_CheckSystemNotificationTemplateName: { + Name: "Admin_CheckSystemNotificationTemplateName", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplates: { - Name: "GetOrganizationSystemNotificationTemplates", + GetOrganizationSystemNotificationTemplates: { + Name: "GetOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplate: { - Name: "GetOrganizationSystemNotificationTemplate", + GetOrganizationSystemNotificationTemplate: { + Name: "GetOrganizationSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - AddOrganizationSystemNotificationTemplates: { - Name: "AddOrganizationSystemNotificationTemplates", + AddOrganizationSystemNotificationTemplates: { + Name: "AddOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - RemoveOrganizationSystemNotificationTemplates: { - Name: "RemoveOrganizationSystemNotificationTemplates", + RemoveOrganizationSystemNotificationTemplates: { + Name: "RemoveOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - CreateSystemNotificationRule: { - Name: "CreateSystemNotificationRule", + CreateSystemNotificationRule: { + Name: "CreateSystemNotificationRule", Group: "SystemNotificationRule", }, - GetSystemNotificationRules: { - Name: "GetSystemNotificationRules", + GetSystemNotificationRules: { + Name: "GetSystemNotificationRules", Group: "SystemNotificationRule", }, - GetSystemNotificationRule: { - Name: "GetSystemNotificationRule", + GetSystemNotificationRule: { + Name: "GetSystemNotificationRule", Group: "SystemNotificationRule", }, - CheckSystemNotificationRuleName: { - Name: "CheckSystemNotificationRuleName", + CheckSystemNotificationRuleName: { + Name: "CheckSystemNotificationRuleName", Group: "SystemNotificationRule", }, - DeleteSystemNotificationRule: { - Name: "DeleteSystemNotificationRule", + DeleteSystemNotificationRule: { + Name: "DeleteSystemNotificationRule", Group: "SystemNotificationRule", }, - UpdateSystemNotificationRule: { - Name: "UpdateSystemNotificationRule", + UpdateSystemNotificationRule: { + Name: "UpdateSystemNotificationRule", Group: "SystemNotificationRule", }, - MakeDefaultSystemNotificationRules: { - Name: "MakeDefaultSystemNotificationRules", + MakeDefaultSystemNotificationRules: { + Name: "MakeDefaultSystemNotificationRules", Group: "SystemNotificationRule", }, - CreateSystemNotification: { - Name: "CreateSystemNotification", + CreateSystemNotification: { + Name: "CreateSystemNotification", Group: "SystemNotification", }, - GetSystemNotifications: { - Name: "GetSystemNotifications", + GetSystemNotifications: { + Name: "GetSystemNotifications", Group: "SystemNotification", }, - GetSystemNotification: { - Name: "GetSystemNotification", + GetSystemNotification: { + Name: "GetSystemNotification", Group: "SystemNotification", }, - DeleteSystemNotification: { - Name: "DeleteSystemNotification", + DeleteSystemNotification: { + Name: "DeleteSystemNotification", Group: "SystemNotification", }, - UpdateSystemNotification: { - Name: "UpdateSystemNotification", + UpdateSystemNotification: { + Name: "UpdateSystemNotification", Group: "SystemNotification", }, - CreateSystemNotificationAction: { - Name: "CreateSystemNotificationAction", + CreateSystemNotificationAction: { + Name: "CreateSystemNotificationAction", Group: "SystemNotification", }, - GetPolicyNotifications: { - Name: "GetPolicyNotifications", + GetPolicyNotifications: { + Name: "GetPolicyNotifications", Group: "PolicyNotification", }, - GetPolicyNotification: { - Name: "GetPolicyNotification", + GetPolicyNotification: { + Name: "GetPolicyNotification", Group: "PolicyNotification", }, - GetStacks: { - Name: "GetStacks", + GetStacks: { + Name: "GetStacks", Group: "Stack", }, - CreateStack: { - Name: "CreateStack", + CreateStack: { + Name: "CreateStack", Group: "Stack", }, - CheckStackName: { - Name: "CheckStackName", + CheckStackName: { + Name: "CheckStackName", Group: "Stack", }, - GetStack: { - Name: "GetStack", + GetStack: { + Name: "GetStack", Group: "Stack", }, - UpdateStack: { - Name: "UpdateStack", + UpdateStack: { + Name: "UpdateStack", Group: "Stack", }, - DeleteStack: { - Name: "DeleteStack", + DeleteStack: { + Name: "DeleteStack", Group: "Stack", }, - GetStackKubeConfig: { - Name: "GetStackKubeConfig", + GetStackKubeconfig: { + Name: "GetStackKubeconfig", Group: "Stack", }, - GetStackStatus: { - Name: "GetStackStatus", + GetStackStatus: { + Name: "GetStackStatus", Group: "Stack", }, - SetFavoriteStack: { - Name: "SetFavoriteStack", + SetFavoriteStack: { + Name: "SetFavoriteStack", Group: "Stack", }, - DeleteFavoriteStack: { - Name: "DeleteFavoriteStack", + DeleteFavoriteStack: { + Name: "DeleteFavoriteStack", Group: "Stack", }, - InstallStack: { - Name: "InstallStack", + InstallStack: { + Name: "InstallStack", Group: "Stack", }, - CreateProject: { - Name: "CreateProject", + CreateProject: { + Name: "CreateProject", Group: "Project", }, - GetProjectRoles: { - Name: "GetProjectRoles", + GetProjectRoles: { + Name: "GetProjectRoles", Group: "Project", }, - GetProjectRole: { - Name: "GetProjectRole", + GetProjectRole: { + Name: "GetProjectRole", Group: "Project", }, - GetProjects: { - Name: "GetProjects", + GetProjects: { + Name: "GetProjects", Group: "Project", }, - GetProject: { - Name: "GetProject", + GetProject: { + Name: "GetProject", Group: "Project", }, - UpdateProject: { - Name: "UpdateProject", + UpdateProject: { + Name: "UpdateProject", Group: "Project", }, - DeleteProject: { - Name: "DeleteProject", + DeleteProject: { + Name: "DeleteProject", Group: "Project", }, - AddProjectMember: { - Name: "AddProjectMember", + AddProjectMember: { + Name: "AddProjectMember", Group: "Project", }, - GetProjectMember: { - Name: "GetProjectMember", + GetProjectMember: { + Name: "GetProjectMember", Group: "Project", }, - GetProjectMembers: { - Name: "GetProjectMembers", + GetProjectMembers: { + Name: "GetProjectMembers", Group: "Project", }, - RemoveProjectMember: { - Name: "RemoveProjectMember", + RemoveProjectMember: { + Name: "RemoveProjectMember", Group: "Project", }, - UpdateProjectMemberRole: { - Name: "UpdateProjectMemberRole", + UpdateProjectMemberRole: { + Name: "UpdateProjectMemberRole", Group: "Project", }, - CreateProjectNamespace: { - Name: "CreateProjectNamespace", + CreateProjectNamespace: { + Name: "CreateProjectNamespace", Group: "Project", }, - GetProjectNamespaces: { - Name: "GetProjectNamespaces", + GetProjectNamespaces: { + Name: "GetProjectNamespaces", Group: "Project", }, - GetProjectNamespace: { - Name: "GetProjectNamespace", + GetProjectNamespace: { + Name: "GetProjectNamespace", Group: "Project", }, - UpdateProjectNamespace: { - Name: "UpdateProjectNamespace", + UpdateProjectNamespace: { + Name: "UpdateProjectNamespace", Group: "Project", }, - DeleteProjectNamespace: { - Name: "DeleteProjectNamespace", + DeleteProjectNamespace: { + Name: "DeleteProjectNamespace", Group: "Project", }, - SetFavoriteProject: { - Name: "SetFavoriteProject", + SetFavoriteProject: { + Name: "SetFavoriteProject", Group: "Project", }, - SetFavoriteProjectNamespace: { - Name: "SetFavoriteProjectNamespace", + SetFavoriteProjectNamespace: { + Name: "SetFavoriteProjectNamespace", Group: "Project", }, - UnSetFavoriteProject: { - Name: "UnSetFavoriteProject", + UnSetFavoriteProject: { + Name: "UnSetFavoriteProject", Group: "Project", }, - UnSetFavoriteProjectNamespace: { - Name: "UnSetFavoriteProjectNamespace", + UnSetFavoriteProjectNamespace: { + Name: "UnSetFavoriteProjectNamespace", Group: "Project", }, - GetProjectKubeconfig: { - Name: "GetProjectKubeconfig", + GetProjectKubeconfig: { + Name: "GetProjectKubeconfig", Group: "Project", }, - GetProjectNamespaceK8sResources: { - Name: "GetProjectNamespaceK8sResources", + GetProjectNamespaceK8sResources: { + Name: "GetProjectNamespaceK8sResources", Group: "Project", }, - GetProjectNamespaceKubeconfig: { - Name: "GetProjectNamespaceKubeconfig", + GetProjectNamespaceKubeconfig: { + Name: "GetProjectNamespaceKubeconfig", Group: "Project", }, - GetAudits: { - Name: "GetAudits", + GetAudits: { + Name: "GetAudits", Group: "Audit", }, - GetAudit: { - Name: "GetAudit", + GetAudit: { + Name: "GetAudit", Group: "Audit", }, - DeleteAudit: { - Name: "DeleteAudit", + DeleteAudit: { + Name: "DeleteAudit", Group: "Audit", }, - CreateTksRole: { - Name: "CreateTksRole", + CreateTksRole: { + Name: "CreateTksRole", Group: "Role", }, - ListTksRoles: { - Name: "ListTksRoles", + ListTksRoles: { + Name: "ListTksRoles", Group: "Role", }, - GetTksRole: { - Name: "GetTksRole", + GetTksRole: { + Name: "GetTksRole", Group: "Role", }, - DeleteTksRole: { - Name: "DeleteTksRole", + DeleteTksRole: { + Name: "DeleteTksRole", Group: "Role", }, - UpdateTksRole: { - Name: "UpdateTksRole", + UpdateTksRole: { + Name: "UpdateTksRole", Group: "Role", }, - GetPermissionsByRoleId: { - Name: "GetPermissionsByRoleId", + GetPermissionsByRoleId: { + Name: "GetPermissionsByRoleId", Group: "Role", }, - UpdatePermissionsByRoleId: { - Name: "UpdatePermissionsByRoleId", + UpdatePermissionsByRoleId: { + Name: "UpdatePermissionsByRoleId", Group: "Role", }, - IsRoleNameExisted: { - Name: "IsRoleNameExisted", + IsRoleNameExisted: { + Name: "IsRoleNameExisted", Group: "Role", }, - AppendUsersToRole: { - Name: "AppendUsersToRole", + AppendUsersToRole: { + Name: "AppendUsersToRole", Group: "Role", }, - GetUsersInRoleId: { - Name: "GetUsersInRoleId", + GetUsersInRoleId: { + Name: "GetUsersInRoleId", Group: "Role", }, - RemoveUsersFromRole: { - Name: "RemoveUsersFromRole", + RemoveUsersFromRole: { + Name: "RemoveUsersFromRole", Group: "Role", }, - GetPermissionTemplates: { - Name: "GetPermissionTemplates", + GetPermissionTemplates: { + Name: "GetPermissionTemplates", Group: "Permission", }, - Admin_CreateUser: { - Name: "Admin_CreateUser", + Admin_CreateUser: { + Name: "Admin_CreateUser", Group: "Admin_User", }, - Admin_ListUser: { - Name: "Admin_ListUser", + Admin_ListUser: { + Name: "Admin_ListUser", Group: "Admin_User", }, - Admin_GetUser: { - Name: "Admin_GetUser", + Admin_GetUser: { + Name: "Admin_GetUser", Group: "Admin_User", }, - Admin_DeleteUser: { - Name: "Admin_DeleteUser", + Admin_DeleteUser: { + Name: "Admin_DeleteUser", Group: "Admin_User", }, - Admin_UpdateUser: { - Name: "Admin_UpdateUser", + Admin_UpdateUser: { + Name: "Admin_UpdateUser", Group: "Admin_User", }, - Admin_ListTksRoles: { - Name: "Admin_ListTksRoles", + Admin_ListTksRoles: { + Name: "Admin_ListTksRoles", Group: "Admin Role", }, - Admin_GetTksRole: { - Name: "Admin_GetTksRole", + Admin_GetTksRole: { + Name: "Admin_GetTksRole", Group: "Admin Role", }, - Admin_GetProjects: { - Name: "Admin_GetProjects", + Admin_GetProjects: { + Name: "Admin_GetProjects", Group: "Admin Project", }, - Admin_ListPolicyTemplate: { - Name: "Admin_ListPolicyTemplate", + Admin_ListPolicyTemplate: { + Name: "Admin_ListPolicyTemplate", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplate: { - Name: "Admin_CreatePolicyTemplate", + Admin_CreatePolicyTemplate: { + Name: "Admin_CreatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplate: { - Name: "Admin_DeletePolicyTemplate", + Admin_DeletePolicyTemplate: { + Name: "Admin_DeletePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplate: { - Name: "Admin_GetPolicyTemplate", + Admin_GetPolicyTemplate: { + Name: "Admin_GetPolicyTemplate", Group: "PolicyTemplate", }, - Admin_UpdatePolicyTemplate: { - Name: "Admin_UpdatePolicyTemplate", + Admin_UpdatePolicyTemplate: { + Name: "Admin_UpdatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateDeploy: { - Name: "Admin_GetPolicyTemplateDeploy", + Admin_GetPolicyTemplateDeploy: { + Name: "Admin_GetPolicyTemplateDeploy", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateStatistics: { - Name: "Admin_ListPolicyTemplateStatistics", + Admin_ListPolicyTemplateStatistics: { + Name: "Admin_ListPolicyTemplateStatistics", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateVersions: { - Name: "Admin_ListPolicyTemplateVersions", + Admin_ListPolicyTemplateVersions: { + Name: "Admin_ListPolicyTemplateVersions", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplateVersion: { - Name: "Admin_CreatePolicyTemplateVersion", + Admin_CreatePolicyTemplateVersion: { + Name: "Admin_CreatePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplateVersion: { - Name: "Admin_DeletePolicyTemplateVersion", + Admin_DeletePolicyTemplateVersion: { + Name: "Admin_DeletePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateVersion: { - Name: "Admin_GetPolicyTemplateVersion", + Admin_GetPolicyTemplateVersion: { + Name: "Admin_GetPolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateKind: { - Name: "Admin_ExistsPolicyTemplateKind", + Admin_ExistsPolicyTemplateKind: { + Name: "Admin_ExistsPolicyTemplateKind", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateName: { - Name: "Admin_ExistsPolicyTemplateName", + Admin_ExistsPolicyTemplateName: { + Name: "Admin_ExistsPolicyTemplateName", Group: "PolicyTemplate", }, - Admin_ExtractParameters: { - Name: "Admin_ExtractParameters", + Admin_ExtractParameters: { + Name: "Admin_ExtractParameters", Group: "PolicyTemplate", }, - Admin_AddPermittedPolicyTemplatesForOrganization: { - Name: "Admin_AddPermittedPolicyTemplatesForOrganization", + Admin_AddPermittedPolicyTemplatesForOrganization: { + Name: "Admin_AddPermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - Admin_DeletePermittedPolicyTemplatesForOrganization: { - Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", + Admin_DeletePermittedPolicyTemplatesForOrganization: { + Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - ListStackPolicyStatus: { - Name: "ListStackPolicyStatus", + ListStackPolicyStatus: { + Name: "ListStackPolicyStatus", Group: "StackPolicyStatus", }, - GetStackPolicyTemplateStatus: { - Name: "GetStackPolicyTemplateStatus", + GetStackPolicyTemplateStatus: { + Name: "GetStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - UpdateStackPolicyTemplateStatus: { - Name: "UpdateStackPolicyTemplateStatus", + UpdateStackPolicyTemplateStatus: { + Name: "UpdateStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - GetMandatoryPolicies: { - Name: "GetMandatoryPolicies", + GetMandatoryPolicies: { + Name: "GetMandatoryPolicies", Group: "Policy", }, - SetMandatoryPolicies: { - Name: "SetMandatoryPolicies", + SetMandatoryPolicies: { + Name: "SetMandatoryPolicies", Group: "Policy", }, - GetPolicyStatistics: { - Name: "GetPolicyStatistics", + GetPolicyStatistics: { + Name: "GetPolicyStatistics", Group: "Policy", }, - ListPolicy: { - Name: "ListPolicy", + ListPolicy: { + Name: "ListPolicy", Group: "Policy", }, - CreatePolicy: { - Name: "CreatePolicy", + CreatePolicy: { + Name: "CreatePolicy", Group: "Policy", }, - DeletePolicy: { - Name: "DeletePolicy", + DeletePolicy: { + Name: "DeletePolicy", Group: "Policy", }, - GetPolicy: { - Name: "GetPolicy", + GetPolicy: { + Name: "GetPolicy", Group: "Policy", }, - UpdatePolicy: { - Name: "UpdatePolicy", + UpdatePolicy: { + Name: "UpdatePolicy", Group: "Policy", }, - UpdatePolicyTargetClusters: { - Name: "UpdatePolicyTargetClusters", + UpdatePolicyTargetClusters: { + Name: "UpdatePolicyTargetClusters", Group: "Policy", }, - ExistsPolicyName: { - Name: "ExistsPolicyName", + ExistsPolicyName: { + Name: "ExistsPolicyName", Group: "Policy", }, - ExistsPolicyResourceName: { - Name: "ExistsPolicyResourceName", + ExistsPolicyResourceName: { + Name: "ExistsPolicyResourceName", Group: "Policy", }, - GetPolicyEdit: { - Name: "GetPolicyEdit", + GetPolicyEdit: { + Name: "GetPolicyEdit", Group: "Policy", }, - AddPoliciesForStack: { - Name: "AddPoliciesForStack", + AddPoliciesForStack: { + Name: "AddPoliciesForStack", Group: "Policy", }, - DeletePoliciesForStack: { - Name: "DeletePoliciesForStack", + DeletePoliciesForStack: { + Name: "DeletePoliciesForStack", Group: "Policy", }, - StackPolicyStatistics: { - Name: "StackPolicyStatistics", + StackPolicyStatistics: { + Name: "StackPolicyStatistics", Group: "Policy", }, - ListPolicyTemplate: { - Name: "ListPolicyTemplate", + ListPolicyTemplate: { + Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplate: { - Name: "CreatePolicyTemplate", + CreatePolicyTemplate: { + Name: "CreatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplate: { - Name: "DeletePolicyTemplate", + DeletePolicyTemplate: { + Name: "DeletePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplate: { - Name: "GetPolicyTemplate", + GetPolicyTemplate: { + Name: "GetPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - UpdatePolicyTemplate: { - Name: "UpdatePolicyTemplate", + UpdatePolicyTemplate: { + Name: "UpdatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateDeploy: { - Name: "GetPolicyTemplateDeploy", + GetPolicyTemplateDeploy: { + Name: "GetPolicyTemplateDeploy", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateStatistics: { - Name: "ListPolicyTemplateStatistics", + ListPolicyTemplateStatistics: { + Name: "ListPolicyTemplateStatistics", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateVersions: { - Name: "ListPolicyTemplateVersions", + ListPolicyTemplateVersions: { + Name: "ListPolicyTemplateVersions", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplateVersion: { - Name: "CreatePolicyTemplateVersion", + CreatePolicyTemplateVersion: { + Name: "CreatePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplateVersion: { - Name: "DeletePolicyTemplateVersion", + DeletePolicyTemplateVersion: { + Name: "DeletePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateVersion: { - Name: "GetPolicyTemplateVersion", + GetPolicyTemplateVersion: { + Name: "GetPolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateKind: { - Name: "ExistsPolicyTemplateKind", + ExistsPolicyTemplateKind: { + Name: "ExistsPolicyTemplateKind", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateName: { - Name: "ExistsPolicyTemplateName", + ExistsPolicyTemplateName: { + Name: "ExistsPolicyTemplateName", Group: "OrganizationPolicyTemplate", }, - ExtractParameters: { - Name: "ExtractParameters", + ExtractParameters: { + Name: "ExtractParameters", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateExample: { - Name: "ListPolicyTemplateExample", + ListPolicyTemplateExample: { + Name: "ListPolicyTemplateExample", Group: "PolicyTemplateExample", }, - GetPolicyTemplateExample: { - Name: "GetPolicyTemplateExample", + GetPolicyTemplateExample: { + Name: "GetPolicyTemplateExample", Group: "PolicyTemplateExample", }, - UpdatePolicyTemplateExample: { - Name: "UpdatePolicyTemplateExample", + UpdatePolicyTemplateExample: { + Name: "UpdatePolicyTemplateExample", Group: "PolicyTemplateExample", }, - DeletePolicyTemplateExample: { - Name: "DeletePolicyTemplateExample", + DeletePolicyTemplateExample: { + Name: "DeletePolicyTemplateExample", Group: "PolicyTemplateExample", }, - CompileRego: { - Name: "CompileRego", + CompileRego: { + Name: "CompileRego", Group: "Utility", }, } + func (e Endpoint) String() string { switch e { case Login: @@ -1194,8 +1195,8 @@ func (e Endpoint) String() string { return "UpdateStack" case DeleteStack: return "DeleteStack" - case GetStackKubeConfig: - return "GetStackKubeConfig" + case GetStackKubeconfig: + return "GetStackKubeconfig" case GetStackStatus: return "GetStackStatus" case SetFavoriteStack: @@ -1666,8 +1667,8 @@ func GetEndpoint(name string) Endpoint { return UpdateStack case "DeleteStack": return DeleteStack - case "GetStackKubeConfig": - return GetStackKubeConfig + case "GetStackKubeconfig": + return GetStackKubeconfig case "GetStackStatus": return GetStackStatus case "SetFavoriteStack": diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index bd49b31b..3043ce02 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -605,8 +605,8 @@ func (h *ClusterHandler) GetClusterApplicationsKubeInfo(w http.ResponseWriter, r */ } -func (h *ClusterHandler) GetClusterKubeConfig(w http.ResponseWriter, r *http.Request) { - // GetClusterKubeConfig godoc +func (h *ClusterHandler) GetClusterKubeconfig(w http.ResponseWriter, r *http.Request) { + // GetClusterKubeconfig godoc // @Tags Clusters // @Summary Get kubernetes kubeconfig // @Description Get kubernetes kubeconfig for cluster @@ -626,7 +626,7 @@ func (h *ClusterHandler) GetClusterKubeConfig(w http.ResponseWriter, r *http.Req organizationId := r.Header.Get("OrganizationId") - kubeconfig, err := helper.GetKubeConfig(clusterId) + kubeconfig, err := helper.GetKubeconfig(clusterId) if err != nil { ErrorJSON(w, r, "failed to get admin cluster", http.StatusBadRequest) return diff --git a/internal/delivery/http/project.go b/internal/delivery/http/project.go index 0e5df939..5389c2a1 100644 --- a/internal/delivery/http/project.go +++ b/internal/delivery/http/project.go @@ -1708,7 +1708,7 @@ func (p ProjectHandler) UnSetFavoriteProjectNamespace(w http.ResponseWriter, r * // @Param organizationId path string true "Organization ID" // @Param projectId path string true "Project ID" // @Success 200 {object} domain.GetProjectKubeconfigResponse -// @Router /organizations/{organizationId}/projects/{projectId}/kube-config [get] +// @Router /organizations/{organizationId}/projects/{projectId}/kubeconfig [get] // @Security JWT func (p ProjectHandler) GetProjectKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1863,8 +1863,8 @@ func (p ProjectHandler) GetProjectNamespaceResourcesUsage(w http.ResponseWriter, // @Param projectId path string true "Project ID" // @Param stackId path string true "Stack ID" // @Param projectNamespace path string true "Project Namespace" -// @Success 200 {object} domain.GetProjectNamespaceKubeConfigResponse -// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config [get] +// @Success 200 {object} domain.GetProjectNamespaceKubeconfigResponse +// @Router /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig [get] // @Security JWT func (p ProjectHandler) GetProjectNamespaceKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -1898,8 +1898,8 @@ func (p ProjectHandler) GetProjectNamespaceKubeconfig(w http.ResponseWriter, r * return } - out := domain.GetProjectNamespaceKubeConfigResponse{ - KubeConfig: kubeconfig, + out := domain.GetProjectNamespaceKubeconfigResponse{ + Kubeconfig: kubeconfig, } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 3a3c5423..2afe1705 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -398,19 +398,19 @@ func (h *StackHandler) CheckStackName(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } -// GetStackKubeConfig godoc +// GetStackKubeconfig godoc // // @Tags Stacks -// @Summary Get KubeConfig by stack -// @Description Get KubeConfig by stack +// @Summary Get Kubeconfig by stack +// @Description Get Kubeconfig by stack // @Accept json // @Produce json // @Param organizationId path string true "organizationId" // @Param stackId path string true "organizationId" -// @Success 200 {object} domain.GetStackKubeConfigResponse +// @Success 200 {object} domain.GetStackKubeconfigResponse // @Router /organizations/{organizationId}/stacks/{stackId}/kube-config [get] // @Security JWT -func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request) { +func (h *StackHandler) GetStackKubeconfig(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) _, ok := vars["organizationId"] if !ok { @@ -429,14 +429,14 @@ func (h *StackHandler) GetStackKubeConfig(w http.ResponseWriter, r *http.Request return } - kubeConfig, err := h.usecase.GetKubeConfig(r.Context(), domain.StackId(strId)) + kubeconfig, err := h.usecase.GetKubeconfig(r.Context(), domain.StackId(strId)) if err != nil { ErrorJSON(w, r, err) return } - var out = domain.GetStackKubeConfigResponse{ - KubeConfig: kubeConfig, + var out = domain.GetStackKubeconfigResponse{ + Kubeconfig: kubeconfig, } ResponseJSON(w, r, http.StatusOK, out) diff --git a/internal/middleware/auth/role/default.go b/internal/middleware/auth/role/default.go index 70f1f256..f83306c7 100644 --- a/internal/middleware/auth/role/default.go +++ b/internal/middleware/auth/role/default.go @@ -122,7 +122,7 @@ var defaultPermissionOfAdmin = defaultPermission{ internalApi.GetStack, internalApi.UpdateStack, internalApi.DeleteStack, - internalApi.GetStackKubeConfig, + internalApi.GetStackKubeconfig, internalApi.GetStackStatus, internalApi.SetFavoriteStack, internalApi.DeleteFavoriteStack, @@ -230,7 +230,7 @@ var defaultPermissionOfUser = defaultPermission{ // Stack internalApi.GetStacks, internalApi.GetStack, - internalApi.GetStackKubeConfig, + internalApi.GetStackKubeconfig, internalApi.GetStackStatus, internalApi.SetFavoriteStack, internalApi.DeleteFavoriteStack, diff --git a/internal/model/permission.go b/internal/model/permission.go index be5e3abe..50a15c7c 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -197,7 +197,7 @@ func newStack() *Permission { api.GetStack, api.CheckStackName, api.GetStackStatus, - api.GetStackKubeConfig, + api.GetStackKubeconfig, api.SetFavoriteStack, api.DeleteFavoriteStack, diff --git a/internal/route/route.go b/internal/route/route.go index cc7502a3..06acc7ba 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -259,7 +259,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetStack, http.HandlerFunc(stackHandler.GetStack))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateStack, http.HandlerFunc(stackHandler.UpdateStack))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteStack, http.HandlerFunc(stackHandler.DeleteStack))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/kube-config", customMiddleware.Handle(internalApi.GetStackKubeConfig, http.HandlerFunc(stackHandler.GetStackKubeConfig))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/kubeconfig", customMiddleware.Handle(internalApi.GetStackKubeconfig, http.HandlerFunc(stackHandler.GetStackKubeconfig))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/status", customMiddleware.Handle(internalApi.GetStackStatus, http.HandlerFunc(stackHandler.GetStackStatus))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", customMiddleware.Handle(internalApi.SetFavoriteStack, http.HandlerFunc(stackHandler.SetFavorite))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}/favorite", customMiddleware.Handle(internalApi.DeleteFavoriteStack, http.HandlerFunc(stackHandler.DeleteFavorite))).Methods(http.MethodDelete) @@ -290,8 +290,8 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetProjectNamespace, http.HandlerFunc(projectHandler.GetProjectNamespace))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateProjectNamespace, http.HandlerFunc(projectHandler.UpdateProjectNamespace))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}", customMiddleware.Handle(internalApi.DeleteProjectNamespace, http.HandlerFunc(projectHandler.DeleteProjectNamespace))).Methods(http.MethodDelete) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config", customMiddleware.Handle(internalApi.GetProjectNamespaceKubeconfig, http.HandlerFunc(projectHandler.GetProjectNamespaceKubeconfig))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kube-config", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectNamespaceKubeconfig, http.HandlerFunc(projectHandler.GetProjectNamespaceKubeconfig))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/projects/{projectId}/kubeconfig", customMiddleware.Handle(internalApi.GetProjectKubeconfig, http.HandlerFunc(projectHandler.GetProjectKubeconfig))).Methods(http.MethodGet) auditHandler := delivery.NewAuditHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/admin/audits", customMiddleware.Handle(internalApi.GetAudits, http.HandlerFunc(auditHandler.GetAudits))).Methods(http.MethodGet) diff --git a/internal/usecase/project.go b/internal/usecase/project.go index 2ad792a4..065d196d 100644 --- a/internal/usecase/project.go +++ b/internal/usecase/project.go @@ -590,7 +590,7 @@ func (u *ProjectUsecase) MayRemoveRequiredSetupForCluster(ctx context.Context, o return nil } func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) + kubeconfig, err := kubernetes.GetKubeconfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { return errors.Wrap(err, "Failed to get kubeconfig.") } @@ -613,7 +613,7 @@ func (u *ProjectUsecase) createK8SInitialResource(ctx context.Context, organizat return nil } func (u *ProjectUsecase) deleteK8SInitialResource(ctx context.Context, organizationId string, projectId string, stackId string) error { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) + kubeconfig, err := kubernetes.GetKubeconfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to get kubeconfig.") @@ -665,7 +665,7 @@ func (u *ProjectUsecase) deleteKeycloakClientRoles(ctx context.Context, organiza return nil } func (u *ProjectUsecase) CreateK8SNSRoleBinding(ctx context.Context, organizationId string, projectId string, stackId string, namespace string) error { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) + kubeconfig, err := kubernetes.GetKubeconfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to get kubeconfig.") @@ -731,13 +731,13 @@ func (u *ProjectUsecase) unassignKeycloakClientRoleToMember(ctx context.Context, } func (u *ProjectUsecase) GetProjectNamespaceKubeconfig(ctx context.Context, organizationId string, projectId string, namespace string, stackId domain.StackId) (string, error) { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId.String(), kubernetes.KubeconfigForUser) + kubeconfig, err := kubernetes.GetKubeconfig(ctx, stackId.String(), kubernetes.KubeconfigForUser) if err != nil { log.Error(ctx, err) return "", errors.Wrap(err, "Failed to get kubeconfig.") } - type kubeConfigType struct { + type kubeconfigType struct { APIVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` Clusters []struct { @@ -759,7 +759,7 @@ func (u *ProjectUsecase) GetProjectNamespaceKubeconfig(ctx context.Context, orga Users []interface{} `yaml:"users,omitempty"` } - var config kubeConfigType + var config kubeconfigType err = yaml.Unmarshal(kubeconfig, &config) if err != nil { log.Error(ctx, err) @@ -784,7 +784,7 @@ func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationI return "", errors.Wrap(err, "Failed to retrieve project namespaces.") } - type kubeConfigType struct { + type kubeconfigType struct { APIVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` Clusters []struct { @@ -808,13 +808,13 @@ func (u *ProjectUsecase) GetProjectKubeconfig(ctx context.Context, organizationI kubeconfigs := make([]string, 0) for _, pn := range projectNamespaces { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, pn.StackId, kubernetes.KubeconfigForUser) + kubeconfig, err := kubernetes.GetKubeconfig(ctx, pn.StackId, kubernetes.KubeconfigForUser) if err != nil { log.Error(ctx, err) return "", errors.Wrap(err, "Failed to retrieve kubeconfig.") } - var config kubeConfigType + var config kubeconfigType err = yaml.Unmarshal(kubeconfig, &config) if err != nil { log.Error(ctx, err) @@ -949,7 +949,7 @@ func (u *ProjectUsecase) GetResourcesUsage(ctx context.Context, thanosClient tha } func (u *ProjectUsecase) EnsureNamespaceForCluster(ctx context.Context, organizationId string, stackId string, namespaceName string) error { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId, kubernetes.KubeconfigForAdmin) + kubeconfig, err := kubernetes.GetKubeconfig(ctx, stackId, kubernetes.KubeconfigForAdmin) if err != nil { log.Error(ctx, err) return errors.Wrap(err, "Failed to get kubeconfig.") diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index 7279be2c..ff7299a0 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -34,7 +34,7 @@ type IStackUsecase interface { Install(ctx context.Context, stackId domain.StackId) (err error) Update(ctx context.Context, dto model.Stack) error Delete(ctx context.Context, dto model.Stack) error - GetKubeConfig(ctx context.Context, stackId domain.StackId) (kubeConfig string, err error) + GetKubeconfig(ctx context.Context, stackId domain.StackId) (kubeconfig string, err error) GetStepStatus(ctx context.Context, stackId domain.StackId) (out []domain.StackStepStatus, stackStatus string, err error) SetFavorite(ctx context.Context, stackId domain.StackId) error DeleteFavorite(ctx context.Context, stackId domain.StackId) error @@ -577,14 +577,13 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) return nil } -func (u *StackUsecase) GetKubeConfig(ctx context.Context, stackId domain.StackId) (kubeConfig string, err error) { - kubeconfig, err := kubernetes.GetKubeConfig(ctx, stackId.String(), kubernetes.KubeconfigForUser) - //kubeconfig, err := kubernetes.GetKubeConfig("cmsai5k5l") +func (u *StackUsecase) GetKubeconfig(ctx context.Context, stackId domain.StackId) (kubeconfig string, err error) { + kubeconfigArr, err := kubernetes.GetKubeconfig(ctx, stackId.String(), kubernetes.KubeconfigForUser) if err != nil { return "", err } - return string(kubeconfig[:]), nil + return string(kubeconfigArr[:]), nil } // [TODO] need more pretty... diff --git a/pkg/domain/project.go b/pkg/domain/project.go index 39f7288c..e26e1528 100644 --- a/pkg/domain/project.go +++ b/pkg/domain/project.go @@ -198,6 +198,6 @@ type GetProjectNamespaceResourcesUsageResponse struct { ResourcesUsage ProjectNamespaceResourcesUsage `json:"resourcesUsage"` } -type GetProjectNamespaceKubeConfigResponse struct { - KubeConfig string `json:"kubeconfig"` +type GetProjectNamespaceKubeconfigResponse struct { + Kubeconfig string `json:"kubeconfig"` } diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 8cbbfec6..343b2731 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -168,8 +168,8 @@ type CheckStackNameResponse struct { Existed bool `json:"existed"` } -type GetStackKubeConfigResponse struct { - KubeConfig string `json:"kubeconfig"` +type GetStackKubeconfigResponse struct { + Kubeconfig string `json:"kubeconfig"` } type GetStackStatusResponse struct { diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index 34cc90fc..834f4a92 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -25,11 +25,11 @@ import ( "github.com/openinfradev/tks-api/pkg/log" ) -type KubeConfigType string +type KubeconfigType string const ( - KubeconfigForAdmin KubeConfigType = "admin" - KubeconfigForUser KubeConfigType = "user" + KubeconfigForAdmin KubeconfigType = "admin" + KubeconfigForUser KubeconfigType = "user" ) func getAdminConfig(ctx context.Context) (*rest.Config, error) { @@ -123,7 +123,7 @@ func GetAwsAccountIdSecret(ctx context.Context) (awsAccountId string, err error) return } -func GetKubeConfig(ctx context.Context, clusterId string, configType KubeConfigType) ([]byte, error) { +func GetKubeconfig(ctx context.Context, clusterId string, configType KubeconfigType) ([]byte, error) { clientset, err := GetClientAdminCluster(ctx) if err != nil { return nil, err @@ -624,7 +624,7 @@ func generateClusterRoleToRoleBinding(groupName, objName, roleName, namespace st } func MergeKubeconfigsWithSingleUser(kubeconfigs []string) (string, error) { - type kubeConfigType struct { + type kubeconfigType struct { APIVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` Clusters []struct { @@ -652,8 +652,8 @@ func MergeKubeconfigsWithSingleUser(kubeconfigs []string) (string, error) { encoder.SetIndent(2) - var config kubeConfigType - var combindConfig kubeConfigType + var config kubeconfigType + var combindConfig kubeconfigType for _, kc := range kubeconfigs { err := yaml.Unmarshal([]byte(kc), &config) if err != nil { diff --git a/pkg/kubernetes/kubernetes_test.go b/pkg/kubernetes/kubernetes_test.go index 647d57a1..d8574922 100644 --- a/pkg/kubernetes/kubernetes_test.go +++ b/pkg/kubernetes/kubernetes_test.go @@ -128,7 +128,7 @@ func TestRemoveRoleBinding(t *testing.T) { } func TestMergeKubeconfigsWithSingleUser(t *testing.T) { - type kubeConfigType struct { + type kubeconfigType struct { APIVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` Clusters []struct { @@ -150,7 +150,7 @@ func TestMergeKubeconfigsWithSingleUser(t *testing.T) { Users []interface{} `yaml:"users,omitempty"` } - inputObjs := []kubeConfigType{ + inputObjs := []kubeconfigType{ { APIVersion: "v1", Kind: "Config", @@ -280,7 +280,7 @@ func TestMergeKubeconfigsWithSingleUser(t *testing.T) { }, } - expected := kubeConfigType{ + expected := kubeconfigType{ APIVersion: "v1", Kind: "Config", Clusters: []struct { @@ -381,7 +381,7 @@ func TestMergeKubeconfigsWithSingleUser(t *testing.T) { t.Error(err) } - var result kubeConfigType + var result kubeconfigType if err := yaml.Unmarshal([]byte(r), &result); err != nil { t.Error(err) } From b3a5a733c180fe972f0f78ed90226eb983bd840f Mon Sep 17 00:00:00 2001 From: donggyu Date: Thu, 23 May 2024 10:28:03 +0900 Subject: [PATCH 466/502] trivial. --- combind-kubeconfig | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 combind-kubeconfig diff --git a/combind-kubeconfig b/combind-kubeconfig deleted file mode 100644 index 350db35b..00000000 --- a/combind-kubeconfig +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: "" -kind: "" -clusters: [] -contexts: [] From a42ed8ee4810510f2caa4c0cf0c7cb0595341df2 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 23 May 2024 14:50:56 +0900 Subject: [PATCH 467/502] trivial. add debug log --- internal/usecase/dashboard.go | 2 ++ pkg/thanos-client/client.go | 1 + 2 files changed, 3 insertions(+) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index a47f3fae..504afe6f 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -832,6 +832,8 @@ func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationI return nil, err } + log.Info(ctx, helper.ModelToJson(pm)) + // totalViolation: {"K8sRequiredLabels": {"violation_enforcement": 2}} totalViolation := make(map[string]map[string]int) diff --git a/pkg/thanos-client/client.go b/pkg/thanos-client/client.go index 4dcf93e5..ab017bbd 100644 --- a/pkg/thanos-client/client.go +++ b/pkg/thanos-client/client.go @@ -189,6 +189,7 @@ func (c *ThanosClientImpl) fetchRange(ctx context.Context, query string, start i query = url.QueryEscape(query) + rangeParam requestUrl := c.url + "/api/v1/query_range?query=" + query + log.Info(ctx, requestUrl) res, err := c.client.Get(requestUrl) if err != nil { return nil, err From d2c825cdfd2a2a4b2cc0918f7111dd818058f9b6 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 23 May 2024 16:01:47 +0900 Subject: [PATCH 468/502] feature. fix bug - policy violation --- api/swagger/docs.go | 4 ++-- api/swagger/swagger.json | 6 +++--- api/swagger/swagger.yaml | 4 ++-- internal/usecase/dashboard.go | 13 ++++++++----- pkg/thanos-client/client.go | 2 +- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index ccc20eb1..49a03108 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -6622,7 +6622,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/kube-config": { + "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { "get": { "security": [ { @@ -7463,7 +7463,7 @@ const docTemplate = `{ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig": { "get": { "security": [ { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 40c9d30a..6e5684c6 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -6616,7 +6616,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/kube-config": { + "/organizations/{organizationId}/projects/{projectId}/kubeconfig": { "get": { "security": [ { @@ -7457,7 +7457,7 @@ } } }, - "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config": { + "/organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig": { "get": { "security": [ { @@ -16946,4 +16946,4 @@ "in": "header" } } -} +} \ No newline at end of file diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 5541b25d..d35c272e 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -8529,7 +8529,7 @@ paths: summary: Check duplicate appServeAppName tags: - AppServeApps - /organizations/{organizationId}/projects/{projectId}/kube-config: + /organizations/{organizationId}/projects/{projectId}/kubeconfig: get: consumes: - application/json @@ -9076,7 +9076,7 @@ paths: summary: Get k8s resources for project namespace tags: - Projects - /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kube-config: + /organizations/{organizationId}/projects/{projectId}/namespaces/{projectNamespace}/stacks/{stackId}/kubeconfig: get: consumes: - application/json diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 504afe6f..6c108171 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -832,8 +832,6 @@ func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationI return nil, err } - log.Info(ctx, helper.ModelToJson(pm)) - // totalViolation: {"K8sRequiredLabels": {"violation_enforcement": 2}} totalViolation := make(map[string]map[string]int) @@ -852,10 +850,15 @@ func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationI if len(res.Metric.Violation) == 0 { continue } - count, err := strconv.Atoi(res.Value[1].(string)) - if err != nil { - count = 0 + + count := 0 + if res.Value != nil && len(res.Value) > 1 { + count, err = strconv.Atoi(res.Value[1].(string)) + if err != nil { + count = 0 + } } + violation := res.Metric.Violation if val, ok := totalViolation[policyTemplate][violation]; !ok { totalViolation[policyTemplate] = make(map[string]int) diff --git a/pkg/thanos-client/client.go b/pkg/thanos-client/client.go index ab017bbd..2462e635 100644 --- a/pkg/thanos-client/client.go +++ b/pkg/thanos-client/client.go @@ -189,7 +189,7 @@ func (c *ThanosClientImpl) fetchRange(ctx context.Context, query string, start i query = url.QueryEscape(query) + rangeParam requestUrl := c.url + "/api/v1/query_range?query=" + query - log.Info(ctx, requestUrl) + log.Info(ctx, "ferchRange : ", requestUrl) res, err := c.client.Get(requestUrl) if err != nil { return nil, err From f4e3a1f9d1e0a3b6c5e44e5c689768a4039ac787 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 23 May 2024 16:24:55 +0900 Subject: [PATCH 469/502] trivial. fix error for policyViolationTop5 --- internal/usecase/dashboard.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 6c108171..2dae8e63 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -1073,6 +1073,10 @@ func (u *DashboardUsecase) GetPolicyViolationTop5(ctx context.Context, organizat warnCount := 0 dryrunCount := 0 for _, result := range pvcm.Data.Result { + if result.Value == nil || len(result.Value) <= 1 { + continue + } + switch policy := result.Metric.ViolationEnforcement; policy { case "": denyCount, _ = strconv.Atoi(result.Value[1].(string)) From ede08c06f81f1356c9252851bd53623678799c37 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 23 May 2024 16:31:25 +0900 Subject: [PATCH 470/502] trivial. fix error code for thanosclient --- internal/usecase/dashboard.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/usecase/dashboard.go b/internal/usecase/dashboard.go index 2dae8e63..4877ea5d 100644 --- a/internal/usecase/dashboard.go +++ b/internal/usecase/dashboard.go @@ -815,7 +815,7 @@ func (u *DashboardUsecase) GetPolicyEnforcement(ctx context.Context, organizatio func (u *DashboardUsecase) GetPolicyViolation(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) { thanosClient, err := u.GetThanosClient(ctx, organizationId) if err != nil { - return nil, errors.Wrap(err, "failed to create thanos client") + return nil, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } durationSec, intervalSec := getDurationAndIntervalSec(duration, interval) @@ -950,7 +950,7 @@ func (u *DashboardUsecase) GetPolicyViolationLog(ctx context.Context, organizati func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId string) (*domain.GetDashboardWorkloadResponse, error) { thanosClient, err := u.GetThanosClient(ctx, organizationId) if err != nil { - return nil, errors.Wrap(err, "failed to create thanos client") + return nil, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } clusterIdStr, err := u.GetFlatClusterIds(ctx, organizationId) @@ -1027,7 +1027,7 @@ func (u *DashboardUsecase) GetWorkload(ctx context.Context, organizationId strin func (u *DashboardUsecase) GetPolicyViolationTop5(ctx context.Context, organizationId string, duration string, interval string) (*domain.BarChartData, error) { thanosClient, err := u.GetThanosClient(ctx, organizationId) if err != nil { - return nil, errors.Wrap(err, "failed to create thanos client") + return nil, httpErrors.NewInternalServerError(err, "D_INVALID_PRIMARY_STACK", "") } durationSec, intervalSec := getDurationAndIntervalSec(duration, interval) From 2d8134a1553fc59dd8bd9aec28b3449a3ed9fac8 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 23 May 2024 21:19:47 +0900 Subject: [PATCH 471/502] =?UTF-8?q?=EC=A0=95=EC=B1=85=20api=20match=20kind?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy.go | 204 ++++++++++++++++++++------ internal/policy-template/kind-util.go | 26 ++-- pkg/domain/policy.go | 30 ++-- 3 files changed, 190 insertions(+), 70 deletions(-) diff --git a/internal/delivery/http/policy.go b/internal/delivery/http/policy.go index 2555ac1a..710e43ed 100644 --- a/internal/delivery/http/policy.go +++ b/internal/delivery/http/policy.go @@ -1,9 +1,13 @@ package http import ( + "bytes" + "encoding/json" "fmt" "net/http" + "slices" "strconv" + "strings" "github.com/google/uuid" "github.com/gorilla/mux" @@ -81,34 +85,40 @@ func (h *PolicyHandler) CreatePolicy(w http.ResponseWriter, r *http.Request) { return } - if input.Match != nil && input.MatchYaml != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("both match and match yaml specified"), "P_INVALID_MATCH", "")) - return - } + // if input.Match != nil && input.MatchYaml != nil { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("both match and match yaml specified"), "P_INVALID_MATCH", "")) + // return + // } - if input.MatchYaml != nil { - var match domain.Match + // if input.MatchYaml != nil { + // var match domain.Match - err := yaml.Unmarshal([]byte(*input.MatchYaml), &match) + // err := yaml.Unmarshal([]byte(*input.MatchYaml), &match) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match yaml error: %s", err), "P_INVALID_MATCH", "")) - return - } + // if err != nil { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match yaml error: %s", err), "P_INVALID_MATCH", "")) + // return + // } - if err := ValidateDomainObject(match); err != nil { - ErrorJSON(w, r, err) - return - } - } else if input.Match != nil { - normaized, err := policytemplate.CheckAndNormalizeKinds(input.Match.Kinds) + // if err := ValidateDomainObject(match); err != nil { + // ErrorJSON(w, r, err) + // return + // } + // } else if input.Match != nil { + // normaized, err := policytemplate.CheckAndNormalizeKinds(input.Match.Kinds) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match error: %s", err), "P_INVALID_MATCH", "")) - return - } + // if err != nil { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match error: %s", err), "P_INVALID_MATCH", "")) + // return + // } + + // input.Match.Kinds = normaized + // } - input.Match.Kinds = normaized + match, matchYaml, err := ValidateAndGetMatch(input.Target) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "P_INVALID_MATCH", "")) + return } if len(input.PolicyResourceName) > 0 { @@ -125,6 +135,9 @@ func (h *PolicyHandler) CreatePolicy(w http.ResponseWriter, r *http.Request) { log.Info(r.Context(), err) } + dto.Match = match + dto.MatchYaml = matchYaml + policyId, err := h.usecase.Create(r.Context(), organizationId, dto) if err != nil { ErrorJSON(w, r, err) @@ -182,33 +195,39 @@ func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { return } - if input.Match != nil && input.MatchYaml != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("both match and match yaml specified"), "P_INVALID_MATCH", "")) - return - } + // if input.Match != nil && input.MatchYaml != nil { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("both match and match yaml specified"), "P_INVALID_MATCH", "")) + // return + // } - if input.MatchYaml != nil { - var match domain.Match + // if input.MatchYaml != nil { + // var match domain.Match - err := yaml.Unmarshal([]byte(*input.MatchYaml), &match) + // err := yaml.Unmarshal([]byte(*input.MatchYaml), &match) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match yaml error: %s", err), "P_INVALID_MATCH", "")) - return - } + // if err != nil { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match yaml error: %s", err), "P_INVALID_MATCH", "")) + // return + // } - if err := ValidateDomainObject(match); err != nil { - ErrorJSON(w, r, err) - return - } - } else if input.Match != nil { - normaized, err := policytemplate.CheckAndNormalizeKinds(input.Match.Kinds) - if err != nil { - ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match error: %s", err), "P_INVALID_MATCH", "")) - return - } + // if err := ValidateDomainObject(match); err != nil { + // ErrorJSON(w, r, err) + // return + // } + // } else if input.Match != nil { + // normaized, err := policytemplate.CheckAndNormalizeKinds(input.Match.Kinds) + // if err != nil { + // ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("match error: %s", err), "P_INVALID_MATCH", "")) + // return + // } - input.Match.Kinds = normaized + // input.Match.Kinds = normaized + // } + + match, matchYaml, err := ValidateAndGetMatch(input.Target) + if err != nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(err, "P_INVALID_MATCH", "")) + return } var templateId *uuid.UUID = nil @@ -225,7 +244,7 @@ func (h *PolicyHandler) UpdatePolicy(w http.ResponseWriter, r *http.Request) { err = h.usecase.Update(r.Context(), organizationId, id, input.Mandatory, input.PolicyName, input.Description, templateId, input.EnforcementAction, - input.Parameters, input.Match, input.MatchYaml, input.TargetClusterIds) + input.Parameters, match, matchYaml, input.TargetClusterIds) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) @@ -360,6 +379,8 @@ func (h *PolicyHandler) GetPolicy(w http.ResponseWriter, r *http.Request) { } } + out.Policy.Target = MatchAndMatchYamlToTarget(policy.Match, policy.MatchYaml) + ResponseJSON(w, r, http.StatusOK, out) } @@ -427,6 +448,8 @@ func (h *PolicyHandler) ListPolicy(w http.ResponseWriter, r *http.Request) { } } + out.Policies[i].Target = MatchAndMatchYamlToTarget(policy.Match, policy.MatchYaml) + if filledParameter { parameterSchema := policy.PolicyTemplate.ParametersSchema parameters := policy.Parameters @@ -964,6 +987,8 @@ func (h *PolicyHandler) GetPolicyEdit(w http.ResponseWriter, r *http.Request) { } } + out.Policy.Target = MatchAndMatchYamlToTarget(policy.Match, policy.MatchYaml) + parameterSchema := policy.PolicyTemplate.ParametersSchema parameters := policy.Parameters @@ -1187,3 +1212,92 @@ func (h *PolicyHandler) DeletePoliciesForStack(w http.ResponseWriter, r *http.Re ResponseJSON(w, r, http.StatusOK, nil) } + +func ValidateAndGetMatch(t *domain.Target) (match *domain.Match, matchYaml *string, err error) { + if t.Type != "simple" && t.Type != "yaml" { + return nil, nil, fmt.Errorf("invalid target type '%s'", t.Type) + } + + if t.Type == "simple" { + var simpleMatch domain.SimpleMatch + + jsonbytes := []byte(t.Value) + dec := json.NewDecoder(bytes.NewReader(jsonbytes)) + dec.DisallowUnknownFields() + err = dec.Decode(&simpleMatch) + + if err != nil { + return nil, nil, err + } + + kinds, err := policytemplate.CheckAndNormalizeKinds(simpleMatch.Kinds) + + if err != nil { + return nil, nil, err + } + + return &domain.Match{ + Namespaces: simpleMatch.Namespaces, + ExcludedNamespaces: simpleMatch.ExcludedNamespaces, + Kinds: kinds, + }, nil, nil + } else { + var match domain.Match + + stripped := strings.ReplaceAll(t.Value, "\r", "") + yamlbytes := []byte(stripped) + + dec := yaml.NewDecoder(bytes.NewReader(yamlbytes)) + dec.KnownFields(true) + err = dec.Decode(&match) + + if err != nil { + return nil, nil, err + } + + return nil, &t.Value, nil + } +} + +func MatchAndMatchYamlToTarget(match *domain.Match, matchYaml *string) *domain.Target { + if match != nil { + flattenKinds := []string{} + + for _, kind := range match.Kinds { + for _, kindkind := range kind.Kinds { + if !slices.Contains(flattenKinds, kindkind) { + flattenKinds = append(flattenKinds, kindkind) + } + } + } + + simpleMatch := domain.SimpleMatch{ + Namespaces: match.Namespaces, + ExcludedNamespaces: match.ExcludedNamespaces, + Kinds: flattenKinds, + } + + var value string + bytes, err := json.Marshal(simpleMatch) + + if err == nil { + value = string(bytes) + } else { + value = "" + } + + return &domain.Target{ + Type: "simple", + Value: value, + } + } + + if matchYaml != nil { + return &domain.Target{ + Type: "yaml", + Value: *matchYaml, + } + } + + return nil +} diff --git a/internal/policy-template/kind-util.go b/internal/policy-template/kind-util.go index 5fe13747..5d0982c2 100644 --- a/internal/policy-template/kind-util.go +++ b/internal/policy-template/kind-util.go @@ -54,7 +54,7 @@ var KindToApiGroup = map[string]string{ "PodDisruptionBudget": "policy", } -func CheckAndNormalizeKinds(kinds []domain.Kinds) ([]domain.Kinds, error) { +func CheckAndNormalizeKinds(kinds []string) ([]domain.Kinds, error) { if kinds == nil { return nil, nil } @@ -64,22 +64,20 @@ func CheckAndNormalizeKinds(kinds []domain.Kinds) ([]domain.Kinds, error) { var normalizedMap = map[string]domain.Kinds{} for _, kind := range kinds { - for _, kinditem := range kind.Kinds { - if apiGroup, ok := KindToApiGroup[kinditem]; ok { - if ai, ok := normalizedMap[apiGroup]; ok { - if !slices.Contains(ai.Kinds, kinditem) { - ai.Kinds = append(ai.Kinds, kinditem) - normalizedMap[apiGroup] = ai - } - } else { - normalizedMap[apiGroup] = domain.Kinds{ - APIGroups: []string{apiGroup}, - Kinds: []string{kinditem}, - } + if apiGroup, ok := KindToApiGroup[kind]; ok { + if ai, ok := normalizedMap[apiGroup]; ok { + if !slices.Contains(ai.Kinds, kind) { + ai.Kinds = append(ai.Kinds, kind) + normalizedMap[apiGroup] = ai } } else { - invalidKinds = append(invalidKinds, kinditem) + normalizedMap[apiGroup] = domain.Kinds{ + APIGroups: []string{apiGroup}, + Kinds: []string{kind}, + } } + } else { + invalidKinds = append(invalidKinds, kind) } } diff --git a/pkg/domain/policy.go b/pkg/domain/policy.go index 6550f948..35a31ff6 100644 --- a/pkg/domain/policy.go +++ b/pkg/domain/policy.go @@ -5,15 +5,26 @@ import ( "time" ) -type Kinds struct { - APIGroups []string `json:"apiGroups,omitempty"` - Kinds []string `json:"kinds,omitempty"` +type Target struct { + Type string `json:"type" enum:"simple,yaml"` + Value string `json:"value" example:"{\"kinds\":[\"Pod\",\"Deployment\"]}"` } -type Match struct { +type SimpleMatch struct { Namespaces []string `json:"namespaces,omitempty" validate:"matchnamespace"` ExcludedNamespaces []string `json:"excludedNamespaces,omitempty" validate:"matchnamespace"` - Kinds []Kinds `json:"kinds,omitempty" validate:"matchkinds"` + Kinds []string `json:"kinds,omitempty"` +} + +type Kinds struct { + APIGroups []string `json:"apiGroups,omitempty" yaml:"apiGroups,omitempty"` + Kinds []string `json:"kinds,omitempty" yaml:"kinds,omitempty"` +} + +type Match struct { + Namespaces []string `json:"namespaces,omitempty" yaml:"namespaces,omitempty" validate:"matchnamespace"` + ExcludedNamespaces []string `json:"excludedNamespaces,omitempty" yaml:"excludedNamespaces,omitempty" validate:"matchnamespace"` + Kinds []Kinds `json:"kinds,omitempty" yaml:"kinds,omitempty"` } func (m *Match) JSON() string { @@ -45,8 +56,7 @@ type PolicyResponse struct { EnforcementAction string `json:"enforcementAction" enum:"warn,deny,dryrun" example:"deny"` Parameters string `json:"parameters" example:"{\"key\":\"value\"}"` FilledParameters []*ParameterDef `json:"filledParameters"` - Match *Match `json:"match,omitempty"` - MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` + Target *Target `json:"target,omitempty"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } @@ -60,8 +70,7 @@ type CreatePolicyRequest struct { TemplateId string `json:"templateId" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` EnforcementAction string `json:"enforcementAction" validate:"required,oneof=deny dryrun warn" enum:"warn,deny,dryrun" example:"deny"` Parameters string `json:"parameters" example:"{\"key\":\"value\"}"` - Match *Match `json:"match,omitempty"` - MatchYaml *string `json:"matchYaml,omitempty" example:"namespaces:\r\n- testns1"` + Target *Target `json:"target,omitempty"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } @@ -78,8 +87,7 @@ type UpdatePolicyRequest struct { TemplateId *string `json:"templateId,omitempty" example:"d98ef5f1-4a68-4047-a446-2207787ce3ff"` EnforcementAction *string `json:"enforcementAction" validate:"omitempty,oneof=deny dryrun warn" enum:"warn,deny,dryrun" example:"deny"` Parameters *string `json:"parameters,omitempty" example:"{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}"` - Match *Match `json:"match,omitempty"` - MatchYaml *string `json:"matchYaml,omitempty"` + Target *Target `json:"target,omitempty"` //Tags []string `json:"tags,omitempty" example:"k8s,label"` } From 291cc7c0e829005c97567c77a7abaf9413b51fd3 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Thu, 23 May 2024 23:14:24 +0900 Subject: [PATCH 472/502] =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=9C=A0?= =?UTF-8?q?=ED=98=95(kind)=20=EA=B2=80=EC=A6=9D=20=EC=A0=95=EA=B7=9C?= =?UTF-8?q?=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/validator/validator.go | 11 +++++++++++ pkg/domain/admin/policy-template.go | 2 +- pkg/domain/policy-template.go | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/internal/validator/validator.go b/internal/validator/validator.go index 3a161738..b71daf0a 100644 --- a/internal/validator/validator.go +++ b/internal/validator/validator.go @@ -21,6 +21,7 @@ const ( REGEX_RFC1123_DNS_LABEL = "[a-z0-9]([-a-z0-9]*[a-z0-9])?" REGEX_RESOURCE_NAME = `^` + REGEX_RFC1123_DNS_LABEL + "$" REGEX_RFC1123_SUBDOMAIN = `^` + REGEX_RFC1123_DNS_LABEL + `(\.` + REGEX_RFC1123_DNS_LABEL + `)*$` + REGEX_TEMPLATE_KIND = `^[A-Z][a-zA-Z0-9]+$` ) func NewValidator() (*validator.Validate, *ut.UniversalTranslator) { @@ -42,6 +43,7 @@ func NewValidator() (*validator.Validate, *ut.UniversalTranslator) { _ = v.RegisterValidation("resourcename", validateResourceName) _ = v.RegisterValidation("matchnamespace", validateMatchNamespace) _ = v.RegisterValidation("matchkinds", validateMatchKinds) + _ = v.RegisterValidation("templatekind", validateTemplateKind) // register custom error _ = v.RegisterTranslation("required", trans, func(ut ut.Translator) error { @@ -125,6 +127,15 @@ func validateMatchKinds(fl validator.FieldLevel) bool { return true } +func validateTemplateKind(fl validator.FieldLevel) bool { + if fl.Field().String() == "" { + return false + } + + r, _ := regexp.Compile(REGEX_TEMPLATE_KIND) + return r.MatchString(fl.Field().String()) +} + func validateMatchKindAPIGroup(apigroups []string) bool { if len(apigroups) == 0 { return true diff --git a/pkg/domain/admin/policy-template.go b/pkg/domain/admin/policy-template.go index 9ce9e483..2da72e16 100644 --- a/pkg/domain/admin/policy-template.go +++ b/pkg/domain/admin/policy-template.go @@ -45,7 +45,7 @@ type SimplePolicyTemplateResponse struct { type CreatePolicyTemplateRequest struct { TemplateName string `json:"templateName" validate:"required,name" example:"필수 Label 검사"` - Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required,pascalcase"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required,templatekind"` Severity string `json:"severity" validate:"required,oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` Description string `json:"description,omitempty" example:"이 정책은 ..."` diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 835a1225..7f4919c7 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -57,7 +57,7 @@ type SimplePolicyTemplateResponse struct { type CreatePolicyTemplateRequest struct { TemplateName string `json:"templateName" validate:"required,name" example:"필수 Label 검사"` - Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required,pascalcase"` + Kind string `json:"kind" example:"K8sRequiredLabels" validate:"required,templatekind"` Severity string `json:"severity" validate:"required,oneof=low medium high" enums:"low,medium,high" example:"medium"` Deprecated bool `json:"deprecated" example:"false"` Description string `json:"description,omitempty" example:"이 정책은 ..."` From c659f9f2b0437c7ee5a08383251a173a0021e83b Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sun, 26 May 2024 11:21:53 +0900 Subject: [PATCH 473/502] =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF,=20?= =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EB=B2=84=EC=A0=84=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EC=8B=9C=20rego=20=EB=AC=B8=EB=B2=95=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/usecase/policy-template.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 3fb66ac6..b5c01299 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -96,6 +96,20 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp } } + compileResult, err := u.RegoCompile(&domain.RegoCompileRequest{Rego: dto.Rego, Libs: dto.Libs}, false) + + if len(compileResult.Errors) > 0 { + compileErrors := []string{} + + for _, errorResult := range compileResult.Errors { + compileErrors = append(compileErrors, errorResult.Text) + } + + detail := strings.Join(compileErrors, "\n") + + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("rego compile error"), "PT_INVALID_REGO_SYNTAX", detail) + } + if dto.IsTksTemplate() { exists, err := u.repo.ExistByName(ctx, dto.TemplateName) if err == nil && exists { @@ -541,6 +555,20 @@ func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, } } + compileResult, err := u.RegoCompile(&domain.RegoCompileRequest{Rego: rego, Libs: libs}, false) + + if len(compileResult.Errors) > 0 { + compileErrors := []string{} + + for _, errorResult := range compileResult.Errors { + compileErrors = append(compileErrors, errorResult.Text) + } + + detail := strings.Join(compileErrors, "\n") + + return "", httpErrors.NewBadRequestError(fmt.Errorf("rego compile error"), "PT_INVALID_REGO_SYNTAX", detail) + } + if policyTemplate == nil { return "", httpErrors.NewBadRequestError(fmt.Errorf( "failed to fetch policy template"), From c2dcae034e5bc3a2f8affe079849ed57854a32c0 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sun, 26 May 2024 11:27:34 +0900 Subject: [PATCH 474/502] =?UTF-8?q?lint=20=EC=97=90=EB=9F=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/usecase/policy-template.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index b5c01299..7f850349 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -98,6 +98,10 @@ func (u *PolicyTemplateUsecase) Create(ctx context.Context, dto model.PolicyTemp compileResult, err := u.RegoCompile(&domain.RegoCompileRequest{Rego: dto.Rego, Libs: dto.Libs}, false) + if err != nil { + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("rego compile error"), "PT_INVALID_REGO_SYNTAX", "") + } + if len(compileResult.Errors) > 0 { compileErrors := []string{} @@ -557,6 +561,10 @@ func (u *PolicyTemplateUsecase) CreatePolicyTemplateVersion(ctx context.Context, compileResult, err := u.RegoCompile(&domain.RegoCompileRequest{Rego: rego, Libs: libs}, false) + if err != nil { + return "", httpErrors.NewBadRequestError(fmt.Errorf("rego compile error"), "PT_INVALID_REGO_SYNTAX", "") + } + if len(compileResult.Errors) > 0 { compileErrors := []string{} From 02d6391a9d0962220766268552a31ecdd5412ead Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 28 May 2024 14:27:35 +0900 Subject: [PATCH 475/502] trivial. fix cluster site-value bug --- internal/usecase/cluster.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index 3d64f4d8..eb795c40 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -5,11 +5,12 @@ import ( "encoding/base64" "encoding/json" "fmt" - "github.com/Nerzal/gocloak/v13" - "github.com/openinfradev/tks-api/internal/keycloak" "strings" "time" + "github.com/Nerzal/gocloak/v13" + "github.com/openinfradev/tks-api/internal/keycloak" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/middleware/auth/request" @@ -520,10 +521,6 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom out.TksUserNodeMax = cluster.TksUserNodeMax / domain.MAX_AZ_NUM } - if err := serializer.Map(ctx, cluster, &out); err != nil { - log.Error(ctx, err) - } - /* // 기능 변경 : 20230614 : machine deployment 사용하지 않음. 단, aws-standard 는 사용할 여지가 있으므로 주석처리해둔다. const MAX_AZ_NUM = 4 From 3b0a7704db232a025b3c2e90f8420ae203edc688 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sat, 8 Jun 2024 16:35:51 +0900 Subject: [PATCH 476/502] =?UTF-8?q?GetOrgTemplate=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=20=EC=A0=81=EC=9A=A9=EB=90=9C=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EB=B2=84=EC=A0=84=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/usecase/policy-template.go | 27 +++++++++++++++++++++++++++ pkg/domain/policy-template.go | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index 7f850349..e8b5d78c 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -318,6 +318,33 @@ func (u *PolicyTemplateUsecase) Get(ctx context.Context, organizationId *string, } } + if organizationId != nil { + (*policyTemplate).LatestVersion = policyTemplate.Version + + var primaryClusterId string + + org, err := u.organizationRepo.Get(ctx, *organizationId) + + if err != nil { + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } else { + // 에러 없이 primaryClusterId를 가져왔을 때만 처리 + primaryClusterId = org.PrimaryClusterId + + templateCR, err := policytemplate.GetTksPolicyTemplateCR(ctx, primaryClusterId, policyTemplate.ResoureName()) + + if err == nil && templateCR != nil { + (*policyTemplate).CurrentVersion = templateCR.Spec.Version + } else if errors.IsNotFound(err) || templateCR == nil { + // 템플릿이 존재하지 않으면 최신 버전으로 배포되므로 + (*policyTemplate).CurrentVersion = policyTemplate.LatestVersion + } else { + // 통신 실패 등 기타 에러, 버전을 세팅하지 않아 에러임을 알수 있도록 로그를 남김 + log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) + } + } + } + return policyTemplate, nil } diff --git a/pkg/domain/policy-template.go b/pkg/domain/policy-template.go index 7f4919c7..2045ee80 100644 --- a/pkg/domain/policy-template.go +++ b/pkg/domain/policy-template.go @@ -115,7 +115,7 @@ type CreatePolicyTemplateVersionResponse struct { } type GetPolicyTemplateResponse struct { - PolicyTemplate PolicyTemplateResponse `json:"policyTemplate"` + PolicyTemplate PolicyTemplateTwoVersionResponse `json:"policyTemplate"` } type ListPolicyTemplateResponse struct { From 9858b5a0ae5539152062160b92a2d8c0b6df3286 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sat, 8 Jun 2024 16:57:07 +0900 Subject: [PATCH 477/502] =?UTF-8?q?=EC=9D=BC=EB=B6=80=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=20=EB=B2=84=EC=A0=84=20=EC=A1=B0=ED=9A=8C=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/repository/policy-template.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 1071f813..80d0f885 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -137,7 +137,7 @@ func (r *PolicyTemplateRepository) FetchForOrganization(ctx context.Context, org _, res := pg.Fetch(r.db.WithContext(ctx). Preload("SupportedVersions", func(db *gorm.DB) *gorm.DB { // 최신 버전만 - return db.Order("policy_template_supported_versions.version DESC") + return db.Order("policy_template_supported_versions.created_at DESC") }). Preload("Creator").Preload("Updator"). // organization을 기준으로 조회할 때에는 PermittedOrganizations는 로딩하지 않아도 됨 Model(&model.PolicyTemplate{}). @@ -274,7 +274,7 @@ func (r *PolicyTemplateRepository) GetBy(ctx context.Context, key string, value res := r.db.WithContext(ctx). Preload("SupportedVersions", func(db *gorm.DB) *gorm.DB { // 최신 버전만 - return db.Order("policy_template_supported_versions.version DESC").Limit(1) + return db.Order("policy_template_supported_versions.created_at DESC").Limit(1) }). Preload("PermittedOrganizations").Preload("Creator").Preload("Updator"). Where(query, value). From 3d6ded439acb84d9aa56ff00e3709746a16f71c6 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Sat, 8 Jun 2024 23:14:09 +0900 Subject: [PATCH 478/502] =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20rego=20v1=20=ED=8C=A8=ED=84=B4=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../policy-template/policy-template-rego.go | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/internal/policy-template/policy-template-rego.go b/internal/policy-template/policy-template-rego.go index de39beb0..028f0137 100644 --- a/internal/policy-template/policy-template-rego.go +++ b/internal/policy-template/policy-template-rego.go @@ -23,7 +23,7 @@ const ( obj_get_pattern = `object\.get\((input|input\.parameters|input\.parameters\.[^,]+), \"([^\"]+)\", [^\)]+\)` ref_by_key_pattern = `\[\"([\w-]+)\"\]` package_name_regex = `package ([\w\.]+)[\n\r]+` - import_regex = `import ([\w\.]+)[\n\r]+` + lib_import_regex = `import data\.lib\.([\w\.]+)[\n\r]+` ) var ( @@ -620,11 +620,28 @@ func MergeRegoAndLibs(rego string, libs []string) string { return rego } - var re = regexp.MustCompile(import_regex) + var re = regexp.MustCompile(lib_import_regex) var re2 = regexp.MustCompile(package_name_regex) + // data.lib import 모두 제거 result := re.ReplaceAllString(rego, "") + lib_imports := re.FindAllStringSubmatch(rego, -1) + + // data.lib import 시 data.lib.<라이브러리 이름>인 경우 소스에서 <라이브러리 이름>.<정책 이름>으로 참조됨 + // 이 경우 임프로를 제거했으므로 <라이브러리 이름>.<정책 이름>을 <정책 이름>으로 바꾸기 위해 제거 + // <라이브러리 이름>.<정책 이름>.<규칙 이름> 등의 형식은 <규칙 이름>으로 참조되기 때문에 처리할 필요 없음 + for _, lib_import := range lib_imports { + lib_and_rule := lib_import[1] + + if !strings.Contains(lib_and_rule, ".") { + remove_lib_prefix := lib_and_rule + "." + fmt.Printf("'%s'\n", remove_lib_prefix) + result = strings.ReplaceAll(result, remove_lib_prefix, "") + } + } + // "<라이브러리 이름>." 제거 로직 끝 + for _, lib := range processLibs(libs) { result += re2.ReplaceAllString(lib, "") } From 3c61f413a31082e43a51014bbbfdeea8507ae7f7 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Mon, 17 Jun 2024 22:04:56 +0900 Subject: [PATCH 479/502] =?UTF-8?q?=EC=98=A4=ED=83=80=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/delivery/http/policy-template.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/delivery/http/policy-template.go b/internal/delivery/http/policy-template.go index 4fba4a3a..5b895d95 100644 --- a/internal/delivery/http/policy-template.go +++ b/internal/delivery/http/policy-template.go @@ -716,7 +716,7 @@ func (h *PolicyTemplateHandler) Admin_DeletePolicyTemplateVersion(w http.Respons // Admin_ExistsPolicyTemplateName godoc // // @Tags PolicyTemplate -// @Summary [Admin_ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인 +// @Summary [Admin_ExistsPolicyTemplateName] 정책 템플릿 이름 존재 여부 확인 // @Description 해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다. // @Accept json // @Produce json @@ -1624,7 +1624,7 @@ func (h *PolicyTemplateHandler) DeletePolicyTemplateVersion(w http.ResponseWrite // ExistsPolicyTemplateName godoc // // @Tags PolicyTemplate -// @Summary [ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인 +// @Summary [ExistsPolicyTemplateName] 정책 템플릿 이름 존재 여부 확인 // @Description 해당 이름을 가진 정책 템플릿이 이미 존재하는지 확인한다. // @Accept json // @Produce json From 8e117fc316582034e08c0704898270d5ebb168c2 Mon Sep 17 00:00:00 2001 From: sangkenlee Date: Wed, 19 Jun 2024 13:47:32 +0900 Subject: [PATCH 480/502] =?UTF-8?q?Permitted=20Org=EA=B0=80=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9=20=EC=95=88=20=EB=90=9C=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=EC=A7=81=EC=9D=B4=20Permitted=20?= =?UTF-8?q?Org=EC=97=90=20=ED=91=9C=EC=8B=9C=EB=90=98=EB=8A=94=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/usecase/policy-template.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/internal/usecase/policy-template.go b/internal/usecase/policy-template.go index e8b5d78c..95998878 100644 --- a/internal/usecase/policy-template.go +++ b/internal/usecase/policy-template.go @@ -308,16 +308,6 @@ func (u *PolicyTemplateUsecase) Get(ctx context.Context, organizationId *string, "PT_NOT_FOUND_POLICY_TEMPLATE", "") } - if policyTemplate.IsTksTemplate() && len(policyTemplate.PermittedOrganizations) == 0 { - organizations, err := u.organizationRepo.Fetch(ctx, nil) - - if err != nil { - log.Errorf(ctx, "error is :%s(%T)", err.Error(), err) - } else if organizations != nil { - policyTemplate.PermittedOrganizations = *organizations - } - } - if organizationId != nil { (*policyTemplate).LatestVersion = policyTemplate.Version From 3c938597c3caf423d98b6f72f2cdc9a98c8ffcb3 Mon Sep 17 00:00:00 2001 From: Robert Choi Date: Mon, 24 Jun 2024 13:47:03 +0900 Subject: [PATCH 481/502] trivial: increase num of log lines --- internal/usecase/app-serve-app.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/usecase/app-serve-app.go b/internal/usecase/app-serve-app.go index c59b71eb..c1bee2c0 100644 --- a/internal/usecase/app-serve-app.go +++ b/internal/usecase/app-serve-app.go @@ -268,7 +268,9 @@ func (u *AppServeAppUsecase) GetAppServeAppLog(ctx context.Context, appId string for _, pod := range pods.Items { log.Debugf(ctx, "Processing pod: %s", pod.Name) - tailLines := int64(50) + // NOTE: show last 300 lines of app pod log. + // temporary workaround to show error log in case of the app pod crash + tailLines := int64(300) req := clientset.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &corev1.PodLogOptions{ // name should be "tomcat" for legacy spring app From 397aaeb72207b79a49fb0ec97a5c714faa68e774 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 25 Jun 2024 16:20:50 +0900 Subject: [PATCH 482/502] feature. implementation resume scenario when byoh cluster installing --- api/swagger/docs.go | 166 +-- api/swagger/swagger.json | 166 +-- api/swagger/swagger.yaml | 111 +- internal/delivery/api/endpoint.go | 3 +- .../delivery/api/generated_endpoints.go.go | 951 +++++++++--------- internal/delivery/http/cluster.go | 32 +- internal/delivery/http/stack.go | 12 + internal/route/route.go | 1 + internal/usecase/cluster.go | 28 + internal/usecase/stack.go | 9 +- pkg/argo-client/client-mock.go | 4 + pkg/argo-client/client.go | 43 + pkg/argo-client/mock/client.go | 87 +- pkg/domain/cluster.go | 2 + pkg/domain/stack.go | 2 + 15 files changed, 941 insertions(+), 676 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 49a03108..123604da 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -745,7 +745,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[Admin_ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "summary": "[Admin_ExistsPolicyTemplateName] 정책 템플릿 이름 존재 여부 확인", "parameters": [ { "type": "string", @@ -2480,7 +2480,7 @@ const docTemplate = `{ "JWT": [] } ], - "description": "Install cluster on tks cluster", + "description": "Install cluster on tks cluster ( BYOH )", "consumes": [ "application/json" ], @@ -2490,7 +2490,7 @@ const docTemplate = `{ "tags": [ "Clusters" ], - "summary": "Install cluster on tks cluster", + "summary": "Install cluster on tks cluster ( BYOH )", "parameters": [ { "type": "string", @@ -2544,6 +2544,40 @@ const docTemplate = `{ } } }, + "/clusters/{clusterId}/resume": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Resume Cluster ( BYOH )", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Resume Cluster ( BYOH )", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/clusters/{clusterId}/site-values": { "get": { "security": [ @@ -4942,7 +4976,7 @@ const docTemplate = `{ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "summary": "[ExistsPolicyTemplateName] 정책 템플릿 이름 존재 여부 확인", "parameters": [ { "type": "string", @@ -8607,6 +8641,47 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/stacks/{stackId}/install": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install Stack ( BYOH )", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Install Stack ( BYOH )", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/stacks/{stackId}/kube-config": { "get": { "security": [ @@ -11710,13 +11785,6 @@ const docTemplate = `{ "mandatory": { "type": "boolean" }, - "match": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" - }, - "matchYaml": { - "type": "string", - "example": "namespaces:\r\n- testns1" - }, "parameters": { "type": "string", "example": "{\"key\":\"value\"}" @@ -11729,6 +11797,9 @@ const docTemplate = `{ "type": "string", "example": "labelpolicy" }, + "target": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target" + }, "targetClusterIds": { "type": "array", "items": { @@ -13103,7 +13174,7 @@ const docTemplate = `{ "type": "object", "properties": { "policyTemplate": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse" } } }, @@ -13584,23 +13655,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Kinds": { - "type": "object", - "properties": { - "apiGroups": { - "type": "array", - "items": { - "type": "string" - } - }, - "kinds": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -13847,29 +13901,6 @@ const docTemplate = `{ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Match": { - "type": "object", - "properties": { - "excludedNamespaces": { - "type": "array", - "items": { - "type": "string" - } - }, - "kinds": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Kinds" - } - }, - "namespaces": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { "type": "object", "properties": { @@ -14155,13 +14186,6 @@ const docTemplate = `{ "mandatory": { "type": "boolean" }, - "match": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" - }, - "matchYaml": { - "type": "string", - "example": "namespaces:\r\n- testns1" - }, "parameters": { "type": "string", "example": "{\"key\":\"value\"}" @@ -14174,6 +14198,9 @@ const docTemplate = `{ "type": "string", "example": "labelpolicy" }, + "target": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target" + }, "targetClusters": { "description": "TargetClusterIds []string ` + "`" + `json:\"targetClusterIds\" example:\"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90\"` + "`" + `", "type": "array", @@ -15574,6 +15601,18 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Target": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string", + "example": "{\"kinds\":[\"Pod\",\"Deployment\"]}" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.TemplateCount": { "type": "object", "properties": { @@ -15921,12 +15960,6 @@ const docTemplate = `{ "mandatory": { "type": "boolean" }, - "match": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" - }, - "matchYaml": { - "type": "string" - }, "parameters": { "type": "string", "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" @@ -15935,6 +15968,9 @@ const docTemplate = `{ "type": "string", "example": "label 정책" }, + "target": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target" + }, "targetClusterIds": { "type": "array", "items": { diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 6e5684c6..4540586c 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -739,7 +739,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[Admin_ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "summary": "[Admin_ExistsPolicyTemplateName] 정책 템플릿 이름 존재 여부 확인", "parameters": [ { "type": "string", @@ -2474,7 +2474,7 @@ "JWT": [] } ], - "description": "Install cluster on tks cluster", + "description": "Install cluster on tks cluster ( BYOH )", "consumes": [ "application/json" ], @@ -2484,7 +2484,7 @@ "tags": [ "Clusters" ], - "summary": "Install cluster on tks cluster", + "summary": "Install cluster on tks cluster ( BYOH )", "parameters": [ { "type": "string", @@ -2538,6 +2538,40 @@ } } }, + "/clusters/{clusterId}/resume": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Resume Cluster ( BYOH )", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Clusters" + ], + "summary": "Resume Cluster ( BYOH )", + "parameters": [ + { + "type": "string", + "description": "clusterId", + "name": "clusterId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/clusters/{clusterId}/site-values": { "get": { "security": [ @@ -4936,7 +4970,7 @@ "tags": [ "PolicyTemplate" ], - "summary": "[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인", + "summary": "[ExistsPolicyTemplateName] 정책 템플릿 이름 존재 여부 확인", "parameters": [ { "type": "string", @@ -8601,6 +8635,47 @@ } } }, + "/organizations/{organizationId}/stacks/{stackId}/install": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Install Stack ( BYOH )", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Install Stack ( BYOH )", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackId", + "name": "stackId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}/stacks/{stackId}/kube-config": { "get": { "security": [ @@ -11704,13 +11779,6 @@ "mandatory": { "type": "boolean" }, - "match": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" - }, - "matchYaml": { - "type": "string", - "example": "namespaces:\r\n- testns1" - }, "parameters": { "type": "string", "example": "{\"key\":\"value\"}" @@ -11723,6 +11791,9 @@ "type": "string", "example": "labelpolicy" }, + "target": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target" + }, "targetClusterIds": { "type": "array", "items": { @@ -13097,7 +13168,7 @@ "type": "object", "properties": { "policyTemplate": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse" } } }, @@ -13578,23 +13649,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Kinds": { - "type": "object", - "properties": { - "apiGroups": { - "type": "array", - "items": { - "type": "string" - } - }, - "kinds": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -13841,29 +13895,6 @@ } } }, - "github_com_openinfradev_tks-api_pkg_domain.Match": { - "type": "object", - "properties": { - "excludedNamespaces": { - "type": "array", - "items": { - "type": "string" - } - }, - "kinds": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Kinds" - } - }, - "namespaces": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, "github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse": { "type": "object", "properties": { @@ -14149,13 +14180,6 @@ "mandatory": { "type": "boolean" }, - "match": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" - }, - "matchYaml": { - "type": "string", - "example": "namespaces:\r\n- testns1" - }, "parameters": { "type": "string", "example": "{\"key\":\"value\"}" @@ -14168,6 +14192,9 @@ "type": "string", "example": "labelpolicy" }, + "target": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target" + }, "targetClusters": { "description": "TargetClusterIds []string `json:\"targetClusterIds\" example:\"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90\"`", "type": "array", @@ -15568,6 +15595,18 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Target": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string", + "example": "{\"kinds\":[\"Pod\",\"Deployment\"]}" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.TemplateCount": { "type": "object", "properties": { @@ -15915,12 +15954,6 @@ "mandatory": { "type": "boolean" }, - "match": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match" - }, - "matchYaml": { - "type": "string" - }, "parameters": { "type": "string", "example": "{\"labels\":{\"key\":\"owner\",\"allowedRegex\":\"test*\"}" @@ -15929,6 +15962,9 @@ "type": "string", "example": "label 정책" }, + "target": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target" + }, "targetClusterIds": { "type": "array", "items": { diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index d35c272e..a1cc583d 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -912,11 +912,6 @@ definitions: type: string mandatory: type: boolean - match: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match' - matchYaml: - example: "namespaces:\r\n- testns1" - type: string parameters: example: '{"key":"value"}' type: string @@ -926,6 +921,8 @@ definitions: policyResourceName: example: labelpolicy type: string + target: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target' targetClusterIds: example: - 83bf8081-f0c5-4b31-826d-23f6f366ec90 @@ -1842,7 +1839,7 @@ definitions: github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateResponse: properties: policyTemplate: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.PolicyTemplateTwoVersionResponse' type: object github_com_openinfradev_tks-api_pkg_domain.GetPolicyTemplateVersionResponse: properties: @@ -2153,17 +2150,6 @@ definitions: id: type: string type: object - github_com_openinfradev_tks-api_pkg_domain.Kinds: - properties: - apiGroups: - items: - type: string - type: array - kinds: - items: - type: string - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse: properties: organizations: @@ -2327,21 +2313,6 @@ definitions: example: 레이블 요구 type: string type: object - github_com_openinfradev_tks-api_pkg_domain.Match: - properties: - excludedNamespaces: - items: - type: string - type: array - kinds: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Kinds' - type: array - namespaces: - items: - type: string - type: array - type: object github_com_openinfradev_tks-api_pkg_domain.MergePermissionResponse: properties: children: @@ -2530,11 +2501,6 @@ definitions: type: string mandatory: type: boolean - match: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match' - matchYaml: - example: "namespaces:\r\n- testns1" - type: string parameters: example: '{"key":"value"}' type: string @@ -2544,6 +2510,8 @@ definitions: policyResourceName: example: labelpolicy type: string + target: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target' targetClusters: description: TargetClusterIds []string `json:"targetClusterIds" example:"83bf8081-f0c5-4b31-826d-23f6f366ec90,83bf8081-f0c5-4b31-826d-23f6f366ec90"` @@ -3485,6 +3453,14 @@ definitions: required: - metricQuery type: object + github_com_openinfradev_tks-api_pkg_domain.Target: + properties: + type: + type: string + value: + example: '{"kinds":["Pod","Deployment"]}' + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.TemplateCount: properties: organizationTemplate: @@ -3717,16 +3693,14 @@ definitions: type: string mandatory: type: boolean - match: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Match' - matchYaml: - type: string parameters: example: '{"labels":{"key":"owner","allowedRegex":"test*"}' type: string policyName: example: label 정책 type: string + target: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Target' targetClusterIds: example: - 83bf8081-f0c5-4b31-826d-23f6f366ec90 @@ -5148,7 +5122,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain_admin.ExistsPolicyTemplateNameResponse' security: - JWT: [] - summary: '[Admin_ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인' + summary: '[Admin_ExistsPolicyTemplateName] 정책 템플릿 이름 존재 여부 확인' tags: - PolicyTemplate /admin/stack-templates: @@ -5961,7 +5935,7 @@ paths: post: consumes: - application/json - description: Install cluster on tks cluster + description: Install cluster on tks cluster ( BYOH ) parameters: - description: clusterId in: path @@ -5975,7 +5949,7 @@ paths: description: OK security: - JWT: [] - summary: Install cluster on tks cluster + summary: Install cluster on tks cluster ( BYOH ) tags: - Clusters /clusters/{clusterId}/nodes: @@ -6001,6 +5975,27 @@ paths: summary: Get nodes information for BYOH tags: - Clusters + /clusters/{clusterId}/resume: + put: + consumes: + - application/json + description: Resume Cluster ( BYOH ) + parameters: + - description: clusterId + in: path + name: clusterId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Resume Cluster ( BYOH ) + tags: + - Clusters /clusters/{clusterId}/site-values: get: consumes: @@ -7850,7 +7845,7 @@ paths: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ExistsPolicyTemplateNameResponse' security: - JWT: [] - summary: '[ExistsPolicyTemplateName] 정책 템플릿 아름 존재 여부 확인' + summary: '[ExistsPolicyTemplateName] 정책 템플릿 이름 존재 여부 확인' tags: - PolicyTemplate /organizations/{organizationId}/primary-cluster: @@ -9865,6 +9860,32 @@ paths: summary: Set favorite stack tags: - Stacks + /organizations/{organizationId}/stacks/{stackId}/install: + post: + consumes: + - application/json + description: Install Stack ( BYOH ) + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackId + in: path + name: stackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Install Stack ( BYOH ) + tags: + - Stacks /organizations/{organizationId}/stacks/{stackId}/kube-config: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 30280502..957418c2 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -56,6 +56,7 @@ const ( DeleteCluster GetClusterSiteValues InstallCluster + ResumeCluster CreateBootstrapKubeconfig GetBootstrapKubeconfig GetNodes @@ -172,7 +173,7 @@ const ( GetStackStatus // 스택관리/조회 SetFavoriteStack // 스택관리/조회 DeleteFavoriteStack // 스택관리/조회 - InstallStack // 스택관리 / 조회 + InstallStack // 스택관리/조회 // Project CreateProject // 프로젝트 관리/프로젝트/생성 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 25f0364d..829820a1 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -1,942 +1,949 @@ -// This is generated code. DO NOT EDIT. + // This is generated code. DO NOT EDIT. package api var ApiMap = map[Endpoint]EndpointInfo{ - Login: { - Name: "Login", + Login: { + Name: "Login", Group: "Auth", }, - Logout: { - Name: "Logout", + Logout: { + Name: "Logout", Group: "Auth", }, - RefreshToken: { - Name: "RefreshToken", + RefreshToken: { + Name: "RefreshToken", Group: "Auth", }, - FindId: { - Name: "FindId", + FindId: { + Name: "FindId", Group: "Auth", }, - FindPassword: { - Name: "FindPassword", + FindPassword: { + Name: "FindPassword", Group: "Auth", }, - VerifyIdentityForLostId: { - Name: "VerifyIdentityForLostId", + VerifyIdentityForLostId: { + Name: "VerifyIdentityForLostId", Group: "Auth", }, - VerifyIdentityForLostPassword: { - Name: "VerifyIdentityForLostPassword", + VerifyIdentityForLostPassword: { + Name: "VerifyIdentityForLostPassword", Group: "Auth", }, - VerifyToken: { - Name: "VerifyToken", + VerifyToken: { + Name: "VerifyToken", Group: "Auth", }, - CreateUser: { - Name: "CreateUser", + CreateUser: { + Name: "CreateUser", Group: "User", }, - ListUser: { - Name: "ListUser", + ListUser: { + Name: "ListUser", Group: "User", }, - GetUser: { - Name: "GetUser", + GetUser: { + Name: "GetUser", Group: "User", }, - DeleteUser: { - Name: "DeleteUser", + DeleteUser: { + Name: "DeleteUser", Group: "User", }, - UpdateUsers: { - Name: "UpdateUsers", + UpdateUsers: { + Name: "UpdateUsers", Group: "User", }, - UpdateUser: { - Name: "UpdateUser", + UpdateUser: { + Name: "UpdateUser", Group: "User", }, - ResetPassword: { - Name: "ResetPassword", + ResetPassword: { + Name: "ResetPassword", Group: "User", }, - CheckId: { - Name: "CheckId", + CheckId: { + Name: "CheckId", Group: "User", }, - CheckEmail: { - Name: "CheckEmail", + CheckEmail: { + Name: "CheckEmail", Group: "User", }, - GetPermissionsByAccountId: { - Name: "GetPermissionsByAccountId", + GetPermissionsByAccountId: { + Name: "GetPermissionsByAccountId", Group: "User", }, - GetMyProfile: { - Name: "GetMyProfile", + GetMyProfile: { + Name: "GetMyProfile", Group: "MyProfile", }, - UpdateMyProfile: { - Name: "UpdateMyProfile", + UpdateMyProfile: { + Name: "UpdateMyProfile", Group: "MyProfile", }, - UpdateMyPassword: { - Name: "UpdateMyPassword", + UpdateMyPassword: { + Name: "UpdateMyPassword", Group: "MyProfile", }, - RenewPasswordExpiredDate: { - Name: "RenewPasswordExpiredDate", + RenewPasswordExpiredDate: { + Name: "RenewPasswordExpiredDate", Group: "MyProfile", }, - DeleteMyProfile: { - Name: "DeleteMyProfile", + DeleteMyProfile: { + Name: "DeleteMyProfile", Group: "MyProfile", }, - Admin_CreateOrganization: { - Name: "Admin_CreateOrganization", + Admin_CreateOrganization: { + Name: "Admin_CreateOrganization", Group: "Organization", }, - Admin_DeleteOrganization: { - Name: "Admin_DeleteOrganization", + Admin_DeleteOrganization: { + Name: "Admin_DeleteOrganization", Group: "Organization", }, - GetOrganizations: { - Name: "GetOrganizations", + GetOrganizations: { + Name: "GetOrganizations", Group: "Organization", }, - GetOrganization: { - Name: "GetOrganization", + GetOrganization: { + Name: "GetOrganization", Group: "Organization", }, - CheckOrganizationName: { - Name: "CheckOrganizationName", + CheckOrganizationName: { + Name: "CheckOrganizationName", Group: "Organization", }, - UpdateOrganization: { - Name: "UpdateOrganization", + UpdateOrganization: { + Name: "UpdateOrganization", Group: "Organization", }, - UpdatePrimaryCluster: { - Name: "UpdatePrimaryCluster", + UpdatePrimaryCluster: { + Name: "UpdatePrimaryCluster", Group: "Organization", }, - CreateCluster: { - Name: "CreateCluster", + CreateCluster: { + Name: "CreateCluster", Group: "Cluster", }, - GetClusters: { - Name: "GetClusters", + GetClusters: { + Name: "GetClusters", Group: "Cluster", }, - ImportCluster: { - Name: "ImportCluster", + ImportCluster: { + Name: "ImportCluster", Group: "Cluster", }, - GetCluster: { - Name: "GetCluster", + GetCluster: { + Name: "GetCluster", Group: "Cluster", }, - DeleteCluster: { - Name: "DeleteCluster", + DeleteCluster: { + Name: "DeleteCluster", Group: "Cluster", }, - GetClusterSiteValues: { - Name: "GetClusterSiteValues", + GetClusterSiteValues: { + Name: "GetClusterSiteValues", Group: "Cluster", }, - InstallCluster: { - Name: "InstallCluster", + InstallCluster: { + Name: "InstallCluster", Group: "Cluster", }, - CreateBootstrapKubeconfig: { - Name: "CreateBootstrapKubeconfig", + ResumeCluster: { + Name: "ResumeCluster", Group: "Cluster", }, - GetBootstrapKubeconfig: { - Name: "GetBootstrapKubeconfig", + CreateBootstrapKubeconfig: { + Name: "CreateBootstrapKubeconfig", Group: "Cluster", }, - GetNodes: { - Name: "GetNodes", + GetBootstrapKubeconfig: { + Name: "GetBootstrapKubeconfig", Group: "Cluster", }, - CreateAppgroup: { - Name: "CreateAppgroup", + GetNodes: { + Name: "GetNodes", + Group: "Cluster", + }, + CreateAppgroup: { + Name: "CreateAppgroup", Group: "Appgroup", }, - GetAppgroups: { - Name: "GetAppgroups", + GetAppgroups: { + Name: "GetAppgroups", Group: "Appgroup", }, - GetAppgroup: { - Name: "GetAppgroup", + GetAppgroup: { + Name: "GetAppgroup", Group: "Appgroup", }, - DeleteAppgroup: { - Name: "DeleteAppgroup", + DeleteAppgroup: { + Name: "DeleteAppgroup", Group: "Appgroup", }, - GetApplications: { - Name: "GetApplications", + GetApplications: { + Name: "GetApplications", Group: "Appgroup", }, - CreateApplication: { - Name: "CreateApplication", + CreateApplication: { + Name: "CreateApplication", Group: "Appgroup", }, - GetAppServeAppTasksByAppId: { - Name: "GetAppServeAppTasksByAppId", + GetAppServeAppTasksByAppId: { + Name: "GetAppServeAppTasksByAppId", Group: "AppServeApp", }, - GetAppServeAppTaskDetail: { - Name: "GetAppServeAppTaskDetail", + GetAppServeAppTaskDetail: { + Name: "GetAppServeAppTaskDetail", Group: "AppServeApp", }, - CreateAppServeApp: { - Name: "CreateAppServeApp", + CreateAppServeApp: { + Name: "CreateAppServeApp", Group: "AppServeApp", }, - GetAppServeApps: { - Name: "GetAppServeApps", + GetAppServeApps: { + Name: "GetAppServeApps", Group: "AppServeApp", }, - GetNumOfAppsOnStack: { - Name: "GetNumOfAppsOnStack", + GetNumOfAppsOnStack: { + Name: "GetNumOfAppsOnStack", Group: "AppServeApp", }, - GetAppServeApp: { - Name: "GetAppServeApp", + GetAppServeApp: { + Name: "GetAppServeApp", Group: "AppServeApp", }, - GetAppServeAppLatestTask: { - Name: "GetAppServeAppLatestTask", + GetAppServeAppLatestTask: { + Name: "GetAppServeAppLatestTask", Group: "AppServeApp", }, - IsAppServeAppExist: { - Name: "IsAppServeAppExist", + GetAppServeAppLog: { + Name: "GetAppServeAppLog", Group: "AppServeApp", }, - IsAppServeAppNameExist: { - Name: "IsAppServeAppNameExist", + IsAppServeAppExist: { + Name: "IsAppServeAppExist", Group: "AppServeApp", }, - DeleteAppServeApp: { - Name: "DeleteAppServeApp", + IsAppServeAppNameExist: { + Name: "IsAppServeAppNameExist", Group: "AppServeApp", }, - UpdateAppServeApp: { - Name: "UpdateAppServeApp", + DeleteAppServeApp: { + Name: "DeleteAppServeApp", Group: "AppServeApp", }, - UpdateAppServeAppStatus: { - Name: "UpdateAppServeAppStatus", + UpdateAppServeApp: { + Name: "UpdateAppServeApp", Group: "AppServeApp", }, - UpdateAppServeAppEndpoint: { - Name: "UpdateAppServeAppEndpoint", + UpdateAppServeAppStatus: { + Name: "UpdateAppServeAppStatus", Group: "AppServeApp", }, - RollbackAppServeApp: { - Name: "RollbackAppServeApp", + UpdateAppServeAppEndpoint: { + Name: "UpdateAppServeAppEndpoint", Group: "AppServeApp", }, - GetCloudAccounts: { - Name: "GetCloudAccounts", + RollbackAppServeApp: { + Name: "RollbackAppServeApp", + Group: "AppServeApp", + }, + GetCloudAccounts: { + Name: "GetCloudAccounts", Group: "CloudAccount", }, - CreateCloudAccount: { - Name: "CreateCloudAccount", + CreateCloudAccount: { + Name: "CreateCloudAccount", Group: "CloudAccount", }, - CheckCloudAccountName: { - Name: "CheckCloudAccountName", + CheckCloudAccountName: { + Name: "CheckCloudAccountName", Group: "CloudAccount", }, - CheckAwsAccountId: { - Name: "CheckAwsAccountId", + CheckAwsAccountId: { + Name: "CheckAwsAccountId", Group: "CloudAccount", }, - GetCloudAccount: { - Name: "GetCloudAccount", + GetCloudAccount: { + Name: "GetCloudAccount", Group: "CloudAccount", }, - UpdateCloudAccount: { - Name: "UpdateCloudAccount", + UpdateCloudAccount: { + Name: "UpdateCloudAccount", Group: "CloudAccount", }, - DeleteCloudAccount: { - Name: "DeleteCloudAccount", + DeleteCloudAccount: { + Name: "DeleteCloudAccount", Group: "CloudAccount", }, - DeleteForceCloudAccount: { - Name: "DeleteForceCloudAccount", + DeleteForceCloudAccount: { + Name: "DeleteForceCloudAccount", Group: "CloudAccount", }, - GetResourceQuota: { - Name: "GetResourceQuota", + GetResourceQuota: { + Name: "GetResourceQuota", Group: "CloudAccount", }, - Admin_GetStackTemplates: { - Name: "Admin_GetStackTemplates", + Admin_GetStackTemplates: { + Name: "Admin_GetStackTemplates", Group: "StackTemplate", }, - Admin_GetStackTemplate: { - Name: "Admin_GetStackTemplate", + Admin_GetStackTemplate: { + Name: "Admin_GetStackTemplate", Group: "StackTemplate", }, - Admin_GetStackTemplateServices: { - Name: "Admin_GetStackTemplateServices", + Admin_GetStackTemplateServices: { + Name: "Admin_GetStackTemplateServices", Group: "StackTemplate", }, - Admin_GetStackTemplateTemplateIds: { - Name: "Admin_GetStackTemplateTemplateIds", + Admin_GetStackTemplateTemplateIds: { + Name: "Admin_GetStackTemplateTemplateIds", Group: "StackTemplate", }, - Admin_CreateStackTemplate: { - Name: "Admin_CreateStackTemplate", + Admin_CreateStackTemplate: { + Name: "Admin_CreateStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplate: { - Name: "Admin_UpdateStackTemplate", + Admin_UpdateStackTemplate: { + Name: "Admin_UpdateStackTemplate", Group: "StackTemplate", }, - Admin_DeleteStackTemplate: { - Name: "Admin_DeleteStackTemplate", + Admin_DeleteStackTemplate: { + Name: "Admin_DeleteStackTemplate", Group: "StackTemplate", }, - Admin_UpdateStackTemplateOrganizations: { - Name: "Admin_UpdateStackTemplateOrganizations", + Admin_UpdateStackTemplateOrganizations: { + Name: "Admin_UpdateStackTemplateOrganizations", Group: "StackTemplate", }, - Admin_CheckStackTemplateName: { - Name: "Admin_CheckStackTemplateName", + Admin_CheckStackTemplateName: { + Name: "Admin_CheckStackTemplateName", Group: "StackTemplate", }, - GetOrganizationStackTemplates: { - Name: "GetOrganizationStackTemplates", + GetOrganizationStackTemplates: { + Name: "GetOrganizationStackTemplates", Group: "StackTemplate", }, - GetOrganizationStackTemplate: { - Name: "GetOrganizationStackTemplate", + GetOrganizationStackTemplate: { + Name: "GetOrganizationStackTemplate", Group: "StackTemplate", }, - AddOrganizationStackTemplates: { - Name: "AddOrganizationStackTemplates", + AddOrganizationStackTemplates: { + Name: "AddOrganizationStackTemplates", Group: "StackTemplate", }, - RemoveOrganizationStackTemplates: { - Name: "RemoveOrganizationStackTemplates", + RemoveOrganizationStackTemplates: { + Name: "RemoveOrganizationStackTemplates", Group: "StackTemplate", }, - CreateDashboard: { - Name: "CreateDashboard", + CreateDashboard: { + Name: "CreateDashboard", Group: "Dashboard", }, - GetDashboard: { - Name: "GetDashboard", + GetDashboard: { + Name: "GetDashboard", Group: "Dashboard", }, - UpdateDashboard: { - Name: "UpdateDashboard", + UpdateDashboard: { + Name: "UpdateDashboard", Group: "Dashboard", }, - GetChartsDashboard: { - Name: "GetChartsDashboard", + GetChartsDashboard: { + Name: "GetChartsDashboard", Group: "Dashboard", }, - GetChartDashboard: { - Name: "GetChartDashboard", + GetChartDashboard: { + Name: "GetChartDashboard", Group: "Dashboard", }, - GetStacksDashboard: { - Name: "GetStacksDashboard", + GetStacksDashboard: { + Name: "GetStacksDashboard", Group: "Dashboard", }, - GetResourcesDashboard: { - Name: "GetResourcesDashboard", + GetResourcesDashboard: { + Name: "GetResourcesDashboard", Group: "Dashboard", }, - GetPolicyStatusDashboard: { - Name: "GetPolicyStatusDashboard", + GetPolicyStatusDashboard: { + Name: "GetPolicyStatusDashboard", Group: "Dashboard", }, - GetPolicyUpdateDashboard: { - Name: "GetPolicyUpdateDashboard", + GetPolicyUpdateDashboard: { + Name: "GetPolicyUpdateDashboard", Group: "Dashboard", }, - GetPolicyEnforcementDashboard: { - Name: "GetPolicyEnforcementDashboard", + GetPolicyEnforcementDashboard: { + Name: "GetPolicyEnforcementDashboard", Group: "Dashboard", }, - GetPolicyViolationDashboard: { - Name: "GetPolicyViolationDashboard", + GetPolicyViolationDashboard: { + Name: "GetPolicyViolationDashboard", Group: "Dashboard", }, - GetPolicyViolationLogDashboard: { - Name: "GetPolicyViolationLogDashboard", + GetPolicyViolationLogDashboard: { + Name: "GetPolicyViolationLogDashboard", Group: "Dashboard", }, - GetPolicyStatisticsDashboard: { - Name: "GetPolicyStatisticsDashboard", + GetPolicyStatisticsDashboard: { + Name: "GetPolicyStatisticsDashboard", Group: "Dashboard", }, - GetWorkloadDashboard: { - Name: "GetWorkloadDashboard", + GetWorkloadDashboard: { + Name: "GetWorkloadDashboard", Group: "Dashboard", }, - GetPolicyViolationTop5Dashboard: { - Name: "GetPolicyViolationTop5Dashboard", + GetPolicyViolationTop5Dashboard: { + Name: "GetPolicyViolationTop5Dashboard", Group: "Dashboard", }, - Admin_CreateSystemNotificationTemplate: { - Name: "Admin_CreateSystemNotificationTemplate", + Admin_CreateSystemNotificationTemplate: { + Name: "Admin_CreateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_UpdateSystemNotificationTemplate: { - Name: "Admin_UpdateSystemNotificationTemplate", + Admin_UpdateSystemNotificationTemplate: { + Name: "Admin_UpdateSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_DeleteSystemNotificationTemplate: { - Name: "Admin_DeleteSystemNotificationTemplate", + Admin_DeleteSystemNotificationTemplate: { + Name: "Admin_DeleteSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplates: { - Name: "Admin_GetSystemNotificationTemplates", + Admin_GetSystemNotificationTemplates: { + Name: "Admin_GetSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - Admin_GetSystemNotificationTemplate: { - Name: "Admin_GetSystemNotificationTemplate", + Admin_GetSystemNotificationTemplate: { + Name: "Admin_GetSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - Admin_CheckSystemNotificationTemplateName: { - Name: "Admin_CheckSystemNotificationTemplateName", + Admin_CheckSystemNotificationTemplateName: { + Name: "Admin_CheckSystemNotificationTemplateName", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplates: { - Name: "GetOrganizationSystemNotificationTemplates", + GetOrganizationSystemNotificationTemplates: { + Name: "GetOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - GetOrganizationSystemNotificationTemplate: { - Name: "GetOrganizationSystemNotificationTemplate", + GetOrganizationSystemNotificationTemplate: { + Name: "GetOrganizationSystemNotificationTemplate", Group: "SystemNotificationTemplate", }, - AddOrganizationSystemNotificationTemplates: { - Name: "AddOrganizationSystemNotificationTemplates", + AddOrganizationSystemNotificationTemplates: { + Name: "AddOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - RemoveOrganizationSystemNotificationTemplates: { - Name: "RemoveOrganizationSystemNotificationTemplates", + RemoveOrganizationSystemNotificationTemplates: { + Name: "RemoveOrganizationSystemNotificationTemplates", Group: "SystemNotificationTemplate", }, - CreateSystemNotificationRule: { - Name: "CreateSystemNotificationRule", + CreateSystemNotificationRule: { + Name: "CreateSystemNotificationRule", Group: "SystemNotificationRule", }, - GetSystemNotificationRules: { - Name: "GetSystemNotificationRules", + GetSystemNotificationRules: { + Name: "GetSystemNotificationRules", Group: "SystemNotificationRule", }, - GetSystemNotificationRule: { - Name: "GetSystemNotificationRule", + GetSystemNotificationRule: { + Name: "GetSystemNotificationRule", Group: "SystemNotificationRule", }, - CheckSystemNotificationRuleName: { - Name: "CheckSystemNotificationRuleName", + CheckSystemNotificationRuleName: { + Name: "CheckSystemNotificationRuleName", Group: "SystemNotificationRule", }, - DeleteSystemNotificationRule: { - Name: "DeleteSystemNotificationRule", + DeleteSystemNotificationRule: { + Name: "DeleteSystemNotificationRule", Group: "SystemNotificationRule", }, - UpdateSystemNotificationRule: { - Name: "UpdateSystemNotificationRule", + UpdateSystemNotificationRule: { + Name: "UpdateSystemNotificationRule", Group: "SystemNotificationRule", }, - MakeDefaultSystemNotificationRules: { - Name: "MakeDefaultSystemNotificationRules", + MakeDefaultSystemNotificationRules: { + Name: "MakeDefaultSystemNotificationRules", Group: "SystemNotificationRule", }, - CreateSystemNotification: { - Name: "CreateSystemNotification", + CreateSystemNotification: { + Name: "CreateSystemNotification", Group: "SystemNotification", }, - GetSystemNotifications: { - Name: "GetSystemNotifications", + GetSystemNotifications: { + Name: "GetSystemNotifications", Group: "SystemNotification", }, - GetSystemNotification: { - Name: "GetSystemNotification", + GetSystemNotification: { + Name: "GetSystemNotification", Group: "SystemNotification", }, - DeleteSystemNotification: { - Name: "DeleteSystemNotification", + DeleteSystemNotification: { + Name: "DeleteSystemNotification", Group: "SystemNotification", }, - UpdateSystemNotification: { - Name: "UpdateSystemNotification", + UpdateSystemNotification: { + Name: "UpdateSystemNotification", Group: "SystemNotification", }, - CreateSystemNotificationAction: { - Name: "CreateSystemNotificationAction", + CreateSystemNotificationAction: { + Name: "CreateSystemNotificationAction", Group: "SystemNotification", }, - GetPolicyNotifications: { - Name: "GetPolicyNotifications", + GetPolicyNotifications: { + Name: "GetPolicyNotifications", Group: "PolicyNotification", }, - GetPolicyNotification: { - Name: "GetPolicyNotification", + GetPolicyNotification: { + Name: "GetPolicyNotification", Group: "PolicyNotification", }, - GetStacks: { - Name: "GetStacks", + GetStacks: { + Name: "GetStacks", Group: "Stack", }, - CreateStack: { - Name: "CreateStack", + CreateStack: { + Name: "CreateStack", Group: "Stack", }, - CheckStackName: { - Name: "CheckStackName", + CheckStackName: { + Name: "CheckStackName", Group: "Stack", }, - GetStack: { - Name: "GetStack", + GetStack: { + Name: "GetStack", Group: "Stack", }, - UpdateStack: { - Name: "UpdateStack", + UpdateStack: { + Name: "UpdateStack", Group: "Stack", }, - DeleteStack: { - Name: "DeleteStack", + DeleteStack: { + Name: "DeleteStack", Group: "Stack", }, - GetStackKubeconfig: { - Name: "GetStackKubeconfig", + GetStackKubeconfig: { + Name: "GetStackKubeconfig", Group: "Stack", }, - GetStackStatus: { - Name: "GetStackStatus", + GetStackStatus: { + Name: "GetStackStatus", Group: "Stack", }, - SetFavoriteStack: { - Name: "SetFavoriteStack", + SetFavoriteStack: { + Name: "SetFavoriteStack", Group: "Stack", }, - DeleteFavoriteStack: { - Name: "DeleteFavoriteStack", + DeleteFavoriteStack: { + Name: "DeleteFavoriteStack", Group: "Stack", }, - InstallStack: { - Name: "InstallStack", + InstallStack: { + Name: "InstallStack", Group: "Stack", }, - CreateProject: { - Name: "CreateProject", + CreateProject: { + Name: "CreateProject", Group: "Project", }, - GetProjectRoles: { - Name: "GetProjectRoles", + GetProjectRoles: { + Name: "GetProjectRoles", Group: "Project", }, - GetProjectRole: { - Name: "GetProjectRole", + GetProjectRole: { + Name: "GetProjectRole", Group: "Project", }, - GetProjects: { - Name: "GetProjects", + GetProjects: { + Name: "GetProjects", Group: "Project", }, - GetProject: { - Name: "GetProject", + GetProject: { + Name: "GetProject", Group: "Project", }, - UpdateProject: { - Name: "UpdateProject", + UpdateProject: { + Name: "UpdateProject", Group: "Project", }, - DeleteProject: { - Name: "DeleteProject", + DeleteProject: { + Name: "DeleteProject", Group: "Project", }, - AddProjectMember: { - Name: "AddProjectMember", + AddProjectMember: { + Name: "AddProjectMember", Group: "Project", }, - GetProjectMember: { - Name: "GetProjectMember", + GetProjectMember: { + Name: "GetProjectMember", Group: "Project", }, - GetProjectMembers: { - Name: "GetProjectMembers", + GetProjectMembers: { + Name: "GetProjectMembers", Group: "Project", }, - RemoveProjectMember: { - Name: "RemoveProjectMember", + RemoveProjectMember: { + Name: "RemoveProjectMember", Group: "Project", }, - UpdateProjectMemberRole: { - Name: "UpdateProjectMemberRole", + UpdateProjectMemberRole: { + Name: "UpdateProjectMemberRole", Group: "Project", }, - CreateProjectNamespace: { - Name: "CreateProjectNamespace", + CreateProjectNamespace: { + Name: "CreateProjectNamespace", Group: "Project", }, - GetProjectNamespaces: { - Name: "GetProjectNamespaces", + GetProjectNamespaces: { + Name: "GetProjectNamespaces", Group: "Project", }, - GetProjectNamespace: { - Name: "GetProjectNamespace", + GetProjectNamespace: { + Name: "GetProjectNamespace", Group: "Project", }, - UpdateProjectNamespace: { - Name: "UpdateProjectNamespace", + UpdateProjectNamespace: { + Name: "UpdateProjectNamespace", Group: "Project", }, - DeleteProjectNamespace: { - Name: "DeleteProjectNamespace", + DeleteProjectNamespace: { + Name: "DeleteProjectNamespace", Group: "Project", }, - SetFavoriteProject: { - Name: "SetFavoriteProject", + SetFavoriteProject: { + Name: "SetFavoriteProject", Group: "Project", }, - SetFavoriteProjectNamespace: { - Name: "SetFavoriteProjectNamespace", + SetFavoriteProjectNamespace: { + Name: "SetFavoriteProjectNamespace", Group: "Project", }, - UnSetFavoriteProject: { - Name: "UnSetFavoriteProject", + UnSetFavoriteProject: { + Name: "UnSetFavoriteProject", Group: "Project", }, - UnSetFavoriteProjectNamespace: { - Name: "UnSetFavoriteProjectNamespace", + UnSetFavoriteProjectNamespace: { + Name: "UnSetFavoriteProjectNamespace", Group: "Project", }, - GetProjectKubeconfig: { - Name: "GetProjectKubeconfig", + GetProjectKubeconfig: { + Name: "GetProjectKubeconfig", Group: "Project", }, - GetProjectNamespaceK8sResources: { - Name: "GetProjectNamespaceK8sResources", + GetProjectNamespaceK8sResources: { + Name: "GetProjectNamespaceK8sResources", Group: "Project", }, - GetProjectNamespaceKubeconfig: { - Name: "GetProjectNamespaceKubeconfig", + GetProjectNamespaceKubeconfig: { + Name: "GetProjectNamespaceKubeconfig", Group: "Project", }, - GetAudits: { - Name: "GetAudits", + GetAudits: { + Name: "GetAudits", Group: "Audit", }, - GetAudit: { - Name: "GetAudit", + GetAudit: { + Name: "GetAudit", Group: "Audit", }, - DeleteAudit: { - Name: "DeleteAudit", + DeleteAudit: { + Name: "DeleteAudit", Group: "Audit", }, - CreateTksRole: { - Name: "CreateTksRole", + CreateTksRole: { + Name: "CreateTksRole", Group: "Role", }, - ListTksRoles: { - Name: "ListTksRoles", + ListTksRoles: { + Name: "ListTksRoles", Group: "Role", }, - GetTksRole: { - Name: "GetTksRole", + GetTksRole: { + Name: "GetTksRole", Group: "Role", }, - DeleteTksRole: { - Name: "DeleteTksRole", + DeleteTksRole: { + Name: "DeleteTksRole", Group: "Role", }, - UpdateTksRole: { - Name: "UpdateTksRole", + UpdateTksRole: { + Name: "UpdateTksRole", Group: "Role", }, - GetPermissionsByRoleId: { - Name: "GetPermissionsByRoleId", + GetPermissionsByRoleId: { + Name: "GetPermissionsByRoleId", Group: "Role", }, - UpdatePermissionsByRoleId: { - Name: "UpdatePermissionsByRoleId", + UpdatePermissionsByRoleId: { + Name: "UpdatePermissionsByRoleId", Group: "Role", }, - IsRoleNameExisted: { - Name: "IsRoleNameExisted", + IsRoleNameExisted: { + Name: "IsRoleNameExisted", Group: "Role", }, - AppendUsersToRole: { - Name: "AppendUsersToRole", + AppendUsersToRole: { + Name: "AppendUsersToRole", Group: "Role", }, - GetUsersInRoleId: { - Name: "GetUsersInRoleId", + GetUsersInRoleId: { + Name: "GetUsersInRoleId", Group: "Role", }, - RemoveUsersFromRole: { - Name: "RemoveUsersFromRole", + RemoveUsersFromRole: { + Name: "RemoveUsersFromRole", Group: "Role", }, - GetPermissionTemplates: { - Name: "GetPermissionTemplates", + GetPermissionTemplates: { + Name: "GetPermissionTemplates", Group: "Permission", }, - Admin_CreateUser: { - Name: "Admin_CreateUser", + Admin_CreateUser: { + Name: "Admin_CreateUser", Group: "Admin_User", }, - Admin_ListUser: { - Name: "Admin_ListUser", + Admin_ListUser: { + Name: "Admin_ListUser", Group: "Admin_User", }, - Admin_GetUser: { - Name: "Admin_GetUser", + Admin_GetUser: { + Name: "Admin_GetUser", Group: "Admin_User", }, - Admin_DeleteUser: { - Name: "Admin_DeleteUser", + Admin_DeleteUser: { + Name: "Admin_DeleteUser", Group: "Admin_User", }, - Admin_UpdateUser: { - Name: "Admin_UpdateUser", + Admin_UpdateUser: { + Name: "Admin_UpdateUser", Group: "Admin_User", }, - Admin_ListTksRoles: { - Name: "Admin_ListTksRoles", + Admin_ListTksRoles: { + Name: "Admin_ListTksRoles", Group: "Admin Role", }, - Admin_GetTksRole: { - Name: "Admin_GetTksRole", + Admin_GetTksRole: { + Name: "Admin_GetTksRole", Group: "Admin Role", }, - Admin_GetProjects: { - Name: "Admin_GetProjects", + Admin_GetProjects: { + Name: "Admin_GetProjects", Group: "Admin Project", }, - Admin_ListPolicyTemplate: { - Name: "Admin_ListPolicyTemplate", + Admin_ListPolicyTemplate: { + Name: "Admin_ListPolicyTemplate", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplate: { - Name: "Admin_CreatePolicyTemplate", + Admin_CreatePolicyTemplate: { + Name: "Admin_CreatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplate: { - Name: "Admin_DeletePolicyTemplate", + Admin_DeletePolicyTemplate: { + Name: "Admin_DeletePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplate: { - Name: "Admin_GetPolicyTemplate", + Admin_GetPolicyTemplate: { + Name: "Admin_GetPolicyTemplate", Group: "PolicyTemplate", }, - Admin_UpdatePolicyTemplate: { - Name: "Admin_UpdatePolicyTemplate", + Admin_UpdatePolicyTemplate: { + Name: "Admin_UpdatePolicyTemplate", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateDeploy: { - Name: "Admin_GetPolicyTemplateDeploy", + Admin_GetPolicyTemplateDeploy: { + Name: "Admin_GetPolicyTemplateDeploy", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateStatistics: { - Name: "Admin_ListPolicyTemplateStatistics", + Admin_ListPolicyTemplateStatistics: { + Name: "Admin_ListPolicyTemplateStatistics", Group: "PolicyTemplate", }, - Admin_ListPolicyTemplateVersions: { - Name: "Admin_ListPolicyTemplateVersions", + Admin_ListPolicyTemplateVersions: { + Name: "Admin_ListPolicyTemplateVersions", Group: "PolicyTemplate", }, - Admin_CreatePolicyTemplateVersion: { - Name: "Admin_CreatePolicyTemplateVersion", + Admin_CreatePolicyTemplateVersion: { + Name: "Admin_CreatePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_DeletePolicyTemplateVersion: { - Name: "Admin_DeletePolicyTemplateVersion", + Admin_DeletePolicyTemplateVersion: { + Name: "Admin_DeletePolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_GetPolicyTemplateVersion: { - Name: "Admin_GetPolicyTemplateVersion", + Admin_GetPolicyTemplateVersion: { + Name: "Admin_GetPolicyTemplateVersion", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateKind: { - Name: "Admin_ExistsPolicyTemplateKind", + Admin_ExistsPolicyTemplateKind: { + Name: "Admin_ExistsPolicyTemplateKind", Group: "PolicyTemplate", }, - Admin_ExistsPolicyTemplateName: { - Name: "Admin_ExistsPolicyTemplateName", + Admin_ExistsPolicyTemplateName: { + Name: "Admin_ExistsPolicyTemplateName", Group: "PolicyTemplate", }, - Admin_ExtractParameters: { - Name: "Admin_ExtractParameters", + Admin_ExtractParameters: { + Name: "Admin_ExtractParameters", Group: "PolicyTemplate", }, - Admin_AddPermittedPolicyTemplatesForOrganization: { - Name: "Admin_AddPermittedPolicyTemplatesForOrganization", + Admin_AddPermittedPolicyTemplatesForOrganization: { + Name: "Admin_AddPermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - Admin_DeletePermittedPolicyTemplatesForOrganization: { - Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", + Admin_DeletePermittedPolicyTemplatesForOrganization: { + Name: "Admin_DeletePermittedPolicyTemplatesForOrganization", Group: "PolicyTemplate", }, - ListStackPolicyStatus: { - Name: "ListStackPolicyStatus", + ListStackPolicyStatus: { + Name: "ListStackPolicyStatus", Group: "StackPolicyStatus", }, - GetStackPolicyTemplateStatus: { - Name: "GetStackPolicyTemplateStatus", + GetStackPolicyTemplateStatus: { + Name: "GetStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - UpdateStackPolicyTemplateStatus: { - Name: "UpdateStackPolicyTemplateStatus", + UpdateStackPolicyTemplateStatus: { + Name: "UpdateStackPolicyTemplateStatus", Group: "StackPolicyStatus", }, - GetMandatoryPolicies: { - Name: "GetMandatoryPolicies", + GetMandatoryPolicies: { + Name: "GetMandatoryPolicies", Group: "Policy", }, - SetMandatoryPolicies: { - Name: "SetMandatoryPolicies", + SetMandatoryPolicies: { + Name: "SetMandatoryPolicies", Group: "Policy", }, - GetPolicyStatistics: { - Name: "GetPolicyStatistics", + GetPolicyStatistics: { + Name: "GetPolicyStatistics", Group: "Policy", }, - ListPolicy: { - Name: "ListPolicy", + ListPolicy: { + Name: "ListPolicy", Group: "Policy", }, - CreatePolicy: { - Name: "CreatePolicy", + CreatePolicy: { + Name: "CreatePolicy", Group: "Policy", }, - DeletePolicy: { - Name: "DeletePolicy", + DeletePolicy: { + Name: "DeletePolicy", Group: "Policy", }, - GetPolicy: { - Name: "GetPolicy", + GetPolicy: { + Name: "GetPolicy", Group: "Policy", }, - UpdatePolicy: { - Name: "UpdatePolicy", + UpdatePolicy: { + Name: "UpdatePolicy", Group: "Policy", }, - UpdatePolicyTargetClusters: { - Name: "UpdatePolicyTargetClusters", + UpdatePolicyTargetClusters: { + Name: "UpdatePolicyTargetClusters", Group: "Policy", }, - ExistsPolicyName: { - Name: "ExistsPolicyName", + ExistsPolicyName: { + Name: "ExistsPolicyName", Group: "Policy", }, - ExistsPolicyResourceName: { - Name: "ExistsPolicyResourceName", + ExistsPolicyResourceName: { + Name: "ExistsPolicyResourceName", Group: "Policy", }, - GetPolicyEdit: { - Name: "GetPolicyEdit", + GetPolicyEdit: { + Name: "GetPolicyEdit", Group: "Policy", }, - AddPoliciesForStack: { - Name: "AddPoliciesForStack", + AddPoliciesForStack: { + Name: "AddPoliciesForStack", Group: "Policy", }, - DeletePoliciesForStack: { - Name: "DeletePoliciesForStack", + DeletePoliciesForStack: { + Name: "DeletePoliciesForStack", Group: "Policy", }, - StackPolicyStatistics: { - Name: "StackPolicyStatistics", + StackPolicyStatistics: { + Name: "StackPolicyStatistics", Group: "Policy", }, - ListPolicyTemplate: { - Name: "ListPolicyTemplate", + ListPolicyTemplate: { + Name: "ListPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplate: { - Name: "CreatePolicyTemplate", + CreatePolicyTemplate: { + Name: "CreatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplate: { - Name: "DeletePolicyTemplate", + DeletePolicyTemplate: { + Name: "DeletePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplate: { - Name: "GetPolicyTemplate", + GetPolicyTemplate: { + Name: "GetPolicyTemplate", Group: "OrganizationPolicyTemplate", }, - UpdatePolicyTemplate: { - Name: "UpdatePolicyTemplate", + UpdatePolicyTemplate: { + Name: "UpdatePolicyTemplate", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateDeploy: { - Name: "GetPolicyTemplateDeploy", + GetPolicyTemplateDeploy: { + Name: "GetPolicyTemplateDeploy", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateStatistics: { - Name: "ListPolicyTemplateStatistics", + ListPolicyTemplateStatistics: { + Name: "ListPolicyTemplateStatistics", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateVersions: { - Name: "ListPolicyTemplateVersions", + ListPolicyTemplateVersions: { + Name: "ListPolicyTemplateVersions", Group: "OrganizationPolicyTemplate", }, - CreatePolicyTemplateVersion: { - Name: "CreatePolicyTemplateVersion", + CreatePolicyTemplateVersion: { + Name: "CreatePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - DeletePolicyTemplateVersion: { - Name: "DeletePolicyTemplateVersion", + DeletePolicyTemplateVersion: { + Name: "DeletePolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - GetPolicyTemplateVersion: { - Name: "GetPolicyTemplateVersion", + GetPolicyTemplateVersion: { + Name: "GetPolicyTemplateVersion", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateKind: { - Name: "ExistsPolicyTemplateKind", + ExistsPolicyTemplateKind: { + Name: "ExistsPolicyTemplateKind", Group: "OrganizationPolicyTemplate", }, - ExistsPolicyTemplateName: { - Name: "ExistsPolicyTemplateName", + ExistsPolicyTemplateName: { + Name: "ExistsPolicyTemplateName", Group: "OrganizationPolicyTemplate", }, - ExtractParameters: { - Name: "ExtractParameters", + ExtractParameters: { + Name: "ExtractParameters", Group: "OrganizationPolicyTemplate", }, - ListPolicyTemplateExample: { - Name: "ListPolicyTemplateExample", + ListPolicyTemplateExample: { + Name: "ListPolicyTemplateExample", Group: "PolicyTemplateExample", }, - GetPolicyTemplateExample: { - Name: "GetPolicyTemplateExample", + GetPolicyTemplateExample: { + Name: "GetPolicyTemplateExample", Group: "PolicyTemplateExample", }, - UpdatePolicyTemplateExample: { - Name: "UpdatePolicyTemplateExample", + UpdatePolicyTemplateExample: { + Name: "UpdatePolicyTemplateExample", Group: "PolicyTemplateExample", }, - DeletePolicyTemplateExample: { - Name: "DeletePolicyTemplateExample", + DeletePolicyTemplateExample: { + Name: "DeletePolicyTemplateExample", Group: "PolicyTemplateExample", }, - CompileRego: { - Name: "CompileRego", + CompileRego: { + Name: "CompileRego", Group: "Utility", }, } - func (e Endpoint) String() string { switch e { case Login: @@ -1013,6 +1020,8 @@ func (e Endpoint) String() string { return "GetClusterSiteValues" case InstallCluster: return "InstallCluster" + case ResumeCluster: + return "ResumeCluster" case CreateBootstrapKubeconfig: return "CreateBootstrapKubeconfig" case GetBootstrapKubeconfig: @@ -1045,6 +1054,8 @@ func (e Endpoint) String() string { return "GetAppServeApp" case GetAppServeAppLatestTask: return "GetAppServeAppLatestTask" + case GetAppServeAppLog: + return "GetAppServeAppLog" case IsAppServeAppExist: return "IsAppServeAppExist" case IsAppServeAppNameExist: @@ -1485,6 +1496,8 @@ func GetEndpoint(name string) Endpoint { return GetClusterSiteValues case "InstallCluster": return InstallCluster + case "ResumeCluster": + return ResumeCluster case "CreateBootstrapKubeconfig": return CreateBootstrapKubeconfig case "GetBootstrapKubeconfig": @@ -1517,6 +1530,8 @@ func GetEndpoint(name string) Endpoint { return GetAppServeApp case "GetAppServeAppLatestTask": return GetAppServeAppLatestTask + case "GetAppServeAppLog": + return GetAppServeAppLog case "IsAppServeAppExist": return IsAppServeAppExist case "IsAppServeAppNameExist": diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 3043ce02..02db9d12 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -238,8 +238,8 @@ func (h *ClusterHandler) ImportCluster(w http.ResponseWriter, r *http.Request) { // InstallCluster godoc // // @Tags Clusters -// @Summary Install cluster on tks cluster -// @Description Install cluster on tks cluster +// @Summary Install cluster on tks cluster ( BYOH ) +// @Description Install cluster on tks cluster ( BYOH ) // @Accept json // @Produce json // @Param clusterId path string true "clusterId" @@ -263,6 +263,34 @@ func (h *ClusterHandler) InstallCluster(w http.ResponseWriter, r *http.Request) ResponseJSON(w, r, http.StatusOK, nil) } +// ResumeCluster godoc +// +// @Tags Clusters +// @Summary Resume Cluster ( BYOH ) +// @Description Resume Cluster ( BYOH ) +// @Accept json +// @Produce json +// @Param clusterId path string true "clusterId" +// @Success 200 {object} nil +// @Router /clusters/{clusterId}/resume [put] +// @Security JWT +func (h *ClusterHandler) ResumeCluster(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + clusterId, ok := vars["clusterId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid clusterId"), "C_INVALID_CLUSTER_ID", "")) + return + } + + err := h.usecase.Resume(r.Context(), domain.ClusterId(clusterId)) + if err != nil { + ErrorJSON(w, r, err) + return + } + + ResponseJSON(w, r, http.StatusOK, nil) +} + // DeleteCluster godoc // // @Tags Clusters diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 2afe1705..cf996048 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -94,6 +94,18 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } +// InstallStack godoc +// +// @Tags Stacks +// @Summary Install Stack ( BYOH ) +// @Description Install Stack ( BYOH ) +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param stackId path string true "stackId" +// @Success 200 {object} nil +// @Router /organizations/{organizationId}/stacks/{stackId}/install [post] +// @Security JWT func (h *StackHandler) InstallStack(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) stackId, ok := vars["stackId"] diff --git a/internal/route/route.go b/internal/route/route.go index 06acc7ba..1b3db302 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -150,6 +150,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/bootstrap-kubeconfig", customMiddleware.Handle(internalApi.CreateBootstrapKubeconfig, http.HandlerFunc(clusterHandler.CreateBootstrapKubeconfig))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/bootstrap-kubeconfig", customMiddleware.Handle(internalApi.GetBootstrapKubeconfig, http.HandlerFunc(clusterHandler.GetBootstrapKubeconfig))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/nodes", customMiddleware.Handle(internalApi.GetNodes, http.HandlerFunc(clusterHandler.GetNodes))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/clusters/{clusterId}/resume", customMiddleware.Handle(internalApi.ResumeCluster, http.HandlerFunc(clusterHandler.ResumeCluster))).Methods(http.MethodPut) appGroupHandler := delivery.NewAppGroupHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/app-groups", customMiddleware.Handle(internalApi.CreateAppgroup, http.HandlerFunc(appGroupHandler.CreateAppGroup))).Methods(http.MethodPost) diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index eb795c40..425bdd7d 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -40,6 +40,7 @@ type IClusterUsecase interface { Import(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) Bootstrap(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) Install(ctx context.Context, clusterId domain.ClusterId) (err error) + Resume(ctx context.Context, clusterId domain.ClusterId) (err error) Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) GetClusterSiteValues(ctx context.Context, clusterId domain.ClusterId) (out domain.ClusterSiteValuesResponse, err error) Delete(ctx context.Context, clusterId domain.ClusterId) (err error) @@ -432,6 +433,33 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId return nil } +func (u *ClusterUsecase) Resume(ctx context.Context, clusterId domain.ClusterId) (err error) { + cluster, err := u.Get(ctx, clusterId) + if err != nil { + return httpErrors.NewBadRequestError(fmt.Errorf("Invalid stackId"), "S_INVALID_STACK_ID", "") + } + + if cluster.CloudService != domain.CloudService_BYOH { + return httpErrors.NewBadRequestError(fmt.Errorf("Invalid cloud service"), "S_INVALID_CLOUD_SERVICE", "") + } + + if cluster.WorkflowId == "" { + return httpErrors.NewInternalServerError(fmt.Errorf("Invalid workflow id"), "", "") + } + + workflow, err := u.argo.ResumeWorkflow(ctx, "argo", cluster.WorkflowId) + if err != nil { + log.Error(ctx, err) + return httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") + } + log.Debug(ctx, "Resume workflow: ", workflow) + + if err := u.repo.InitWorkflow(ctx, cluster.ID, cluster.WorkflowId, domain.ClusterStatus_INSTALLING); err != nil { + return errors.Wrap(err, "Failed to initialize status") + } + return nil +} + func (u *ClusterUsecase) Get(ctx context.Context, clusterId domain.ClusterId) (out model.Cluster, err error) { cluster, err := u.repo.Get(ctx, clusterId) if err != nil { diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index ff7299a0..c57f3683 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -3,12 +3,13 @@ package usecase import ( "context" "fmt" - "github.com/Nerzal/gocloak/v13" - "github.com/openinfradev/tks-api/internal/keycloak" "sort" "strings" "time" + "github.com/Nerzal/gocloak/v13" + "github.com/openinfradev/tks-api/internal/keycloak" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/middleware/auth/request" @@ -476,6 +477,7 @@ func (u *StackUsecase) Delete(ctx context.Context, dto model.Stack) (err error) // cluster 의 상태가 비정상 상태라면, DB 데이터만 삭제 if cluster.Status != domain.ClusterStatus_RUNNING && cluster.Status != domain.ClusterStatus_BOOTSTRAPPING && + cluster.Status != domain.ClusterStatus_STOPPED && cluster.Status != domain.ClusterStatus_INSTALLING && cluster.Status != domain.ClusterStatus_DELETING { return u.clusterRepo.Delete(ctx, domain.ClusterId(dto.ID)) @@ -782,6 +784,9 @@ func getStackStatus(cluster model.Cluster, appGroups []model.AppGroup) (domain.S } } + if cluster.Status == domain.ClusterStatus_STOPPED { + return domain.StackStatus_CLUETER_STOPPED, cluster.StatusDesc + } if cluster.Status == domain.ClusterStatus_BOOTSTRAPPING { return domain.StackStatus_CLUSTER_BOOTSTRAPPING, cluster.StatusDesc } diff --git a/pkg/argo-client/client-mock.go b/pkg/argo-client/client-mock.go index 47891107..8a3412fd 100644 --- a/pkg/argo-client/client-mock.go +++ b/pkg/argo-client/client-mock.go @@ -43,3 +43,7 @@ func (c *ArgoClientMockImpl) GetWorkflows(ctx context.Context, namespace string) func (c *ArgoClientMockImpl) SumbitWorkflowFromWftpl(ctx context.Context, wftplName string, opts SubmitOptions) (string, error) { return "", nil } + +func (c *ArgoClientMockImpl) ResumeWorkflow(ctx context.Context, namespace string, workflowName string) (*Workflow, error) { + return nil, nil +} diff --git a/pkg/argo-client/client.go b/pkg/argo-client/client.go index 3b10eb50..4adabc6b 100644 --- a/pkg/argo-client/client.go +++ b/pkg/argo-client/client.go @@ -18,6 +18,7 @@ type ArgoClient interface { GetWorkflowLog(ctx context.Context, namespace string, container string, workflowName string) (logs string, err error) GetWorkflows(ctx context.Context, namespace string) (*GetWorkflowsResponse, error) SumbitWorkflowFromWftpl(ctx context.Context, wftplName string, opts SubmitOptions) (string, error) + ResumeWorkflow(ctx context.Context, namespace string, workflowName string) (*Workflow, error) } type ArgoClientImpl struct { @@ -217,3 +218,45 @@ func (c *ArgoClientImpl) SumbitWorkflowFromWftpl(ctx context.Context, wftplName } return submitRes.Metadata.Name, nil } + +func (c *ArgoClientImpl) ResumeWorkflow(ctx context.Context, namespace string, workflowName string) (*Workflow, error) { + /* + { + "name": "string", + "namespace": "string", + "nodeFieldSelector": "string" + } + */ + req, err := http.NewRequest("PUT", fmt.Sprintf("%s/api/v1/workflows/%s/%s/resume", c.url, namespace, workflowName), nil) + if err != nil { + return nil, err + } + + res, err := c.client.Do(req) + if err != nil { + return nil, err + } + + if res == nil { + return nil, fmt.Errorf("Failed to call resume argo workflow.") + } + if res.StatusCode != 200 { + return nil, fmt.Errorf("Invalid http status. return code: %d", res.StatusCode) + } + defer func() { + if err := res.Body.Close(); err != nil { + log.Error(ctx, "error closing http body") + } + }() + + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + workflowRes := Workflow{} + if err := json.Unmarshal(body, &workflowRes); err != nil { + log.Error(ctx, "an error was unexpected while parsing response from api /workflow template.") + return nil, err + } + return &workflowRes, nil +} diff --git a/pkg/argo-client/mock/client.go b/pkg/argo-client/mock/client.go index f4946649..8d9f23ce 100644 --- a/pkg/argo-client/mock/client.go +++ b/pkg/argo-client/mock/client.go @@ -1,95 +1,126 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: client.go +// Source: pkg/argo-client/client.go // Package mock_argowf is a generated GoMock package. package mock_argowf import ( + context "context" reflect "reflect" gomock "github.com/golang/mock/gomock" argowf "github.com/openinfradev/tks-api/pkg/argo-client" ) -// MockClient is a mock of Client interface. -type MockClient struct { +// MockArgoClient is a mock of ArgoClient interface. +type MockArgoClient struct { ctrl *gomock.Controller - recorder *MockClientMockRecorder + recorder *MockArgoClientMockRecorder } -// MockClientMockRecorder is the mock recorder for MockClient. -type MockClientMockRecorder struct { - mock *MockClient +// MockArgoClientMockRecorder is the mock recorder for MockArgoClient. +type MockArgoClientMockRecorder struct { + mock *MockArgoClient } -// NewMockClient creates a new mock instance. -func NewMockClient(ctrl *gomock.Controller) *MockClient { - mock := &MockClient{ctrl: ctrl} - mock.recorder = &MockClientMockRecorder{mock} +// NewMockArgoClient creates a new mock instance. +func NewMockArgoClient(ctrl *gomock.Controller) *MockArgoClient { + mock := &MockArgoClient{ctrl: ctrl} + mock.recorder = &MockArgoClientMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockClient) EXPECT() *MockClientMockRecorder { +func (m *MockArgoClient) EXPECT() *MockArgoClientMockRecorder { return m.recorder } // GetWorkflow mocks base method. -func (m *MockClient) GetWorkflow(namespace, workflowName string) (*argowf.Workflow, error) { +func (m *MockArgoClient) GetWorkflow(ctx context.Context, namespace, workflowName string) (*argowf.Workflow, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWorkflow", namespace, workflowName) + ret := m.ctrl.Call(m, "GetWorkflow", ctx, namespace, workflowName) ret0, _ := ret[0].(*argowf.Workflow) ret1, _ := ret[1].(error) return ret0, ret1 } // GetWorkflow indicates an expected call of GetWorkflow. -func (mr *MockClientMockRecorder) GetWorkflow(namespace, workflowName interface{}) *gomock.Call { +func (mr *MockArgoClientMockRecorder) GetWorkflow(ctx, namespace, workflowName interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkflow", reflect.TypeOf((*MockClient)(nil).GetWorkflow), namespace, workflowName) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkflow", reflect.TypeOf((*MockArgoClient)(nil).GetWorkflow), ctx, namespace, workflowName) +} + +// GetWorkflowLog mocks base method. +func (m *MockArgoClient) GetWorkflowLog(ctx context.Context, namespace, container, workflowName string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetWorkflowLog", ctx, namespace, container, workflowName) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetWorkflowLog indicates an expected call of GetWorkflowLog. +func (mr *MockArgoClientMockRecorder) GetWorkflowLog(ctx, namespace, container, workflowName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkflowLog", reflect.TypeOf((*MockArgoClient)(nil).GetWorkflowLog), ctx, namespace, container, workflowName) } // GetWorkflowTemplates mocks base method. -func (m *MockClient) GetWorkflowTemplates(namespace string) (*argowf.GetWorkflowTemplatesResponse, error) { +func (m *MockArgoClient) GetWorkflowTemplates(ctx context.Context, namespace string) (*argowf.GetWorkflowTemplatesResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWorkflowTemplates", namespace) + ret := m.ctrl.Call(m, "GetWorkflowTemplates", ctx, namespace) ret0, _ := ret[0].(*argowf.GetWorkflowTemplatesResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // GetWorkflowTemplates indicates an expected call of GetWorkflowTemplates. -func (mr *MockClientMockRecorder) GetWorkflowTemplates(namespace interface{}) *gomock.Call { +func (mr *MockArgoClientMockRecorder) GetWorkflowTemplates(ctx, namespace interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkflowTemplates", reflect.TypeOf((*MockClient)(nil).GetWorkflowTemplates), namespace) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkflowTemplates", reflect.TypeOf((*MockArgoClient)(nil).GetWorkflowTemplates), ctx, namespace) } // GetWorkflows mocks base method. -func (m *MockClient) GetWorkflows(namespace string) (*argowf.GetWorkflowsResponse, error) { +func (m *MockArgoClient) GetWorkflows(ctx context.Context, namespace string) (*argowf.GetWorkflowsResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWorkflows", namespace) + ret := m.ctrl.Call(m, "GetWorkflows", ctx, namespace) ret0, _ := ret[0].(*argowf.GetWorkflowsResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // GetWorkflows indicates an expected call of GetWorkflows. -func (mr *MockClientMockRecorder) GetWorkflows(namespace interface{}) *gomock.Call { +func (mr *MockArgoClientMockRecorder) GetWorkflows(ctx, namespace interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkflows", reflect.TypeOf((*MockArgoClient)(nil).GetWorkflows), ctx, namespace) +} + +// ResumeWorkflow mocks base method. +func (m *MockArgoClient) ResumeWorkflow(ctx context.Context, namespace, workflowName string) (*argowf.Workflow, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ResumeWorkflow", ctx, namespace, workflowName) + ret0, _ := ret[0].(*argowf.Workflow) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ResumeWorkflow indicates an expected call of ResumeWorkflow. +func (mr *MockArgoClientMockRecorder) ResumeWorkflow(ctx, namespace, workflowName interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkflows", reflect.TypeOf((*MockClient)(nil).GetWorkflows), namespace) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResumeWorkflow", reflect.TypeOf((*MockArgoClient)(nil).ResumeWorkflow), ctx, namespace, workflowName) } // SumbitWorkflowFromWftpl mocks base method. -func (m *MockClient) SumbitWorkflowFromWftpl(wftplName, targetNamespace string, opts argowf.SubmitOptions) (string, error) { +func (m *MockArgoClient) SumbitWorkflowFromWftpl(ctx context.Context, wftplName string, opts argowf.SubmitOptions) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SumbitWorkflowFromWftpl", wftplName, targetNamespace, opts) + ret := m.ctrl.Call(m, "SumbitWorkflowFromWftpl", ctx, wftplName, opts) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // SumbitWorkflowFromWftpl indicates an expected call of SumbitWorkflowFromWftpl. -func (mr *MockClientMockRecorder) SumbitWorkflowFromWftpl(wftplName, targetNamespace, opts interface{}) *gomock.Call { +func (mr *MockArgoClientMockRecorder) SumbitWorkflowFromWftpl(ctx, wftplName, opts interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SumbitWorkflowFromWftpl", reflect.TypeOf((*MockClient)(nil).SumbitWorkflowFromWftpl), wftplName, targetNamespace, opts) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SumbitWorkflowFromWftpl", reflect.TypeOf((*MockArgoClient)(nil).SumbitWorkflowFromWftpl), ctx, wftplName, opts) } diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index 891abfad..0cad4b85 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -35,6 +35,7 @@ const ( ClusterStatus_BOOTSTRAPPING ClusterStatus_BOOTSTRAPPED ClusterStatus_BOOTSTRAP_ERROR + ClusterStatus_STOPPED ) var clusterStatus = [...]string{ @@ -48,6 +49,7 @@ var clusterStatus = [...]string{ "BOOTSTRAPPING", "BOOTSTRAPPED", "BOOTSTRAP_ERROR", + "STOPPED", } func (m ClusterStatus) String() string { return clusterStatus[(m)] } diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 343b2731..f35ec1e0 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -37,6 +37,7 @@ const ( StackStatus_CLUSTER_BOOTSTRAPPING StackStatus_CLUSTER_BOOTSTRAPPED + StackStatus_CLUETER_STOPPED ) var stackStatus = [...]string{ @@ -53,6 +54,7 @@ var stackStatus = [...]string{ "RUNNING", "BOOTSTRAPPING", "BOOTSTRAPPED", + "STOPPED", } func (m StackStatus) String() string { return stackStatus[(m)] } From 06add2270db165e1cce61f4d564f084111a7dc3d Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 26 Jun 2024 16:00:22 +0900 Subject: [PATCH 483/502] trivial. change stopped status --- pkg/domain/stack.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index f35ec1e0..5033c5ea 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -54,7 +54,7 @@ var stackStatus = [...]string{ "RUNNING", "BOOTSTRAPPING", "BOOTSTRAPPED", - "STOPPED", + "CLUSTER_STOPPED", } func (m StackStatus) String() string { return stackStatus[(m)] } From 9889a37b66fcf9d8c2aa9339067fa634a1926a4f Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 26 Jun 2024 16:04:01 +0900 Subject: [PATCH 484/502] tirivial. change stop status --- pkg/domain/stack.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 5033c5ea..6aac9851 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -54,7 +54,7 @@ var stackStatus = [...]string{ "RUNNING", "BOOTSTRAPPING", "BOOTSTRAPPED", - "CLUSTER_STOPPED", + "CLUSTER_INSTALL_STOPPED", } func (m StackStatus) String() string { return stackStatus[(m)] } From 68ababc5ed5e180b6104192fe656509eb1f859fc Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 2 Jul 2024 14:49:03 +0900 Subject: [PATCH 485/502] feature. add api IsPausedWorkflow --- pkg/argo-client/client-mock.go | 4 +++ pkg/argo-client/client.go | 55 ++++++++++++++++++++++++++++++++++ pkg/argo-client/mock/client.go | 15 ++++++++++ 3 files changed, 74 insertions(+) diff --git a/pkg/argo-client/client-mock.go b/pkg/argo-client/client-mock.go index 8a3412fd..739adbd3 100644 --- a/pkg/argo-client/client-mock.go +++ b/pkg/argo-client/client-mock.go @@ -32,6 +32,10 @@ func (c *ArgoClientMockImpl) GetWorkflow(ctx context.Context, namespace string, return nil, nil } +func (c *ArgoClientMockImpl) IsPausedWorkflow(ctx context.Context, namespace string, workflowName string) (bool, error) { + return false, nil +} + func (c *ArgoClientMockImpl) GetWorkflowLog(ctx context.Context, namespace string, container string, workflowName string) (string, error) { return "", nil } diff --git a/pkg/argo-client/client.go b/pkg/argo-client/client.go index 4adabc6b..9a16e456 100644 --- a/pkg/argo-client/client.go +++ b/pkg/argo-client/client.go @@ -15,6 +15,7 @@ import ( type ArgoClient interface { GetWorkflowTemplates(ctx context.Context, namespace string) (*GetWorkflowTemplatesResponse, error) GetWorkflow(ctx context.Context, namespace string, workflowName string) (*Workflow, error) + IsPausedWorkflow(ctx context.Context, namespace string, workflowName string) (bool, error) GetWorkflowLog(ctx context.Context, namespace string, container string, workflowName string) (logs string, err error) GetWorkflows(ctx context.Context, namespace string) (*GetWorkflowsResponse, error) SumbitWorkflowFromWftpl(ctx context.Context, wftplName string, opts SubmitOptions) (string, error) @@ -111,6 +112,60 @@ func (c *ArgoClientImpl) GetWorkflow(ctx context.Context, namespace string, work return &workflowRes, nil } +func (c *ArgoClientImpl) IsPausedWorkflow(ctx context.Context, namespace string, workflowName string) (bool, error) { + res, err := c.client.Get(fmt.Sprintf("%s/api/v1/workflows/%s/%s", c.url, namespace, workflowName)) + if err != nil { + return false, err + } + if res == nil { + return false, fmt.Errorf("Failed to call argo workflow.") + } + if res.StatusCode != 200 { + return false, fmt.Errorf("Invalid http status. return code: %d", res.StatusCode) + } + + defer func() { + if err := res.Body.Close(); err != nil { + log.Error(ctx, "error closing http body") + } + }() + + body, err := io.ReadAll(res.Body) + if err != nil { + return false, err + } + + var workflowRes interface{} + if err := json.Unmarshal(body, &workflowRes); err != nil { + log.Error(ctx, "an error was unexpected while parsing response from api /workflow template.") + return false, err + } + + dataMap, ok := workflowRes.(map[string]interface{}) + if !ok { + fmt.Println("Invalid JSON structure") + return false, err + } + + status, ok := dataMap["status"].(map[string]interface{}) + if !ok { + return false, err + } + nodes, ok := status["nodes"].(map[string]interface{}) + if !ok { + return false, err + } + + for _, node := range nodes { + nodeJson, ok := node.(map[string]interface{}) + if ok && nodeJson["displayName"] == "suspend" && nodeJson["phase"] == "Running" { + return true, err + } + } + + return false, nil +} + func (c *ArgoClientImpl) GetWorkflowLog(ctx context.Context, namespace string, container string, workflowName string) (logs string, err error) { log.Info(ctx, fmt.Sprintf("%s/api/v1/workflows/%s/%s/log?logOptions.container=%s", c.url, namespace, workflowName, container)) res, err := c.client.Get(fmt.Sprintf("%s/api/v1/workflows/%s/%s/log?logOptions.container=%s", c.url, namespace, workflowName, container)) diff --git a/pkg/argo-client/mock/client.go b/pkg/argo-client/mock/client.go index 8d9f23ce..0575de14 100644 --- a/pkg/argo-client/mock/client.go +++ b/pkg/argo-client/mock/client.go @@ -95,6 +95,21 @@ func (mr *MockArgoClientMockRecorder) GetWorkflows(ctx, namespace interface{}) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkflows", reflect.TypeOf((*MockArgoClient)(nil).GetWorkflows), ctx, namespace) } +// IsPausedWorkflow mocks base method. +func (m *MockArgoClient) IsPausedWorkflow(ctx context.Context, namespace, workflowName string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsPausedWorkflow", ctx, namespace, workflowName) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsPausedWorkflow indicates an expected call of IsPausedWorkflow. +func (mr *MockArgoClientMockRecorder) IsPausedWorkflow(ctx, namespace, workflowName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsPausedWorkflow", reflect.TypeOf((*MockArgoClient)(nil).IsPausedWorkflow), ctx, namespace, workflowName) +} + // ResumeWorkflow mocks base method. func (m *MockArgoClient) ResumeWorkflow(ctx context.Context, namespace, workflowName string) (*argowf.Workflow, error) { m.ctrl.T.Helper() From 8c2e7178d694b83db58590144d8970a1df65822e Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 4 Jul 2024 09:57:29 +0900 Subject: [PATCH 486/502] feature. add domains to createCluster --- api/swagger/docs.go | 43 ++++++++++++++++++++++++++++ api/swagger/swagger.json | 43 ++++++++++++++++++++++++++++ api/swagger/swagger.yaml | 30 ++++++++++++++++++++ internal/database/database.go | 1 + internal/delivery/http/cluster.go | 13 +++++++++ internal/delivery/http/stack.go | 12 ++++++++ internal/model/cluster.go | 43 +++++++++++++++++----------- internal/model/stack.go | 1 + internal/repository/cluster.go | 46 ++++++++++-------------------- pkg/domain/cluster.go | 47 ++++++++++++++++++------------- pkg/domain/stack.go | 36 ++++++++++++----------- 11 files changed, 230 insertions(+), 85 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 123604da..c8a78a80 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -11267,6 +11267,25 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterDomain": { + "type": "object", + "properties": { + "domainType": { + "type": "string", + "enum": [ + "grafana", + "loki", + "minio", + "thanos_sidecar", + "jaeger", + "kiali" + ] + }, + "url": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ClusterHost": { "type": "object", "properties": { @@ -11340,6 +11359,12 @@ const docTemplate = `{ "description": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "favorited": { "type": "boolean" }, @@ -11657,6 +11682,12 @@ const docTemplate = `{ "description": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "isStack": { "type": "boolean" }, @@ -12039,6 +12070,12 @@ const docTemplate = `{ "description": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "name": { "type": "string" }, @@ -15164,6 +15201,12 @@ const docTemplate = `{ "description": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "favorited": { "type": "boolean" }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 4540586c..b4c7a7f3 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -11261,6 +11261,25 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ClusterDomain": { + "type": "object", + "properties": { + "domainType": { + "type": "string", + "enum": [ + "grafana", + "loki", + "minio", + "thanos_sidecar", + "jaeger", + "kiali" + ] + }, + "url": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ClusterHost": { "type": "object", "properties": { @@ -11334,6 +11353,12 @@ "description": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "favorited": { "type": "boolean" }, @@ -11651,6 +11676,12 @@ "description": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "isStack": { "type": "boolean" }, @@ -12033,6 +12064,12 @@ "description": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "name": { "type": "string" }, @@ -15158,6 +15195,12 @@ "description": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "favorited": { "type": "boolean" }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index a1cc583d..57ced9f4 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -564,6 +564,20 @@ definitions: tksUserNodeType: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ClusterDomain: + properties: + domainType: + enum: + - grafana + - loki + - minio + - thanos_sidecar + - jaeger + - kiali + type: string + url: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ClusterHost: properties: name: @@ -612,6 +626,10 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string + domains: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' + type: array favorited: type: boolean id: @@ -823,6 +841,10 @@ definitions: type: string description: type: string + domains: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' + type: array isStack: type: boolean name: @@ -1088,6 +1110,10 @@ definitions: type: string description: type: string + domains: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' + type: array name: type: string policyIds: @@ -3165,6 +3191,10 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string + domains: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' + type: array favorited: type: boolean grafanaUrl: diff --git a/internal/database/database.go b/internal/database/database.go index 13aac578..96640077 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -69,6 +69,7 @@ func migrateSchema(db *gorm.DB) error { &model.User{}, &model.Cluster{}, &model.ClusterFavorite{}, + &model.ClusterDomain{}, &model.AppGroup{}, &model.Application{}, &model.AppServeApp{}, diff --git a/internal/delivery/http/cluster.go b/internal/delivery/http/cluster.go index 02db9d12..c7521947 100644 --- a/internal/delivery/http/cluster.go +++ b/internal/delivery/http/cluster.go @@ -104,6 +104,12 @@ func (h *ClusterHandler) GetCluster(w http.ResponseWriter, r *http.Request) { if err := serializer.Map(r.Context(), cluster, &out.Cluster); err != nil { log.Info(r.Context(), err) } + out.Cluster.Domains = make([]domain.ClusterDomain, len(cluster.Domains)) + for i, domain := range cluster.Domains { + if err = serializer.Map(r.Context(), domain, &out.Cluster.Domains[i]); err != nil { + log.Info(r.Context(), err) + } + } ResponseJSON(w, r, http.StatusOK, out) } @@ -177,6 +183,13 @@ func (h *ClusterHandler) CreateCluster(w http.ResponseWriter, r *http.Request) { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid byoh cluster endpoint"), "CL_INVALID_BYOH_CLUSTER_ENDPOINT", "")) return } + + dto.Domains = make([]model.ClusterDomain, len(input.Domains)) + for i, domain := range input.Domains { + if err = serializer.Map(r.Context(), domain, &dto.Domains[i]); err != nil { + log.Info(r.Context(), err) + } + } clusterId, err = h.usecase.Bootstrap(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index cf996048..a4e1a3e6 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -66,6 +66,12 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { if err = serializer.Map(r.Context(), input, &dto.Conf); err != nil { log.Info(r.Context(), err) } + dto.Domains = make([]model.ClusterDomain, len(input.Domains)) + for i, domain := range input.Domains { + if err = serializer.Map(r.Context(), domain, &dto.Domains[i]); err != nil { + log.Info(r.Context(), err) + } + } dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) @@ -208,6 +214,12 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { if err := serializer.Map(r.Context(), stack, &out.Stack); err != nil { log.Info(r.Context(), err) } + out.Stack.Domains = make([]domain.ClusterDomain, len(stack.Domains)) + for i, domain := range stack.Domains { + if err = serializer.Map(r.Context(), domain, &out.Stack.Domains[i]); err != nil { + log.Info(r.Context(), err) + } + } err = json.Unmarshal(stack.StackTemplate.Services, &out.Stack.StackTemplate.Services) if err != nil { diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 0166546a..416b640a 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -7,6 +7,24 @@ import ( ) // Models +type ClusterFavorite struct { + gorm.Model + + ID uuid.UUID `gorm:"primarykey;type:uuid"` + ClusterId domain.ClusterId + Cluster Cluster `gorm:"foreignKey:ClusterId"` + UserId uuid.UUID `gorm:"type:uuid"` + User User `gorm:"foreignKey:UserId"` +} + +type ClusterDomain struct { + gorm.Model + + ClusterId domain.ClusterId + DomainType string + Url string +} + type Cluster struct { gorm.Model @@ -37,13 +55,14 @@ type Cluster struct { TksUserNode int TksUserNodeMax int TksUserNodeType string - Kubeconfig []byte `gorm:"-:all"` - PolicyIds []string `gorm:"-:all"` - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator User `gorm:"foreignKey:UpdatorId"` - Policies []Policy `gorm:"many2many:policy_target_clusters"` + Kubeconfig []byte `gorm:"-:all"` + PolicyIds []string `gorm:"-:all"` + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator User `gorm:"foreignKey:UpdatorId"` + Policies []Policy `gorm:"many2many:policy_target_clusters"` + Domains []ClusterDomain `gorm:"foreignKey:ClusterId;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT"` } func (m *Cluster) SetDefaultConf() { @@ -69,13 +88,3 @@ func (m *Cluster) SetDefaultConf() { m.TksUserNodeType = "t3.large" } } - -type ClusterFavorite struct { - gorm.Model - - ID uuid.UUID `gorm:"primarykey;type:uuid"` - ClusterId domain.ClusterId - Cluster Cluster `gorm:"foreignKey:ClusterId"` - UserId uuid.UUID `gorm:"type:uuid"` - User User `gorm:"foreignKey:UserId"` -} diff --git a/internal/model/stack.go b/internal/model/stack.go index 4d837019..02a951a7 100644 --- a/internal/model/stack.go +++ b/internal/model/stack.go @@ -33,6 +33,7 @@ type Stack = struct { PolicyIds []string Conf StackConf AppServeAppCnt int + Domains []ClusterDomain } type StackConf struct { diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 88c786ee..07a7610a 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -119,42 +119,26 @@ func (r *ClusterRepository) Create(ctx context.Context, dto model.Cluster) (clus if dto.CloudService == domain.CloudService_BYOH || *dto.CloudAccountId == uuid.Nil { cloudAccountId = nil } - cluster := model.Cluster{ - ID: domain.ClusterId(helper.GenerateClusterId()), - OrganizationId: dto.OrganizationId, - Name: dto.Name, - Description: dto.Description, - CloudAccountId: cloudAccountId, - StackTemplateId: dto.StackTemplateId, - CreatorId: dto.CreatorId, - UpdatorId: nil, - Status: domain.ClusterStatus_PENDING, - ClusterType: dto.ClusterType, - CloudService: dto.CloudService, - ByoClusterEndpointHost: dto.ByoClusterEndpointHost, - ByoClusterEndpointPort: dto.ByoClusterEndpointPort, - IsStack: dto.IsStack, - TksCpNode: dto.TksCpNode, - TksCpNodeMax: dto.TksCpNodeMax, - TksCpNodeType: dto.TksCpNodeType, - TksInfraNode: dto.TksInfraNode, - TksInfraNodeMax: dto.TksInfraNodeMax, - TksInfraNodeType: dto.TksInfraNodeType, - TksUserNode: dto.TksUserNode, - TksUserNodeMax: dto.TksUserNodeMax, - TksUserNodeType: dto.TksUserNodeType, - } - if dto.ID != "" { - cluster.ID = dto.ID - } - - res := r.db.WithContext(ctx).Create(&cluster) + if dto.ID == "" { + dto.ID = domain.ClusterId(helper.GenerateClusterId()) + } + + dto.CloudAccountId = cloudAccountId + dto.UpdatorId = nil + dto.Status = domain.ClusterStatus_PENDING + + res := r.db.WithContext(ctx).Create(&dto) if res.Error != nil { log.Error(ctx, res.Error) return "", res.Error } - return cluster.ID, nil + err = r.db.WithContext(ctx).Model(&dto).Association("Domains").Replace(dto.Domains) + if err != nil { + log.Error(ctx, err) + } + + return dto.ID, nil } func (r *ClusterRepository) Delete(ctx context.Context, clusterId domain.ClusterId) error { diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index 0cad4b85..be1e7d55 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -116,6 +116,11 @@ type BootstrapKubeconfig struct { Expiration int `json:"expiration"` } +type ClusterDomain struct { + DomainType string `json:"domainType" validate:"oneof=grafana loki minio thanos_sidecar jaeger kiali"` + Url string `json:"url"` +} + // [TODO] annotaion 으로 가능하려나? func (m *ClusterConf) SetDefault() { m.TksCpNodeMax = m.TksCpNode @@ -142,26 +147,27 @@ func (m *ClusterConf) SetDefault() { } type CreateClusterRequest struct { - OrganizationId string `json:"organizationId" validate:"required"` - CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` - StackTemplateId string `json:"stackTemplateId" validate:"required"` - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` - CloudAccountId string `json:"cloudAccountId"` - ClusterType string `json:"clusterType"` - ByoClusterEndpointHost string `json:"byoClusterEndpointHost,omitempty"` - ByoClusterEndpointPort int `json:"byoClusterEndpointPort,omitempty"` - IsStack bool `json:"isStack,omitempty"` - PolicyIds []string `json:"policyIds,omitempty"` - TksCpNode int `json:"tksCpNode"` - TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` - TksCpNodeType string `json:"tksCpNodeType,omitempty"` - TksInfraNode int `json:"tksInfraNode"` - TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` - TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` - TksUserNode int `json:"tksUserNode"` - TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` - TksUserNodeType string `json:"tksUserNodeType,omitempty"` + OrganizationId string `json:"organizationId" validate:"required"` + CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + CloudAccountId string `json:"cloudAccountId"` + ClusterType string `json:"clusterType"` + ByoClusterEndpointHost string `json:"byoClusterEndpointHost,omitempty"` + ByoClusterEndpointPort int `json:"byoClusterEndpointPort,omitempty"` + IsStack bool `json:"isStack,omitempty"` + PolicyIds []string `json:"policyIds,omitempty"` + TksCpNode int `json:"tksCpNode"` + TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` + TksCpNodeType string `json:"tksCpNodeType,omitempty"` + TksInfraNode int `json:"tksInfraNode"` + TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` + TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` + TksUserNode int `json:"tksUserNode"` + TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` + TksUserNodeType string `json:"tksUserNodeType,omitempty"` + Domains []ClusterDomain `json:"domains,omitempty"` } type ImportClusterRequest struct { @@ -214,6 +220,7 @@ type ClusterResponse struct { ByoClusterEndpointInt int `json:"byoClusterEndpointPort,omitempty"` IsStack bool `json:"isStack,omitempty"` Favorited bool `json:"favorited,omitempty"` + Domains []ClusterDomain `json:"domains"` } type SimpleClusterResponse struct { diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 6aac9851..afd7c0ee 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -83,23 +83,24 @@ type StackStepStatus struct { } type CreateStackRequest struct { - Name string `json:"name" validate:"required,name,rfc1123"` - Description string `json:"description"` - ClusterId string `json:"clusterId"` - CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` - StackTemplateId string `json:"stackTemplateId" validate:"required"` - CloudAccountId string `json:"cloudAccountId"` - ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` - PolicyIds []string `json:"policyIds,omitempty"` - TksCpNode int `json:"tksCpNode"` - TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` - TksCpNodeType string `json:"tksCpNodeType,omitempty"` - TksInfraNode int `json:"tksInfraNode"` - TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` - TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` - TksUserNode int `json:"tksUserNode"` - TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` - TksUserNodeType string `json:"tksUserNodeType,omitempty"` + Name string `json:"name" validate:"required,name,rfc1123"` + Description string `json:"description"` + ClusterId string `json:"clusterId"` + CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + CloudAccountId string `json:"cloudAccountId"` + ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` + PolicyIds []string `json:"policyIds,omitempty"` + TksCpNode int `json:"tksCpNode"` + TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` + TksCpNodeType string `json:"tksCpNodeType,omitempty"` + TksInfraNode int `json:"tksInfraNode"` + TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` + TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` + TksUserNode int `json:"tksUserNode"` + TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` + TksUserNodeType string `json:"tksUserNodeType,omitempty"` + Domains []ClusterDomain `json:"domains,omitempty"` } type CreateStackResponse struct { @@ -136,6 +137,7 @@ type StackResponse struct { ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` Resource DashboardStackResponse `json:"resource,omitempty"` AppServeAppCnt int `json:"appServeAppCnt"` + Domains []ClusterDomain `json:"domains"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } From 16f575842f91bdd598a284057b483bf9cef9e2dd Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Mon, 8 Jul 2024 15:59:00 +0900 Subject: [PATCH 487/502] trivial. add clusterDomains to sitevalues api --- internal/usecase/cluster.go | 6 ++++++ pkg/domain/cluster.go | 29 +++++++++++++++-------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index 425bdd7d..1a76d3d7 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -543,6 +543,12 @@ func (u *ClusterUsecase) GetClusterSiteValues(ctx context.Context, clusterId dom if err := serializer.Map(ctx, cluster, &out); err != nil { log.Error(ctx, err) } + out.Domains = make([]domain.ClusterDomain, len(cluster.Domains)) + for i, domain := range cluster.Domains { + if err = serializer.Map(ctx, domain, &out.Domains[i]); err != nil { + log.Info(ctx, err) + } + } if cluster.StackTemplate.CloudService == "AWS" && cluster.StackTemplate.KubeType == "AWS" { out.TksUserNode = cluster.TksUserNode / domain.MAX_AZ_NUM diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index be1e7d55..f9bbb3bd 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -230,20 +230,21 @@ type SimpleClusterResponse struct { } type ClusterSiteValuesResponse struct { - ClusterType string `json:"clusterType"` - SshKeyName string `json:"sshKeyName"` - ClusterRegion string `json:"clusterRegion"` - TksCpNode int `json:"tksCpNode"` - TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` - TksCpNodeType string `json:"tksCpNodeType,omitempty"` - TksInfraNode int `json:"tksInfraNode"` - TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` - TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` - TksUserNode int `json:"tksUserNode"` - TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` - TksUserNodeType string `json:"tksUserNodeType,omitempty"` - ByoClusterEndpointHost string `json:"byoClusterEndpointHost"` - ByoClusterEndpointPort int `json:"byoClusterEndpointPort"` + ClusterType string `json:"clusterType"` + SshKeyName string `json:"sshKeyName"` + ClusterRegion string `json:"clusterRegion"` + TksCpNode int `json:"tksCpNode"` + TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` + TksCpNodeType string `json:"tksCpNodeType,omitempty"` + TksInfraNode int `json:"tksInfraNode"` + TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` + TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` + TksUserNode int `json:"tksUserNode"` + TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` + TksUserNodeType string `json:"tksUserNodeType,omitempty"` + ByoClusterEndpointHost string `json:"byoClusterEndpointHost"` + ByoClusterEndpointPort int `json:"byoClusterEndpointPort"` + Domains []ClusterDomain `json:"domains,omitempty"` } type GetClustersResponse struct { From 65855748dbf4838ab59dded5f507e1409438d928 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 10 Jul 2024 15:45:42 +0900 Subject: [PATCH 488/502] feature. change model clusterdomains --- internal/delivery/http/stack.go | 48 ++++++++++++++++++++++++++------- pkg/domain/stack.go | 47 +++++++++++++++++++------------- 2 files changed, 67 insertions(+), 28 deletions(-) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index a4e1a3e6..ed467a6b 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -66,11 +66,31 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { if err = serializer.Map(r.Context(), input, &dto.Conf); err != nil { log.Info(r.Context(), err) } - dto.Domains = make([]model.ClusterDomain, len(input.Domains)) - for i, domain := range input.Domains { - if err = serializer.Map(r.Context(), domain, &dto.Domains[i]); err != nil { - log.Info(r.Context(), err) - } + + dto.Domains = make([]model.ClusterDomain, 6) + dto.Domains[0] = model.ClusterDomain{ + DomainType: "grafana", + Url: input.Domain.Grafana, + } + dto.Domains[1] = model.ClusterDomain{ + DomainType: "loki", + Url: input.Domain.Loki, + } + dto.Domains[2] = model.ClusterDomain{ + DomainType: "minio", + Url: input.Domain.Minio, + } + dto.Domains[3] = model.ClusterDomain{ + DomainType: "thanos_sidecar", + Url: input.Domain.ThanosSidecar, + } + dto.Domains[4] = model.ClusterDomain{ + DomainType: "jaeger", + Url: input.Domain.Jaeger, + } + dto.Domains[5] = model.ClusterDomain{ + DomainType: "kiali", + Url: input.Domain.Kiali, } dto.OrganizationId = organizationId @@ -214,10 +234,20 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { if err := serializer.Map(r.Context(), stack, &out.Stack); err != nil { log.Info(r.Context(), err) } - out.Stack.Domains = make([]domain.ClusterDomain, len(stack.Domains)) - for i, domain := range stack.Domains { - if err = serializer.Map(r.Context(), domain, &out.Stack.Domains[i]); err != nil { - log.Info(r.Context(), err) + for _, domain := range stack.Domains { + switch domain.DomainType { + case "grafana": + out.Stack.Domain.Grafana = domain.Url + case "loki": + out.Stack.Domain.Loki = domain.Url + case "minio": + out.Stack.Domain.Minio = domain.Url + case "thanos_sidecar": + out.Stack.Domain.ThanosSidecar = domain.Url + case "jaeger": + out.Stack.Domain.Jaeger = domain.Url + case "kiali": + out.Stack.Domain.Kiali = domain.Url } } diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index afd7c0ee..dbd9b20e 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -83,24 +83,24 @@ type StackStepStatus struct { } type CreateStackRequest struct { - Name string `json:"name" validate:"required,name,rfc1123"` - Description string `json:"description"` - ClusterId string `json:"clusterId"` - CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` - StackTemplateId string `json:"stackTemplateId" validate:"required"` - CloudAccountId string `json:"cloudAccountId"` - ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` - PolicyIds []string `json:"policyIds,omitempty"` - TksCpNode int `json:"tksCpNode"` - TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` - TksCpNodeType string `json:"tksCpNodeType,omitempty"` - TksInfraNode int `json:"tksInfraNode"` - TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` - TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` - TksUserNode int `json:"tksUserNode"` - TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` - TksUserNodeType string `json:"tksUserNodeType,omitempty"` - Domains []ClusterDomain `json:"domains,omitempty"` + Name string `json:"name" validate:"required,name,rfc1123"` + Description string `json:"description"` + ClusterId string `json:"clusterId"` + CloudService string `json:"cloudService" validate:"required,oneof=AWS BYOH"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + CloudAccountId string `json:"cloudAccountId"` + ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` + PolicyIds []string `json:"policyIds,omitempty"` + TksCpNode int `json:"tksCpNode"` + TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` + TksCpNodeType string `json:"tksCpNodeType,omitempty"` + TksInfraNode int `json:"tksInfraNode"` + TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` + TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` + TksUserNode int `json:"tksUserNode"` + TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` + TksUserNodeType string `json:"tksUserNodeType,omitempty"` + Domain StackDomain `json:"domain,omitempty"` } type CreateStackResponse struct { @@ -119,6 +119,15 @@ type StackConfResponse struct { TksUserNodeType string `json:"tksUserNodeType,omitempty"` } +type StackDomain struct { + Grafana string `json:"grafana"` + Loki string `json:"loki"` + Minio string `json:"minio"` + ThanosSidecar string `json:"thanosSidecar"` + Jaeger string `json:"jaeger"` + Kiali string `json:"kiali"` +} + type StackResponse struct { ID StackId `json:"id"` Name string `json:"name"` @@ -137,7 +146,7 @@ type StackResponse struct { ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` Resource DashboardStackResponse `json:"resource,omitempty"` AppServeAppCnt int `json:"appServeAppCnt"` - Domains []ClusterDomain `json:"domains"` + Domain StackDomain `json:"domain"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } From 2a8bd68b36e9e8313e3fdde609ce8ed44baa78ab Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 11 Jul 2024 13:45:59 +0900 Subject: [PATCH 489/502] trivial. minor fixes --- internal/repository/cluster.go | 2 +- internal/usecase/stack.go | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 07a7610a..20f3db55 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -142,7 +142,7 @@ func (r *ClusterRepository) Create(ctx context.Context, dto model.Cluster) (clus } func (r *ClusterRepository) Delete(ctx context.Context, clusterId domain.ClusterId) error { - res := r.db.WithContext(ctx).Unscoped().Delete(&model.Cluster{}, "id = ?", clusterId) + res := r.db.WithContext(ctx).Delete(&model.Cluster{}, "id = ?", clusterId) if res.Error != nil { return fmt.Errorf("could not delete cluster for clusterId %s", clusterId) } diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index c57f3683..a7590832 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -132,6 +132,11 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Invalid node conf"), "", "") } + domains := make([]string, len(dto.Domains)) + for i, domain := range dto.Domains { + domains[i] = domain.DomainType + "_" + domain.Url + } + workflow := "tks-stack-create" workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ Parameters: []string{ @@ -147,6 +152,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom "cloud_service=" + dto.CloudService, "cluster_endpoint=" + dto.ClusterEndpoint, "policy_ids=" + strings.Join(dto.PolicyIds, ","), + "cluster_domains=" + strings.Join(domains, ","), }, }) if err != nil { From e3c37c5c46c25d087dfb60608dd9b60ed01f138b Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 16 Jul 2024 15:02:02 +0900 Subject: [PATCH 490/502] trivial. fix parameters for creating lma --- internal/usecase/app-group.go | 6 ++---- internal/usecase/cluster.go | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index 9d9490d5..37896b64 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -80,8 +80,7 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do // check cloudAccount tksCloudAccountId := "" - //tksObjectStore := "minio" // FOR TEST - tksObjectStore := "s3" + tksObjectStore := "minio" if cluster.CloudService != domain.CloudService_BYOH { tksObjectStore = "s3" cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, cluster.OrganizationId, nil) @@ -181,8 +180,7 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err // check cloudAccount tksCloudAccountId := "" - //tksObjectStore := "minio" // FOR TEST - tksObjectStore := "s3" + tksObjectStore := "minio" if cluster.CloudService != domain.CloudService_BYOH { tksObjectStore = "s3" cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, cluster.OrganizationId, nil) diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index 1a76d3d7..dcdd7e9e 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -417,6 +417,7 @@ func (u *ClusterUsecase) Install(ctx context.Context, clusterId domain.ClusterId "cloud_account_id=NULL", "base_repo_branch=" + viper.GetString("revision"), "keycloak_url=" + viper.GetString("keycloak-address"), + "policy_ids=", //"manifest_repo_url=" + viper.GetString("git-base-url") + "/" + viper.GetString("git-account") + "/" + clusterId + "-manifests", }, }) From 2d255a57ea4cf8f6047ed778b06e112aa91af744 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 16 Jul 2024 17:57:43 +0900 Subject: [PATCH 491/502] feature. add domain to clusterDomains --- internal/delivery/http/stack.go | 107 +++++++++++++++++++------------- pkg/domain/stack.go | 2 + 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index ed467a6b..b7714901 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -67,32 +67,7 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { log.Info(r.Context(), err) } - dto.Domains = make([]model.ClusterDomain, 6) - dto.Domains[0] = model.ClusterDomain{ - DomainType: "grafana", - Url: input.Domain.Grafana, - } - dto.Domains[1] = model.ClusterDomain{ - DomainType: "loki", - Url: input.Domain.Loki, - } - dto.Domains[2] = model.ClusterDomain{ - DomainType: "minio", - Url: input.Domain.Minio, - } - dto.Domains[3] = model.ClusterDomain{ - DomainType: "thanos_sidecar", - Url: input.Domain.ThanosSidecar, - } - dto.Domains[4] = model.ClusterDomain{ - DomainType: "jaeger", - Url: input.Domain.Jaeger, - } - dto.Domains[5] = model.ClusterDomain{ - DomainType: "kiali", - Url: input.Domain.Kiali, - } - + dto.Domains = clusterDomainFromRequest(input) dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -234,22 +209,8 @@ func (h *StackHandler) GetStack(w http.ResponseWriter, r *http.Request) { if err := serializer.Map(r.Context(), stack, &out.Stack); err != nil { log.Info(r.Context(), err) } - for _, domain := range stack.Domains { - switch domain.DomainType { - case "grafana": - out.Stack.Domain.Grafana = domain.Url - case "loki": - out.Stack.Domain.Loki = domain.Url - case "minio": - out.Stack.Domain.Minio = domain.Url - case "thanos_sidecar": - out.Stack.Domain.ThanosSidecar = domain.Url - case "jaeger": - out.Stack.Domain.Jaeger = domain.Url - case "kiali": - out.Stack.Domain.Kiali = domain.Url - } - } + + out.Stack.Domain = clusterDomainFromResponse(stack.Domains) err = json.Unmarshal(stack.StackTemplate.Services, &out.Stack.StackTemplate.Services) if err != nil { @@ -612,3 +573,65 @@ func (h StackHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context return nil } + +func clusterDomainFromRequest(input domain.CreateStackRequest) []model.ClusterDomain { + domains := make([]model.ClusterDomain, 6) + domains[0] = model.ClusterDomain{ + DomainType: "grafana", + Url: input.Domain.Grafana, + } + domains[1] = model.ClusterDomain{ + DomainType: "loki", + Url: input.Domain.Loki, + } + domains[2] = model.ClusterDomain{ + DomainType: "loki_user", + Url: input.Domain.LokiUser, + } + domains[3] = model.ClusterDomain{ + DomainType: "minio", + Url: input.Domain.Minio, + } + domains[4] = model.ClusterDomain{ + DomainType: "thanos_sidecar", + Url: input.Domain.ThanosSidecar, + } + domains[5] = model.ClusterDomain{ + DomainType: "thanos_ruler", + Url: input.Domain.ThanosRuler, + } + domains[6] = model.ClusterDomain{ + DomainType: "jaeger", + Url: input.Domain.Jaeger, + } + domains[7] = model.ClusterDomain{ + DomainType: "kiali", + Url: input.Domain.Kiali, + } + + return domains +} + +func clusterDomainFromResponse(domains []model.ClusterDomain) (out domain.StackDomain) { + for _, domain := range domains { + switch domain.DomainType { + case "grafana": + out.Grafana = domain.Url + case "loki": + out.Loki = domain.Url + case "loki_user": + out.LokiUser = domain.Url + case "minio": + out.Minio = domain.Url + case "thanos_sidecar": + out.ThanosSidecar = domain.Url + case "thanos_ruler": + out.ThanosRuler = domain.Url + case "jaeger": + out.Jaeger = domain.Url + case "kiali": + out.Kiali = domain.Url + } + } + return out +} diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index dbd9b20e..b8f1a5a3 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -122,8 +122,10 @@ type StackConfResponse struct { type StackDomain struct { Grafana string `json:"grafana"` Loki string `json:"loki"` + LokiUser string `json:"lokiUser"` Minio string `json:"minio"` ThanosSidecar string `json:"thanosSidecar"` + ThanosRuler string `json:"thanosRuler"` Jaeger string `json:"jaeger"` Kiali string `json:"kiali"` } From c5b9d4b52521a81db2a03d0873359240b21f7fdc Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 16 Jul 2024 18:26:18 +0900 Subject: [PATCH 492/502] trivial. fix minor bug --- internal/delivery/http/stack.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index b7714901..91733ba0 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -575,7 +575,7 @@ func (h StackHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context } func clusterDomainFromRequest(input domain.CreateStackRequest) []model.ClusterDomain { - domains := make([]model.ClusterDomain, 6) + domains := make([]model.ClusterDomain, 8) domains[0] = model.ClusterDomain{ DomainType: "grafana", Url: input.Domain.Grafana, From 9cfd907b7915e0fe8a6cd611dcf3019cede5dabe Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 17 Jul 2024 16:14:11 +0900 Subject: [PATCH 493/502] feature. add import api to stacks resource --- api/swagger/docs.go | 174 +++++++++++++++++- api/swagger/swagger.json | 174 +++++++++++++++++- api/swagger/swagger.yaml | 117 +++++++++++- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 + internal/delivery/http/stack.go | 87 +++++++-- internal/model/stack.go | 1 + internal/route/route.go | 1 + internal/usecase/stack.go | 130 +++++++++++++ pkg/domain/cloud-account.go | 1 + pkg/domain/cluster.go | 16 +- pkg/domain/stack.go | 13 ++ 12 files changed, 676 insertions(+), 47 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index c8a78a80..9aff60bb 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -8382,6 +8382,52 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/stacks/import": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Import Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Import Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "import stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ @@ -11412,6 +11458,12 @@ const docTemplate = `{ "clusterType": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "sshKeyName": { "type": "string" }, @@ -12070,11 +12122,8 @@ const docTemplate = `{ "description": { "type": "string" }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" - } + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, "name": { "type": "string" @@ -13692,6 +13741,85 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest": { + "type": "object", + "required": [ + "cloudService", + "name", + "stackTemplateId" + ], + "properties": { + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "BYOH" + ] + }, + "clusterId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" + }, + "name": { + "type": "string" + }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "stackTemplateId": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + }, + "userClusterEndpoint": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -15117,6 +15245,35 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackDomain": { + "type": "object", + "properties": { + "grafana": { + "type": "string" + }, + "jaeger": { + "type": "string" + }, + "kiali": { + "type": "string" + }, + "loki": { + "type": "string" + }, + "lokiUser": { + "type": "string" + }, + "minio": { + "type": "string" + }, + "thanosRuler": { + "type": "string" + }, + "thanosSidecar": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics": { "type": "object", "properties": { @@ -15201,11 +15358,8 @@ const docTemplate = `{ "description": { "type": "string" }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" - } + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, "favorited": { "type": "boolean" diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index b4c7a7f3..48a9e924 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -8376,6 +8376,52 @@ } } }, + "/organizations/{organizationId}/stacks/import": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Import Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Import Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "import stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ @@ -11406,6 +11452,12 @@ "clusterType": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "sshKeyName": { "type": "string" }, @@ -12064,11 +12116,8 @@ "description": { "type": "string" }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" - } + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, "name": { "type": "string" @@ -13686,6 +13735,85 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest": { + "type": "object", + "required": [ + "cloudService", + "name", + "stackTemplateId" + ], + "properties": { + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "BYOH" + ] + }, + "clusterId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" + }, + "name": { + "type": "string" + }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "stackTemplateId": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + }, + "userClusterEndpoint": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -15111,6 +15239,35 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackDomain": { + "type": "object", + "properties": { + "grafana": { + "type": "string" + }, + "jaeger": { + "type": "string" + }, + "kiali": { + "type": "string" + }, + "loki": { + "type": "string" + }, + "lokiUser": { + "type": "string" + }, + "minio": { + "type": "string" + }, + "thanosRuler": { + "type": "string" + }, + "thanosSidecar": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics": { "type": "object", "properties": { @@ -15195,11 +15352,8 @@ "description": { "type": "string" }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" - } + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, "favorited": { "type": "boolean" diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 57ced9f4..2c0a0d7a 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -661,6 +661,10 @@ definitions: type: string clusterType: type: string + domains: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' + type: array sshKeyName: type: string tksCpNode: @@ -1110,10 +1114,8 @@ definitions: type: string description: type: string - domains: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' - type: array + domain: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain' name: type: string policyIds: @@ -2176,6 +2178,59 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest: + properties: + cloudAccountId: + type: string + cloudService: + enum: + - AWS + - BYOH + type: string + clusterId: + type: string + description: + type: string + domain: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain' + name: + type: string + policyIds: + items: + type: string + type: array + stackTemplateId: + type: string + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + userClusterEndpoint: + type: string + required: + - cloudService + - name + - stackTemplateId + type: object + github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse: + properties: + id: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse: properties: organizations: @@ -3133,6 +3188,25 @@ definitions: - tksInfraNode - tksUserNode type: object + github_com_openinfradev_tks-api_pkg_domain.StackDomain: + properties: + grafana: + type: string + jaeger: + type: string + kiali: + type: string + loki: + type: string + lokiUser: + type: string + minio: + type: string + thanosRuler: + type: string + thanosSidecar: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics: properties: outofdatePolicyCount: @@ -3191,10 +3265,8 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string - domains: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' - type: array + domain: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain' favorited: type: boolean grafanaUrl: @@ -10204,6 +10276,35 @@ paths: summary: Get Stack Status tags: - Stacks + /organizations/{organizationId}/stacks/import: + post: + consumes: + - application/json + description: Import Stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: import stack request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse' + security: + - JWT: [] + summary: Import Stack + tags: + - Stacks /organizations/{organizationId}/stacks/name/{name}/existence: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 957418c2..d8099b20 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -165,6 +165,7 @@ const ( // Stack GetStacks // 스택관리/조회 CreateStack // 스택관리/생성 + ImportStack // 스택관리/생성 CheckStackName // 스택관리/조회 GetStack // 스택관리/조회 UpdateStack // 스택관리/수정 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 829820a1..f0011fbc 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -507,6 +507,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CreateStack", Group: "Stack", }, + ImportStack: { + Name: "ImportStack", + Group: "Stack", + }, CheckStackName: { Name: "CheckStackName", Group: "Stack", @@ -1198,6 +1202,8 @@ func (e Endpoint) String() string { return "GetStacks" case CreateStack: return "CreateStack" + case ImportStack: + return "ImportStack" case CheckStackName: return "CheckStackName" case GetStack: @@ -1674,6 +1680,8 @@ func GetEndpoint(name string) Endpoint { return GetStacks case "CreateStack": return CreateStack + case "ImportStack": + return ImportStack case "CheckStackName": return CheckStackName case "GetStack": diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 91733ba0..48d7e99a 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -67,7 +67,7 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { log.Info(r.Context(), err) } - dto.Domains = clusterDomainFromRequest(input) + dto.Domains = clusterDomainFromRequest(input.Domain) dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -95,6 +95,69 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } +// ImportStack godoc +// +// @Tags Stacks +// @Summary Import Stack +// @Description Import Stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.ImportStackRequest true "import stack request" +// @Success 200 {object} domain.ImportStackResponse +// @Router /organizations/{organizationId}/stacks/import [post] +// @Security JWT +func (h *StackHandler) ImportStack(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.ImportStackRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto model.Stack + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + if err = serializer.Map(r.Context(), input, &dto.Conf); err != nil { + log.Info(r.Context(), err) + } + + dto.Domains = clusterDomainFromRequest(input.Domain) + dto.OrganizationId = organizationId + stackId, err := h.usecase.Import(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // Sync ClusterAdmin Permission to Keycloak + // First get all users in the organization + users, err := h.usecaseUser.List(r.Context(), organizationId) + if err != nil { + ErrorJSON(w, r, err) + return + } + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, []string{stackId.String()}, *users) + if err != nil { + ErrorJSON(w, r, err) + return + } + + out := domain.ImportStackResponse{ + ID: stackId.String(), + } + + ResponseJSON(w, r, http.StatusOK, out) +} + // InstallStack godoc // // @Tags Stacks @@ -574,39 +637,39 @@ func (h StackHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context return nil } -func clusterDomainFromRequest(input domain.CreateStackRequest) []model.ClusterDomain { +func clusterDomainFromRequest(domain domain.StackDomain) []model.ClusterDomain { domains := make([]model.ClusterDomain, 8) domains[0] = model.ClusterDomain{ DomainType: "grafana", - Url: input.Domain.Grafana, + Url: domain.Grafana, } domains[1] = model.ClusterDomain{ DomainType: "loki", - Url: input.Domain.Loki, + Url: domain.Loki, } domains[2] = model.ClusterDomain{ DomainType: "loki_user", - Url: input.Domain.LokiUser, + Url: domain.LokiUser, } domains[3] = model.ClusterDomain{ DomainType: "minio", - Url: input.Domain.Minio, + Url: domain.Minio, } domains[4] = model.ClusterDomain{ - DomainType: "thanos_sidecar", - Url: input.Domain.ThanosSidecar, + DomainType: "prometheus", + Url: domain.ThanosSidecar, } domains[5] = model.ClusterDomain{ DomainType: "thanos_ruler", - Url: input.Domain.ThanosRuler, + Url: domain.ThanosRuler, } domains[6] = model.ClusterDomain{ DomainType: "jaeger", - Url: input.Domain.Jaeger, + Url: domain.Jaeger, } domains[7] = model.ClusterDomain{ DomainType: "kiali", - Url: input.Domain.Kiali, + Url: domain.Kiali, } return domains @@ -623,7 +686,7 @@ func clusterDomainFromResponse(domains []model.ClusterDomain) (out domain.StackD out.LokiUser = domain.Url case "minio": out.Minio = domain.Url - case "thanos_sidecar": + case "prometheus": out.ThanosSidecar = domain.Url case "thanos_ruler": out.ThanosRuler = domain.Url diff --git a/internal/model/stack.go b/internal/model/stack.go index 02a951a7..b0f0a0e5 100644 --- a/internal/model/stack.go +++ b/internal/model/stack.go @@ -34,6 +34,7 @@ type Stack = struct { Conf StackConf AppServeAppCnt int Domains []ClusterDomain + Kubeconfig string } type StackConf struct { diff --git a/internal/route/route.go b/internal/route/route.go index 1b3db302..79341469 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -256,6 +256,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.CreateStack, http.HandlerFunc(stackHandler.CreateStack))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/import", customMiddleware.Handle(internalApi.ImportStack, http.HandlerFunc(stackHandler.ImportStack))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/name/{name}/existence", customMiddleware.Handle(internalApi.CheckStackName, http.HandlerFunc(stackHandler.CheckStackName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetStack, http.HandlerFunc(stackHandler.GetStack))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateStack, http.HandlerFunc(stackHandler.UpdateStack))).Methods(http.MethodPut) diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index a7590832..dcb00208 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -32,6 +32,7 @@ type IStackUsecase interface { GetByName(ctx context.Context, organizationId string, name string) (model.Stack, error) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Stack, error) Create(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) + Import(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) Install(ctx context.Context, stackId domain.StackId) (err error) Update(ctx context.Context, dto model.Stack) error Delete(ctx context.Context, dto model.Stack) error @@ -290,6 +291,135 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err return nil } +func (u *StackUsecase) Import(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) { + user, ok := request.UserFrom(ctx) + if !ok { + return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + + _, err = u.GetByName(ctx, dto.OrganizationId, dto.Name) + if err == nil { + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "S_CREATE_ALREADY_EXISTED_NAME", "") + } + + _, err = u.stackTemplateRepo.Get(ctx, dto.StackTemplateId) + if err != nil { + return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Invalid stackTemplateId"), "S_INVALID_STACK_TEMPLATE", "") + } + + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, dto.OrganizationId, user.GetUserId(), nil) + if err != nil { + return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Failed to get clusters"), "S_FAILED_GET_CLUSTERS", "") + } + isPrimary := false + if len(clusters) == 0 { + isPrimary = true + } + log.Debug(ctx, "isPrimary ", isPrimary) + + domains := make([]string, len(dto.Domains)) + for i, domain := range dto.Domains { + domains[i] = domain.DomainType + "_" + domain.Url + } + + workflow := "tks-stack-import" + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ + Parameters: []string{ + fmt.Sprintf("tks_api_url=%s", viper.GetString("external-address")), + "cluster_name=" + dto.Name, + "description=" + dto.Description, + "organization_id=" + dto.OrganizationId, + "stack_template_id=" + dto.StackTemplateId.String(), + "creator=" + user.GetUserId().String(), + "base_repo_branch=" + viper.GetString("revision"), + "policy_ids=" + strings.Join(dto.PolicyIds, ","), + "cluster_domains=" + strings.Join(domains, ","), + "kubeconfig=" + dto.Kubeconfig, + }, + }) + if err != nil { + log.Error(ctx, err) + return "", httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") + } + log.Debug(ctx, "Submitted workflow: ", workflowId) + + // wait & get clusterId ( max 1min ) + dto.ID = domain.StackId("") + for i := 0; i < 60; i++ { + time.Sleep(time.Second * 5) + workflow, err := u.argo.GetWorkflow(ctx, "argo", workflowId) + if err != nil { + return "", err + } + + log.Debug(ctx, "workflow ", workflow) + if workflow.Status.Phase != "" && workflow.Status.Phase != "Running" { + return "", fmt.Errorf("Invalid workflow status [%s]", workflow.Status.Phase) + } + + cluster, err := u.clusterRepo.GetByName(ctx, dto.OrganizationId, dto.Name) + if err != nil { + continue + } + if cluster.Name == dto.Name { + dto.ID = domain.StackId(cluster.ID) + break + } + } + + // keycloak setting + log.Debugf(ctx, "Create keycloak client for %s", dto.ID) + // Create keycloak client + clientUUID, err := u.kc.CreateClient(ctx, dto.OrganizationId, dto.ID.String()+"-k8s-api", "", nil) + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client for %s", dto.ID) + return "", err + } + // Create keycloak client protocol mapper + _, err = u.kc.CreateClientProtocolMapper(ctx, dto.OrganizationId, clientUUID, gocloak.ProtocolMapperRepresentation{ + Name: gocloak.StringP("k8s-role-mapper"), + Protocol: gocloak.StringP("openid-connect"), + ProtocolMapper: gocloak.StringP("oidc-usermodel-client-role-mapper"), + ConsentRequired: gocloak.BoolP(false), + Config: &map[string]string{ + "usermodel.clientRoleMapping.clientId": dto.ID.String() + "-k8s-api", + "claim.name": "groups", + "access.token.claim": "false", + "id.token.claim": "true", + "userinfo.token.claim": "true", + "multivalued": "true", + "jsonType.label": "String", + }, + }) + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client protocol mapper for %s", dto.ID) + return "", err + } + // Create keycloak client role + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-create") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-create", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-read") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-read", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-update") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-update", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-delete") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-delete", dto.ID) + return "", err + } + + return dto.ID, nil +} + func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out model.Stack, err error) { cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(stackId)) if err != nil { diff --git a/pkg/domain/cloud-account.go b/pkg/domain/cloud-account.go index dfac5409..ddd090cc 100644 --- a/pkg/domain/cloud-account.go +++ b/pkg/domain/cloud-account.go @@ -12,6 +12,7 @@ const ( CloudService_AZURE = "AZZURE" CloudService_GCP = "GCP" CloudService_BYOH = "BYOH" + CloudService_BYOK = "BYOK" ) // enum diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index f9bbb3bd..321c086c 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -171,13 +171,15 @@ type CreateClusterRequest struct { } type ImportClusterRequest struct { - OrganizationId string `json:"organizationId" validate:"required"` - StackTemplateId string `json:"stackTemplateId" validate:"required"` - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` - ClusterType string `json:"clusterType"` - Kubeconfig []byte `json:"kubeconfig"` - CloudService string `json:"cloudService"` + OrganizationId string `json:"organizationId" validate:"required"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + ClusterType string `json:"clusterType"` + Kubeconfig []byte `json:"kubeconfig"` + CloudService string `json:"cloudService"` + PolicyIds []string `json:"policyIds,omitempty"` + Domains []ClusterDomain `json:"domains,omitempty"` } type CreateClusterResponse struct { diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index b8f1a5a3..66a419c4 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -103,6 +103,19 @@ type CreateStackRequest struct { Domain StackDomain `json:"domain,omitempty"` } +type ImportStackResponse struct { + ID string `json:"id"` +} + +type ImportStackRequest struct { + Name string `json:"name" validate:"required,name,rfc1123"` + Description string `json:"description"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + PolicyIds []string `json:"policyIds,omitempty"` + Domain StackDomain `json:"domain,omitempty"` + Kubeconfig string `json:"kubeconfig" validate:"required"` +} + type CreateStackResponse struct { ID string `json:"id"` } From a48427c124a915d069d628025c1f055bbbb61f2c Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 17 Jul 2024 16:14:11 +0900 Subject: [PATCH 494/502] feature. add import api to stacks resource --- api/swagger/docs.go | 174 +++++++++++++++++- api/swagger/swagger.json | 174 +++++++++++++++++- api/swagger/swagger.yaml | 117 +++++++++++- internal/delivery/api/endpoint.go | 1 + .../delivery/api/generated_endpoints.go.go | 8 + internal/delivery/http/stack.go | 87 +++++++-- internal/model/stack.go | 1 + internal/repository/cluster.go | 2 +- internal/route/route.go | 1 + internal/usecase/stack.go | 130 +++++++++++++ pkg/domain/cloud-account.go | 1 + pkg/domain/cluster.go | 18 +- pkg/domain/stack.go | 13 ++ 13 files changed, 678 insertions(+), 49 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index c8a78a80..9aff60bb 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -8382,6 +8382,52 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/stacks/import": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Import Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Import Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "import stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ @@ -11412,6 +11458,12 @@ const docTemplate = `{ "clusterType": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "sshKeyName": { "type": "string" }, @@ -12070,11 +12122,8 @@ const docTemplate = `{ "description": { "type": "string" }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" - } + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, "name": { "type": "string" @@ -13692,6 +13741,85 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest": { + "type": "object", + "required": [ + "cloudService", + "name", + "stackTemplateId" + ], + "properties": { + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "BYOH" + ] + }, + "clusterId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" + }, + "name": { + "type": "string" + }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "stackTemplateId": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + }, + "userClusterEndpoint": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -15117,6 +15245,35 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackDomain": { + "type": "object", + "properties": { + "grafana": { + "type": "string" + }, + "jaeger": { + "type": "string" + }, + "kiali": { + "type": "string" + }, + "loki": { + "type": "string" + }, + "lokiUser": { + "type": "string" + }, + "minio": { + "type": "string" + }, + "thanosRuler": { + "type": "string" + }, + "thanosSidecar": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics": { "type": "object", "properties": { @@ -15201,11 +15358,8 @@ const docTemplate = `{ "description": { "type": "string" }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" - } + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, "favorited": { "type": "boolean" diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index b4c7a7f3..48a9e924 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -8376,6 +8376,52 @@ } } }, + "/organizations/{organizationId}/stacks/import": { + "post": { + "security": [ + { + "JWT": [] + } + ], + "description": "Import Stack", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Stacks" + ], + "summary": "Import Stack", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "import stack request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse" + } + } + } + } + }, "/organizations/{organizationId}/stacks/name/{name}/existence": { "get": { "security": [ @@ -11406,6 +11452,12 @@ "clusterType": { "type": "string" }, + "domains": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" + } + }, "sshKeyName": { "type": "string" }, @@ -12064,11 +12116,8 @@ "description": { "type": "string" }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" - } + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, "name": { "type": "string" @@ -13686,6 +13735,85 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest": { + "type": "object", + "required": [ + "cloudService", + "name", + "stackTemplateId" + ], + "properties": { + "cloudAccountId": { + "type": "string" + }, + "cloudService": { + "type": "string", + "enum": [ + "AWS", + "BYOH" + ] + }, + "clusterId": { + "type": "string" + }, + "description": { + "type": "string" + }, + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" + }, + "name": { + "type": "string" + }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "stackTemplateId": { + "type": "string" + }, + "tksCpNode": { + "type": "integer" + }, + "tksCpNodeMax": { + "type": "integer" + }, + "tksCpNodeType": { + "type": "string" + }, + "tksInfraNode": { + "type": "integer" + }, + "tksInfraNodeMax": { + "type": "integer" + }, + "tksInfraNodeType": { + "type": "string" + }, + "tksUserNode": { + "type": "integer" + }, + "tksUserNodeMax": { + "type": "integer" + }, + "tksUserNodeType": { + "type": "string" + }, + "userClusterEndpoint": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse": { "type": "object", "properties": { @@ -15111,6 +15239,35 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.StackDomain": { + "type": "object", + "properties": { + "grafana": { + "type": "string" + }, + "jaeger": { + "type": "string" + }, + "kiali": { + "type": "string" + }, + "loki": { + "type": "string" + }, + "lokiUser": { + "type": "string" + }, + "minio": { + "type": "string" + }, + "thanosRuler": { + "type": "string" + }, + "thanosSidecar": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics": { "type": "object", "properties": { @@ -15195,11 +15352,8 @@ "description": { "type": "string" }, - "domains": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" - } + "domain": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, "favorited": { "type": "boolean" diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 57ced9f4..2c0a0d7a 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -661,6 +661,10 @@ definitions: type: string clusterType: type: string + domains: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' + type: array sshKeyName: type: string tksCpNode: @@ -1110,10 +1114,8 @@ definitions: type: string description: type: string - domains: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' - type: array + domain: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain' name: type: string policyIds: @@ -2176,6 +2178,59 @@ definitions: id: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest: + properties: + cloudAccountId: + type: string + cloudService: + enum: + - AWS + - BYOH + type: string + clusterId: + type: string + description: + type: string + domain: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain' + name: + type: string + policyIds: + items: + type: string + type: array + stackTemplateId: + type: string + tksCpNode: + type: integer + tksCpNodeMax: + type: integer + tksCpNodeType: + type: string + tksInfraNode: + type: integer + tksInfraNodeMax: + type: integer + tksInfraNodeType: + type: string + tksUserNode: + type: integer + tksUserNodeMax: + type: integer + tksUserNodeType: + type: string + userClusterEndpoint: + type: string + required: + - cloudService + - name + - stackTemplateId + type: object + github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse: + properties: + id: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.ListOrganizationResponse: properties: organizations: @@ -3133,6 +3188,25 @@ definitions: - tksInfraNode - tksUserNode type: object + github_com_openinfradev_tks-api_pkg_domain.StackDomain: + properties: + grafana: + type: string + jaeger: + type: string + kiali: + type: string + loki: + type: string + lokiUser: + type: string + minio: + type: string + thanosRuler: + type: string + thanosSidecar: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.StackPolicyStatistics: properties: outofdatePolicyCount: @@ -3191,10 +3265,8 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' description: type: string - domains: - items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' - type: array + domain: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain' favorited: type: boolean grafanaUrl: @@ -10204,6 +10276,35 @@ paths: summary: Get Stack Status tags: - Stacks + /organizations/{organizationId}/stacks/import: + post: + consumes: + - application/json + description: Import Stack + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: import stack request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ImportStackResponse' + security: + - JWT: [] + summary: Import Stack + tags: + - Stacks /organizations/{organizationId}/stacks/name/{name}/existence: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 957418c2..d8099b20 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -165,6 +165,7 @@ const ( // Stack GetStacks // 스택관리/조회 CreateStack // 스택관리/생성 + ImportStack // 스택관리/생성 CheckStackName // 스택관리/조회 GetStack // 스택관리/조회 UpdateStack // 스택관리/수정 diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 829820a1..f0011fbc 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -507,6 +507,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "CreateStack", Group: "Stack", }, + ImportStack: { + Name: "ImportStack", + Group: "Stack", + }, CheckStackName: { Name: "CheckStackName", Group: "Stack", @@ -1198,6 +1202,8 @@ func (e Endpoint) String() string { return "GetStacks" case CreateStack: return "CreateStack" + case ImportStack: + return "ImportStack" case CheckStackName: return "CheckStackName" case GetStack: @@ -1674,6 +1680,8 @@ func GetEndpoint(name string) Endpoint { return GetStacks case "CreateStack": return CreateStack + case "ImportStack": + return ImportStack case "CheckStackName": return CheckStackName case "GetStack": diff --git a/internal/delivery/http/stack.go b/internal/delivery/http/stack.go index 91733ba0..48d7e99a 100644 --- a/internal/delivery/http/stack.go +++ b/internal/delivery/http/stack.go @@ -67,7 +67,7 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { log.Info(r.Context(), err) } - dto.Domains = clusterDomainFromRequest(input) + dto.Domains = clusterDomainFromRequest(input.Domain) dto.OrganizationId = organizationId stackId, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -95,6 +95,69 @@ func (h *StackHandler) CreateStack(w http.ResponseWriter, r *http.Request) { ResponseJSON(w, r, http.StatusOK, out) } +// ImportStack godoc +// +// @Tags Stacks +// @Summary Import Stack +// @Description Import Stack +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.ImportStackRequest true "import stack request" +// @Success 200 {object} domain.ImportStackResponse +// @Router /organizations/{organizationId}/stacks/import [post] +// @Security JWT +func (h *StackHandler) ImportStack(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.ImportStackRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto model.Stack + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + if err = serializer.Map(r.Context(), input, &dto.Conf); err != nil { + log.Info(r.Context(), err) + } + + dto.Domains = clusterDomainFromRequest(input.Domain) + dto.OrganizationId = organizationId + stackId, err := h.usecase.Import(r.Context(), dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + // Sync ClusterAdmin Permission to Keycloak + // First get all users in the organization + users, err := h.usecaseUser.List(r.Context(), organizationId) + if err != nil { + ErrorJSON(w, r, err) + return + } + err = h.syncKeycloakWithClusterAdminPermission(r.Context(), organizationId, []string{stackId.String()}, *users) + if err != nil { + ErrorJSON(w, r, err) + return + } + + out := domain.ImportStackResponse{ + ID: stackId.String(), + } + + ResponseJSON(w, r, http.StatusOK, out) +} + // InstallStack godoc // // @Tags Stacks @@ -574,39 +637,39 @@ func (h StackHandler) syncKeycloakWithClusterAdminPermission(ctx context.Context return nil } -func clusterDomainFromRequest(input domain.CreateStackRequest) []model.ClusterDomain { +func clusterDomainFromRequest(domain domain.StackDomain) []model.ClusterDomain { domains := make([]model.ClusterDomain, 8) domains[0] = model.ClusterDomain{ DomainType: "grafana", - Url: input.Domain.Grafana, + Url: domain.Grafana, } domains[1] = model.ClusterDomain{ DomainType: "loki", - Url: input.Domain.Loki, + Url: domain.Loki, } domains[2] = model.ClusterDomain{ DomainType: "loki_user", - Url: input.Domain.LokiUser, + Url: domain.LokiUser, } domains[3] = model.ClusterDomain{ DomainType: "minio", - Url: input.Domain.Minio, + Url: domain.Minio, } domains[4] = model.ClusterDomain{ - DomainType: "thanos_sidecar", - Url: input.Domain.ThanosSidecar, + DomainType: "prometheus", + Url: domain.ThanosSidecar, } domains[5] = model.ClusterDomain{ DomainType: "thanos_ruler", - Url: input.Domain.ThanosRuler, + Url: domain.ThanosRuler, } domains[6] = model.ClusterDomain{ DomainType: "jaeger", - Url: input.Domain.Jaeger, + Url: domain.Jaeger, } domains[7] = model.ClusterDomain{ DomainType: "kiali", - Url: input.Domain.Kiali, + Url: domain.Kiali, } return domains @@ -623,7 +686,7 @@ func clusterDomainFromResponse(domains []model.ClusterDomain) (out domain.StackD out.LokiUser = domain.Url case "minio": out.Minio = domain.Url - case "thanos_sidecar": + case "prometheus": out.ThanosSidecar = domain.Url case "thanos_ruler": out.ThanosRuler = domain.Url diff --git a/internal/model/stack.go b/internal/model/stack.go index 02a951a7..b0f0a0e5 100644 --- a/internal/model/stack.go +++ b/internal/model/stack.go @@ -34,6 +34,7 @@ type Stack = struct { Conf StackConf AppServeAppCnt int Domains []ClusterDomain + Kubeconfig string } type StackConf struct { diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 20f3db55..f6023559 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -116,7 +116,7 @@ func (r *ClusterRepository) GetByName(ctx context.Context, organizationId string func (r *ClusterRepository) Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { var cloudAccountId *uuid.UUID cloudAccountId = dto.CloudAccountId - if dto.CloudService == domain.CloudService_BYOH || *dto.CloudAccountId == uuid.Nil { + if dto.CloudService == domain.CloudService_BYOH || dto.CloudService == domain.CloudService_BYOK || *dto.CloudAccountId == uuid.Nil { cloudAccountId = nil } if dto.ID == "" { diff --git a/internal/route/route.go b/internal/route/route.go index 1b3db302..79341469 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -256,6 +256,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.CreateStack, http.HandlerFunc(stackHandler.CreateStack))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/import", customMiddleware.Handle(internalApi.ImportStack, http.HandlerFunc(stackHandler.ImportStack))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/name/{name}/existence", customMiddleware.Handle(internalApi.CheckStackName, http.HandlerFunc(stackHandler.CheckStackName))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.GetStack, http.HandlerFunc(stackHandler.GetStack))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks/{stackId}", customMiddleware.Handle(internalApi.UpdateStack, http.HandlerFunc(stackHandler.UpdateStack))).Methods(http.MethodPut) diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index a7590832..e4f22eb5 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -32,6 +32,7 @@ type IStackUsecase interface { GetByName(ctx context.Context, organizationId string, name string) (model.Stack, error) Fetch(ctx context.Context, organizationId string, pg *pagination.Pagination) ([]model.Stack, error) Create(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) + Import(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) Install(ctx context.Context, stackId domain.StackId) (err error) Update(ctx context.Context, dto model.Stack) error Delete(ctx context.Context, dto model.Stack) error @@ -290,6 +291,135 @@ func (u *StackUsecase) Install(ctx context.Context, stackId domain.StackId) (err return nil } +func (u *StackUsecase) Import(ctx context.Context, dto model.Stack) (stackId domain.StackId, err error) { + user, ok := request.UserFrom(ctx) + if !ok { + return "", httpErrors.NewUnauthorizedError(fmt.Errorf("Invalid token"), "A_INVALID_TOKEN", "") + } + + _, err = u.GetByName(ctx, dto.OrganizationId, dto.Name) + if err == nil { + return "", httpErrors.NewBadRequestError(httpErrors.DuplicateResource, "S_CREATE_ALREADY_EXISTED_NAME", "") + } + + _, err = u.stackTemplateRepo.Get(ctx, dto.StackTemplateId) + if err != nil { + return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Invalid stackTemplateId"), "S_INVALID_STACK_TEMPLATE", "") + } + + clusters, err := u.clusterRepo.FetchByOrganizationId(ctx, dto.OrganizationId, user.GetUserId(), nil) + if err != nil { + return "", httpErrors.NewInternalServerError(errors.Wrap(err, "Failed to get clusters"), "S_FAILED_GET_CLUSTERS", "") + } + isPrimary := false + if len(clusters) == 0 { + isPrimary = true + } + log.Debug(ctx, "isPrimary ", isPrimary) + + domains := make([]string, len(dto.Domains)) + for i, domain := range dto.Domains { + domains[i] = domain.DomainType + "_" + domain.Url + } + + workflow := "tks-stack-import" + workflowId, err := u.argo.SumbitWorkflowFromWftpl(ctx, workflow, argowf.SubmitOptions{ + Parameters: []string{ + fmt.Sprintf("tks_api_url=%s", viper.GetString("external-address")), + "cluster_name=" + dto.Name, + "description=" + dto.Description, + "organization_id=" + dto.OrganizationId, + "stack_template_id=" + dto.StackTemplateId.String(), + "creator=" + user.GetUserId().String(), + "base_repo_branch=" + viper.GetString("revision"), + "policy_ids=" + strings.Join(dto.PolicyIds, ","), + "cluster_domains=" + strings.Join(domains, ","), + "kubeconfig_string=" + dto.Kubeconfig, + }, + }) + if err != nil { + log.Error(ctx, err) + return "", httpErrors.NewInternalServerError(err, "S_FAILED_TO_CALL_WORKFLOW", "") + } + log.Debug(ctx, "Submitted workflow: ", workflowId) + + // wait & get clusterId ( max 1min ) + dto.ID = domain.StackId("") + for i := 0; i < 60; i++ { + time.Sleep(time.Second * 5) + workflow, err := u.argo.GetWorkflow(ctx, "argo", workflowId) + if err != nil { + return "", err + } + + log.Debug(ctx, "workflow ", workflow) + if workflow.Status.Phase != "" && workflow.Status.Phase != "Running" { + return "", fmt.Errorf("Invalid workflow status [%s]", workflow.Status.Phase) + } + + cluster, err := u.clusterRepo.GetByName(ctx, dto.OrganizationId, dto.Name) + if err != nil { + continue + } + if cluster.Name == dto.Name { + dto.ID = domain.StackId(cluster.ID) + break + } + } + + // keycloak setting + log.Debugf(ctx, "Create keycloak client for %s", dto.ID) + // Create keycloak client + clientUUID, err := u.kc.CreateClient(ctx, dto.OrganizationId, dto.ID.String()+"-k8s-api", "", nil) + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client for %s", dto.ID) + return "", err + } + // Create keycloak client protocol mapper + _, err = u.kc.CreateClientProtocolMapper(ctx, dto.OrganizationId, clientUUID, gocloak.ProtocolMapperRepresentation{ + Name: gocloak.StringP("k8s-role-mapper"), + Protocol: gocloak.StringP("openid-connect"), + ProtocolMapper: gocloak.StringP("oidc-usermodel-client-role-mapper"), + ConsentRequired: gocloak.BoolP(false), + Config: &map[string]string{ + "usermodel.clientRoleMapping.clientId": dto.ID.String() + "-k8s-api", + "claim.name": "groups", + "access.token.claim": "false", + "id.token.claim": "true", + "userinfo.token.claim": "true", + "multivalued": "true", + "jsonType.label": "String", + }, + }) + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client protocol mapper for %s", dto.ID) + return "", err + } + // Create keycloak client role + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-create") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-create", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-read") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-read", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-update") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-update", dto.ID) + return "", err + } + err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-delete") + if err != nil { + log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-delete", dto.ID) + return "", err + } + + return dto.ID, nil +} + func (u *StackUsecase) Get(ctx context.Context, stackId domain.StackId) (out model.Stack, err error) { cluster, err := u.clusterRepo.Get(ctx, domain.ClusterId(stackId)) if err != nil { diff --git a/pkg/domain/cloud-account.go b/pkg/domain/cloud-account.go index dfac5409..ddd090cc 100644 --- a/pkg/domain/cloud-account.go +++ b/pkg/domain/cloud-account.go @@ -12,6 +12,7 @@ const ( CloudService_AZURE = "AZZURE" CloudService_GCP = "GCP" CloudService_BYOH = "BYOH" + CloudService_BYOK = "BYOK" ) // enum diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index f9bbb3bd..4c1caa2f 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -171,13 +171,15 @@ type CreateClusterRequest struct { } type ImportClusterRequest struct { - OrganizationId string `json:"organizationId" validate:"required"` - StackTemplateId string `json:"stackTemplateId" validate:"required"` - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` - ClusterType string `json:"clusterType"` - Kubeconfig []byte `json:"kubeconfig"` - CloudService string `json:"cloudService"` + OrganizationId string `json:"organizationId" validate:"required"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + ClusterType string `json:"clusterType"` + Kubeconfig []byte `json:"kubeconfig"` + CloudService string `json:"cloudService"` + PolicyIds []string `json:"policyIds,omitempty"` + Domains []ClusterDomain `json:"domains,omitempty"` } type CreateClusterResponse struct { @@ -244,7 +246,7 @@ type ClusterSiteValuesResponse struct { TksUserNodeType string `json:"tksUserNodeType,omitempty"` ByoClusterEndpointHost string `json:"byoClusterEndpointHost"` ByoClusterEndpointPort int `json:"byoClusterEndpointPort"` - Domains []ClusterDomain `json:"domains,omitempty"` + Domains []ClusterDomain `json:"domains"` } type GetClustersResponse struct { diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index b8f1a5a3..66a419c4 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -103,6 +103,19 @@ type CreateStackRequest struct { Domain StackDomain `json:"domain,omitempty"` } +type ImportStackResponse struct { + ID string `json:"id"` +} + +type ImportStackRequest struct { + Name string `json:"name" validate:"required,name,rfc1123"` + Description string `json:"description"` + StackTemplateId string `json:"stackTemplateId" validate:"required"` + PolicyIds []string `json:"policyIds,omitempty"` + Domain StackDomain `json:"domain,omitempty"` + Kubeconfig string `json:"kubeconfig" validate:"required"` +} + type CreateStackResponse struct { ID string `json:"id"` } From 0e39cdf8cd7bb6b090a02b4d4c9b8f713306b65e Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 18 Jul 2024 14:31:06 +0900 Subject: [PATCH 495/502] trivial. change type to string from []byte for kubeconfig --- internal/model/cluster.go | 2 +- internal/usecase/cluster.go | 7 +++++-- pkg/domain/cluster.go | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 416b640a..73a4e3fa 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -55,7 +55,7 @@ type Cluster struct { TksUserNode int TksUserNodeMax int TksUserNodeType string - Kubeconfig []byte `gorm:"-:all"` + Kubeconfig string `gorm:"-:all"` PolicyIds []string `gorm:"-:all"` CreatorId *uuid.UUID `gorm:"type:uuid"` Creator User `gorm:"foreignKey:CreatorId"` diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index dcdd7e9e..02f30583 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -253,7 +253,10 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster return "", errors.Wrap(err, "Failed to create cluster") } - kubeconfigBase64 := base64.StdEncoding.EncodeToString([]byte(dto.Kubeconfig)) + _, err = base64.StdEncoding.DecodeString(dto.Kubeconfig) + if err != nil { + return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid kubeconfig string"), "", "") + } workflowId, err := u.argo.SumbitWorkflowFromWftpl( ctx, @@ -264,7 +267,7 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster "contract_id=" + dto.OrganizationId, "cluster_id=" + clusterId.String(), "template_name=" + stackTemplate.Template, - "kubeconfig=" + kubeconfigBase64, + "kubeconfig=" + dto.Kubeconfig, "git_account=" + viper.GetString("git-account"), "keycloak_url=" + strings.TrimSuffix(viper.GetString("keycloak-address"), "/auth"), "base_repo_branch=" + viper.GetString("revision"), diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index 4c1caa2f..c884d227 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -176,7 +176,7 @@ type ImportClusterRequest struct { Name string `json:"name" validate:"required,name"` Description string `json:"description"` ClusterType string `json:"clusterType"` - Kubeconfig []byte `json:"kubeconfig"` + Kubeconfig string `json:"kubeconfig" validate:"required"` CloudService string `json:"cloudService"` PolicyIds []string `json:"policyIds,omitempty"` Domains []ClusterDomain `json:"domains,omitempty"` From c72fee6151b386de925885d90f476778ccc0e0e3 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 18 Jul 2024 14:31:06 +0900 Subject: [PATCH 496/502] trivial. change type to string from []byte for kubeconfig --- internal/model/cluster.go | 2 +- internal/repository/cluster.go | 2 +- internal/usecase/app-group.go | 4 +- internal/usecase/cluster.go | 74 ++++++++-------------------------- pkg/domain/cluster.go | 26 ++++++------ 5 files changed, 33 insertions(+), 75 deletions(-) diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 416b640a..73a4e3fa 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -55,7 +55,7 @@ type Cluster struct { TksUserNode int TksUserNodeMax int TksUserNodeType string - Kubeconfig []byte `gorm:"-:all"` + Kubeconfig string `gorm:"-:all"` PolicyIds []string `gorm:"-:all"` CreatorId *uuid.UUID `gorm:"type:uuid"` Creator User `gorm:"foreignKey:CreatorId"` diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index f6023559..a2b450cc 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -116,7 +116,7 @@ func (r *ClusterRepository) GetByName(ctx context.Context, organizationId string func (r *ClusterRepository) Create(ctx context.Context, dto model.Cluster) (clusterId domain.ClusterId, err error) { var cloudAccountId *uuid.UUID cloudAccountId = dto.CloudAccountId - if dto.CloudService == domain.CloudService_BYOH || dto.CloudService == domain.CloudService_BYOK || *dto.CloudAccountId == uuid.Nil { + if dto.CloudService != domain.CloudService_AWS || *dto.CloudAccountId == uuid.Nil { cloudAccountId = nil } if dto.ID == "" { diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index 37896b64..60ce2213 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -81,7 +81,7 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do // check cloudAccount tksCloudAccountId := "" tksObjectStore := "minio" - if cluster.CloudService != domain.CloudService_BYOH { + if cluster.CloudService == domain.CloudService_AWS { tksObjectStore = "s3" cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, cluster.OrganizationId, nil) if err != nil { @@ -181,7 +181,7 @@ func (u *AppGroupUsecase) Delete(ctx context.Context, id domain.AppGroupId) (err // check cloudAccount tksCloudAccountId := "" tksObjectStore := "minio" - if cluster.CloudService != domain.CloudService_BYOH { + if cluster.CloudService == domain.CloudService_AWS { tksObjectStore = "s3" cloudAccounts, err := u.cloudAccountRepo.Fetch(ctx, cluster.OrganizationId, nil) if err != nil { diff --git a/internal/usecase/cluster.go b/internal/usecase/cluster.go index dcdd7e9e..6fa35281 100644 --- a/internal/usecase/cluster.go +++ b/internal/usecase/cluster.go @@ -8,7 +8,6 @@ import ( "strings" "time" - "github.com/Nerzal/gocloak/v13" "github.com/openinfradev/tks-api/internal/keycloak" "github.com/google/uuid" @@ -248,12 +247,24 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster dto.ID = "tks-admin" dto.Name = "tks-admin" } + + // [TODO] check nodes + dto.TksCpNode = 1 + dto.TksCpNodeMax = 1 + dto.TksInfraNode = 1 + dto.TksInfraNodeMax = 1 + dto.TksUserNode = 1 + dto.TksUserNodeMax = 1 + clusterId, err = u.repo.Create(ctx, dto) if err != nil { return "", errors.Wrap(err, "Failed to create cluster") } - kubeconfigBase64 := base64.StdEncoding.EncodeToString([]byte(dto.Kubeconfig)) + _, err = base64.StdEncoding.DecodeString(dto.Kubeconfig) + if err != nil { + return "", httpErrors.NewBadRequestError(fmt.Errorf("Invalid kubeconfig string"), "", "") + } workflowId, err := u.argo.SumbitWorkflowFromWftpl( ctx, @@ -263,8 +274,9 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster fmt.Sprintf("tks_api_url=%s", viper.GetString("external-address")), "contract_id=" + dto.OrganizationId, "cluster_id=" + clusterId.String(), + "site_name=" + clusterId.String(), "template_name=" + stackTemplate.Template, - "kubeconfig=" + kubeconfigBase64, + "kubeconfig=" + dto.Kubeconfig, "git_account=" + viper.GetString("git-account"), "keycloak_url=" + strings.TrimSuffix(viper.GetString("keycloak-address"), "/auth"), "base_repo_branch=" + viper.GetString("revision"), @@ -280,56 +292,6 @@ func (u *ClusterUsecase) Import(ctx context.Context, dto model.Cluster) (cluster return "", errors.Wrap(err, "Failed to initialize status") } - // keycloak setting - log.Debugf(ctx, "Create keycloak client for %s", dto.ID) - // Create keycloak client - clientUUID, err := u.kc.CreateClient(ctx, dto.OrganizationId, dto.ID.String()+"-k8s-api", "", nil) - if err != nil { - log.Errorf(ctx, "Failed to create keycloak client for %s", dto.ID) - return "", err - } - // Create keycloak client protocol mapper - _, err = u.kc.CreateClientProtocolMapper(ctx, dto.OrganizationId, clientUUID, gocloak.ProtocolMapperRepresentation{ - Name: gocloak.StringP("k8s-role-mapper"), - Protocol: gocloak.StringP("openid-connect"), - ProtocolMapper: gocloak.StringP("oidc-usermodel-client-role-mapper"), - ConsentRequired: gocloak.BoolP(false), - Config: &map[string]string{ - "usermodel.clientRoleMapping.clientId": dto.ID.String() + "-k8s-api", - "claim.name": "groups", - "access.token.claim": "false", - "id.token.claim": "true", - "userinfo.token.claim": "true", - "multivalued": "true", - "jsonType.label": "String", - }, - }) - if err != nil { - log.Errorf(ctx, "Failed to create keycloak client protocol mapper for %s", dto.ID) - return "", err - } - // Create keycloak client role - err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-create") - if err != nil { - log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-create", dto.ID) - return "", err - } - err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-read") - if err != nil { - log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-read", dto.ID) - return "", err - } - err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-update") - if err != nil { - log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-update", dto.ID) - return "", err - } - err = u.kc.CreateClientRole(ctx, dto.OrganizationId, clientUUID, "cluster-admin-delete") - if err != nil { - log.Errorf(ctx, "Failed to create keycloak client role named %s for %s", "cluster-admin-delete", dto.ID) - return "", err - } - return clusterId, nil } @@ -440,10 +402,6 @@ func (u *ClusterUsecase) Resume(ctx context.Context, clusterId domain.ClusterId) return httpErrors.NewBadRequestError(fmt.Errorf("Invalid stackId"), "S_INVALID_STACK_ID", "") } - if cluster.CloudService != domain.CloudService_BYOH { - return httpErrors.NewBadRequestError(fmt.Errorf("Invalid cloud service"), "S_INVALID_CLOUD_SERVICE", "") - } - if cluster.WorkflowId == "" { return httpErrors.NewInternalServerError(fmt.Errorf("Invalid workflow id"), "", "") } @@ -494,7 +452,7 @@ func (u *ClusterUsecase) Delete(ctx context.Context, clusterId domain.ClusterId) // FOR TEST. ADD MAGIC KEYWORD // check cloudAccount tksCloudAccountId := "NULL" - if cluster.CloudService != domain.CloudService_BYOH { + if cluster.CloudService == domain.CloudService_AWS { cloudAccount, err := u.cloudAccountRepo.Get(ctx, cluster.CloudAccount.ID) if err != nil { return httpErrors.NewInternalServerError(fmt.Errorf("Failed to get cloudAccount"), "", "") diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index 4c1caa2f..a57ea73e 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -176,7 +176,7 @@ type ImportClusterRequest struct { Name string `json:"name" validate:"required,name"` Description string `json:"description"` ClusterType string `json:"clusterType"` - Kubeconfig []byte `json:"kubeconfig"` + Kubeconfig string `json:"kubeconfig" validate:"required"` CloudService string `json:"cloudService"` PolicyIds []string `json:"policyIds,omitempty"` Domains []ClusterDomain `json:"domains,omitempty"` @@ -192,14 +192,14 @@ type ImportClusterResponse struct { type ClusterConfResponse struct { TksCpNode int `json:"tksCpNode"` - TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` - TksCpNodeType string `json:"tksCpNodeType,omitempty"` + TksCpNodeMax int `json:"tksCpNodeMax"` + TksCpNodeType string `json:"tksCpNodeType"` TksInfraNode int `json:"tksInfraNode"` - TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` - TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` + TksInfraNodeMax int `json:"tksInfraNodeMax"` + TksInfraNodeType string `json:"tksInfraNodeType"` TksUserNode int `json:"tksUserNode"` - TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` - TksUserNodeType string `json:"tksUserNodeType,omitempty"` + TksUserNodeMax int `json:"tksUserNodeMax"` + TksUserNodeType string `json:"tksUserNodeType"` } type ClusterResponse struct { @@ -236,14 +236,14 @@ type ClusterSiteValuesResponse struct { SshKeyName string `json:"sshKeyName"` ClusterRegion string `json:"clusterRegion"` TksCpNode int `json:"tksCpNode"` - TksCpNodeMax int `json:"tksCpNodeMax,omitempty"` - TksCpNodeType string `json:"tksCpNodeType,omitempty"` + TksCpNodeMax int `json:"tksCpNodeMax"` + TksCpNodeType string `json:"tksCpNodeType"` TksInfraNode int `json:"tksInfraNode"` - TksInfraNodeMax int `json:"tksInfraNodeMax,omitempty"` - TksInfraNodeType string `json:"tksInfraNodeType,omitempty"` + TksInfraNodeMax int `json:"tksInfraNodeMax"` + TksInfraNodeType string `json:"tksInfraNodeType"` TksUserNode int `json:"tksUserNode"` - TksUserNodeMax int `json:"tksUserNodeMax,omitempty"` - TksUserNodeType string `json:"tksUserNodeType,omitempty"` + TksUserNodeMax int `json:"tksUserNodeMax"` + TksUserNodeType string `json:"tksUserNodeType"` ByoClusterEndpointHost string `json:"byoClusterEndpointHost"` ByoClusterEndpointPort int `json:"byoClusterEndpointPort"` Domains []ClusterDomain `json:"domains"` From 54c0aca53ac20bb16704b15aa0284eb421ef5e7a Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Tue, 23 Jul 2024 15:07:05 +0900 Subject: [PATCH 497/502] feature. add GetCloudServices to stack-template API --- api/swagger/docs.go | 136 +++++++++++++++-------- api/swagger/swagger.json | 136 +++++++++++++++-------- api/swagger/swagger.yaml | 93 ++++++++++------ internal/delivery/api/endpoint.go | 1 + internal/delivery/http/stack-template.go | 55 +++++++-- internal/route/route.go | 1 + internal/usecase/stack-template.go | 23 ++++ pkg/domain/stack-template.go | 4 + 8 files changed, 314 insertions(+), 135 deletions(-) diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 9aff60bb..fdcedb78 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -8136,6 +8136,13 @@ const docTemplate = `{ ], "summary": "Get Organization StackTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -8198,6 +8205,13 @@ const docTemplate = `{ ], "summary": "Remove organization stackTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "Remove organization stack templates request", "name": "body", @@ -8232,6 +8246,13 @@ const docTemplate = `{ ], "summary": "Add organization stackTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "Add organization stack templates request", "name": "body", @@ -8249,6 +8270,43 @@ const docTemplate = `{ } } }, + "/organizations/{organizationId}/stack-templates/cloud-services": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization CloudServices", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization CloudServices", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + } + }, "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { "get": { "security": [ @@ -8267,6 +8325,22 @@ const docTemplate = `{ "StackTemplates" ], "summary": "Get Organization StackTemplate", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -13702,6 +13776,7 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest": { "type": "object", "required": [ + "kubeconfig", "name", "organizationId", "stackTemplateId" @@ -13716,18 +13791,27 @@ const docTemplate = `{ "description": { "type": "string" }, - "kubeconfig": { + "domains": { "type": "array", "items": { - "type": "integer" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" } }, + "kubeconfig": { + "type": "string" + }, "name": { "type": "string" }, "organizationId": { "type": "string" }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, "stackTemplateId": { "type": "string" } @@ -13744,30 +13828,20 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest": { "type": "object", "required": [ - "cloudService", + "kubeconfig", "name", "stackTemplateId" ], "properties": { - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "BYOH" - ] - }, - "clusterId": { - "type": "string" - }, "description": { "type": "string" }, "domain": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, + "kubeconfig": { + "type": "string" + }, "name": { "type": "string" }, @@ -13779,36 +13853,6 @@ const docTemplate = `{ }, "stackTemplateId": { "type": "string" - }, - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - }, - "userClusterEndpoint": { - "type": "string" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 48a9e924..df599c82 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -8130,6 +8130,13 @@ ], "summary": "Get Organization StackTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "type": "string", "description": "pageSize", @@ -8192,6 +8199,13 @@ ], "summary": "Remove organization stackTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "Remove organization stack templates request", "name": "body", @@ -8226,6 +8240,13 @@ ], "summary": "Add organization stackTemplates", "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, { "description": "Add organization stack templates request", "name": "body", @@ -8243,6 +8264,43 @@ } } }, + "/organizations/{organizationId}/stack-templates/cloud-services": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Get Organization CloudServices", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "StackTemplates" + ], + "summary": "Get Organization CloudServices", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse" + } + } + } + } + }, "/organizations/{organizationId}/stack-templates/{stackTemplateId}": { "get": { "security": [ @@ -8261,6 +8319,22 @@ "StackTemplates" ], "summary": "Get Organization StackTemplate", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "stackTemplateId", + "name": "stackTemplateId", + "in": "path", + "required": true + } + ], "responses": { "200": { "description": "OK", @@ -13696,6 +13770,7 @@ "github_com_openinfradev_tks-api_pkg_domain.ImportClusterRequest": { "type": "object", "required": [ + "kubeconfig", "name", "organizationId", "stackTemplateId" @@ -13710,18 +13785,27 @@ "description": { "type": "string" }, - "kubeconfig": { + "domains": { "type": "array", "items": { - "type": "integer" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain" } }, + "kubeconfig": { + "type": "string" + }, "name": { "type": "string" }, "organizationId": { "type": "string" }, + "policyIds": { + "type": "array", + "items": { + "type": "string" + } + }, "stackTemplateId": { "type": "string" } @@ -13738,30 +13822,20 @@ "github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest": { "type": "object", "required": [ - "cloudService", + "kubeconfig", "name", "stackTemplateId" ], "properties": { - "cloudAccountId": { - "type": "string" - }, - "cloudService": { - "type": "string", - "enum": [ - "AWS", - "BYOH" - ] - }, - "clusterId": { - "type": "string" - }, "description": { "type": "string" }, "domain": { "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain" }, + "kubeconfig": { + "type": "string" + }, "name": { "type": "string" }, @@ -13773,36 +13847,6 @@ }, "stackTemplateId": { "type": "string" - }, - "tksCpNode": { - "type": "integer" - }, - "tksCpNodeMax": { - "type": "integer" - }, - "tksCpNodeType": { - "type": "string" - }, - "tksInfraNode": { - "type": "integer" - }, - "tksInfraNodeMax": { - "type": "integer" - }, - "tksInfraNodeType": { - "type": "string" - }, - "tksUserNode": { - "type": "integer" - }, - "tksUserNodeMax": { - "type": "integer" - }, - "tksUserNodeType": { - "type": "string" - }, - "userClusterEndpoint": { - "type": "string" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 2c0a0d7a..d18429fe 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -2158,17 +2158,24 @@ definitions: type: string description: type: string - kubeconfig: + domains: items: - type: integer + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ClusterDomain' type: array + kubeconfig: + type: string name: type: string organizationId: type: string + policyIds: + items: + type: string + type: array stackTemplateId: type: string required: + - kubeconfig - name - organizationId - stackTemplateId @@ -2180,19 +2187,12 @@ definitions: type: object github_com_openinfradev_tks-api_pkg_domain.ImportStackRequest: properties: - cloudAccountId: - type: string - cloudService: - enum: - - AWS - - BYOH - type: string - clusterId: - type: string description: type: string domain: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackDomain' + kubeconfig: + type: string name: type: string policyIds: @@ -2201,28 +2201,8 @@ definitions: type: array stackTemplateId: type: string - tksCpNode: - type: integer - tksCpNodeMax: - type: integer - tksCpNodeType: - type: string - tksInfraNode: - type: integer - tksInfraNodeMax: - type: integer - tksInfraNodeType: - type: string - tksUserNode: - type: integer - tksUserNodeMax: - type: integer - tksUserNodeType: - type: string - userClusterEndpoint: - type: string required: - - cloudService + - kubeconfig - name - stackTemplateId type: object @@ -9666,6 +9646,11 @@ paths: - application/json description: Get Organization StackTemplates parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: pageSize in: query name: pageSize @@ -9706,6 +9691,11 @@ paths: - application/json description: Add organization stackTemplates parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: Add organization stack templates request in: body name: body @@ -9727,6 +9717,11 @@ paths: - application/json description: Remove organization stackTemplates parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string - description: Remove organization stack templates request in: body name: body @@ -9748,6 +9743,17 @@ paths: consumes: - application/json description: Get Organization StackTemplate + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: stackTemplateId + in: path + name: stackTemplateId + required: true + type: string produces: - application/json responses: @@ -9760,6 +9766,29 @@ paths: summary: Get Organization StackTemplate tags: - StackTemplates + /organizations/{organizationId}/stack-templates/cloud-services: + get: + consumes: + - application/json + description: Get Organization CloudServices + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.GetStackTemplatesResponse' + security: + - JWT: [] + summary: Get Organization CloudServices + tags: + - StackTemplates /organizations/{organizationId}/stacks: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index d8099b20..423df5d0 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -111,6 +111,7 @@ const ( GetOrganizationStackTemplate AddOrganizationStackTemplates RemoveOrganizationStackTemplates + GetOrganizationCloudServices // Dashboard CreateDashboard diff --git a/internal/delivery/http/stack-template.go b/internal/delivery/http/stack-template.go index 78faf378..3cdf43a3 100644 --- a/internal/delivery/http/stack-template.go +++ b/internal/delivery/http/stack-template.go @@ -350,12 +350,13 @@ func (h *StackTemplateHandler) UpdateStackTemplateOrganizations(w http.ResponseW // @Description Get Organization StackTemplates // @Accept json // @Produce json -// @Param pageSize query string false "pageSize" -// @Param pageNumber query string false "pageNumber" -// @Param soertColumn query string false "sortColumn" -// @Param sortOrder query string false "sortOrder" -// @Param filters query []string false "filters" -// @Success 200 {object} domain.GetStackTemplatesResponse +// @Param organizationId path string true "organizationId" +// @Param pageSize query string false "pageSize" +// @Param pageNumber query string false "pageNumber" +// @Param soertColumn query string false "sortColumn" +// @Param sortOrder query string false "sortOrder" +// @Param filters query []string false "filters" +// @Success 200 {object} domain.GetStackTemplatesResponse // @Router /organizations/{organizationId}/stack-templates [get] // @Security JWT func (h *StackTemplateHandler) GetOrganizationStackTemplates(w http.ResponseWriter, r *http.Request) { @@ -401,6 +402,34 @@ func (h *StackTemplateHandler) GetOrganizationStackTemplates(w http.ResponseWrit ResponseJSON(w, r, http.StatusOK, out) } +// GetOrganizationCloudServices godoc +// +// @Tags StackTemplates +// @Summary Get Organization CloudServices +// @Description Get Organization CloudServices +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Success 200 {object} domain.GetStackTemplatesResponse +// @Router /organizations/{organizationId}/stack-templates/cloud-services [get] +// @Security JWT +func (h *StackTemplateHandler) GetOrganizationCloudServices(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + cloudServices, err := h.usecase.GetCloudServices(r.Context(), organizationId) + if err != nil { + ErrorJSON(w, r, err) + return + } + var out domain.GetCloudServicesResponse + out.CloudServices = cloudServices + ResponseJSON(w, r, http.StatusOK, out) +} + // GetOrganizationStackTemplate godoc // // @Tags StackTemplates @@ -408,7 +437,9 @@ func (h *StackTemplateHandler) GetOrganizationStackTemplates(w http.ResponseWrit // @Description Get Organization StackTemplate // @Accept json // @Produce json -// @Success 200 {object} domain.GetStackTemplateResponse +// @Param organizationId path string true "organizationId" +// @Param stackTemplateId path string true "stackTemplateId" +// @Success 200 {object} domain.GetStackTemplateResponse // @Router /organizations/{organizationId}/stack-templates/{stackTemplateId} [get] // @Security JWT func (h *StackTemplateHandler) GetOrganizationStackTemplate(w http.ResponseWriter, r *http.Request) { @@ -500,8 +531,9 @@ func (h *StackTemplateHandler) CheckStackTemplateName(w http.ResponseWriter, r * // @Description Add organization stackTemplates // @Accept json // @Produce json -// @Param body body domain.AddOrganizationStackTemplatesRequest true "Add organization stack templates request" -// @Success 200 {object} nil +// @Param organizationId path string true "organizationId" +// @Param body body domain.AddOrganizationStackTemplatesRequest true "Add organization stack templates request" +// @Success 200 {object} nil // @Router /organizations/{organizationId}/stack-templates [post] // @Security JWT func (h *StackTemplateHandler) AddOrganizationStackTemplates(w http.ResponseWriter, r *http.Request) { @@ -534,8 +566,9 @@ func (h *StackTemplateHandler) AddOrganizationStackTemplates(w http.ResponseWrit // @Description Remove organization stackTemplates // @Accept json // @Produce json -// @Param body body domain.RemoveOrganizationStackTemplatesRequest true "Remove organization stack templates request" -// @Success 200 {object} nil +// @Param organizationId path string true "organizationId" +// @Param body body domain.RemoveOrganizationStackTemplatesRequest true "Remove organization stack templates request" +// @Success 200 {object} nil // @Router /organizations/{organizationId}/stack-templates [put] // @Security JWT func (h *StackTemplateHandler) RemoveOrganizationStackTemplates(w http.ResponseWriter, r *http.Request) { diff --git a/internal/route/route.go b/internal/route/route.go index 79341469..df7e5304 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -198,6 +198,7 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_UpdateStackTemplate, http.HandlerFunc(stackTemplateHandler.UpdateStackTemplate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.Admin_DeleteStackTemplate, http.HandlerFunc(stackTemplateHandler.DeleteStackTemplate))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.GetOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplates))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates/cloud-services", customMiddleware.Handle(internalApi.GetOrganizationCloudServices, http.HandlerFunc(stackTemplateHandler.GetOrganizationCloudServices))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates/{stackTemplateId}", customMiddleware.Handle(internalApi.GetOrganizationStackTemplate, http.HandlerFunc(stackTemplateHandler.GetOrganizationStackTemplate))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.AddOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.AddOrganizationStackTemplates))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stack-templates", customMiddleware.Handle(internalApi.RemoveOrganizationStackTemplates, http.HandlerFunc(stackTemplateHandler.RemoveOrganizationStackTemplates))).Methods(http.MethodPut) diff --git a/internal/usecase/stack-template.go b/internal/usecase/stack-template.go index 41c95a46..feedea43 100644 --- a/internal/usecase/stack-template.go +++ b/internal/usecase/stack-template.go @@ -33,6 +33,7 @@ type IStackTemplateUsecase interface { AddOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error RemoveOrganizationStackTemplates(ctx context.Context, organizationId string, stackTemplateIds []string) error GetTemplateIds(ctx context.Context) ([]string, error) + GetCloudServices(ctx context.Context, organizationId string) ([]string, error) } type StackTemplateUsecase struct { @@ -278,6 +279,28 @@ func (u *StackTemplateUsecase) GetTemplateIds(ctx context.Context) (out []string return } +func (u *StackTemplateUsecase) GetCloudServices(ctx context.Context, organizationId string) (out []string, err error) { + stackTemplates, err := u.repo.FetchWithOrganization(ctx, organizationId, nil) + if err != nil { + return nil, err + } + + for _, stackTemplate := range stackTemplates { + bExist := false + for _, val := range out { + if val == stackTemplate.CloudService { + bExist = true + break + } + } + + if !bExist { + out = append(out, stackTemplate.CloudService) + } + } + return +} + func servicesFromIds(serviceIds []string) []byte { services := "[" for i, serviceId := range serviceIds { diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index a2cdaca4..a66f035f 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -116,3 +116,7 @@ type RemoveOrganizationStackTemplatesRequest struct { type GetStackTemplateTemplateIdsResponse struct { TemplateIds []string `json:"templateIds"` } + +type GetCloudServicesResponse struct { + CloudServices []string `json:"cloudServices"` +} From 198c35e95dc89d8898e02e760c88373d64cf9d80 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 24 Jul 2024 19:29:13 +0900 Subject: [PATCH 498/502] feature. add pprof for profiling --- cmd/server/main.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/server/main.go b/cmd/server/main.go index d5e62bde..0b495748 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -5,6 +5,7 @@ import ( "flag" "fmt" "net/http" + _ "net/http/pprof" "strconv" "strings" @@ -110,6 +111,10 @@ func main() { } log.Info(ctx, "****************** ") + go func() { + http.ListenAndServe("0.0.0.0:6060", nil) + }() + // For web service asset := route.NewAssetHandler(viper.GetString("web-root")) From 1f4e342f98cc009790e1537aa46c1ca538a325a9 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 26 Jul 2024 14:19:42 +0900 Subject: [PATCH 499/502] trivial. remove omitempty for getStack response --- pkg/domain/stack.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/domain/stack.go b/pkg/domain/stack.go index 66a419c4..fcda2764 100644 --- a/pkg/domain/stack.go +++ b/pkg/domain/stack.go @@ -158,7 +158,7 @@ type StackResponse struct { Creator SimpleUserResponse `json:"creator,omitempty"` Updator SimpleUserResponse `json:"updator,omitempty"` Favorited bool `json:"favorited"` - ClusterEndpoint string `json:"userClusterEndpoint,omitempty"` + ClusterEndpoint string `json:"userClusterEndpoint"` Resource DashboardStackResponse `json:"resource,omitempty"` AppServeAppCnt int `json:"appServeAppCnt"` Domain StackDomain `json:"domain"` From 8d0651489bfd2f88a4ad8298dace409046d2fbdc Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 6 Sep 2024 17:14:40 +0900 Subject: [PATCH 500/502] trivial. change deliminator for domains --- internal/usecase/stack.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index e4f22eb5..130a62f7 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -135,7 +135,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom domains := make([]string, len(dto.Domains)) for i, domain := range dto.Domains { - domains[i] = domain.DomainType + "_" + domain.Url + domains[i] = domain.DomainType + "|" + domain.Url } workflow := "tks-stack-create" @@ -319,7 +319,7 @@ func (u *StackUsecase) Import(ctx context.Context, dto model.Stack) (stackId dom domains := make([]string, len(dto.Domains)) for i, domain := range dto.Domains { - domains[i] = domain.DomainType + "_" + domain.Url + domains[i] = domain.DomainType + "|" + domain.Url } workflow := "tks-stack-import" From c3953817d325a607ab4623be0f51ec2937079605 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Fri, 6 Sep 2024 17:14:40 +0900 Subject: [PATCH 501/502] trivial. change deliminator for domains --- internal/usecase/stack.go | 4 ++-- pkg/domain/cluster.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/usecase/stack.go b/internal/usecase/stack.go index e4f22eb5..130a62f7 100644 --- a/internal/usecase/stack.go +++ b/internal/usecase/stack.go @@ -135,7 +135,7 @@ func (u *StackUsecase) Create(ctx context.Context, dto model.Stack) (stackId dom domains := make([]string, len(dto.Domains)) for i, domain := range dto.Domains { - domains[i] = domain.DomainType + "_" + domain.Url + domains[i] = domain.DomainType + "|" + domain.Url } workflow := "tks-stack-create" @@ -319,7 +319,7 @@ func (u *StackUsecase) Import(ctx context.Context, dto model.Stack) (stackId dom domains := make([]string, len(dto.Domains)) for i, domain := range dto.Domains { - domains[i] = domain.DomainType + "_" + domain.Url + domains[i] = domain.DomainType + "|" + domain.Url } workflow := "tks-stack-import" diff --git a/pkg/domain/cluster.go b/pkg/domain/cluster.go index a57ea73e..4bd82ae0 100644 --- a/pkg/domain/cluster.go +++ b/pkg/domain/cluster.go @@ -117,7 +117,7 @@ type BootstrapKubeconfig struct { } type ClusterDomain struct { - DomainType string `json:"domainType" validate:"oneof=grafana loki minio thanos_sidecar jaeger kiali"` + DomainType string `json:"domainType"` Url string `json:"url"` } From 94bf5e2d665dd833d2cdd4143da785e9794993a1 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Wed, 2 Oct 2024 13:40:10 +0900 Subject: [PATCH 502/502] trivial. fix lint error --- cmd/server/main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 0b495748..b033f8b4 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -112,7 +112,10 @@ func main() { log.Info(ctx, "****************** ") go func() { - http.ListenAndServe("0.0.0.0:6060", nil) + err := http.ListenAndServe("0.0.0.0:6060", nil) + if err != nil { + log.Error(ctx, "0.0.0.0:6060 failed to listen") + } }() // For web service
- {{.TemporaryPassword}} + + + + + + + + + + + + + + + + + + -
+ 조직코드 + + {{.OrganizationId}} +
+ 아이디 + + {{.AccountId}} +
+ 비밀번호 + + {{.TemporaryPassword}}
-